import argparse
import os
import re
import subprocess
import tempfile

import at28c256
import bootstrap

class Label:
    def __init__(self, label):
        self.label = label

    def __str__(self):
        return f'Label[{self.label}]'

class LabelRef:
    def __init__(self, label):
        self.label = label

    def __str__(self):
        return f'LabelRef[{self.label}]'

class Memory:
    def __init__(self, ref):
        self.ref = ref

    def __str__(self):
        return f'Memory[{self.ref}]'

class Register:
    def __init__(self, reg):
        reg = reg.upper()
        if not reg in ['A', 'B', 'C', 'DL', 'DH', 'D', 'SEG']:
            raise Exception(f'Invalid Register Specified {reg}')
        self.reg = reg
        self.reg_offset = {'A': 0, 'B': 1, 'C': 2, 'DL': 3, 'DH': 4, 'D': 5, 'SEG': 6}[reg]

    def __str__(self):
        return f'Register[{self.reg}]'

class Value:
    def __init__(self, val):
        self.val = val

    def __str__(self):
        return f'Value[{self.val}]'

def assemble(tokens):
    for i in range(0, len(tokens)):
        mneumonic, params = tokens[i][0], tokens[i][1:]

        if type(mneumonic) == Label:
            continue
        elif type(mneumonic) != str:
            raise Exception(f'Unknown Mneumonic {mneumonic}')

        mneumonic = mneumonic.upper()

        translation = []

        if mneumonic == 'HLT':
            translation.append(0x01)
        elif mneumonic == 'NOP':
            translation.append(0x00)
        elif mneumonic == 'OUT':
            translation.append(0x43)

        elif mneumonic == 'LD':
            if len(params) != 2:
                raise Exception(f'Syntax: LD SRC DST')
            src, dst = params

            if type(dst) != Register:
                raise Exception(f'LD DST Register Expected {dst}')

            if type(src) == Value:
                translation.append(0x09 + dst.reg_offset)
                translation.append(src.val)
            elif type(src) == Memory:
                src = src.ref
                if type(src) != Value:
                    raise Exception(f'LD SRC Memory Requires Fixed Address {src}')
                translation.append(0x02 + dst.reg_offset)
                translation.append(src.val)
        elif mneumonic == 'MV':
            if len(params) != 2:
                raise Exception(f'Syntax: MV SRC DST')
            src, dst = params

            if type(src) != Register:
                raise Exception(f'MV SRC Register Expected')
            elif type(dst) != Register:
                raise Exception(f'MV DST Register Expected')

            translation.append(0x25 + 7 * src.reg_offset + dst.reg_offset)

        elif mneumonic == 'ST':
            if len(params) != 2:
                raise Exception(f'Syntax: ST SRC DST')
            src, dst = params

            if type(src) != Register:
                raise Exception(f'ST SRC Register Expected')
            elif type(dst) is not Memory:
                raise Exception(f'ST DST Memory Expected')

            dst = dst.ref
            if type(dst) not in [Register, Value]:
                raise Exception(f'ST DST Memory *Register/*Value')

            if type(dst) == Value:
                translation.append(0x10 + src.reg_offset)
                translation.append(dst.val)
            else:
                if dst.reg not in ['C', 'D']:
                    raise Exception(f'ST DST Register Must Be C or D')
                if dst.reg == 'C':
                    translation.append(0x17 + src.reg_offset)
                else:
                    translation.append(0x1e + src.reg_offset)

        elif mneumonic == 'ADD':
            translation.append(0x41)
        elif mneumonic == 'SUB':
            translation.append(0x42)

        elif mneumonic == 'JMP':
            if len(params) != 1:
                raise Exception(f'Syntax: JMP TARGET')
            target = params[0]
            if type(target) not in [LabelRef, Memory, Register]:
                raise Exception('JMP TARGET Memory/Label/Register Expected')

            if type(target) == Register:
                translation.append(0x45 + target.reg_offset)
            else:
                translation.append(0x44)
                if type(target) == Memory:
                    translation.append(target.addr)
                else:
                    translation.append(target)

        elif mneumonic in ['JC', 'JZ']:
            if len(params) != 1:
                raise Exception(f'Syntax: JC/JZ TARGET')
            target = params[0]
            if type(target) not in [LabelRef, Memory]:
                raise Exception('JMP TARGET Memory/Label Expected')
            translation.append({'JC': 0x4c, 'JZ': 0x4d}[mneumonic])
            if type(target) == Memory:
                translation.append(target.addr)
            else:
                translation.append(target)

        else:
            raise Exception(f'Unknown Mneumonic {mneumonic}')

        tokens[i] = translation

    return tokens

def link(object_code):
    labels = {}
    machine_code = []
    offset = 0
    for i in range(0, len(object_code)):
        if len(object_code[i]) == 1 and type(object_code[i][0]) == Label:
            labels[object_code[i][0].label] = offset
            continue
        machine_code.append(object_code[i])
        offset += len(object_code[i])
    for i in range(0, len(machine_code)):
        for j in range(0, len(machine_code[i])):
            if type(machine_code[i][j]) == LabelRef:
                if not machine_code[i][j].label in labels:
                    raise Exception(f'Unmatched Label Reference {machine_code[i][j].label}')
                machine_code[i][j] = labels[machine_code[i][j].label]

    return machine_code

def read_lines(source_file):
    with open(source_file, 'r') as f:
        file_lines = f.readlines()

    for i in range(0, len(file_lines)):
        l = file_lines[i]
        l = l.strip()
        l = l.split('#', maxsplit=1)[0]
        file_lines[i] = l.strip()

    file_lines = [l for l in file_lines if len(l)]
    return file_lines

def parse(file_lines):
    tokens = []

    def _translate(t):
        if t.startswith('*'):
            t = _translate(t[1:])
            if type(t) not in [Register, Value]:
                raise Exception(f'Memory Syntax Error: *0x10')
            t = Memory(t)
        elif t.isdigit():
            t = Value(int(t))
        elif t.startswith('0x') and re.match('[0-9a-fA-F]+', t[2:]):
            t = Value(int(t, 16))
        elif re.match('^[a-zA-Z]{1}[a-zA-Z0-9\-_]+:$', t):
            t = Label(t[:-1])
        elif t.startswith('R'):
            t = Register(t[1:])
        elif j > 0 and re.match('^[a-zA-Z]{1}[a-zA-Z0-9\-_]+$', t):
            t = LabelRef(t)
        return t

    for i in range(0, len(file_lines)):
        l_tokens = file_lines[i].split(' ')
        for j in range(0, len(l_tokens)):
            l_tokens[j] = _translate(l_tokens[j])

        tokens.append(l_tokens)

    return tokens

def print_assembly(file_lines, machine_lines, machine_code):
    print()

    j = 0
    k = 0
    for i in range(0, len(file_lines)):
        if re.match('^[a-zA-Z]{1}[a-zA-Z0-9\-_]+:$', file_lines[i]):
            print(file_lines[i])
        else:
            machine_line = ' '.join([f'{v:02x}' for v in machine_lines[j]])
            pad = (5 - len(machine_line)) * ' '
            print(f'  [ {k:04x} ]  {machine_line}{pad}    {file_lines[i]}')
            k += len(machine_lines[j])
            j += 1

    print()
    at28c256.hexdump(machine_code)
    print()

def run(args):
    source_file = args.file
    bin_file = os.path.splitext(args.file)[0] + '.bin'

    file_lines = read_lines(source_file)
    tokens = parse(file_lines)
    object_lines = assemble(tokens)
    machine_lines = link(object_lines)
    machine_code = b''.join([bytes(b) for b in machine_lines])

    print_assembly(file_lines, machine_lines, machine_code)

    if args.emulator:
        t = tempfile.NamedTemporaryFile('wb', delete=False)
        t.write(machine_code)
        t.close()
        try:
            p = subprocess.run([args.emulator, t.name])
        finally:
            os.unlink(t.name)
    if args.out:
        with open(args.out, 'wb') as f:
            f.write(machine_code)

    if args.port:
        with bootstrap.Bootstrap(args.port) as b:
            b.write_range(0, machine_code)
        print()

    if args.romh:
        machine_code_hex = ['0x%02x' % b for b in machine_code]
        with open(args.romh, 'w') as f:
            print('const uint8_t INIT_PROGRAM[] PROGMEM = {', file=f)
            for i in range(0, len(machine_code_hex), 16):
                print('    ', ', '.join(machine_code_hex[i:i+16]), ',' if i + 16 < len(machine_code_hex) else '', sep='', file=f)
            print('};', file=f)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Assembler.')
    parser.add_argument('--emulator', dest='emulator', default='', type=str)
    parser.add_argument('--out', dest='out', default='', type=str)
    parser.add_argument('--program', dest='port', default='', type=str)
    parser.add_argument('--romh', dest='romh', default='', type=str)
    parser.add_argument('file', type=str)
    args = parser.parse_args()

    if not args.file:
        raise Exception(f'Invalid File {args.file}')

    args.file = os.path.abspath(args.file)
    if not os.path.exists(args.file):
        raise Exception(f'Cannot File File {args.file}')

    run(args)


from flask import (
    Blueprint,
    render_template,
    request,
)
from .models import Books,Author,Tags
from flask_paginate import Pagination,get_page_parameter
import config

# 图书页面的本bp
bp = Blueprint("book",__name__,url_prefix='/book')

# 前台主页
@bp.route('/',endpoint='index')
def index():
    page = request.args.get(get_page_parameter(), type=int, default=1)  # 从前端获取你要查看的页码
    # select * from posts limit start,总共多少条;
    start = (page - 1) * config.PER_PAGE  # 从哪里开始查询  索引值
    # 第几页 start end 每页显示条数
    # 1      0     9      10
    # 2      10    19     10
    end = start + config.PER_PAGE  # 在哪里结束    索引值

    # 表示从数据库中查出来的所有的帖子文章   每一页的
    posts = None

    # 所有文章的总数
    total = 0

    # 上一页 1 2... 48 49 50 51 52... 97 98下一页

    # 查出所有的贴子
    query_obj = Books.query.order_by(Books.join_time.desc())
    # 统计帖子的总数
    total = query_obj.count()
    # 相当于 select * from posts limit 1,2

    # 将查出来的帖子 切割到每一页
    posts = query_obj.slice(start, end)

    # 调用分页对象
    # bs_version bootstrap 样式版本 默认2
    # page 从前端传递过来的 用户想查看第几页
    # total 表示 帖子的总数
    # inner_window 当前页码的 左边 和右边 分别有几个页码
    # outer_window  上一页的右边    下一页的左边  有几个   0 代表有一个 如果你想显示5个  那么就是4

    pagination = Pagination(bs_version=3, page=page, total=total, inner_window=2, outer_window=0)
    context = {
        'pagination':pagination,
        'posts':posts
    }
    return render_template('books/boos_index.html', **context)


import requests
import xml.etree.ElementTree as elemTree

def findStocks(name):
    url = 'http://api.seibro.or.kr/openapi/service/StockSvc/getStkIsinByNmN1'

    servicekey= requests.utils.unquote('CCyHbj1LLKwj5YjI7ycFHNZJNNlRmz06H4SBg0PHzStJzHDKzYVc%2FqMWsM95qQkuUy90qT7NHjJRxDnL4DdldQ%3D%3D')

    secnNm = name

    queryParams = { 'serviceKey' : servicekey
                   , 'secnNm' : secnNm
                   , 'numOfRows' : '10'
                   , 'pageNo' : '1'
                  }

    request = requests.get(url,params=queryParams)
    tree = elemTree.fromstring(request.text)
    iter_element = tree.iter(tag="item")

    array=[]
    idx=1
    for i in iter_element:
        stock_dict={}
        stock_dict['eltscYn'] = i.find("eltscYn").text
        if i.find("engSecnNm") is None:
            stock_dict['engSecnNm'] = ""
        else:
            stock_dict['engSecnNm'] = i.find("engSecnNm").text
        stock_dict['isin'] = i.find("isin").text
        stock_dict['issuDt'] = i.find("issuDt").text
        stock_dict['issucoCustno']= i.find("issucoCustno").text
        stock_dict['korSecnNm']=i.find("korSecnNm").text
        stock_dict['secnKacdNm']=i.find("secnKacdNm").text
        array.append(stock_dict)
        idx+=1
    return array


import requests
import argparse

#getting user inputs
parser = argparse.ArgumentParser()
parser.add_argument('--index', help='Elasticsearch index name"', type=str)
parser.add_argument('--type', help='Elasticsearch type"', type=str)
parser.add_argument('--keywords_list', help='keywords list to query"', type=str)
args = parser.parse_args()

# es_index = 'discovery_dev' # equivalent to SQL database
# es_type = '_doc' # equivalent to SQL table: mandatory to use _doc for text elements
# keywords_list = 'crêpes'

es_index = args.index
es_type = args.type
keywords_list = args.keywords_list

res = requests.get('https://search-PPTECH1-zrhgle3vemuqzhhs7fudth7cae.eu-west-3.es.amazonaws.com/'+es_index+'/_search?q='+keywords_list)

print(res.status_code)
if res.status_code != 200:
    print('ERROR during GET search')
    exit(1)
else:
    print('element correctly GET search!')

print(res)

res_json = res.json()
print(res_json)


"""
:Author: Daniel Mohr
:Email: daniel.mohr@dlr.de
:Date: 2021-04-13 (last change).
:License: GNU GENERAL PUBLIC LICENSE, Version 2, June 1991.
"""

import os
import time

class _EmptyAttrMixin():
    # pylint: disable=too-few-public-methods
    _empty_dir_attr = {'st_mode': 16893, 'st_size': 4096,
                       'st_uid': os.geteuid(), 'st_gid': os.getegid()}
    _empty_dir_attr['st_atime'] = _empty_dir_attr['st_mtime'] = \
        _empty_dir_attr['st_ctime'] = int(time.time())
    _empty_file_attr = {'st_mode': 33204,
                        'st_uid': os.geteuid(), 'st_gid': os.getegid()}
    _empty_file_attr['st_atime'] = _empty_file_attr['st_mtime'] = \
        _empty_file_attr['st_ctime'] = int(time.time())


import math, numpy as np
from .board import is_square_open

player = 1

#Chooses AI based on Player (X or O)
def define_ai(player):
    return 2 / player

#Initial Starting Position
def initial_state():
    return np.zeros((3,3))

def player(board):
    count_1 = 0
    count_2 = 0
    for row in board:
        for col in board:
            if board[row][col] == 1:
                count_1 += 1
            elif board[row][col] == 2:
                count_2 += 1
            else:
                continue
    if count_1 == count_2:
        return 1
    else:
        return 2

def actions(board):
    avaliable_moves = set()
    for row in board:
        for col in board:
            if is_square_open(board[row][col]):
                avaliable_moves.add((row, col))

def result(board, action):
    pass


import json
import pycocotools.mask as mask_util
import ast
import cv2

def decoding(rle_json, decode_all):
    with open(rle_json, 'r') as f:
        targets = json.load(f) # targets: list of string (each string expresses json file as dict)
        # print(type(targets), targets, len(targets))
        # print(type(targets[0]))

        # convert targets to list of dictionary
        cnt = 0
        for target in targets:
            target = target.strip('\n') # delete \n
            target = ast.literal_eval(target) # change str to dict

            if decode_all:
                with open(rle_json[:-5] + '_decoded_({}).json'.format(cnt), 'w') as decoded_f:
                    mask = mask_util.decode(target['segmentation'])[:, :]
                    # target['segmentation'] = polygonFromMask(mask) # if you want to get contour, deannotate this line of codes
                    target['segmentation'] = mask.tolist()

                    decoded_f.write(json.dumps(target))
                    cnt += 1
            else:
                if target["category_id"] == 0:  # if target is person
                    with open(rle_json[:-5] + '_decoded_({}).json'.format(cnt), 'w') as decoded_f:
                        mask = mask_util.decode(target['segmentation'])[:, :]
                        # target['segmentation'] = polygonFromMask(mask) # if you want to get contour, deannotate this line of codes
                        print(mask, type(mask))
                        target['segmentation'] = mask.tolist()

                        decoded_f.write(json.dumps(target))
                        cnt += 1

# The all codes below reference to
# https://github.com/cocodataset/cocoapi/issues/476

'''
maskedArr = mask_util.decode(compactRLESegmentation)
area = float((maskedArr > 0.0).sum())
def polygonFromMask(maskedArr):
  # adapted from https://github.com/hazirbas/coco-json-converter/blob/master/generate_coco_json.py
  contours, _ = cv2.findContours(maskedArr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
  segmentation = []
  valid_poly = 0
  for contour in contours:
  # Valid polygons have >= 6 coordinates (3 points)
     if contour.size >= 6:
        segmentation.append(contour.astype(float).flatten().tolist())
        valid_poly += 1
  if valid_poly == 0:
     raise ValueError
  return segmentation
'''

# This function is for transferring binary masks to contour coordinates
def polygonFromMask(maskedArr):  # https://github.com/hazirbas/coco-json-converter/blob/master/generate_coco_json.py
    # please reference the site below to use findCountours function properly
    # https://opencv-python.readthedocs.io/en/latest/doc/15.imageContours/imageContours.html
    contours, _ = cv2.findContours(maskedArr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

    segmentation = []
    for contour in contours:
        # Valid polygons have >= 6 coordinates (3 points)
        if contour.size >= 6:
            segmentation.append(contour.flatten().tolist())
    RLEs = mask_util.frPyObjects(segmentation, maskedArr.shape[0], maskedArr.shape[1])
    RLE = mask_util.merge(RLEs)
    # RLE = mask.encode(np.asfortranarray(maskedArr))
    area = mask_util.area(RLE)
    [x, y, w, h] = cv2.boundingRect(maskedArr)

    return segmentation[0]  # , [x, y, w, h], area


import os
from dotenv import load_dotenv
from flask import Flask, Blueprint
from google.oauth2 import service_account

import uuid

from flask import Flask, request, jsonify, session,url_for, redirect
from datetime import datetime

import firebase_admin
from firebase_admin import initialize_app, credentials, auth, exceptions as firebase_exceptions, firestore
import requests
import json

default_app = None
db = None
cms = Blueprint('cms', __name__)

def initialize_firebase():
    global default_app
    global db

    if not default_app:
        # Generate a random UUID (UUID version 4)
        random_uuid = uuid.uuid4()
        # Convert the UUID object to a string representation
        uuid_string = str(random_uuid)

        load_dotenv()  # This line loads the environment variables from the .env file

        firebase_service_account_dict = {
            "type": os.environ.get("FIREBASE_TYPE"),
            "project_id": os.environ.get("FIREBASE_PROJECT_ID"),
            "private_key_id": os.environ.get("FIREBASE_PRIVATE_KEY_ID"),
            "private_key": os.environ.get("FIREBASE_PRIVATE_KEY").replace('\\n', '\n'),
            "client_email": os.environ.get("FIREBASE_CLIENT_EMAIL"),
            "client_id": os.environ.get("FIREBASE_CLIENT_ID"),
            "auth_uri": os.environ.get("FIREBASE_AUTH_URI"),
            "token_uri": os.environ.get("FIREBASE_TOKEN_URI"),
            "auth_provider_x509_cert_url": os.environ.get("FIREBASE_AUTH_PROVIDER_X509_CERT_URL"),
            "client_x509_cert_url": os.environ.get("FIREBASE_CLIENT_X509_CERT_URL"),
        }

        os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = os.path.join(os.getcwd(), "mealmate-b3b1e-ebfd113a2e1f.json")

        cred = credentials.Certificate(firebase_service_account_dict)
        default_app = initialize_app(cred)

        print("Current Working Directory: ", os.getcwd())
        print("Files in Current Directory: ", os.listdir())
        print("GOOGLE_APPLICATION_CREDENTIALS: ", os.environ.get('GOOGLE_APPLICATION_CREDENTIALS'))
        print("DEFAULT APP NAME", default_app.name)

    if not db:
        db = firestore.client()

    return db

db = initialize_firebase()

@cms.route('/save_user_data', methods=['POST'])
def save_user_data():
    email = request.form.get('email')
    security_code = request.form.get('security_code')
    uid = request.form.get('auth_token')

    user_ref = db.collection('users').document(uid)

    # Save the user data to Firestore
    user_ref.update({
        # 'email': email,
        'security_code': security_code
    })

    return jsonify({"message": "User data saved successfully"}), 200

def generate_security_code():
    # Implement your code generation logic here
    pass
import requests

@cms.route('/get_user_data', methods=['POST'])
def get_user_data():
    email = request.form.get('email')

    # Get the user data from Firestore
    user_ref = db.collection('users').document(email)
    user_data = user_ref.get().to_dict()

    if user_data:
        return jsonify(user_data)
    else:
        return jsonify({"error": "User data not found"}), 404

# get_user_details
@cms.route('/get_user_details', methods=['GET'])
def get_user_details():
    # Get user ID from query parameters
    uid = request.args.get('uid')

    # Query Firestore for user details
    doc_ref = db.collection('users').document(uid)
    doc = doc_ref.get()
    if doc.exists:
        return jsonify(doc.to_dict()), 200
    else:
        return jsonify({"error": "User not found"}), 404

@cms.route('/get_chat', methods=['GET'])
def get_chat():
    chat_id = request.args.get('chat_id')
    user_id = request.args.get('user_id')  # Add this line
    if not chat_id or not user_id:  # Update this line
        return jsonify({'error': 'Missing chat_id or user_id'}), 400

    chat_ref = db.collection('users').document(user_id).collection('chats').document(chat_id)
    chat = chat_ref.get()
    if not chat.exists:
        return jsonify({'error': 'Chat not found'}), 404

    return jsonify(chat.to_dict()), 200

@cms.route('/get_chats', methods=['POST'])
def get_chats():
    user_id = request.form.get('user_id')

    if not user_id:
        return jsonify({"error": "Missing user_id"}), 400

    user_chats = []
    chat_refs = db.collection('chats').where('user_id', '==', user_id).get()

    for chat_ref in chat_refs:
        chat_data = chat_ref.to_dict()
        chat_data['chat_id'] = chat_ref.id
        user_chats.append(chat_data)

    return jsonify(user_chats), 200

@cms.route('/get_user_chats', methods=['GET'])
def get_user_chats():
    user_id = request.args.get('user_id')
    chats_ref = db.collection('chats')
    user_chats = chats_ref.where('user_id', '==', user_id).stream()
    user_chats_list = [chat.to_dict() for chat in user_chats]
    return jsonify({'success': True, 'chats': user_chats_list})

@cms.route('/create_new_chat', methods=['POST'])
def create_new_chat():
    user_id = request.json.get('user_id')
    if not user_id:
        return jsonify({'error': 'Missing user_id'}), 400

    chat_id = str(uuid.uuid4())
    chat_data = {
        'createdAt': datetime.utcnow().isoformat() + 'Z',  # ISO 8601 format
        'updatedAt': datetime.utcnow().isoformat() + 'Z',  # ISO 8601 format
    }
    # Create the chat
    chat_ref = db.collection('users').document(user_id).collection('chats').document(chat_id)
    chat_ref.set(chat_data)

    # Create the initial message
    message_data = {
        'chat_id': chat_id,
        'content': "Hello! How can I assist you today on restaurant menus?",
        'created_at': firestore.SERVER_TIMESTAMP,
        'message_id': "bot",
        'processed': True,
        'sender': "bot",
        'type': "text",
        'updated_at': firestore.SERVER_TIMESTAMP,
    }
    chat_ref.collection('messages').document().set(message_data)

    # Update the user document
    user_ref = db.collection('users').document(user_id)
    user_ref.update({
        'current_chat_id': chat_id,
    })

    return jsonify({'success': True, 'message': 'New chat created', 'chatId': chat_id, 'chat': chat_data}), 200

@cms.route("/store_message", methods=["POST"])
def store_message():
    data = request.get_json()

    user_id = data.get("user_id")
    chat_id = data.get("chat_id")
    message = data.get("message")

    if not user_id or not chat_id or not message:
        return jsonify({"error": "Missing user_id, chat_id, or message"}), 400

    # Add created_at and updated_at fields
    # now = datetime.datetime.now().isoformat()
    message['created_at'] = firestore.SERVER_TIMESTAMP
    message['updated_at'] = firestore.SERVER_TIMESTAMP

    try:
        print(f'storing message {message}');
        db.collection('users').document(user_id).collection('chats').document(chat_id).collection('messages').add(message)
        return jsonify({"success": "Message stored successfully"}), 200
    except Exception as e:
        print(f"Failed to store message. Error: {str(e)}")  # Log the error
        return jsonify({"error": str(e)}), 500

@cms.route('/update_user_details', methods=['PUT'])
def update_user_details():
    data = request.get_json()

    if 'user_id' in data and 'user_details' in data:
        user_id = data['user_id']
        user_details = data['user_details']

        # Check if user_details contains 'preferredLanguage' field
        if 'preferredLanguage' not in user_details:
            return jsonify({'error': 'Missing preferredLanguage in user details'}), 400

        user_ref = db.collection('users').document(user_id)

        # First, check if the user exists
        if not user_ref.get().exists:
            return jsonify({'error': 'User not found'}), 404

        # Update the user's details
        user_ref.update(user_details)

        return jsonify({'success': True, 'message': 'User details updated'}), 200
    else:
        return jsonify({'error': 'Missing user_id or user_details in request data'}), 400

@cms.route('/add_message', methods=['POST'])
def add_message():
    user_id = request.json['user_id']
    chat_id = request.json['chat_id']
    message_content = request.json['message_content']
    message_id = str(uuid.uuid4())
    message_data = {
        'messageId': message_id,
        'createdAt': firestore.SERVER_TIMESTAMP,
        'updatedAt': firestore.SERVER_TIMESTAMP,
        'type': 'text',  # For simplicity, type is hard-coded as 'text'. You can update this based on your requirements
        'content': message_content,
        'sender': 'user',  # For simplicity, sender is hard-coded as 'user'. You can update this based on your requirements
        'processed': False,
        'response': {
            'content': '',
            'createdAt': None
        }
    }
    chat_ref = db.collection('users').document(user_id).collection('chats').document(chat_id)
    chat_data = chat_ref.get().to_dict()
    chat_data['messages'][message_id] = message_data
    chat_data['updatedAt'] = firestore.SERVER_TIMESTAMP
    chat_ref.set(chat_data)
    return jsonify({'success': True, 'message': 'New message added', 'message': message_data})

@cms.route('/add_summary', methods=['POST'])
def add_summary():
    user_id = request.json['user_id']
    chat_id = request.json['chat_id']
    summary_content = request.json['summary_content']
    summary_id = str(uuid.uuid4())
    summary_data = {
        'summaryId': summary_id,
        'createdAt': firestore.SERVER_TIMESTAMP,
        'updatedAt': firestore.SERVER_TIMESTAMP,
        'content': summary_content
    }
    db.collection('users').document(user_id).collection('chats').document(chat_id).collection('summary').document(summary_id).set(summary_data)
    return jsonify({'success': True, 'message': 'New summary added', 'summary': summary_data})

@cms.route('/get_messages_for_chat', methods=['POST'])
def get_messages_for_chat():
    print("Inside get_messages_for_chat")  # Add this line
    data = request.get_json()
    chat_id = data['chat_id']
    user_id = data['user_id']
    limit = data.get('limit', 40)  # Default limit is 40
    # print(f"data: {data}")
    print(f"chat_id: {chat_id}")
    print(f"user_id: {user_id}")
    print(f"limit: {limit}")
    try:
        # Query Firestore for all messages in a chat
        messages_ref = db.collection('users').document(user_id).collection('chats').document(chat_id).collection('messages')
        messages_query = messages_ref.order_by('created_at', direction=firestore.Query.DESCENDING).limit(limit)
        messages = messages_query.stream()

        messages_list = [msg.to_dict() for msg in messages]

        if messages_list:
            return jsonify(messages_list), 200
        else:
            return jsonify({'message': 'No messages found'}), 404

    except Exception as e:
        return jsonify({'error': str(e)}), 500

@cms.route('/get_message_test', methods=['GET'])
def get_message():
    print("Inside get_message")
    chat_id = request.args.get('chat_id')
    user_id = request.args.get('user_id')
    limit = request.args.get('limit', default=40, type=int)
    print(f"chat_id: {chat_id}")
    print(f"user_id: {user_id}")
    print(f"limit: {limit}")
    try:
        # Query Firestore for all messages in a chat
        messages_ref = db.collection('users').document(user_id).collection('chats').document(chat_id).collection('messages')
        messages_query = messages_ref.order_by('created_at', direction=firestore.Query.DESCENDING) # ASCENDING
        messages = messages_query.stream()

        messages_list = [msg.to_dict() for msg in messages]

        if messages_list:
            return jsonify(messages_list), 200
        else:
            return jsonify({'message': 'No messages found'}), 404

    except Exception as e:
        return jsonify({'error': str(e)}), 500

@cms.route('/get_messages_for_chat_v2', methods=['GET'])
def get_messages_for_chat_v2():
    chat_id = request.args.get('chat_id')
    user_id = request.args.get('user_id')

    # Query Firestore for all messages in a chat
    messages_ref = db.collection('users').document(user_id).collection('chats').document(chat_id).collection('messages')
    messages = messages_ref.stream()

    messages_list = []
    for message in messages:
        messages_list.append(message.to_dict())

    if messages_list:
        return jsonify(messages_list), 200
    else:
        return jsonify({'message': 'No messages found'}), 404


# -*- coding: utf-8 -*-

"""
@author: Marine FIGAROL & Christelle VIGUIER
"""

# --------------------------------- Imports -----------------------------------

import pylab
from distance import *
import numpy as np
from math import inf
from pdb import *

# --------------------------------- Interface ---------------------------------

def interface(dic, seuil) :

    """ Obj : Savoir si un résidu appartient à l'interface entre la protéine
              et l'ARN. Calcul à partir des barycentres.
        Input : dic le dictionnaires du fichier pdb
                seuil le seuil d'appartenance à l'interface.
        Output : zone d'interface
    """

#==============================================================================

# Calcul des distances

#==============================================================================

    dom_prot = ['A1', 'A2', 'A3', 'A4']                         # Domaines de la protéine

    # Création d'un dictionnaire qui contiendra les résidus appartenant à l'interface
    res_interface = {}

    #Parcours des domaines de la protéine
    for domain in dom_prot :

        # Stocke les résidus du domaine appartenant à l'interface
        res_interface[domain] = {}
        res_interface[domain]['list'] = []

        # Parcours des conformations
        for model in dic['model_list'] :

            # On récupère le résidu de la protéine
            for residu1 in dic[model][domain]['res_list'] :

                min = inf                           # On fixe la distance min à l'infini
                # Pour stocker les coordonnées du résidu de la protéine
                coord1 = []

                # On récupère les coordonnées des atomes du premier résidu
                for atom1 in dic[model][domain][residu1]['atom_list'] :

                    coord1.append(dic[model][domain][residu1][atom1]['coord'])

                # Caclul du barycentre du résidu de la protéine
                bar1 = barycentre(coord1)

                # On récupère le résidu de l'ARN
                for residu2 in dic[model]['B']['res_list'] :
                    # Pour stocker les coordonnées du résidu de l'ARN
                    coord2 = []

                    # On récupère les coordonnées des atomes du second résidu
                    for atom2 in dic[model]['B'][residu2]['atom_list'] :

                        coord2.append(dic[model]['B'][residu2][atom2]['coord'])

                    # Caclul du barycentre du résidu de l'ARN
                    bar2 = barycentre(coord2)

                    # Caclul de la distance entre les 2 résidus
                    dist = dist_inter_atom(bar1, bar2)
                    #Recherche de la distance min entre le résidu et l'ARN
                    min = dist if dist < min else min

                # On regarde si le résidu appartient à l'interface
                if min < seuil :
                    # S'il n'appartenait pas déja à l'interface
                    if residu1 not in res_interface[domain]['list'] :
                        res_interface[domain]['list'].append(residu1)

                        # Initialisation du nombre de fois où il appartient à l'interface
                        res_interface[domain][residu1] = 0

                    res_interface[domain][residu1] += 1

    return(res_interface)

def printInterface(dicInterface) :

    """ Obj :  Produit un fichier contenant les fréqauences d'appartenance à
            l'interface
        Input : dicRMSD le dictionnaire contenant les RMSD.
        Output : fichier contenant les RMSD.
    """

    # Création du fichier qui contiendra les RMSD
    fichier = open("interface.txt", "w")

    dom_prot = ['A1', 'A2', 'A3', 'A4']                         # Domaines de la protéine

    # Création des "colonnes" du fichier
    fichier.write("Domaine\t Residu n°\tFréquence")
    fichier.close()

#==============================================================================

# Calcul des fréquences et écriture dans le fichier

#==============================================================================

    # On complète maintenant le fichier

    fichier = open("interface.txt", "a")                              # Mode ajout

    # Parcours des domaines de la protéine
    for domain in dom_prot :
        # On parcours la liste des résidus qui appartiennent à l'interface
        for res in dicInterface[domain]['list'] :
            # Calcul de la fréquence
            dicInterface[domain][res] = dicInterface[domain][res]/500
            # Ajout dans le fichier
            fichier.write("\n\t" + domain + "\t\t " + str(res) + " \t " + str(dicInterface[domain][res]))

    fichier.close()


from fastapi import APIRouter, Query, File, UploadFile, HTTPException

from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, PrimaryKeyConstraint
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship

# THis includes the initialized RDBS function and the Objects for the MySQL database

# Create the base model for SQLAlchemy
Base = declarative_base()

def initialize_rdbs():
    print("Initializing rdbs")
    try:
        # Create the SQLAlchemy engine and session
    # Create a connection to the MySQL server without specifying a database
        DATABASE_URL = "mysql+pymysql://root@localhost/citidream"
        engine = create_engine(DATABASE_URL, echo=True)

        # Create a connection to the MySQL server without specifying a database
        # connection = engine.connect()

        # Close the connection to the MySQL server

        Base.metadata.create_all(bind=engine)

        SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
        session = SessionLocal()

        # connection.close()
        return session
    except Exception as e:
        print("Error in initializing RDBS")
        print(e)

initialize_rdbs()

# ObjectID | ExcerptID |
# If it is a PDF, the object will relate to the PDF in S3, isLink = 0, URL = None
# If it is a Link, the objectID will be a random uuid. isLink = 1, URL = link
class ObjectExcerptPair(Base):
    """
    This table stores
        - ObjectID: This ID refers to the ID of the object in S3, or a random UUID if it is a link
        - ExcerptID: This ID refers to the ID of the excerpt generated by LLM, an object can have many excerpts.

    The composite primary key is ObjectID and ExcerptID
    """
    __tablename__ = "ObjectExcerptPair"

    ObjectID = Column(String(64))
    ExcerptID = Column(String(64))

    ObjectID = Column(String(64), ForeignKey('ObjectInfo.ObjectID'))
    object_entries = relationship('ObjectInfo', backref='votes')

    __table_args__ = (
        PrimaryKeyConstraint('ObjectID', 'ExcerptID'),
    )

# ObjectID | Name | Upvotes | Downvotes
class ObjectInfo(Base):
    """
    This table stores
        - ObjectID: This ID refers to the ID of the object in S3
        - Upvotes: This is the number of upvotes that the object has
        - Downvotes: This is the number of downvotes that the object has
    """

    __tablename__ = "ObjectInfo"

    ObjectID = Column(String(64))
    ObjectName = Column(String(255))
    Department = Column(String(128))
    Classification = Column(String(32)) # Restricted, Unclassified
    Upvotes = Column(Integer, default=0)
    Downvotes = Column(Integer, default=0)
    isLink = Column(Boolean, default=0)
    URL = Column(String(255))

    __table_args__ = (
        PrimaryKeyConstraint('ObjectID'),
    )


import flask
import pytest

import sys
sys.path.append('../src')

from flask_restful_api import app

def test_endpoint_endpoints():
    with app.test_client() as c:
        rv = c.get('/endpoints')
        json_data = rv.get_json()
        assert json_data == {
            'endpoints': [
                {
                    'endpoint': '/autocomplete/?q=[PARTIAL_OR_FULL_NAME]',
                    'about:': 'Lists all the names found that starts with the given text.',
                    'warning': 'For searches containing blank spaces, replace them for: "%20".',
                    'examples': [
                        'rasm',
                        'rasmus%20po'
                    ]
                },
                {
                    'endpoint': '/endpoints',
                    'about': 'Lists all available endpoints.'
                },
                {
                    'endpoint': '/find/?q=[NAME]',
                    'about': 'Checks if the given name exists in the dataset.'
                }
            ]
        }

def test_find():
    with app.test_request_context('/find/?q=abby bates'):
        assert flask.request.path == '/find/'
        assert flask.request.args['q'] == 'abby bates'

def test_autocomplete():
    with app.test_request_context('/autocomplete/?q=ras'):
        assert flask.request.path == '/autocomplete/'
        assert flask.request.args['q'] == 'ras'

    with app.test_request_context('/autocomplete/?q=rasmus po'):
        assert flask.request.path == '/autocomplete/'
        assert flask.request.args['q'] == 'rasmus po'


import os
import logging
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from pathlib import Path
from dotenv import load_dotenv

env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)

from utils.ses_service import SESService, SESInternalException

logger = logging.getLogger(__name__)

CHANNEL_NAME = "#slack-bot-tutorial"

client = WebClient(token=os.environ['SLACK_TOKEN'])

_NEW_ORDER_MESSAGE = {
    'subject': '[TABLETOP] We have the new order #%s',
    'message': 'Hi, we have the new order with id #%s'
}

_SENDER = os.environ.get('ORDER_NOTIFICATION_SENDER', '')
_DESTINATION = os.environ.get('ORDER_NOTIFICATION_DESTINATION', '').split(',')

class OrderNotificationService():
    """ Class to handle the way to notify user when we have something happend with order """

    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(OrderNotificationService, cls).__new__(cls)

        return cls.instance

    def send_new_paid_order_notification(
        self, order_id, sender=_SENDER,  destination=_DESTINATION,
        subject=_NEW_ORDER_MESSAGE['subject'], message=_NEW_ORDER_MESSAGE['message']
    ):
        """ Send notification to the admin when we have new order """
        try:
            SESService().send_text_email(
                sender, destination,
                subject % (order_id), message % (order_id))
            logger.info('Sent email to %s', str(destination))
        except SESInternalException as err:
            logger.error('Error when sending email %s', str(err))

        try:
            client.chat_postMessage(channel=CHANNEL_NAME, text=message)
        except SlackApiError as e:
            print(f"Error: {e.response['error']}")


#
# @lc app=leetcode id=138 lang=python3
#
# [138] Copy List with Random Pointer
#

# @lc code=start
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random

class Solution:
    def copyRandomList(self, head: Node) -> Node:
        if head is None:
            return None

        table = {}

        # create a table
        # record origin node index
        t = head
        index = 0
        while t is not None:
            table[t] = index
            index += 1
            t = t.next

        # create a new linked list
        t = head
        new_list = []
        while t is not None:
            n = Node(t.val, None, None)
            t = t.next
            new_list.append(n)

        # last is None
        new_list.append(None)
        table[None] = len(new_list) - 1

        t = head
        n = new_list[0]
        while t is not None:
            # index
            index = table[t.next]
            n.next = new_list[index]

            if t.random is not None:
                index = table[t.random]
                n.random = new_list[index]
            else:
                n.random = None

            n = n.next
            t = t.next

        return new_list[0]

# @lc code=end


import bpy

# -----------------------------------------------------------------------------

class QANIM_OT_overscan_reset(bpy.types.Operator):
    bl_label = "reset_overScan"
    bl_idname = "qanim.overscan_reset"
    bl_description = ""
    bl_options = {'REGISTER', 'UNDO'}   # undo効くようにする設定

    def resetOverScan(self, context):
        ''' オーバースキャンで設定したパラメータをリセット
        '''
        camera_object = context.active_object
        camera = camera_object.data

        bpy.context.scene.render.resolution_x = camera.oriResX
        bpy.context.scene.render.resolution_y = camera.oriResY
        camera.shift_x = camera.overscan_original_shift_x
        camera.shift_y = camera.overscan_original_shift_y
        camera.sensor_width = camera.sensorWidth

        camera_object.delta_rotation_euler.x = 0
        camera_object.delta_rotation_euler.z = 0

        del camera["oriResX"]
        del camera["oriResY"]
        del camera["sensorWidth"]

        bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)

    def execute(self, context):
        ''' メイン処理
        '''

        camera_object = context.active_object
        camera = camera_object.data

        if hasattr(camera, "oriResX") is False:    # 初回起動時はこちらでオーバースキャン実行
            self.resetOverScan( context )
        elif camera.oriResX > 0:                   # 2回目以降はこちら
            self.resetOverScan( context )

        return{'FINISHED'}

class QANIM_OT_overscan_run(bpy.types.Operator):
    bl_label = "run_overScan"
    bl_idname = "qanim.overscan_run"
    bl_description = ""
    bl_options = {'REGISTER', 'UNDO'}   # undo効くようにする設定

    def overScan(self, context):
        ''' オーバースキャン設定
        '''

        camera_object = context.active_object
        camera = camera_object.data
        pivot = camera.pivot_prop_enum
        scaleRatioX = camera.magnification_prop_FloatX
        scaleRatioY = camera.magnification_prop_FloatY

        # 解像度変更
        curResX = bpy.context.scene.render.resolution_x
        curResY = bpy.context.scene.render.resolution_y

        if camera.pixOrPer_prop_enum == 'percent':
            bpy.context.scene.render.resolution_x = int( curResX * scaleRatioX )
            bpy.context.scene.render.resolution_y = int( curResY * scaleRatioY )
        elif camera.pixOrPer_prop_enum == 'pixcel':
            bpy.context.scene.render.resolution_x = camera.magnification_prop_IntX
            bpy.context.scene.render.resolution_y = camera.magnification_prop_IntY

        resResult = bpy.context.scene.render.resolution_y / bpy.context.scene.render.resolution_x

        # センサーフィットが自動だったら水平に変換しセンサーの初期値確定
        curSensor = camera.sensor_width
        if camera.sensor_fit == 'AUTO':
            camera.sensor_fit = 'HORIZONTAL'
            if curResY > curResX:
                camera.sensor_width = (curResY / curResX * curSensor) / 2

        # 元のカメラ設定・解像度をカスタムプロパティに格納
        bpy.types.Camera.oriResX = bpy.props.IntProperty(name="oriResX")
        bpy.types.Camera.oriResY = bpy.props.IntProperty(name="oriResY")
        bpy.types.Camera.sensorWidth = bpy.props.FloatProperty(name="sensor_width")
        camera.oriResX = curResX
        camera.oriResY = curResY
        camera.sensorWidth = camera.sensor_width

        # センサーサイズ変更によるオーバースキャン
        sensor_width = camera.sensor_width
        if camera.pixOrPer_prop_enum == 'percent':
            camera.sensor_width = sensor_width * scaleRatioX
        elif camera.pixOrPer_prop_enum == 'pixcel':
            camera.sensor_width = sensor_width * (camera.magnification_prop_IntX / camera.oriResX)

        # オーバースキャン基点設定
        if pivot[0] == 'U':
            LRPivot = 1
        elif pivot[0] == 'D':
            LRPivot = -1
        elif pivot[0] == 'M':
            LRPivot = 0

        if pivot[1] == 'L':
            UDPivot = -1
        elif pivot[1] == 'R':
            UDPivot = 1
        elif pivot[1] == 'M':
            UDPivot = 0

        if camera.pixOrPer_prop_enum == 'pixcel':
            scaleRatioX = camera.magnification_prop_IntX / camera.oriResX
            scaleRatioY = camera.magnification_prop_IntY / camera.oriResY

        camera.overscan_original_shift_x = camera.shift_x
        camera.overscan_original_shift_y = camera.shift_y
        camera.shift_x = camera.overscan_original_shift_x + (scaleRatioX - 1) / scaleRatioX / 2 * LRPivot
        camera.shift_y = camera.overscan_original_shift_y + (scaleRatioY - 1) / scaleRatioY / 2 * resResult * UDPivot
        camera.temp_camera_overscan_force_apply = False

    def execute(self, context):
        ''' メイン処理
        '''

        camera_object = context.active_object
        camera = camera_object.data

        # オーバースキャン実行
        if 'CAMERA' == camera_object.type:
            if hasattr(camera, "oriResX") is False:       # 初回起動時はこちらでオーバースキャン実行
                self.overScan( context )
            elif camera.oriResX == 0:                     # 2回目以降はこちら
                self.overScan( context )
            elif camera.temp_camera_overscan_force_apply: # 多重かけ防止だが、強制的にONにする
                self.overScan( context )

        return{'FINISHED'}

# -----------------------------------------------------------------------------

def _initialized():
    ''' プロパティの初期化
    '''

    scene = bpy.types.Camera
    # scene = bpy.types.Scene

    # 比を固定して変更するようにするか
    scene.temp_ratio_interlocked = bpy.props.BoolProperty(
        name='temp_ratio_interlocked',
        description='lock/unlock screen/pixel ratio',
        default=True,
    )

    # 更新中に追加更新しないように(無限ループになる)
    scene.temp_updating_locked = bpy.props.BoolProperty(
        name='temp_updating_locked',
        description='block infinity loop for update value',
        default=False,
    )
    scene.temp_camera_overscan_force_apply = bpy.props.BoolProperty(
        name='Force applies overscan',
        description='Force applies overscan',
        default=False,
    )

    # オーバースキャン比率プロパティ
    scene.magnification_prop_FloatX = bpy.props.FloatProperty(precision=1, default=1.2, step=10.0, update=_update_magnification_prop_FloatX)
    scene.magnification_prop_FloatY = bpy.props.FloatProperty(precision=1, default=1.2, step=10.0, update=_update_magnification_prop_FloatY)

    # オーバースキャン後解像度プロパティ
    scene.magnification_prop_IntX = bpy.props.IntProperty(default=2304)
    scene.magnification_prop_IntY = bpy.props.IntProperty(default=1296)

    # オリジナルシフト値を保存
    scene.overscan_original_shift_x = bpy.props.FloatProperty(name="Original Camera Shift X")
    scene.overscan_original_shift_y = bpy.props.FloatProperty(name="Original Camera Shift Y")

    # オーバースキャン比率か解像度のいずれをえらぶかのプロパティ
    scene.pixOrPer_prop_enum = bpy.props.EnumProperty(
        name='pixOrPer',
        description='select method',
        items=[
            ('percent', 'percent', 'percent'),
            ('pixcel', 'pixcel', 'pixcel'),
        ],
        default='percent'
    )

    # オーバースキャンpivot
    scene.pivot_prop_enum = bpy.props.EnumProperty(
        name='pivot',
        description='overscan pivot',
        items=[
            ('UL', '', 'up_left'),
            ('UM', '', 'up_mid'),
            ('UR', '', 'up_right'),
            ('ML', '', 'mid_left'),
            ('MM', '', 'mid_mid'),
            ('MR', '', 'mid_right'),
            ('DL', '', 'down_left'),
            ('DM', '', 'down_mid'),
            ('DR', '', 'down_right'),
        ],
        default='MM'
    )

def _deinitialized( ):
    """
        後始末
    """
    scene = bpy.types.Camera

    del scene.pixOrPer_prop_enum
    del scene.temp_ratio_interlocked
    del scene.temp_updating_locked
    del scene.temp_camera_overscan_force_apply
    del scene.magnification_prop_FloatX
    del scene.magnification_prop_FloatY
    del scene.magnification_prop_IntX
    del scene.magnification_prop_IntY

    del scene.overscan_original_shift_x
    del scene.overscan_original_shift_y
    del scene.pivot_prop_enum

def _update_magnification_prop_FloatX( self, context ):
    scene = context.active_object.data
    if scene.temp_updating_locked:
        return
    scene.temp_updating_locked = True
    if scene.temp_ratio_interlocked:
        scene.magnification_prop_FloatY = scene.magnification_prop_FloatX
    scene.temp_updating_locked = False

def _update_magnification_prop_FloatY( self, context ):
    scene = context.active_object.data
    if scene.temp_updating_locked:
        return
    scene.temp_updating_locked = True
    if scene.temp_ratio_interlocked:
        scene.magnification_prop_FloatX = scene.magnification_prop_FloatY
    scene.temp_updating_locked = False


# Implementation for
# Comparator-learning Combinatorial Functions (JMLR, 2016)
# @author: Yuhao Wan

import numpy as np
import pandas as pd
from functools import cmp_to_key
import math
import copy
from sklearn.linear_model import perceptron
from sklearn.metrics import accuracy_score

class pairwise_oracle():
  # Implementation of pairwise comparison oracle

    def __init__(self, preference_list):
        """ taken in an ordered list as given preference
        the list is in ascending order (so later in the list means more preferred)
        assuming strict preference for now """
        self.preference = np.array(preference_list)

    def compare(self, s1, s2):
        """ output -1 or 1 according to the preference list
        # s1 > s2 --> 1; s1 < s2 --> -1 """
        i, j = np.where(self.preference == s1), np.where(self.preference == s2)
        return 1 if i > j else -1

    def batch_compare(self, s_table):
        """ Input dim: k x 2 matrix, each row is (s1, s2)
        Return a vector of length k according to the preference list """
        vectorCompare = np.vectorize(self.compare)
        return vectorCompare(s_table.T[0], s_table.T[1])

class comparison_learner():
  # Implementation of a comparison learning function

    def __init__(self, S, n, oracle, epsilon, delta):
        """initialize with
        # a training sample S, ground set size n
        # an oracle
        # initial dictionary R[(i, j)] = [w, theta]
        # hyper-parameters epsilon, delta"""

        self.S = S
        self.n = n
        self.oracle = oracle
        self.R = {}
        self.epsilon = epsilon
        self.delta = delta
        self.m = self.calculate_m(epsilon, delta)

    def train(self):
        """main function, updates dictionary R with weights"""

        # step 1
        S1 = np.random.choice(self.S, self.m, replace = False)
        S2 = np.setdiff1d(self.S, S1)

        # step 2
        S1_sorted = self.sort_1d(S1)

        # step 3
        S2_dict = self.sort_2d(S1_sorted, S2)

        # step 4 & 5
        R = self.get_weights(S1_sorted, S2_dict)

        # step 6
        self.R = self.minimalize(R)

    def predict(self, s1, s2):
        """Input s1, s2. Returns comparison result. (s1 > s2 --> 1; s1 < s2 --> -1)"""

        chi_s1 = np.append(num_to_ind(s1, self.n), 1) # add intercept term
        chi_s2 = np.append(num_to_ind(s2, self.n), 1)

        for (a, b) in self.R:
            weight = self.R[(a, b)]
            if np.dot(weight, chi_s1) < 0 and np.dot(weight, chi_s2) > 0:
                return -1
        return 1

    def batch_predict(self, test_sample):
        """Input dimension: K x 2. Returns a vector of length K comparison result"""
        return [self.predict(row[0], row[1]) for row in test_sample]

    def test_accuracy(self, test_sample, test_truth):
        """Input vector of length k. Returns accuracy rate"""
        predict_results = self.batch_predict(test_sample)
        accuracy = sum(np.equal(predict_results, test_truth)) / len(test_truth)
        return accuracy

    def calculate_m(self, epsilon, delta):
        """Input hyperparameters. Returns m"""
        return int((2/epsilon)*math.log(1/(epsilon*delta)))

    def sort_1d(self, S1):
        """Sorts S1 by value function"""
        return sorted(S1, key=cmp_to_key(self.oracle.compare))

    def sort_2d(self, S1, S2):
        """Sorts S2 2-dimensionally"""
        S2_dict = {}
        for i in range(self.m):
            for j in range(i+1, self.m):
                S2_dict[(i, j)] = []
                for s in S2:
                    # add into S2_dict if s < s_i or s > s_j
                    if self.oracle.compare(s, S1[i]) == -1 or self.oracle.compare(s, S1[j]) == 1:
                        S2_dict[(i, j)].append(s)
        return S2_dict

    def minimalize(self, R):
        """Returns a minimalized dictionary R to contain only minimal pairs"""
        R_copy = copy.deepcopy(R)
        for (a, b) in R_copy:
            for (c, d) in R_copy:
                if (a, b)!= (c, d) and a <= c and b >= d and (a, b) in R:
                    del R[(a, b)]
        return R

    def get_weights(self, S1, S2_dict):
        """Returns a dictionary R where key is (i, j) and value is the weights [w_ij, theta_ij]"""
        R = {}
        for i in range(self.m):
            for j in range(i+1, self.m):
                S_ij = S2_dict[(i, j)]
                labels = [-1 if self.oracle.compare(s, S1[i]) == -1 else 1 for s in S_ij]
                S_ij = set_to_matrix(S_ij, self.n)
                net = perceptron.Perceptron(max_iter=100,
                                            fit_intercept=True,
                                            eta0=0.002)
                if len(np.unique(labels)) == 2: # fit if having two unique labels
                    net.fit(S_ij, labels)
                    if net.score(S_ij, labels) == 1: # add to R if no training error
                        w = net.coef_[0]
                        theta = net.intercept_[0]
                        R[(i, j)] = np.append(w, theta)
        return R

# Helper functions
def num_to_ind(k, n):
    """Input number. Returns a list of binary with length n."""
    length = '0' + str(n) + 'b'
    return np.array([int(x) for x in format(k, length)])

def ind_to_num(ind_vec):
    """Input a list of binary with length n. Returns a number."""
    return np.array(int(''.join(map(str, list(ind_vec))), 2))

def set_to_matrix(num_list, n):
    """Input set of numbers. Returns a matrix where each row is a indicator vector."""
    return np.array([num_to_ind(x, n) for x in num_list])

def run_test(n, epsilon, delta, S_size, pref_list, test_size):
    """Input learning model hyper-parameters and test parameters. Return accuracy rate."""
    # build pair-comparison oracle
    oracle = pairwise_oracle(pref_list)

    # build comparison learner
    S = np.random.choice(pref_list, S_size, replace = False)
    myLearner = comparison_learner(S, n, oracle, epsilon, delta)

    # train
    myLearner.train()

    # test
    select_sample = np.random.choice(pref_list, 2*test_size, replace = False)
    test_sample = [select_sample[0:test_size], select_sample[test_size:2*test_size]]
    test_sample = np.rot90(test_sample) # k x 2 dimension
    test_truth  = oracle.batch_compare(test_sample)
    accuracy    = myLearner.test_accuracy(test_sample, test_truth)

    return accuracy

if __name__ == "__main__":
    run_test(n=10, epsilon=0.2, delta=0.2, S_size=200,
        pref_list=range(1024), test_size=100)


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def traverse(self, root: Optional[TreeNode], check_left: int, lefts: list[int]):
        if not root:
            return

        if not root.left and not root.right:
            if check_left:
                lefts.append(root.val)

        self.traverse(root.left, True, lefts)
        self.traverse(root.right, False, lefts)

    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        lefts = []
        self.traverse(root, False, lefts)
        return sum(lefts)


import abc
from typing import Any, Generator, Iterable, List, NamedTuple, Optional, Union
import unittest

from nmigen import *
from nmigen.sim import *

from nmigen_nexys.core import edge
from nmigen_nexys.core import util
from nmigen_nexys.test import test_util

Event = Any  # TODO: Maybe a protocol type?

class TimestampedEvent(NamedTuple):
    cycle: int
    event: Event

class EdgeEvent(NamedTuple):
    """Simulation event: GPIO toggled."""
    signal: Signal
    direction: str  # TODO(python-3.8): Literal['rose', 'fell']

class DelayConstraint(object):

    def __init__(self, *, seconds: Optional[float] = None,
                 cycles: Optional[int] = None):
        super().__init__()
        if seconds is not None:
            assert cycles is None
            self.cycles = int(seconds * util.SIMULATION_CLOCK_FREQUENCY)
        else:
            assert cycles is not None
            self.cycles = cycles

class MinDelay(DelayConstraint):
    pass

class MaxDelay(DelayConstraint):
    pass

EventConstraints = Iterable[Union[Event, DelayConstraint]]

class EventSeries(object):

    def __init__(self, cycle_counter: Signal):
        super().__init__()
        self._cycle_counter = cycle_counter
        self._events: List[TimestampedEvent] = []

    def add(self, event: Event) -> Generator[None, Signal, int]:
        cycle = yield self._cycle_counter
        self._events.append(TimestampedEvent(cycle, event))

    def ShowEvents(self):
        if not self._events:
            print('No simulation events captured')
            return
        dbg_table = []
        for e1, e2 in zip([None] + self._events[:-1], self._events):
            diff = f'({e2.cycle - e1.cycle:+})' if e1 else ' '
            dbg_table.append((str(e2.cycle), diff, repr(e2.event)))
        widths = [max(len(row[col]) for row in dbg_table) for col in range(2)]
        dbg_out = ['Simulation events:']
        for ts, diff, disp in dbg_table:
            dbg_out.append(f'  {ts:>{widths[0]}} {diff:>{widths[1]}} {disp}')
        print('\n'.join(dbg_out))

    def ValidateConstraints(self, tc: unittest.TestCase,
                            expected: EventConstraints):
        actual_iter = iter(self._events)
        last_ts = 0
        delay_constraints = []
        for constraint in expected:
            if isinstance(constraint, DelayConstraint):
                delay_constraints.append(constraint)
                continue
            event = next(actual_iter)
            # tc.assertIsInstance(constraint, Event)
            tc.assertEqual(event.event, constraint)
            if delay_constraints:
                total = sum(c.cycles for c in delay_constraints)
                if all(isinstance(c, MinDelay) for c in delay_constraints):
                    tc.assertGreaterEqual(event.cycle - last_ts, total)
                elif all(isinstance(c, MinDelay) for c in delay_constraints):
                    tc.assertGreaterEqual(event.cycle - last_ts, total)
                else:
                    tc.fail('Invalid mix of delay constraints')
                delay_constraints = []
            last_ts = event.cycle

class Monitor(abc.ABC):

    def __init__(self):
        super().__init__()
        self._event_series = None

    def emit(self, event: Event) -> Generator[None, Signal, int]:
        yield from self._event_series.add(event)

    @abc.abstractmethod
    def process(self) -> test_util.CoroutineProcess[None]:
        pass

    def attach(self, sim: Simulator, event_series: EventSeries):
        self._event_series = event_series
        sim.add_sync_process(self.process)

class EdgeMonitor(Monitor):

    def __init__(self, detectors: Iterable[edge.Detector]):
        super().__init__()
        self._detectors = detectors

    def process(self) -> test_util.CoroutineProcess[None]:
        yield Passive()
        while True:
            yield
            for detector in self._detectors:
                if (yield detector.rose):
                    yield from self.emit(EdgeEvent(detector.input, 'rose'))
                if (yield detector.fell):
                    yield from self.emit(EdgeEvent(detector.input, 'fell'))


country_mapping = {
    'id' : 'ID_0',
    'iso' : 'ISO',
    'name_english' : 'NAME_ENGLI',
    'name_iso' : 'NAME_ISO',
    'name_fao' : 'NAME_FAO',
    'name_local' : 'NAME_LOCAL',
    'name_obsolete' : 'NAME_OBSOL',
    'name_variants' : 'NAME_VARIA',
    'name_nonlatin' : 'NAME_NONLA',
    'name_french' : 'NAME_FRENC',
    'name_spanish' : 'NAME_SPANI',
    'name_russian' : 'NAME_RUSSI',
    'name_arabic' : 'NAME_ARABI',
    'name_chinese' : 'NAME_CHINE',
    'waspartof' : 'WASPARTOF',
    'contains' : 'CONTAINS',
    'sovereign' : 'SOVEREIGN',
    'iso2' : 'ISO2',
    'www' : 'WWW',
    'fips' : 'FIPS',
    'ison' : 'ISON',
    'validfr' : 'VALIDFR',
    'validto' : 'VALIDTO',
    'pop2000' : 'POP2000',
    'sqkm' : 'SQKM',
    'popsqkm' : 'POPSQKM',
    'unregion1' : 'UNREGION1',
    'unregion2' : 'UNREGION2',
    'developing' : 'DEVELOPING',
    'cis' : 'CIS',
    'transition' : 'Transition',
    'oecd' : 'OECD',
    'wbregion' : 'WBREGION',
    'wbincome' : 'WBINCOME',
    'wbdebt' : 'WBDEBT',
    'wbother' : 'WBOTHER',
    'ceeac' : 'CEEAC',
    'cemac' : 'CEMAC',
    'ceplg' : 'CEPLG',
    'comesa' : 'COMESA',
    'eac' : 'EAC',
    'ecowas' : 'ECOWAS',
    'igad' : 'IGAD',
    'ioc' : 'IOC',
    'mru' : 'MRU',
    'sacu' : 'SACU',
    'uemoa' : 'UEMOA',
    'uma' : 'UMA',
    'palop' : 'PALOP',
    'parta' : 'PARTA',
    'cacm' : 'CACM',
    'eurasec' : 'EurAsEC',
    'agadir' : 'Agadir',
    'saarc' : 'SAARC',
    'asean' : 'ASEAN',
    'nafta' : 'NAFTA',
    'gcc' : 'GCC',
    'csn' : 'CSN',
    'caricom' : 'CARICOM',
    'eu' : 'EU',
    'can' : 'CAN',
    'acp' : 'ACP',
    'landlocked' : 'Landlocked',
    'aosis' : 'AOSIS',
    'sids' : 'SIDS',
    'islands' : 'Islands',
    'ldc' : 'LDC',
    'geom' : 'MULTIPOLYGON',
}

adm1_mapping = {
    'country' : {'id': 'ID_0'},
    'id_0' : 'ID_0',
    'iso' : 'ISO',
    'name_0' : 'NAME_0',
    'id_1' : 'ID_1',
    'name_1' : 'NAME_1',
    'hasc_1' : 'HASC_1',
    'ccn_1' : 'CCN_1',
    'cca_1' : 'CCA_1',
    'type_1' : 'TYPE_1',
    'engtype_1' : 'ENGTYPE_1',
    'nl_name_1' : 'NL_NAME_1',
    'varname_1' : 'VARNAME_1',
    'geom' : 'MULTIPOLYGON',
}

adm2_mapping = {
    'country' : {'id': 'ID_0'},
    'id_0' : 'ID_0',
    'iso' : 'ISO',
    'name_0' : 'NAME_0',
    'id_1' : 'ID_1',
    'name_1' : 'NAME_1',
    'id_2' : 'ID_2',
    'name_2' : 'NAME_2',
    'hasc_2' : 'HASC_2',
    'ccn_2' : 'CCN_2',
    'cca_2' : 'CCA_2',
    'type_2' : 'TYPE_2',
    'engtype_2' : 'ENGTYPE_2',
    'nl_name_2' : 'NL_NAME_2',
    'varname_2' : 'VARNAME_2',
    'geom' : 'MULTIPOLYGON',
}

adm3_mapping = {
    'country' : {'id': 'ID_0'},
    'id_0' : 'ID_0',
    'iso' : 'ISO',
    'name_0' : 'NAME_0',
    'id_1' : 'ID_1',
    'name_1' : 'NAME_1',
    'id_2' : 'ID_2',
    'name_2' : 'NAME_2',
    'id_3' : 'ID_3',
    'name_3' : 'NAME_3',
    'ccn_3' : 'CCN_3',
    'cca_3' : 'CCA_3',
    'type_3' : 'TYPE_3',
    'engtype_3' : 'ENGTYPE_3',
    'nl_name_3' : 'NL_NAME_3',
    'varname_3' : 'VARNAME_3',
    'geom' : 'MULTIPOLYGON',
}

adm4_mapping = {
    'country' : {'id': 'ID_0'},
    'id_0' : 'ID_0',
    'iso' : 'ISO',
    'name_0' : 'NAME_0',
    'id_1' : 'ID_1',
    'name_1' : 'NAME_1',
    'id_2' : 'ID_2',
    'name_2' : 'NAME_2',
    'id_3' : 'ID_3',
    'name_3' : 'NAME_3',
    'id_4' : 'ID_4',
    'name_4' : 'NAME_4',
    'varname_4' : 'VARNAME_4',
    'ccn_4' : 'CCN_4',
    'cca_4' : 'CCA_4',
    'type_4' : 'TYPE_4',
    'engtype_4' : 'ENGTYPE_4',
    'geom' : 'MULTIPOLYGON',
}

adm5_mapping = {
    'country' : {'id': 'ID_0'},
    'id_0' : 'ID_0',
    'iso' : 'ISO',
    'name_0' : 'NAME_0',
    'id_1' : 'ID_1',
    'name_1' : 'NAME_1',
    'id_2' : 'ID_2',
    'name_2' : 'NAME_2',
    'id_3' : 'ID_3',
    'name_3' : 'NAME_3',
    'id_4' : 'ID_4',
    'name_4' : 'NAME_4',
    'id_5' : 'ID_5',
    'name_5' : 'NAME_5',
    'ccn_5' : 'CCN_5',
    'cca_5' : 'CCA_5',
    'type_5' : 'TYPE_5',
    'engtype_5' : 'ENGTYPE_5',
    'geom' : 'MULTIPOLYGON',
}


# -*- coding: UTF-8 -*-

from random import getrandbits
from Crypto import Random
from Crypto.PublicKey.pubkey import bignum, getPrime

_g = 2

def GetBigPrime(bits = 300):
    "获取大素数"
    return bignum(getPrime(bits-1, Random.new().read))

class DiffieHellman:
    "p大素数,g底数,公钥可以公开，私钥_randnum要保密"
    def __init__(self, prime, bits = 300):
        self.__prime = prime
        while True:
            r = getrandbits(bits)
            if r < self.__prime:
                self.__randnum = r
                break
        self.pubkey = pow(_g, self.__randnum, self.__prime)

    def getPubkey(self):
        "获取公钥"
        return self.pubkey

    def getKey(self,otherpubkey):
        "获取最终的协商密钥"
        return pow(otherpubkey,self.__randnum, self.__prime)

if __name__ == '__main__':
    p = GetBigPrime()
    d1 = DiffieHellman(p)
    d2 = DiffieHellman(p)


'''
: Make a dictionary called favorite_places. Think of three
names to use as keys in the dictionary, and store one to three favorite places for
each person. To make this exercise a bit more interesting, ask some friends to
name a few of their favorite places. Loop through the dictionary, and print each
person’s name and their favorite places.
'''

favorite_places = {
    'james': {'home', 'apri', 'indigo',},
    'myke' : {'home', "parent's house in the states", 'with my friends',},
    'daniel' : {'home', 'japan', 'france',},
    'cath': {'Niagra Falls', 'Amusement park with a Ferris Wheel', 'Anywhere with water'},
    'crystal': {'Hanjan', 'EKCA', 'Terwillegar foot bridge'},
    'julia': {'home', 'home', 'home',},
}

for key, value in favorite_places.items():
    name = key.title()
    print(f"\n{name}'s three favorite places are:")
    for favorite_place in value:
        print(f"\t{favorite_place.capitalize()}")