from flask import render_template, request, session
from flask import Blueprint
import flask
import flask_login
import time
import datetime
import sys
import smtplib
from email.mime.text import MIMEText
from email.header import Header

# sys.path.append('../')

# Basic function
from ..app import db
from ..mail import sendEmail
# register blueprint
bp = flask.Blueprint('task', __name__)

# table record all the task and its property
class c_task_list(db.Model):
    __tablename__ = 'tb_task_list'
    id = db.Column(db.Integer, primary_key=True,
                   unique=True, autoincrement=True)
    task_id = db.Column(db.String(10))
    task_name = db.Column(db.String(200))
    pj_dpt = db.Column(db.String(20))
    task_type = db.Column(db.String(20))
    priority = db.Column(db.String(20))
    owner = db.Column(db.String(20))
    description = db.Column(db.String(1000))
    task_status = db.Column(db.String(20))
    log_by = db.Column(db.String(20))
    log_time = db.Column(db.String(20))
    update_time = db.Column(db.String(20))

# table record the update of the task
class c_task_content(db.Model):
    __tablename__ = 'tb_task_content'
    id = db.Column(db.Integer, primary_key=True,
                   unique=True, autoincrement=True)
    task_id = db.Column(db.String(10))
    task_seq = db.Column(db.Integer)
    update_name = db.Column(db.String(20))
    update_time = db.Column(db.String(20))
    time_consume = db.Column(db.Float)
    content = db.Column(db.String(2000))
    task_status = db.Column(db.String(20))
    file_qty = db.Column(db.Integer)

# table record the task property change for history tracking
class c_task_log(db.Model):
    __tablename__ = 'tb_task_log'
    id = db.Column(db.Integer, primary_key=True,
                   unique=True, autoincrement=True)
    task_id = db.Column(db.String(10))
    property = db.Column(db.String(20))
    name = db.Column(db.String(20))
    change_time = db.Column(db.String(20))
    old = db.Column(db.String(500))
    new = db.Column(db.String(500))

# table record the setting of the system
class c_task_config(db.Model):
    __tablename__ = 'tb_task_config'
    id = db.Column(db.Integer, primary_key=True,
                   unique=True, autoincrement=True)
    property = db.Column(db.String(20))
    setting = db.Column(db.String(20))

# table record the user access right
class c_task_role(db.Model):
    __tablename__ = 'tb_task_role'
    id = db.Column(db.Integer, primary_key=True,
                   unique=True, autoincrement=True)
    user_name = db.Column(db.String(20))
    property = db.Column(db.String(20))
    value = db.Column(db.String(20))

# table record the user's email
class c_task_user(db.Model):
    __tablename__ = 'tb_task_user'
    id = db.Column(db.Integer, primary_key=True,
                   unique=True, autoincrement=True)
    user_name = db.Column(db.String(20))
    email = db.Column(db.String(30))

def is_access(user_name, property1, val):
    result = 0
    if user_name:
        if val:
            filters = {
                c_task_role.user_name == user_name,
                c_task_role.property == property1,
                c_task_role.value == val
            }
            all_results = c_task_role.query.filter(*filters).all()
            if all_results:  # the resource's property user access match to the settinig
                result = 1
    return result

def send_email(title, task_id, content):
    try:
        all_results = c_task_list.query.filter(
            c_task_list.task_id == task_id).first()
        if all_results:
            to_addr = []
            user = c_task_user.query.filter(
                c_task_user.user_name == all_results.owner).first()
            if user:
                to_addr.append(user.email)
            user = c_task_user.query.filter(
                c_task_user.user_name == all_results.log_by).first()
            if user:
                to_addr.append(user.email)

            sendEmail(receivers=to_addr, subject=title,
                      content=content, sender='task@leadrive.com')

        print("邮件发送成功")
    except smtplib.SMTPException:
        print("Error: 无法发送邮件")

@bp.route('/')
@flask_login.login_required
def defaultPage():
    display_name = flask_login.current_user.displayName
    return render_template('/task/task_search.html', display_name=display_name)

@bp.route("/search")
@flask_login.login_required
def task_search():
    display_name = flask_login.current_user.displayName
    return render_template('/task/task_search.html', display_name=display_name)

@bp.route("/create")
@flask_login.login_required
def task_create():
    display_name = flask_login.current_user.displayName
    return render_template('/task/task_new.html', display_name=display_name)

@bp.route("/<task_id>")
@flask_login.login_required
def task_view(task_id):
    display_name = flask_login.current_user.displayName
    id1 = task_id.upper()
    return render_template('/task/task_view.html', task_id=id1, display_name=display_name)

# return the project & department the user can access

@bp.route("/role/get", methods=['POST'])
@flask_login.login_required
def task_role_get():

    property1 = request.form.get('property')
    user_name = flask_login.current_user.displayName
    all_results = c_task_role.query.filter(c_task_role.user_name == user_name, c_task_role.property == property1)\
        .all()

    if all_results:
        result_json = '['
        for i in all_results:
            result_json = result_json + '{' + '"setting":"' + i.value + '"},'
        status = '200'
        value_msg = 'get successfully!'
        result_json = result_json[0:len(result_json) - 1]
        result_json = result_json + ']'
    else:
        status = '401'
        value_msg = 'No Result Found!'
        result_json = '"No Data!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result

# return the config
# now only return the task_type of each project & department
@bp.route("/config/get", methods=['POST'])
def task_config_get():
    property1 = request.form.get('property')
    all_results = c_task_config.query.filter(
        c_task_config.property == property1).all()

    if all_results:
        result_json = '['
        for i in all_results:
            result_json = result_json + '{' + '"setting":"' + i.setting + '"},'
        status = '200'
        value_msg = 'get successfully!'
        result_json = result_json[0:len(result_json) - 1]
        result_json = result_json + ']'
    else:
        status = '401'
        value_msg = 'No Result Found!'
        result_json = '"No Data!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result

# create the new task
@bp.route("/list/new", methods=['POST'])
def task_list_new():
    if flask_login.current_user.displayName:  # if log in
        task_name = request.form.get('task_name')
        pj_dpt = request.form.get('pj_dpt')
        task_type = request.form.get('task_type')
        priority = request.form.get('priority')
        owner = request.form.get('owner')
        description = request.form.get('description')
        task_status = '1-新建'

        user_name = flask_login.current_user.displayName
        # check if can access the resource
        valid = is_access(user_name, 'pj_dpt', pj_dpt)
        if valid == 1:
            log_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            update_time = ''
            task_id = 'TK' + time.strftime("%y", time.localtime())
            return_id = c_task_list.query.filter(c_task_list.task_id.like(task_id + '%'))\
                .order_by(c_task_list.task_id.desc()).first()
            if return_id:
                print(return_id.task_id)
                last_id = return_id.task_id
                last_id = last_id[2:8]
                task_id = 'TK' + str(int(last_id) + 1)
            else:
                task_id = task_id + '0001'

            record = c_task_list(task_id=task_id, task_name=task_name, pj_dpt=pj_dpt, task_type=task_type,
                                 priority=priority, owner=owner, description=description, task_status=task_status,
                                 log_by=user_name, log_time=log_time, update_time=update_time)
            db.session.add(record)
            db.session.commit()

            # email to inform the related people
            email_title = '新建任务---' + task_id + ': ' + task_name
            email_content = '

' \
                '属性	内容
' \
                '
任务号	' + task_id + '
' \
                '
任务名	' + task_name + '
' \
                '
任务描述	' + description + '
' \
                '
项目或部门	' + pj_dpt + '
' \
                '
任务类型	' + task_type + '
' \
                '
优先级	' + priority + '
' \
                '
负责人	' + owner + '
' \
                '
创建人	' + user_name + '
' \
                '
任务状态	' + task_status + '

'
            send_email(email_title, task_id, email_content)

            status = '200'
            value_msg = 'Create successfully!'
            result_json = '[{"task_id":"' + task_id + '", "task_name":"' + task_name + '", "task_type":"' + task_type \
                          + '", "description":"' + description + '", "pj_dpt":"' + pj_dpt \
                          + '", "priority":"' + priority + '", "owner":"' + owner \
                          + '", "task_status":"' + task_status + '", "log_time":"' + str(log_time) \
                          + '", "log_by":"' + user_name + '", "update_time":"' + update_time + '"}]'
        else:
            status = '403'
            value_msg = 'Access Deny!'
            result_json = '"Access Deny"'
    else:
        status = '401'
        value_msg = 'Please log in first!'
        result_json = '"Please log in first!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result

# return the task list front end search

@bp.route("/list/search", methods=['POST'])
def task_list_search():
    task_start_id = request.form.get('start_id')
    task_end_id = request.form.get('end_id')
    pj_dpt = request.form.get('pj_dpt')
    task_type = request.form.get('task_type')
    priority = request.form.get('priority')
    owner = request.form.get('owner')
    task_status = request.form.get('task_status')

    user_name = flask_login.current_user.displayName
    # check if can access the resource
    valid = is_access(user_name, 'pj_dpt', pj_dpt)
    if valid == 1:
        filters = {
            c_task_list.task_id.between(task_start_id, task_end_id),
            c_task_list.pj_dpt == pj_dpt
        }

        if task_type != '不限':
            filters.add(c_task_list.task_type == task_type)

        if priority != '不限':
            filters.add(c_task_list.priority == priority)

        if owner != '不限':
            filters.add(c_task_list.owner == owner)

        if task_status != '不限':
            filters.add(c_task_list.task_status == task_status)

        all_results = c_task_list.query.filter(*filters).all()

        if all_results:
            result_json = '['
            for i in all_results:
                last_update = '无更新记录！'
                aaa = c_task_content.query.filter(
                    c_task_content.task_id == i.task_id).all()
                if aaa:
                    last_update = aaa[-1].content
                result_json = result_json + '{' + '"task_id":"' + i.task_id\
                                                + '","task_name":"' + i.task_name\
                                                + '","pj_dpt":"' + i.pj_dpt\
                                                + '","task_type":"' + i.task_type\
                                                + '", "priority":"' + i.priority\
                                                + '", "owner":"' + i.owner\
                                                + '", "task_status":"' + i.task_status\
                                                + '", "last_update":"' + last_update\
                                                + '", "update_time":"' + i.update_time\
                                                + '", "log_by":"' + i.log_by\
                                                + '", "log_time":"' + i.log_time + '"},'
            status = '200'
            value_msg = 'Search successfully!'
            result_json = result_json[0:len(result_json) - 1]
            result_json = result_json + ']'
        else:
            status = '404'
            value_msg = 'No Result Found!'
            result_json = '"No Data!"'
    else:
        status = '403'
        value_msg = 'Access deny!'
        result_json = '"Access Deny!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result

# return the detailed task info of the task
#   1) task property such as task name, description, priority, owner
#   2) task updates
#   3) task property change history

@bp.route("/info/get", methods=['POST'])
def task_info_get():
    task_id = request.form.get('task_id')
    all_results = c_task_list.query.filter(
        c_task_list.task_id == task_id).first()

    if all_results:
        i = all_results
        user_name = flask_login.current_user.displayName
        valid = is_access(user_name, 'pj_dpt', i.pj_dpt)  # check if can access
        if valid == 1:
            #   1) task property such as task name, description, priority, owner
            result_json = '{' + '"task_id":"' + i.task_id\
                + '","task_name":"' + i.task_name\
                + '","pj_dpt":"' + i.pj_dpt\
                + '","task_type":"' + i.task_type\
                + '", "priority":"' + i.priority\
                + '", "owner":"' + i.owner \
                + '", "description":"' + i.description \
                + '", "task_status":"' + i.task_status\
                + '", "update_time":"' + i.update_time\
                + '", "log_by":"' + i.log_by\
                + '", "log_time":"' + i.log_time + '",'

            # 2) task updates
            all_results = c_task_content.query.filter(
                c_task_content.task_id == task_id).all()
            if all_results:
                result_json = result_json + '"content_valid":"True",'
                result_json = result_json + '"content":['
                for i in all_results:
                    time_consume = str(round(i.time_consume, 1))
                    result_json = result_json + '{' + '"task_id":"' + i.task_id \
                        + '","task_seq":' + str(i.task_seq) \
                        + ' ,"update_name":"' + i.update_name \
                        + '","update_time":"' + i.update_time \
                        + '", "time_consume":' + time_consume \
                        + ' , "task_status":"' + i.task_status \
                        + '", "content":"' + i.content \
                        + '", "file_qty":' + str(i.file_qty) + '},'

                result_json = result_json[0:len(result_json) - 1]
                result_json = result_json + '],'
            else:
                result_json = result_json + '"content_valid":"False",'

            #   3) task property change history
            all_results = c_task_log.query.filter(
                c_task_log.task_id == task_id).all()
            if all_results:
                result_json = result_json + '"log_valid":"True",'
                result_json = result_json + '"log":['
                for i in all_results:
                    result_json = result_json + '{' + '"task_id":"' + i.task_id \
                        + '","property":"' + i.property \
                        + '","old_p":"' + i.old \
                        + '","new_p":"' + i.new \
                        + '", "name":"' + i.name \
                        + '", "change_time":"' + i.change_time + '"},'
                result_json = result_json[0:len(result_json) - 1]
                result_json = result_json + ']'
                result_json = result_json + '}'
            else:
                result_json = result_json + '"log_valid":"False"}'

            status = '200'
            value_msg = 'Get successfully!'

        else:
            status = '403'
            value_msg = 'Access Deny!'
            result_json = '"Access Deny!"'
    else:
        status = '404'
        value_msg = 'No Result Found!'
        result_json = '"No Data!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result

# update the task property to the database
# such as description, project & department, prioroty, owner

@bp.route("/info/update", methods=['POST'])
def task_info_update():
    task_id = request.form.get('task_id')
    description = request.form.get('description')
    pj_dpt = request.form.get('pj_dpt')
    task_type = request.form.get('task_type')
    priority = request.form.get('priority')
    owner = request.form.get('owner')

    all_results = c_task_list.query.filter(
        c_task_list.task_id == task_id).first()

    user_name = flask_login.current_user.displayName
    valid = is_access(user_name, 'pj_dpt', pj_dpt)  # check if can access
    if valid == 1:
        change_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        count = 0
        if all_results:
            old_pj_dpt = all_results.pj_dpt
            old_type = all_results.task_type
            old_priority = all_results.priority
            old_owner = all_results.owner

            if all_results.description != description:
                all_results.description = description
                count = 1

            if old_pj_dpt != pj_dpt:
                all_results.pj_dpt = pj_dpt
                count = 1

            if old_type != task_type:
                all_results.task_type = task_type
                count = 1

            if old_priority != priority:
                all_results.priority = priority
                count = 1

            if old_owner != owner:
                all_results.owner = owner
                count = 1

            if count == 1:
                db.session.commit()
                status = '200'
                value_msg = 'Change successfully!'
                result_json = '"Change successfully!"'
            else:
                status = '410'
                value_msg = 'No need to update!'
                result_json = '"No need to update!"'

            if old_pj_dpt != pj_dpt:
                record = c_task_log(task_id=task_id, property='项目或部门', old=old_pj_dpt, new=pj_dpt,
                                    name=user_name, change_time=change_time)
                db.session.add(record)
                db.session.commit()

            if old_type != task_type:
                record = c_task_log(task_id=task_id, property='任务类型', old=old_type, new=task_type,
                                    name=user_name, change_time=change_time)
                db.session.add(record)
                db.session.commit()

            if old_priority != priority:
                record = c_task_log(task_id=task_id, property='优先级', old=old_priority, new=priority,
                                    name=user_name, change_time=change_time)
                db.session.add(record)
                db.session.commit()

            if old_owner != owner:
                record = c_task_log(task_id=task_id, property='负责人', old=old_owner, new=owner,
                                    name=user_name, change_time=change_time)
                db.session.add(record)
                db.session.commit()

                email_title = '任务负责人变更---' + task_id + ': ' + all_results.task_name
                email_content = '

' \
                    '属性	内容
' \
                    '
任务号	' + task_id + '
' \
                    '
任务名	' + all_results.task_name + '
' \
                    '
任务描述	' + all_results.description + '
' \
                    '
项目或部门	' + all_results.pj_dpt + '
' \
                    '
任务类型	' + all_results.task_type + '
' \
                    '
优先级	' + all_results.priority + '
' \
                    '
任务状态	' + all_results.task_status + '
' \
                    '
新负责人	' + owner + '

'
                send_email(email_title, task_id, email_content)
        else:
            status = '404'
            value_msg = 'No Result Found!'
            result_json = '"No Data!"'
    else:
        status = '403'
        value_msg = 'Access Deny!'
        result_json = '"Access Deny!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result

# update the task status
# total had 6 status: 1-新建，2-进行中，3-待评审，4-暂停，5-关闭，6-完成

@bp.route("/status/change", methods=['POST'])
def task_status_change():
    task_id = request.form.get('task_id')
    new_status = request.form.get('task_status')

    all_results = c_task_list.query.filter(
        c_task_list.task_id == task_id).first()

    user_name = flask_login.current_user.displayName
    # check if can access
    valid = is_access(user_name, 'pj_dpt', all_results.pj_dpt)
    if valid == 1:
        count = 0
        email = 0
        task_name = all_results.task_name
        if all_results:
            old_status = all_results.task_status

            if old_status != '2-进行中' and new_status == '2-进行中':
                count = 1
            if old_status == '2-进行中' and (new_status == '3-待评审' or new_status == '4-暂停'):
                count = 1
                email = 1
            if old_status == '3-待评审' and (new_status == '4-暂停' or new_status == '6-完成'):
                count = 1
                email = 1
            if old_status == '4-暂停' and new_status == '5-终止':
                count = 1
                email = 1

            if count == 1:
                all_results.task_status = new_status
                db.session.commit()

                change_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                record = c_task_log(task_id=task_id, property='任务状态', old=old_status, new=new_status,
                                    name=user_name, change_time=change_time)
                db.session.add(record)
                db.session.commit()
                status = '200'
                value_msg = 'Change successfully!'
                result_json = '{"task_id":"' + task_id + \
                    '","task_status":"' + new_status + '"}'
            else:
                status = '404'
                value_msg = 'No need to update!'
                result_json = '"No need to update!"'

            if email == 1:
                email_title = '任务状态变化---' + task_id + ': ' + task_name
                email_content = '

' \
                                '属性	内容
' \
                                '
任务号	' + task_id + '
' \
                                '
任务名	' + task_name + '
' \
                                '
任务描述	' + all_results.description + '
' \
                                '
负责人	' + all_results.owner + '
' \
                                '
更新人	' + user_name + '
' \
                                '
新任务状态	' + new_status + '

'
                send_email(email_title, task_id, email_content)

        else:
            status = '404'
            value_msg = 'No Result Found!'
            result_json = '"No Data!"'
    else:
        status = '403'
        value_msg = 'Access Deny!'
        result_json = '"Access Deny!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result

# record the task content update

@bp.route("/content/update", methods=['POST'])
def task_content_update():
    task_id = request.form.get('task_id')
    time_consume = request.form.get('task_time')
    input_content = request.form.get('input_content')
    change_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    all_results = c_task_list.query.filter(
        c_task_list.task_id == task_id).first()

    user_name = flask_login.current_user.displayName
    # check if can access
    valid = is_access(user_name, 'pj_dpt', all_results.pj_dpt)
    if valid == 1:
        if all_results:
            task_status = all_results.task_status
            task_name = all_results.task_name
            description = all_results.description
            owner = all_results.owner

            all_results.update_time = change_time
            db.session.commit()

            all_results = c_task_content.query.filter(c_task_content.task_id == task_id)\
                .order_by(c_task_content.task_seq.desc()).all()
            if all_results:
                task_seq = all_results[0].task_seq + 1
            else:
                task_seq = 1

            record = c_task_content(task_id=task_id, task_seq=task_seq, time_consume=time_consume,
                                    content=input_content, task_status=task_status, file_qty=0,
                                    update_name=user_name, update_time=change_time)
            db.session.add(record)
            db.session.commit()

            email_title = '任务更新---' + task_id + ': ' + task_name
            email_content = '

' \
                            '属性	内容
' \
                            '
任务号	' + task_id + '
' \
                            '
任务名	' + task_name + '
' \
                            '
任务描述	' + description + '
' \
                            '
负责人	' + owner + '
' \
                            '
更新人	' + user_name + '
' \
                            '
更新内容	' + input_content + '

'
            send_email(email_title, task_id, email_content)

            status = '200'
            value_msg = 'Change successfully!'
            result_json = '{"task_id":"' + task_id + '","task_seq":' + str(task_seq) + ' ,"task_time":' \
                          + str(time_consume) + ',"name":"' + user_name + '","update_time":"' \
                          + change_time + '","content":"' + input_content + '"}'
        else:
            status = '404'
            value_msg = 'Task ID is wrong!'
            result_json = '"No Task Record!"'
    else:
        status = '403'
        value_msg = 'Access Deny!'
        result_json = '"Access Deny!"'

    result = '{"status":' + status + ',"msg":"' + \
        value_msg + '","result":' + result_json + '}'
    print(result)
    return result


import logging

from pecan import expose, response, conf, render
from stevedore import driver

from cauth.auth import base
from cauth.model import db
from cauth.utils import common
from cauth.utils import transaction

OAUTH_PROVIDERS_PLUGINS = ['Github',
                           'Google',
                           'BitBucket', ]

class OAuth2Controller(transaction.TransactionLogger):
    log = logging.getLogger("cauth.Oauth2Controller")

    def __init__(self):
        self.auth_plugins = {}
        for p in OAUTH_PROVIDERS_PLUGINS:
            try:
                self.auth_plugins[p] = driver.DriverManager(
                    namespace='cauth.authentication',
                    name=p,
                    invoke_on_load=True,
                    invoke_args=(conf,)).driver
                self.log.debug('Loaded OAuth2 plugin %s' % p)
            except Exception:
                pass
        if not self.auth_plugins:
            msg = ('no valid configuration found for any of the '
                   'supported OAuth '
                   'providers (%s)' % ', '.join(OAUTH_PROVIDERS_PLUGINS))
            raise base.AuthProtocolNotAvailableError(msg)

    @expose()
    def callback(self, **kwargs):
        auth_context = kwargs
        auth_context['response'] = kwargs
        auth_context['calling_back'] = True
        transactionID = transaction.ensure_tid(auth_context)
        try:
            # Verify the state previously put in the db
            state = auth_context.get('state', None)
            back, provider = db.get_url(state)
            if not back:
                err = 'OAuth callback with forged state, discarding'
                self.tdebug(err, transactionID)
                raise base.UnauthenticatedError(err)
            auth_plugin = self.auth_plugins.get(provider)
            if not auth_plugin:
                msg = 'Unknown OAuth provider: %s' % provider
                self.terror(msg, transactionID)
                raise base.UnauthenticatedError(msg)
            self.tdebug('Callback called by OAuth provider %s',
                        transactionID, provider)
            auth_context['back'] = back
            valid_user = auth_plugin.authenticate(**auth_context)
        except base.UnauthenticatedError as e:
            response.status = 401
            auth_methods = [k for k, v in conf.get('auth', {})]
            return render('login.html',
                          dict(back=back,
                               message='Authorization failure: %s' % e,
                               auth_methods=auth_methods))
        except Exception:
            msg = "Failure to authenticate"
            self.texception(msg, transactionID)
            response.status = 401
            auth_methods = [k for k, v in conf.get('auth', {})]
            return render('login.html',
                          dict(back=back,
                               message=msg,
                               auth_methods=auth_methods))
        self.tinfo("%s (%s) successfully authenticated with %s.",
                   transactionID,
                   valid_user["login"],
                   valid_user.get('email'),
                   auth_plugin.name)
        common.setup_response(valid_user,
                              back)

#    @expose()
#    def index(self, **kwargs):
#        auth_context = kwargs
#        auth_context['response'] = response
#        # we don't expect a return value, we set up the redirect here
#        self.auth_plugin.authenticate(**auth_context)


import logging
import os
import sys

from cumulus_lambda_functions.lib.constants import Constants

class LambdaLoggerGenerator:
    @staticmethod
    def remove_default_handlers():
        root_logger = logging.getLogger()
        for each in root_logger.handlers:
            root_logger.removeHandler(each)
        return

    @staticmethod
    def get_level_from_env():
        return int(os.environ.get(Constants.LOG_LEVEL, logging.INFO))

    @staticmethod
    def get_logger(logger_name: str, log_level: int = logging.INFO, log_format: str = None):
        if log_format is None:
            log_format = Constants.LOG_FORMAT
        new_logger = logging.getLogger(logger_name)
        stream_handler = logging.StreamHandler(sys.stdout)
        stream_handler.setFormatter(logging.Formatter(log_format))
        stream_handler.setLevel(log_level)
        new_logger.setLevel(log_level)
        new_logger.addHandler(stream_handler)
        return new_logger


from rest_framework.response import Response
from rest_framework.decorators import api_view
from .serializers import RegisterSerializer

@api_view(['POST'])
def register(request):
    try:
        serializer = RegisterSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'msg':'operation successful'})
        else:
            return Response(serializer.errors, 400)

    except Exception as ex:
        print('internal server error -> ', ex)
        return Response({'msg':'internal server error'}, 500)


import sys, math
import matplotlib.image as mpimg

_max_count = 25
_arm_len = 3

def main():
    imgpath = sys.argv[1]
    img = mpimg.imread(imgpath)
    height = len(img)
    width = len(img[0])

    row = [grayscale(x) for x in img[height / 2]]
    thresh = (min(row) + max(row)) / 2
    apply_thresh = lambda x: 1 if x >= thresh else 0
    start = [-1,-1]
    for i in range(width / 2):
        if start[0] == -1 and apply_thresh(row[width / 2 + i]) == 1:
            start[0] = width / 2 + i - 1
        if start[1] == -1 and apply_thresh(row[width / 2 - i]) == 1:
            start[1] = width / 2 - i + 1

        if start[0] != -1 and start[1] != -1:
            break

    p1 = p2 = [start[0], height / 2]
    p3 = p4 = [start[1], height / 2]
    count = 0
    while count < _max_count:
        skip_p2 = skip_p4 = False
        for i in range(8):
            angle = i * math.pi / 4
            if not skip_p2:
                x2 = int(math.ceil(_arm_len * math.cos(angle) + p2[0]))
                y2 = int(math.ceil(_arm_len * math.sin(angle) + p2[1]))
                if apply_thresh(grayscale(img[y2][x2])) == 0:
                    p2 = [x2, y2]
                    skip_p2 = True

            if not skip_p4:
                x4 = int(math.ceil(_arm_len * math.cos(angle) + p4[0]))
                y4 = int(math.ceil(_arm_len * math.sin(angle) + p4[1]))
                if apply_thresh(grayscale(img[y4][x4])) == 0:
                    p4 = [x4, y4]
                    skip_p4 = True

            if skip_p2 and skip_p4:
                break
        count += _arm_len

    c1 = [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2]
    c2 = [(p3[0] + p4[0]) / 2, (p3[1] + p4[1]) / 2]
    m1 = -1 / slope(p1, p2)
    m2 = -1 / slope(p3, p4)
    x = ((-m1 * c1[0] + c1[1] - c2[1]) / m2 + c2[0]) / (1 - m1 / m2)
    y = m1 * (x - c1[0]) + c1[1]
    print [x, y]

def grayscale(x):
    return sum(x) / 3

def slope(p1, p2):
    return (p2[1] - p1[1]) / (p2[0] - p1[0])

main()


import os
import unittest
import json
from flask_sqlalchemy import SQLAlchemy

from flaskr import create_app
from models import setup_db, Question, Category

class TriviaTestCase(unittest.TestCase):
    """This class represents the trivia test case"""

    def setUp(self):
        """Define test variables and initialize app."""
        self.app = create_app()
        self.client = self.app.test_client
        self.database_name = "trivia_test"
        self.database_path = "postgresql://{}:{}@{}/{}".format('postgres', 'admin', 'localhost:5432', self.database_name)
        setup_db(self.app, self.database_path)
        self.new_object = {
            'question': 'who is the best player in the world?',
            'answer': 'mputu',
            'difficulty': 5,
            'category': 2
        }

        self.erreur_question = {
            'question': 'What is your name?',
        }

        # binds the app to the current context
        with self.app.app_context():
            self.db = SQLAlchemy()
            self.db.init_app(self.app)
            # create all tables
            self.db.create_all()

    def tearDown(self):
        """Executed after reach test"""
        pass

    """
    TODO
    Write at least one test for each test for successful operation and for expected errors.
    """

    def test_trouver_categories(self):
        res = self.client().get('/categories')
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 200)
        self.assertEqual(data['success'], True)
        self.assertTrue(len(data['categories']))

    def test_recuperer_questions(self):
        res = self.client().get('/questions')
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 200)
        self.assertEqual(data['success'], True)
        self.assertTrue(len(data['questions']))
        self.assertTrue(len(data['categories']))

    def test_erreur_pour_trouver_une_question(self):

        res = self.client().post('/questions/chercher', json={'terme': 'mbula'})
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 404)
        self.assertEqual(data['success'], False)

    def test_404_trouver_questions(self):
        res = self.client().get('/questions?page=5000')
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 404)
        self.assertEqual(data['success'], False)
        self.assertEqual(data['message'], 'resource not found')

    def test_questions_par_categorie(self):
        res = self.client().get('/categories/2/questions')
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 200)
        self.assertEqual(data['success'], True)
        self.assertIsNotNone((data['questions']))
        self.assertTrue((data['total_de_questions'] > 0 , True))
        self.assertTrue((data['categorie_courante'] == 2,True))

    def test_404_questions_par_categorie(self):
        res = self.client().get('/categories/c/questions')
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 404)

    def test_poster_question(self):
        res = self.client().post('/questions', json=self.new_object)
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 200)
        self.assertEqual(data['success'], True)
        self.assertEqual(data['total_questions'] > 0,True)

    def test_poster_question(self):
        res = self.client().post('/questions', json=self.erreur_question)
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 422)

    def test_quiziew(self):
        new_quiz = {'quiz_category': {'type': 'Entertainment', 'id': 9},'last_questions': []}

        res = self.client().post('/quizzes', json=new_quiz)
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 200)
        self.assertEqual(data['success'], True)

    def test_404_if_book_does_not_exist(self):
        res = self.client().delete('/questions/5000')
        data = json.loads(res.data)

        self.assertEqual(res.status_code, 422)
        self.assertEqual(data['success'], False)
        self.assertEqual(data['message'], 'non traetable')

    def test_supprimer_question(self):
        NQuestion = Question(question='what is your name', answer='Abdullah Alessa',difficulty=5 , category=6)
        NQuestion.insert()
        res = self.client().delete(f'/questions/{NQuestion.id}')
        data = json.loads(res.data)

        question = Question.query.filter(Question.id == NQuestion.id).one_or_none()

        self.assertEqual(res.status_code, 200)
        self.assertEqual(data['success'], True)
        self.assertEqual(data['deleted'], (NQuestion.id))

# Make the tests conveniently executable
if __name__ == "__main__":
    unittest.main()


from django.conf import settings
from django.http import Http404
from django.db.models import Q
from accounts.models import CustomUser
from django.core.exceptions import FieldDoesNotExist
import datetime

import logging
logger = logging.getLogger()

def search(keyword):
    """ 検索機能 """
    if keyword:
        queryset = CustomUser.objects.filter(
            Q(deleted_at=None)
            & (Q(name__icontains=keyword)
                | Q(description__icontains=keyword)
            )
        )
    else:
        queryset = CustomUser.objects.all().filter(
            Q(is_active=True)
            & Q(partner__isnull=False)
        )[:100]
    return queryset

def getEngineer(user_id):
    engineer = CustomUser.objects.filter(Q(id=user_id) & Q(is_active=True)).first()
    if not engineer:
        raise Http404("Project Id={} Not Found".format(user_id))
    return engineer

# """ 案件作成/更新 """
def save_user(form, partner_id):
    # 保存する前に一旦取り出す
    user = form.save(commit=False)
    # パスワードをハッシュ化してセット
    user.set_password(form.cleaned_data['password'])
    # ユーザーオブジェクトを保存
    user.partner_id = partner_id
    user.save()
    form.save_m2m()

# """ 案件削除 """
# def delete_project(project, user_id):
#     now = datetime.datetime.now()
#     project.deleted_at = now
#     project.deleted_id = user_id
#     project.save()


"""Pullers Collection"""
# -*- coding: utf-8 -*-
from __future__ import annotations
import os
import asyncio
from asyncio import Future
from typing import Iterable, Mapping, Any, Callable, Awaitable, Sequence, TypeVar
from abc import abstractmethod
from httpx import Request, Response, Timeout
from ..misc import DummyAioFileStream as Dummyf
from ...io import aio
from ...collections import StrChain
from ...react import ActionChain, EventHook, EventHint as Hint
from httpx._types import HeaderTypes, ProxiesTypes, CookieTypes, QueryParamTypes
import httpx

__all__ = (
    "MaxRetryReached",
    "BasePuller",
    "BaseWorker",
    "BaseMaster",
    "AsyncPuller",
    "AsyncWorker",
    "AsyncMaster",
)

class MaxRetryReached(Exception):
    """Raised when the maximum number of retries is reached."""

class BasePuller:
    """Base class for pullers."""
    @property
    def event_hooks(self) -> EventHook:
        """Event hook for this puller."""
        raise NotImplementedError()

    @abstractmethod
    def pull(self, url: str, path: str) -> Any:
        """Pull the file from the url to the path."""

class BaseWorker:
    """Base class for workers."""

class BaseMaster:
    """Base class for masters."""

HttpActionType = Callable[[Request | Response], Awaitable]
ActionVar = TypeVar('ActionVar', bound=Callable)

class AsyncHttpActionChain(ActionChain[HttpActionType]):
    """Async Http Action Chain"""

    def __init__(self, actions: Iterable[HttpActionType] = None) -> None:
        super().__init__(actions=actions)

class AsyncPullerEventHook(EventHook):
    """Async Puller Event Hook"""

    def __init__(self, chain: Mapping[str, Iterable[Callable[..., Any]]] | None = None):
        self.hook("request", AsyncHttpActionChain())
        self.hook("response", AsyncHttpActionChain())
        self.hook("worker.spawn", ActionChain())
        self.hook("worker.destroy", ActionChain())
        self.hook("worker.start", ActionChain())
        self.hook("worker.response_get", ActionChain())
        self.hook("worker.bytes_get", ActionChain())
        self.hook("worker.retry", ActionChain())
        self.hook("worker.success", ActionChain())
        self.hook("worker.fail", ActionChain())
        self.hook("puller.spawn", ActionChain())
        self.hook("puller.destroy", ActionChain())
        self.hook("puller.join", ActionChain())
        EventHook.__init__(self, chain=chain)

class AsyncWorker(BaseWorker):
    def __init__(
        self,
        puller: AsyncPuller,
        url: str,
        path: str | None,
        retry: int,
        overwrite: bool,
        *,
        future: Future = None,
        timeout: Timeout | float | None,
        extra_headers: HeaderTypes | None,
        extra_params: QueryParamTypes | None,
        extra_cookies: CookieTypes | None,
        **kw
    ):
        self.puller = puller
        self.url = url
        self.path = path
        self.future: Future = future  # type: ignore[assignment]
        self.timeout = timeout
        self.max_retry = retry
        self.overwrite = overwrite
        self.extra_headers = extra_headers
        self.extra_params = extra_params
        self.extra_cookies = extra_cookies
        self.kw = kw
        self.event_hooks = AsyncPullerEventHook(
            self.puller.event_hooks)  # snapshot

    async def run(self):
        """Run the worker."""
        event_hooks = self.event_hooks
        try:
            await event_hooks.aemit("worker.start", self)
            if self.path and os.path.exists(self.path) and not self.overwrite:
                raise FileExistsError(f"{self.path} already exists")
            client = self.puller.client
            retry = 0
            while True:
                try:
                    # Open file in async mode, if path is None, write to void
                    async with aio.open(self.path, "wb") \
                            if self.path else Dummyf() as f:  # type: ignore
                        # Establish connection
                        async with client.stream(
                            method=self.kw.pop("method", "GET"),
                            url=self.url,
                            params=self.extra_params,
                            headers=self.extra_headers,
                            cookies=self.extra_cookies,
                            timeout=self.timeout or self.puller.client.timeout,
                            **self.kw
                        ) as r:
                            await event_hooks.aemit("worker.response_get", self, r)
                            # Iterate over response chunks
                            # 256KB
                            async for chunk in r.aiter_bytes(chunk_size=2**18):
                                await event_hooks.aemit(
                                    "worker.bytes_get", self, r, chunk)
                                await f.write(chunk)
                            await f.flush()
                            await event_hooks.aemit("worker.success", self, r)
                    # set result for placeholder
                    self.future.set_result(self.path)
                    self.puller._ft_map.pop(id(self.future))  # type: ignore
                    break  # Quit successfully
                # Retry on network IO error
                except (httpx.HTTPError, httpx.StreamError) as e:
                    retry += 1
                    if retry > self.max_retry:
                        raise MaxRetryReached(
                            f"Max retry reached: {retry} times") from e
                    await event_hooks.aemit("worker.retry", self, e, retry)
                    await asyncio.sleep(min(30, 1.7 ** retry))
        # Fatal Errors
        except (Exception, asyncio.CancelledError) as e:
            handled = await event_hooks.aemit("worker.fail", self, e)
            if True not in handled:
                self.future.set_exception(e)
                raise e
            self.puller._ft_map.pop(id(self.future))  # type: ignore
        finally:
            await event_hooks.aemit("worker.destroy", self)
            self.puller._workers.get_nowait()
            self.puller._workers.task_done()  # workers count - 1

    def __repr__(self) -> str:
        return f"AsynWorker({self.url}, {self.path})"

class AsyncMaster(BaseMaster):
    def __init__(self, puller: AsyncPuller):
        self.puller = puller

    async def run(self):
        """Run the master."""
        try:
            buffer = self.puller._buffer
            workers = self.puller._workers
            while True:
                worker = await buffer.get()
                if worker is None:  # Kill signal
                    buffer.task_done()
                    break
                await workers.put(worker)  # blocks when max_workers reached
                self.puller.loop.create_task(worker.run())
                buffer.task_done()
                await asyncio.sleep(self.puller.interval)  # sleep a while
        finally:
            self.puller._master = None  # Reset master

class AsyncPuller(BasePuller):
    """### Async Puller"""

    def __init__(
        self,
        *,
        headers: HeaderTypes = None,
        params: QueryParamTypes = None,
        proxies: ProxiesTypes = None,
        cookies: CookieTypes = None,
        event_hooks: Mapping[str, Sequence[Callable]] = None,
        interval: float = 0.0,
        max_workers: int = 8,
        timeout: Timeout | float | None = 10,
        retry: int = 3,
        overwrite: bool = False,
        loop: asyncio.AbstractEventLoop = None,
        **kw
    ):
        """### Init Puller
        * `headers`: Default headers for all requests
        * `params`: Default query params for all requests
        * `proxies`: Default proxies for all requests
        * `cookies`: Default cookies for all requests
        * `event_hooks`: dict[str, Iterable[Callable]]
        * `interval`: Interval between each request
        * `max_workers`: Max downloading threads count
        * `timeout`: Timeout for each request
        * `retry`: Max retry times for each request
        * `overwrite`: Overwrite existing files
        * `loop`: Event loop
        * `**kw`: Other keyword arguments for httpx.Client
        """
        self._loop = loop
        self.interval = interval
        self.max_retry = max(retry, 0)
        self.overwrite = overwrite

        self._proxies = proxies
        self._master: AsyncMaster | None = None
        self._buffer: asyncio.Queue = asyncio.Queue()  # Pending workers
        self._workers: asyncio.Queue = asyncio.Queue(
            maxsize=max_workers)  # Running workers
        self._ft_map: dict[int, Future] = {}

        limits = httpx.Limits(
            max_connections=None,
            max_keepalive_connections=None,
            keepalive_expiry=10)

        self._client = httpx.AsyncClient(
            headers=headers,
            params=params,
            proxies=proxies,
            cookies=cookies,
            timeout=timeout,
            limits=limits,
            follow_redirects=True,
            http2=True,
            **kw
        )
        self.event_hooks = event_hooks or AsyncPullerEventHook()

        # Set up event hook
        def subscribe(event: StrChain, action: ActionVar) -> ActionVar:
            ev = str(event)
            self._event_hooks[ev].append(action)
            if ev in ["request", "response"]:
                self._client.event_hooks = self._event_hooks  # type: ignore[assignment]
            return action

        self._on = PullerEventHint(
            strchain=StrChain(joint='.', callback=subscribe))

    @property
    def client(self):
        return self._client

    @property
    def loop(self):
        if self._loop is None:
            self._loop = asyncio.get_running_loop()
        return self._loop

    @property
    def headers(self):
        """Get headers."""
        return self._client.headers

    @headers.setter
    def headers(self, value: HeaderTypes):
        """Set headers for all requests."""
        self._client.headers = value  # type: ignore[assignment]

    @property
    def cookies(self):
        return self._client.cookies

    @cookies.setter
    def cookies(self, value: CookieTypes):
        """Set cookies for all requests."""
        self._client.cookies = value  # type: ignore[assignment]

    @property
    def params(self):
        return self._client.params

    @params.setter
    def params(self, value: QueryParamTypes):
        """Set params for all requests."""
        self._client.params = value  # type: ignore[assignment]

    @property
    def event_hooks(self):
        return self._event_hooks

    @event_hooks.setter
    def event_hooks(self, hooks: Mapping[str, Sequence[Callable]]):
        """Set event hooks for all requests."""
        self._event_hooks = AsyncPullerEventHook(hooks)  # deepcopy
        self._client.event_hooks = self._event_hooks  # type: ignore[assignment]

    @property
    def on(self):
        """Shortcut for `Puller.event_hooks.on`"""
        return self._on

    @property
    def proxies(self):
        return self._proxies

    async def pull(
        self,
        url: str,
        path: str | None,
        *,
        extra_headers: HeaderTypes | None = None,
        extra_params: QueryParamTypes | None = None,
        extra_cookies: CookieTypes | None = None,
        timeout: Timeout | float | None = 0,
        retry: int | None = None,
        overwrite: bool | None = None,
        **kw
    ) -> Future:
        """
        ### Asynchronously pull a file from a url.
        File will be decompressed and saved in binary mode.

        Returns a `Future` instance refer to the path of the downloaded file.
        * `url`: url to pull from
        * `path`: path to save to, set to `None` or `""` will not save file

        Optional Parameters:
        * `extra_headers`: extra headers to add to request
        * `extra_params`: extra params to add to request
        * `extra_cookies`: extra cookies to add to request
        * `timeout`: timeout for this request, set to None will be no limit, 0 for default
        * `retry`: retry times for this request, set to None will use default
        * `overwrite`: overwrite file if exists, set to None will use default
        * `**kw`: extra keyword arguments for httpx.stream
        """
        timeout = self.client.timeout if timeout == 0 else timeout
        self._loop = self.loop or asyncio.get_running_loop()
        if self._master is None:
            self._master = AsyncMaster(self)
            self._loop.create_task(self._master.run())
        future: Future = Future()  # A placeholder for the worker.run() task
        self._ft_map[id(future)] = future
        worker = AsyncWorker(
            self,
            url=url,
            path=path,
            extra_headers=extra_headers,
            extra_params=extra_params,
            extra_cookies=extra_cookies,
            future=future,
            timeout=timeout,
            retry=self.max_retry if retry is None else retry,
            overwrite=overwrite or self.overwrite,
            **kw
        )
        await self._event_hooks.aemit("worker.spawn", worker)
        await self._buffer.put(worker)
        return future

    async def join(self) -> None:
        """### Wait for all workers to finish."""
        await self._event_hooks.aemit("puller.join", self)
        await self._buffer.join()  # Make sure no pending tasks
        await self._workers.join()  # Make sure all workers finished
        jobs = list(self._ft_map.values())
        self._ft_map.clear()
        await asyncio.gather(*jobs)  # Make sure all tasks are done

    async def aclose(self):
        await self.join()  # Make sure all tasks are done
        await self._buffer.put(None)  # Kill master
        await self._event_hooks.aemit("puller.destroy", self)
        await self._client.aclose()

    async def __aenter__(self) -> AsyncPuller:
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb) -> bool:
        await self.aclose()
        return False

    def __repr__(self):
        return f"{self.__class__.__name__}:\n" +\
            f"  max_retry: {self.max_retry}\n" +\
            f"  overwrite: {self.overwrite}\n" +\
            f"  headers: {self.headers}\n" +\
            f"  params: {self.params}\n" +\
            f"  cookies: {self.cookies}\n" +\
            f"  proxies: {self.proxies}\n" +\
            f"  event_hooks: {self.event_hooks}\n"

#### Start Hinting: Add hints for event names ####

class on_puller_hint(Hint):  # pragma: no cover
    @property
    def spawn(self):
        """Callback Type: (event_name: str, AsyncPuller) -> None"""
        return self._chain.spawn

    @property
    def destroy(self):
        """Callback Type: (event_name: str, AsyncPuller) -> None"""
        return self._chain.destroy

    @property
    def join(self):
        """Callback Type: (event_name: str, AsyncPuller) -> None"""
        return self._chain.join

class on_worker_hint(Hint):  # pragma: no cover
    @property
    def spawn(self):
        """Callback Type: (event_name: str, AsyncWorker) -> None"""
    @property
    def destroy(self):
        """Callback Type: (event_name: str, AsyncWorker) -> None"""
    @property
    def start(self):
        """Callback Type: (event_name: str, AsyncWorker) -> None"""
    @property
    def response_get(self):
        """Callback Type: (event_name: str, AsyncWorker, Response) -> None"""
    @property
    def bytes_get(self):
        """Callback Type: (event_name: str, AsyncWorker, Response, bytes) -> None"""
    @property
    def retry(self):
        """Callback Type: (event_name: str, AsyncWorker, Exception, retry: int) -> None"""
    @property
    def success(self):
        """Callback Type: (event_name: str, AsyncWorker) -> None"""
    @property
    def fail(self):
        """Callback Type: (event_name: str, AsyncWorker, Exception) -> bool:
        whether to ignore the exception"""

class PullerEventHint(Hint):  # pragma: no cover
    """Puller Event Hint."""
    @property
    def puller(self) -> on_puller_hint:
        return self._chain.puller  # type: ignore

    @property
    def worker(self) -> on_worker_hint:
        return self._chain.worker  # type: ignore

    @property
    def request(self):
        """Callback Type: (Request) -> None"""
        return self._chain.request

    @property
    def response(self):
        """Callback Type: (Response) -> None"""
        return self._chain.response

### End Hinting ###


from pypdf import PdfReader
import os
import openai
import json
from PIL import Image
from io import BytesIO
import urllib

openai.api_key = ""

'''

Get byte stream of image

Input:
- img_path (str): path to image to generate
- image_size (tuple_int): image size

Output:

- byte_array(byte stream): output byte stream of image file

'''

def image_to_byte_stream(img_path, image_size):

    image = Image.open(img_path)
    image = image.resize(image_size)

    # Convert the image to a BytesIO object
    byte_stream = BytesIO()
    image.save(byte_stream, format='PNG')
    byte_array = byte_stream.getvalue()
    return byte_array

'''

Get variation generation of image

Input:

- img_stream(byte stream): output byte stream of image file

- img_out_path (str): output path of image

'''

def generate_variation(img_stream, img_out_path):
    # Generate augmentation
    response = openai.Image.create_variation(
      image= img_stream,
      n=1,
      size="512x512"
    )

    image_url = response['data'][0]['url']

    urllib.request.urlretrieve(image_url, img_out_path)

# Quick using
if __name__ == "__main__":

    img_path = "test.png"
    path_out = "out.png"

    img_byte = image_to_byte_stream(img_path, 256)
    generate_variation(img_byte, path_out)


"""
NN model with glove embeddings
layers:
    1. embedding layer (glove)
    2. SpatialDropout1D (0.24)
    3. bidirectional lstm & gru
    4. [global_max_pooling1d, attention, features]
    5. dense 128 & 16
    6. output (sigmoid)
"""
import os
import gc
import numpy as np
import pandas as pd
from sklearn.preprocessing import minmax_scale
from keras.layers import (Input, Embedding, SpatialDropout1D, Bidirectional,
                          LSTM, GRU, GlobalMaxPool1D, Concatenate, Dropout,
                          Dense)
from keras.models import Model

from neural_networks import Attention, DropConnect
from neural_networks import NeuralNetworkClassifier

from tqdm import tqdm
tqdm.pandas()

# model configs
MAX_FEATURES = int(2.5e5)  # total word count = 227,538; clean word count = 186,551   # noqa
MAX_LEN = 75    # mean_len = 12; Q99_len = 40; max_len = 189;
RNN_UNITS = 40
F_DROPOUT = 0.05
DENSE_UNITS_1 = 128
DENSE_UNITS_2 = 16

# file configs
MODEL_FILEPATH = os.path.join(
    os.environ['DATA_PATH'],
    'models',
    'model_v50.hdf5'
)
EMBED_FILEPATH = os.path.join(
    os.environ['DATA_PATH'],
    'embeddings',
    'glove.840B.300d',
    'glove.pkl'
)

def get_network(embed_filepath):
    # features network
    input_features = Input(shape=(136, ), name='input_features')
    dense_features = DropConnect(
        Dense(16, activation="relu"),
        prob=F_DROPOUT)(input_features)
    # tokens network
    input_tokens = Input(shape=(MAX_LEN, ), name='input_tokens')
    # 1. embedding layer
    # get embedding weights
    print('load pre-trained embedding weights ......')
    embed_weights = pd.read_pickle(embed_filepath)
    input_dim = embed_weights.shape[0]
    output_dim = embed_weights.shape[1]
    x = Embedding(
        input_dim=input_dim,
        output_dim=output_dim,
        weights=[embed_weights],
        trainable=False,
        name='embedding'
    )(input_tokens)
    # clean up
    del embed_weights, input_dim, output_dim
    gc.collect()
    # 2. dropout
    x = SpatialDropout1D(rate=0.24)(x)
    # 3. bidirectional lstm & gru
    x = Bidirectional(
        layer=LSTM(RNN_UNITS, return_sequences=True),
        name='bidirectional_lstm'
    )(x)
    x = Bidirectional(
        layer=GRU(RNN_UNITS, return_sequences=True),
        name='bidirectional_gru'
    )(x)
    # 4. concat global_max_pooling1d and attention
    max_pool = GlobalMaxPool1D(name='global_max_pooling1d')(x)
    atten = Attention(step_dim=MAX_LEN, name='attention')(x)
    x = Concatenate(axis=-1)([max_pool, atten, dense_features])
    # 5. dense
    x = Dense(units=DENSE_UNITS_1, activation='relu', name='dense_1')(x)
    x = Dropout(rate=0.1)(x)
    x = Dense(units=DENSE_UNITS_2, activation='relu', name='dense_2')(x)
    # 6. output (sigmoid)
    output_layer = Dense(units=1, activation='sigmoid', name='output')(x)
    return Model(inputs=[input_tokens, input_features], outputs=output_layer)

def get_model():
    print('build network ......')
    model = get_network(embed_filepath=EMBED_FILEPATH)
    print(model.summary())
    return NeuralNetworkClassifier(
        model,
        balancing_class_weight=True,
        filepath=MODEL_FILEPATH)

"""
text cleaning
"""

def token_transformer(df_text):
    from model_v30 import transform
    return transform(df_text)

def features_transformer(df_text):
    from nlp import meta_features_transformer
    from nlp import topic_features_transformer
    # get features
    meta_features = meta_features_transformer(df_text).values
    topic_features = topic_features_transformer(df_text).values
    # concat
    joined_features = np.hstack([meta_features, topic_features])
    return minmax_scale(joined_features)

def transform(df_text):
    X1 = token_transformer(df_text)
    X2 = features_transformer(df_text)
    return [X1, X2]


# 2023/8/8 by DKZ https://github.com/davidkingzyb/BlenderSlot

import bpy
import os
from .ui import MainPanel

root_path=os.path.dirname(__file__)

class DeleteCode(bpy.types.Operator):
    bl_idname='bs.deletecode'
    bl_label='delete'
    bl_options = {'REGISTER', 'UNDO'}

    file_name:bpy.props.StringProperty(
        name="file_name",
        description="file name",
        default="",
    )

    def execute(self, context):
        try:
            os.remove(os.path.join(root_path,'slot\\'+self.file_name))
        except Exception as e:
            pass

        bpy.utils.unregister_class(MainPanel)
        bpy.utils.register_class(MainPanel)
        return {'FINISHED'}

class SaveCode(bpy.types.Operator):
    bl_idname='bs.savecode'
    bl_label='save'
    bl_options = {'REGISTER', 'UNDO'}

    file_name:bpy.props.StringProperty(
        name="file_name",
        description="file name",
        default="",
    )

    code:bpy.props.StringProperty(
        name="code",
        description="code",
        default="",
    )

    def execute(self, context):
        text = bpy.data.texts.get(self.file_name)
        self.code=text.as_string()
        with open(os.path.join(root_path,'slot\\'+self.file_name),'w') as f:
            f.write(self.code)
        bpy.utils.unregister_class(MainPanel)
        bpy.utils.register_class(MainPanel)
        return {'FINISHED'}

class ExecCode(bpy.types.Operator):
    bl_idname='bs.execcode'
    bl_label='exec'
    bl_options = {'REGISTER', 'UNDO'}

    file_name:bpy.props.StringProperty(
        name="file_name",
        description="file name",
        default="",
    )

    code:bpy.props.StringProperty(
        name="code",
        description="code",
        default="",
    )

    def execute(self, context):
        text = bpy.data.texts.get(self.file_name)
        if text is not None:
            self.code=text.as_string()
        else:
            try:
                with open(os.path.join(root_path,'slot\\'+self.file_name),'r') as f:
                    self.code=f.read()
            except Exception as e:
                self.report({'ERROR'}, f"Error executing generated code: {e}")
                return {'CANCELLED'}
        global_namespace = globals().copy()
        try:
            exec(self.code,global_namespace)
        except Exception as e:
            self.report({'ERROR'}, f"Error executing generated code: {e}")
            return {'CANCELLED'}
        return {'FINISHED'}

class ShowCode(bpy.types.Operator):
    bl_idname='bs.showcode'
    bl_label='show'
    bl_options = {'REGISTER', 'UNDO'}

    file_name:bpy.props.StringProperty(
        name="file_name",
        description="file name",
        default="",
    )

    code:bpy.props.StringProperty(
        name="code",
        description="code",
        default="",
    )

    def execute(self, context):
        print(self.file_name)
        text = bpy.data.texts.get(self.file_name)
        if text is None:
            text = bpy.data.texts.new(self.file_name)
            try:
                with open(os.path.join(root_path,'slot\\'+self.file_name),'r') as f:
                    self.code=f.read()
            except Exception as e:
                # self.report({'ERROR'}, f"Error executing generated code: {e}")
                pass
            text.clear()
            text.write(self.code)
        else:
            self.code=text.as_string()

        text_editor_area = None
        for area in context.screen.areas:
            if area.type == 'TEXT_EDITOR':
                text_editor_area = area
                break

        if text_editor_area is None:
            text_editor_area = split_area_to_text_editor(context)

        text_editor_area.spaces.active.text = text

        return {'FINISHED'}

def split_area_to_text_editor(context):
    area = context.area
    for region in area.regions:
        if region.type == 'WINDOW':
            override = {'area': area, 'region': region}
            bpy.ops.screen.area_split(override, direction='VERTICAL', factor=0.5)
            break

    new_area = context.screen.areas[-1]
    new_area.type = 'TEXT_EDITOR'
    return new_area


import soundfile as sf
import os

# def compute_similar(au1, au2):
#     audiofolder = '/home/hieuld/workspace/ASVmodel/input/test'
#     audiolist = os.listdir(audiofolder)
#     audiolist.sort()
#     print(audiolist)
#     audiodata = []
#     for audio in audiolist:
#         audio = os.path.join(audiofolder, audio)
#         data, fs = sf.read(audio)
#         audiodata.append(data)

#     import numpy as np
#     corr1 = np.correlate(a=audiodata[3], v=audiodata[4])
#     corr2 = np.correlate(a=audiodata[0], v=audiodata[1])

#     print(corr1)
#     print(corr2)
ROOTDIR = '/home/hieuld/workspace/AntiSpoof/ASVapp/ASVmodel/input/tmp'
import numpy as np
def compute_similar(au1, au2):
    audio1 = os.path.join(ROOTDIR, au1)
    audio2 = os.path.join(ROOTDIR, au2)
    au1, _ = sf.read(audio1)
    au2, _ = sf.read(audio2)
    if len(au1) > len(au2):
        au2 = np.pad(au2, (0, len(au1) - len(au2)), 'constant', constant_values=(0))
    else :
        au1 = np.pad(au1, (0, len(au2) - len(au1)), 'constant', constant_values=(0))
    corr = np.correlate(a=au1, v=au2)
    return corr
if __name__ == '__main__':
    au1 = 'atachfromaMinh.flac'
    au2 = 'atachfromaMinh_cutnoise.flac'
    au1 = os.path.join(ROOTDIR, au1)
    au2 = os.path.join(ROOTDIR, au2)
    print(compute_similar(au1,au2))


# Code Release for ICLR-22 work
# 'Differentiable Gradient Sampling for Learning Implicit 3D Scene Reconstructions from a Single Image'
# Any question please contact Shizhan Zhu: zhshzhutah2@gmail.com
# Released on 04/25/2022.

# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.

# Borrowed and developed from: https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix/blob/master/util/html.py
# This tool does not care about functional / non-functional
from ..np_ext.np_image_io_v1 import gifWrite
from ..py_ext.misc_v1 import mkdir_full
import dominate
from dominate.tags import *
import os
import skimage.io as io
import numpy as np
import shutil

class HTML:
    def __init__(self, web_dir, title, reflesh=0):

        if os.path.isdir(web_dir):
            shutil.rmtree(web_dir)
        mkdir_full(web_dir + 'images/')

        self.title = title
        self.web_dir = web_dir
        self.img_dir = os.path.join(self.web_dir, 'images')

        self.doc = dominate.document(title=title)
        if reflesh > 0:
            with self.doc.head:
                meta(http_equiv="reflesh", content=str(reflesh))

    def get_image_dir(self):
        return self.img_dir

    def add_header(self, str):
        with self.doc:
            h3(str)

    def add_header_h4(self, str):
        with self.doc:
            h4(str)

    def add_header_h5(self, str):
        with self.doc:
            h5(str)

    def add_text(self, s):
        with self.doc:
            p(s)

    def add_table(self, border=1):
        self.t = table(border=border, style="table-layout: fixed;")
        self.doc.add(self.t)

    def add_images(self, ims, txts, links, width=400):
        self.add_table()
        with self.t:
            with tr():
                for im, txt, link in zip(ims, txts, links):
                    with td(style="word-wrap: break-word;", halign="center", valign="top"):
                        with p():
                            with a(im):  # zhuzhu
                                br()
                                img(style="width:%dpx" % width, src=link)
                            br()
                            if not(txt is None):
                                p(txt)

    def save(self):
        html_file = '%s/index.html' % self.web_dir
        f = open(html_file, 'wt')
        f.write(self.doc.render())
        f.close()

def storeImagesAndReturnLinks(str_store, str_link, strs_imgs, imgsContents):
    links = []
    assert len(strs_imgs) == len(imgsContents)
    for i in range(len(strs_imgs)):
        if len(imgsContents[i].shape) in [2, 3]:  # It is png
            if len(imgsContents[i].shape) == 2:
                assert imgsContents[i].shape[0] > 5
                assert imgsContents[i].shape[1] > 5
            if 'float32' in str(imgsContents[i].dtype):
                tmp = imgsContents[i].copy()
                tmp[tmp < 0] = 0.
                tmp[tmp > 1] = 1.
                tmp = (tmp * 255.).astype(np.uint8)
                io.imsave(str_store + strs_imgs[i] + '.png', tmp)
            else:
                io.imsave(str_store + strs_imgs[i] + '.png', imgsContents[i])
            links.append(str_link + strs_imgs[i] + '.png')
        elif len(imgsContents[i].shape) == 4:  # It is gif
            gifWrite(str_store + strs_imgs[i] + '.gif', imgsContents[i])
            links.append(str_link + strs_imgs[i] + '.gif')
        else:
            raise ValueError('Shape of imgsContents[i] is wierd %s' % str(imgsContents[i].shape))

    return links

class HTMLStepperAbstract(object):
    def __init__(self, logDir, singleHtmlSteps, htmlName):  # consider to use htmlName to represent different experiments.
        # Static member
        assert os.path.isdir(logDir)
        if not logDir.endswith('/'):
            logDir += '/'
        self.logDir = logDir
        self.htmlName = htmlName
        self.singleHtmlSteps = singleHtmlSteps

        # dynamics
        self.htmlStepCount = float('inf')
        self.currentFileID = None
        self.html = None

    def _printLossTotal(self, loss):
        raise NotImplementedError

    def _printLossEach(self, loss, j):
        raise NotImplementedError

    def step2(self, summary0=None, txt0=None, brInds=(0, ), headerMessage=None, subMessage=None):
        assert brInds[0] == 0
        if txt0 is not None:
            assert len(summary0) == len(txt0)
        if self.htmlStepCount >= self.singleHtmlSteps:  # reset
            assert os.path.isdir(self.logDir)
            mkdir_full(self.logDir + 'html_' + self.htmlName + '/')
            tmp = [int(x[5:]) for x in os.listdir(self.logDir + 'html_' + self.htmlName + '/') if x.startswith('html_')]
            if tmp:  # safe if  # tmp is a non-empty set
                maxHtmlFileID = max(tmp)
            else:  # tmp is an empty set
                maxHtmlFileID = -1
            self.currentFileID = maxHtmlFileID + 1
            self.html = HTML(self.logDir + 'html_' + self.htmlName + '/' + 'html_%06d/' % self.currentFileID,
                             self.htmlName)  # zhuzhu
            self.htmlStepCount = 0

        if headerMessage is not None:
            self.html.add_header(headerMessage)
        if subMessage is not None:
            self.html.add_header_h4(subMessage)
        if summary0 is not None:
            links = storeImagesAndReturnLinks(
                self.logDir + 'html_' + self.htmlName + '/html_%06d/images/%s_%06d_%06d_' %
                    (self.currentFileID, self.htmlName, self.currentFileID, self.htmlStepCount),
                'images/%s_%06d_%06d_' %
                    (self.htmlName, self.currentFileID, self.htmlStepCount),
                list(summary0.keys()),
                list(summary0.values()),
            )
            for o in range(len(brInds)):
                head = brInds[o]
                if head >= len(summary0):
                    break
                if o == len(brInds) - 1 or brInds[o + 1] >= len(summary0):
                    tail = len(summary0)
                else:
                    tail = brInds[o + 1]
                if txt0 is None:
                    self.html.add_images(
                        list(summary0.keys())[head:tail],
                        [None for _ in range(head, tail)], links[head:tail])
                else:
                    self.html.add_images(
                        list(summary0.keys())[head:tail],
                        [txt0[i] for i in range(head, tail)], links[head:tail])
        self.html.save()
        self.htmlStepCount += 1

    def step(self, iterCount, losses, visual, txts=None, brInds=(0, )):  # functional, but file system changed  # losses can be OrderedDict as in here, or also a TreeLog
        assert brInds[0] == 0
        if txts is not None:
            assert len(visual.summary) == len(txts[0])
        if self.htmlStepCount >= self.singleHtmlSteps:  # reset
            assert os.path.isdir(self.logDir)
            mkdir_full(self.logDir + 'html_' + self.htmlName + '/')
            tmp = [int(x[5:]) for x in os.listdir(self.logDir + 'html_' + self.htmlName + '/') if x.startswith('html_')]
            if tmp:  # safe if  # tmp is a non-empty set
                maxHtmlFileID = max(tmp)
            else:  # tmp is an empty set
                maxHtmlFileID = -1
            self.currentFileID = maxHtmlFileID + 1
            self.html = HTML(self.logDir + 'html_' + self.htmlName + '/' + 'html_%06d/' % self.currentFileID, self.htmlName)  # zhuzhu
            self.htmlStepCount = 0

        self.html.add_header('Iter %d %s' % (iterCount, self.htmlName))  # zhuzhu
        self._printLossTotal(losses)

        for j in range(visual.m):
            links = storeImagesAndReturnLinks(
                self.logDir + 'html_' + self.htmlName + '/html_%06d/images/%s_%08d_%06d_%02d_%02d_%08d_%08d_' % \
                    (self.currentFileID, self.htmlName, iterCount, self.currentFileID, j, visual.datasetID[j], visual.index[j], visual.insideBatchIndex[j]),  # zhuzhu
                'images/%s_%08d_%06d_%02d_%02d_%08d_%08d_' % (self.htmlName, iterCount, self.currentFileID, j, visual.datasetID[j], visual.index[j], visual.insideBatchIndex[j]),  # zhuzhu
                list(visual.summary.keys()),
                [x[j] for x in visual.summary.values()],
            )
            self.html.add_header('Iter = %d, Dataset = %s, SampleID = %d, InsideBatchID %d' % \
                                 (iterCount, visual.dataset[j], visual.index[j], visual.insideBatchIndex[j]))
            self._printLossEach(losses, visual.insideBatchIndex[j])
            for o in range(len(brInds)):
                head = brInds[o]
                if head >= len(visual.summary):
                    break
                if o == len(brInds) - 1 or brInds[o + 1] >= len(visual.summary):
                    tail = len(visual.summary)
                else:
                    tail = brInds[o + 1]
                if txts is None:
                    self.html.add_images(list(visual.summary.keys())[head:tail], [None for _ in range(head, tail)], links[head:tail])
                else:
                    self.html.add_images(list(visual.summary.keys())[head:tail], [txts[j][i] for i in range(head, tail)], links[head:tail])
            # self.html.add_images(visual.summary.keys(), [None for _ in visual.summary.keys()], links)
        self.html.save()
        self.htmlStepCount += 1

class HTMLStepper(HTMLStepperAbstract):
    pass

# Do more class extension directly in your code!

class HTMLStepperODTotal(HTMLStepperAbstract):
    # Override
    def _printLossTotal(self, loss_od):
        st = ''
        for k in loss_od.keys():
            assert type(loss_od[k]) is float
            st += ' %s: %.5f,' % (k, loss_od[k])
        self.html.add_header_h4(st)

    # Override
    def _printLossEach(self, loss_od, j):
        pass

class HTMLStepperNoPrinting(HTMLStepperAbstract):
    # Override
    def _printLossTotal(self, loss_none):
        pass

    # Override
    def _printLossEach(self, loss_none, j):
        pass

class HTMLStepperTreeLog(HTMLStepperAbstract):  # dedicated to our framework
    # Notes for __init__(logDir, singleHtmlSteps, htmlName): htmlName in here should be something like 'G_%s_%s_%s_%s' % (P, D, S, R)

    # Override
    def _printLossTotal(self, treeLog):
        for t in treeLog.keys():
            treeLog[t].print_stack(2, self.html.add_header_h4)

    # Override
    def _printLossEach(self, treeLog, j):
        for t in treeLog.keys():
            treeLog[t].print_stack(4, self.html.add_text, j)

if __name__ == '__main__':
    html = HTML('./', 'test_html')
    html.add_header('hello world')

    ims = []
    txts = []
    links = []
    for n in range(1, 5):
        ims.append('image_%d.png' % n)
        txts.append('text_%d' % n)
        # links.append('image_%d.png' % n)  # zhuzhu
        links.append('/home/zhusz/link/play/html/image_%d.png' % n)
    html.add_images(ims, txts, links)

    ims = []
    txts = []
    links = []
    for n in range(1, 5):
        ims.append('image_%d.png' % n)
        txts.append('text_%d' % n)
        # links.append('image_%d.png' % n)  # zhuzhu
        links.append('/home/zhusz/link/play/html/image_%d.png' % n)
    html.add_images(ims, txts, links)
    html.save()


from collections import defaultdict

# This class represents a directed graph using adjacency list representation
class Graph:

    def __init__(self, vertices):
        self.V = vertices  # No. of vertices
        self.graph = defaultdict(list)  # default dictionary to store graph

    # function to add an edge to graph
    def addEdge(self, u, v):
        self.graph[u].append(v)

    def scc(self):
        identified = set()
        stack = []
        index = {}
        boundaries = []

        def dfs(v):
            index[v] = len(stack)
            stack.append(v)
            boundaries.append(index[v])

            for w in self.graph[v]:
                if w not in index:
                    # For Python >= 3.3, replace with "yield from dfs(w)"
                    for scc in dfs(w):
                        yield scc
                elif w not in identified:
                    while index[w] < boundaries[-1]:
                        boundaries.pop()

            if boundaries[-1] == index[v]:
                boundaries.pop()
                scc = set(stack[index[v]:])
                del stack[index[v]:]
                identified.update(scc)
                yield scc

        for v in range(self.V):
            if v not in index:
                # For Python >= 3.3, replace with "yield from dfs(v)"
                for scc in dfs(v):
                    yield scc

# Create a graph given in the above diagram
g = Graph(5)
g.addEdge(1, 0)
g.addEdge(0, 2)
g.addEdge(2, 1)
g.addEdge(0, 3)
g.addEdge(3, 4)

for g in g.scc():
    print(g)


from functools import lru_cache
from app.celery import celery_app
from app.tasks.get_timetable import request_shedule
from celery.result import GroupResult
from core.config import config
from fastapi import APIRouter, Depends, HTTPException, Response
from fastapi.responses import ORJSONResponse

router = APIRouter(
    prefix="/wakeparks",
    tags=["items"],
)

@lru_cache()
def get_items():
    return list(config.SHEDULE_ITEMS.keys())

@router.get("/", response_class=ORJSONResponse)
def items(items: list = Depends(get_items)):
    return items

@router.get("/{item_id}", response_class=ORJSONResponse, status_code=202)
def get_item(item_id: str, date: str | None = None):
    if item_id not in config.SHEDULE_ITEMS:
        raise HTTPException(status_code=404)

    task = request_shedule(item_id, date)

    return {"task_id": task.id}

@router.get("/tasks/{task_id}", response_class=ORJSONResponse)
def get_status(task_id: str, response: Response):
    task_result = GroupResult.restore(task_id, app=celery_app)

    if task_result is None:
        raise HTTPException(status_code=404)
    if task_result.ready():
        result_data = task_result.get()
        return result_data

    response.status_code = 202
    return {"task_id": task_id}


import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
import gym
from gym import spaces
import torch
from itertools import combinations
from scipy.stats import multivariate_normal

def z_func(x, y, cos_mag_scale=3., cos_freq_scale=5., norm_scale=1.):
    return cos_mag_scale * np.cos(cos_freq_scale * x) * np.cos(
        cos_freq_scale * y) - norm_scale * (np.abs(x) + np.abs(y))

class SineRewardEnv(gym.Env):
    """
    This guy is a bit different. What's different? |a|_2 (\sum_i sin(a_i)). But maybe more interestingly,
    there will be state AND action within those things. So, the state is given to you, and the
    action you need to choose yourself. So it's not a bandit anymore. That's actually a much better test-bed. We can do
    standard RBFDQN, latent RBFDQN, and DDPG!
    """
    def get_reward(self, s, a):
        assert s.shape == (self.s_dim, ), f"{s.shape} {self.s_dim}"
        assert a.shape == (self.a_dim, ), f"{a.shape} {self.a_dim}"
        magnitude = np.linalg.norm(np.concatenate([s, a]))
        assert magnitude.shape == (), "Expects a single number"
        sines_1 = np.sin(s*self.FREQ_SCALE)
        sines_2 = np.sin(a*self.FREQ_SCALE)
        sines_sum = (np.sum(sines_1) + np.sum(sines_2)) / (self.s_dim + self.a_dim)
        return magnitude * sines_sum

    def __init__(self, s_dim=1, a_dim=1, episode_length=float('inf')):
        """
        Action is what makes reward
        Observation is always the same.
        For now, episode_length is determined through the registration thing in init
        We'll have a special case where s_dim being zero makes the observation space constant and zero.
        """
        was_zero = False
        if s_dim <= 0:
            s_dim = 1
            was_zero = True

        self.s_dim = s_dim
        self.a_dim = a_dim
        print(f"sdim: {s_dim}\t adim: {a_dim}")
        self.episode_length = episode_length
        self.FREQ_SCALE = 4.

        if was_zero:
            self.observation_space = spaces.Box(0.0, 0.0, shape=(self.s_dim, ))
        else:
            self.observation_space = spaces.Box(-1.0, 1.0, shape=(self.s_dim, ))

        self.action_space = spaces.Box(-1.0, 1.0, shape=(self.a_dim, ))

        self._last_state = None
        self._t = 0

        self.COS_MAG_SCALE = 3.
        self.COS_FREQ_SCALE = 5.
        self.NORM_SCALE = 1.

    def reset(self):
        self._last_state = self.observation_space.sample()
        self._t = 0
        return self._last_state.copy()

    def step(self, action):
        reward = self.get_reward(self._last_state, action)
        assert self.action_space.contains(action), action
        self._last_state = self.observation_space.sample()
        self._t += 1
        done = (self._t >= self.episode_length)

        return self._last_state.copy(), reward, done, {}

    def plot(self, savefile):
        assert self.a_dim == 2
        x = np.arange(-1.0, 1.0, 0.05)
        y = np.arange(-1.0, 1.0, 0.05)
        X, Y = np.meshgrid(x, y)  # grid of point
        actions = np.concatenate([X.reshape(-1, 1), Y.reshape(-1, 1)], axis=1)
        states = np.zeros((actions.shape[0], self.s_dim))
        Z = np.array([self.get_reward(states[i], actions[i]) for i in range(len(actions))])
        Z = Z.reshape(X.shape)

        fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
        surf = ax.plot_surface(X,
                               Y,
                               Z,
                               cmap=cm.coolwarm,
                               linewidth=0,
                               antialiased=False)
        fig.colorbar(surf, shrink=0.5, aspect=5)
        plt.savefig(savefile)
        plt.close()

    def plot_agent(self, Q_object, savefile):
        assert self.a_dim == 2
        x = np.arange(-1.0, 1.0, 0.05)
        y = np.arange(-1.0, 1.0, 0.05)
        X, Y = np.meshgrid(x, y)  # grid of point
        actions = np.concatenate([X.reshape(-1, 1), Y.reshape(-1, 1)], axis=1)
        actions_torch = torch.Tensor(actions).to(Q_object.device)

        states_torch = torch.zeros(actions.shape[0], self.s_dim).to(Q_object.device)
        Z_torch = Q_object.forward(states_torch, actions_torch)
        Z = Z_torch.detach().cpu().numpy()
        Z = Z.reshape(X.shape)

        fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
        surf = ax.plot_surface(X,
                               Y,
                               Z,
                               cmap=cm.coolwarm,
                               linewidth=0,
                               antialiased=False)
        fig.colorbar(surf, shrink=0.5, aspect=5)
        plt.savefig(savefile)
        plt.close()

class MultimodalEnv(gym.Env):
    def __init__(self, s_dim = 1, a_dim = 1, std = 1, scale=1):
        self.observation_space = spaces.Box(-1.0, 1.0, shape=(s_dim, ))
        self.action_space = spaces.Box(-1.0, 1.0, shape=(a_dim, ))
        self.s_dim = s_dim
        self.a_dim = a_dim
        self.std = std
        self.scale = scale

        self.distributionCenters = []
        for count in range(0, self.a_dim + 1):
            Combs = combinations(range(0, self.a_dim), count)
            for indices in Combs:
                center = np.ones((self.a_dim)) * 0.5
                for index in indices:
                    center[index] = -0.5
                self.distributionCenters.append(center)
        self.distributionCenters = np.array(self.distributionCenters)
        self.distributions = []
        for center in self.distributionCenters:
            var = multivariate_normal(mean=center, cov=self.std)
            self.distributions.append(var)

    def reset(self):
        # Since it's a bandit, we should have a constant state
        return np.ones((self.s_dim,))

    def step(self, action):
        reward = 0
        for distribution in self.distributions:
            reward += distribution.pdf(action) * self.scale
        reward = int(reward * 1000) / 1000 # only keep 3 digits after the decimal point
        done = True
        return np.zeros((self.s_dim,)), reward, done, {}

if __name__ == "__main__":
    env = MultimodalEnv(s_dim=1, a_dim=2, std=0.1, scale = 0.5)
    breakpoint()


#!/usr/bin/env python
# coding: utf-8

# In[126]:

import pandas as pd
import re
import numpy as np
import nltk
import matplotlib.pyplot as plt
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.feature_selection import SelectKBest, chi2
from sqlite3 import Error
from sklearn.ensemble import RandomForestClassifier
import sqlite3
import pickle
import seaborn as sns
get_ipython().run_line_magic('matplotlib', 'inline')

# In[2]:

train = pd.read_csv(r'C:\Hackothon\Amozon\Dataset/train.csv')
test = pd.read_csv(r'C:\Hackothon\Amozon\Dataset/test.csv')
train.head(5)

# In[3]:

train = train.rename(columns = {"Review Text": "ReviewText",
                                   "Review Title":"ReviewTitle" })
test = test.rename(columns = {"Review Text": "ReviewText",
                                   "Review Title":"ReviewTitle" })

# In[127]:

def freq_words(x, terms = 30):
  all_words = ' '.join([text for text in x])
  all_words = all_words.split()
  fdist = nltk.FreqDist(all_words)
  words_df = pd.DataFrame({'word':list(fdist.keys()), 'count':list(fdist.values())})

  # selecting top 20 most frequent words
  d = words_df.nlargest(columns="count", n = terms)

  # visualize words and frequencies
  plt.figure(figsize=(12,15))
  ax = sns.barplot(data=d, x= "count", y = "word")
  ax.set(ylabel = 'Word')
  plt.show()

# print 100 most frequent words
freq_words(train['ReviewText'], 100)
train['ReviewText'] = train['ReviewText'].apply(lambda x: remove_stopwords(x))

# In[4]:

stemmer = PorterStemmer()
words = stopwords.words("english")
train['ReviewText'] = train['ReviewText'].apply(lambda x: " ".join([stemmer.stem(i) for i in re.sub("[^a-zA-Z]", " ", x).split() if i not in words]).lower())

# In[5]:

vectorizer = TfidfVectorizer(min_df= 3, stop_words="english", sublinear_tf=True, norm='l2', ngram_range=(1, 2))
final_features = vectorizer.fit_transform(train['ReviewText']).toarray()
final_features.shape

# In[18]:

X_test.head(4)

# In[20]:

X_train.head(3)

# In[50]:

#first we split our dataset into testing and training set:
# this block is to split the dataset into training and testing set
X = train['ReviewText']
Y = train['topic']
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.25)
# instead of doing these steps one at a time, we can use a pipeline to complete them all at once
pipeline = Pipeline([('vect', vectorizer),
                     ('chi',  SelectKBest(chi2, k=1200)),
                     ('clf', RandomForestClassifier())])
# fitting our model and save it in a pickle for later use
model = pipeline.fit(X_train, y_train)
with open('RandomForest.pickle', 'wb') as f:
    pickle.dump(model, f)
ytest = np.array(y_test)
# confusion matrix and classification report(precision, recall, F1-score)
print(classification_report(ytest, model.predict(X_test)))
print(confusion_matrix(ytest, model.predict(X_test)))

# In[85]:

import xgboost as xgb
from xgboost import XGBClassifier
#first we split our dataset into testing and training set:
# this block is to split the dataset into training and testing set
X = train['ReviewText']
Y = train['topic']
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.25)
# instead of doing these steps one at a time, we can use a pipeline to complete them all at once
pipeline = Pipeline([('vect', vectorizer),
                     ('chi',  SelectKBest(chi2, k=1200)),
                     ('clf', XGBClassifier())])
# fitting our model and save it in a pickle for later use
model = pipeline.fit(X_train, y_train)
with open('XGBClassifier.pickle', 'wb') as f:
    pickle.dump(model, f)
ytest = np.array(y_test)
# confusion matrix and classification report(precision, recall, F1-score)
print(classification_report(ytest, model.predict(X_test)))
print(confusion_matrix(ytest, model.predict(X_test)))

# In[104]:

from sklearn.linear_model import LogisticRegression
#first we split our dataset into testing and training set:
# this block is to split the dataset into training and testing set
X = train['ReviewText']
Y = train['topic']
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.25)
# instead of doing these steps one at a time, we can use a pipeline to complete them all at once
pipeline = Pipeline([('vect', vectorizer),
                     ('chi',  SelectKBest(chi2, k=1200)),
                     ('clf', LogisticRegression())])
# fitting our model and save it in a pickle for later use
model = pipeline.fit(X_train, y_train)
with open('LogisticRegression.pickle', 'wb') as f:
    pickle.dump(model, f)
ytest = np.array(y_test)
# confusion matrix and classification report(precision, recall, F1-score)
print(classification_report(ytest, model.predict(X_test)))
print(confusion_matrix(ytest, model.predict(X_test)))

# # test

# In[21]:

X_train.head(4)

# In[86]:

X_test1 =  test['ReviewText']

# In[72]:

X_test1.head(3)

# In[95]:

pred_test = model.predict(X_test1)

# In[96]:

pred_test

# In[97]:

xx = pred_test.tolist()

# In[98]:

df = pd.Series(xx)
df.head(2)

# In[100]:

submission = pd.DataFrame({'Review Text':test['ReviewText'], 'Review Title':test['ReviewTitle'],'topic':df})
submission.head(3)

# In[101]:

filename = 'submission_Amazon_lr.csv'

submission.to_csv(filename,index=False)
print('Saved file: ' + filename)


from typing import TYPE_CHECKING, Any, Dict
from pydantic import ConstrainedDecimal
from pydantic.types import ConstrainedNumberMeta
from udantic.fields.utils import is_float

if TYPE_CHECKING:
    FieldPercent = dict
else:

    class _FieldPercent(ConstrainedDecimal):
        """
        FieldPrice can be:
            - int, float based 1
            - str, folloing format works:
                - int or float as str, based 1
                - symbol % ended with int or float as str based 0.01
        """
        @classmethod
        def __get_validators__(cls) -> 'CallableGenerator':
            # one or more validators may be yielded which will be called in the
            # order to validate the input, each validator will receive as an input
            # the value returned from the previous validator
            yield cls.validate
            return ConstrainedDecimal.__get_validators__()

        @classmethod
        def validate(cls, t: Any):
            if isinstance(t, ConstrainedDecimal) or \
                isinstance(t, int) or isinstance(t, float):
                return cls(t)
            if not isinstance(t, str):
                raise TypeError(f"{t} can't be treated as Percent")
            pstr = str(t).strip()
            if is_float(pstr):
                return cls(float(pstr))
            elif pstr[-1] == "%" and is_float(pstr[0:-2]):
                return cls(float(pstr[0:-1]) * 0.01)
            else:
                raise TypeError(f"{t} unkown format of Percent")

        def __repr__(self):
            return f'{type(self)}({super().__repr__()})'

    class FieldPercent(type):
        def __new__(cls, *,
                    gt: ConstrainedDecimal = None,  ge: ConstrainedDecimal = None,
                    lt: ConstrainedDecimal = None, le: ConstrainedDecimal = None,
                    max_digits: int = None, decimal_places: int = None):
            namespace = dict(
                gt=gt, ge=ge, lt=lt, le=le, max_digits=max_digits, decimal_places=decimal_places
            )
            return type('PercentValue', (_FieldPercent,), namespace)


import sys
import json

from scipy.spatial.distance import cosine
from sklearn.metrics import roc_auc_score, precision_recall_curve
import numpy as np

from nyan.embedder import Embedder

def read_jsonl(path):
    with open(path) as r:
        return [json.loads(line) for line in r]

markup_path = sys.argv[1]
docs_path = sys.argv[2]
model_path = sys.argv[3]

markup = read_jsonl(markup_path)
docs = read_jsonl(docs_path)
docs = {doc["url"]: doc for doc in docs}

embedder = Embedder(model_path)
y_pred = []
y_true = []
for record in markup:
    result = record["result"]
    if result == "trash":
        continue
    url1 = record["url1"]
    url2 = record["url2"]
    doc1 = docs[url1]
    doc2 = docs[url2]
    embeddings = embedder([doc1["text"], doc2["text"]])
    distance = cosine(embeddings[0], embeddings[1])
    y_pred.append(distance)
    label = 1 - int(result == "ok")
    y_true.append(label)

print("AUC:", roc_auc_score(y_true, y_pred))
precision, recall, thresholds = precision_recall_curve(y_true, y_pred)
f1_scores = 2 * recall * precision / (recall + precision)
threshold = thresholds[np.argmax(f1_scores)]
f1 = max(f1_scores)
print('Best threshold: ', threshold)
print("F1: ", f1)


import torch
import torchvision.transforms as transforms
import torchvision.datasets as datasets

def load_data(dataset, model_type, batch_size, nb_workers, data_path):
    """
    Loads data from CIFAR10.

    Args:
        - dataset: cifar10
        - model_type: choose among ['fc', 'conv'] (see main.py)
        - batch_size: train and test batch size
        - nb_workers: number of workers for dataloader
        - data_path: path to dataset. As the dataset is automatically
          downloaded, this can be set to 'data/cifar/'

    """

    if dataset == 'cifar10':
        # transforms
        normalize = transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))

        if model_type == 'linear':
            flatten = transforms.Lambda(lambda x: x.view(-1))
            transform_train = transforms.Compose([transforms.ToTensor(), normalize, flatten])
            transform_val_test = transform_train

        elif model_type == 'conv':
            transform_train = transforms.Compose([
                transforms.RandomCrop(28, padding=2),
                transforms.RandomHorizontalFlip(),
                transforms.ToTensor(),
                normalize
            ])
            transform_val_test = transforms.Compose([
                transforms.CenterCrop(28),
                transforms.ToTensor(),
                normalize
            ])

        else:
            raise NotImplementedError(dataset, model_type)

        # train set
        train_set = datasets.CIFAR10(
               root=data_path, train=True, download=True, transform=transform_train)
        train_sampler = torch.utils.data.sampler.SubsetRandomSampler(range(40960))
        train_loader = torch.utils.data.DataLoader(
            train_set, batch_size=batch_size, sampler=train_sampler, num_workers=nb_workers)

        # val set
        val_set = datasets.CIFAR10(
            root=data_path, train=True, download=True, transform=transform_val_test)
        val_sampler = torch.utils.data.sampler.SubsetRandomSampler(range(40960, 50000))
        val_loader = torch.utils.data.DataLoader(
            val_set, batch_size=batch_size, sampler=val_sampler, num_workers=nb_workers)

        # test
        test_set = datasets.CIFAR10(
            root=data_path, train=False, download=True, transform=transform_val_test)
        test_loader = torch.utils.data.DataLoader(
            test_set, batch_size=batch_size, shuffle=False, num_workers=nb_workers)

        return train_loader, val_loader, test_loader

    else:
        raise NotImplementedError(dataset, model_type)