from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from tensorflow.contrib.model_pruning.python import pruning
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.training import moving_averages
import tensorflow as tf
import argparse
import sys

variable_scope = 'ResNet'

def residual_unit_v3(data, out_filter, stride, dim_match, trainable, name):
    """Return ResNet Unit symbol for building ResNet
    Parameters
    ----------
    data : str
        Input data
    out_filter : int
        Number of output channels
    stride : tuple
        Stride used in convolution
    dim_match : Boolean
        True means channel number between input and output is the same, otherwise means differ
    trainable: Boolean
        trainning or testing, True is trainning, otherwise is testing.
    name : str
        Base name of the operators
    """
    shape = [3, 3]
    in_filter= data.get_shape().as_list()[-1]
    shape.append(int(in_filter))
    shape.append((out_filter))

    # print(name)

    bn1 = batch_normalization(data, variance_epsilon=2e-5, trainable=trainable, name=name + '_bn1')
    bn1_pad = tf.pad(bn1, paddings=[[0, 0], [1, 1], [1, 1], [0, 0]])
    conv1 = convolution(bn1_pad, group=1, shape=shape, strides=[1, 1], padding='VALID', trainable=trainable, name=name + '_conv1')
    bn2 = batch_normalization(conv1, variance_epsilon=2e-5, trainable=trainable, name=name + '_bn2')
    relu1 = prelu(bn2, trainable=trainable, name=name + '_relu1')
    relu1_pad = tf.pad(relu1, paddings=[[0, 0], [1, 1], [1, 1], [0, 0]])
    shape[-2] = relu1_pad.get_shape().as_list()[-1]
    conv2 = convolution(relu1_pad, group=1, shape=shape, strides=stride, padding='VALID', trainable=trainable, name=name + '_conv2')
    bn3 = batch_normalization(conv2, variance_epsilon=2e-5, trainable=trainable, name=name + '_bn3')

    if dim_match:
        shortcut = data
    else:
        shape = [1, 1]
        in_filter = data.get_shape().as_list()[-1]
        shape.append(int(in_filter))
        shape.append((out_filter))

        conv1sc = convolution(data, group=1, shape=shape, strides=stride, padding='VALID', trainable=trainable, name=name + '_conv1sc')
        shortcut = batch_normalization(conv1sc, variance_epsilon=2e-5, trainable=trainable, name=name + '_sc')

    return bn3 + shortcut

def residual_unit(data, out_filter, stride, dim_match, trainable, name, **kwargs):
    return residual_unit_v3(data, out_filter, stride, dim_match, trainable, name=name, **kwargs)

def prelu(input, trainable, name):
    gamma = tf.get_variable(initializer=tf.constant(0.25,dtype=tf.float32,shape=[input.get_shape()[-1]]), trainable=trainable, name=name + "_gamma")
    return tf.maximum(0.0, input) + gamma * tf.minimum(0.0, input)

MOVING_AVERAGE_DECAY = 0.9997
BN_DECAY = MOVING_AVERAGE_DECAY
BN_EPSILON = 0.001
CONV_WEIGHT_DECAY = 0.00004
CONV_WEIGHT_STDDEV = 0.1
FC_WEIGHT_DECAY = 0.00004
FC_WEIGHT_STDDEV = 0.01
RESNET_VARIABLES = 'resnet_variables'
UPDATE_OPS_COLLECTION = 'resnet_update_ops'  # must be grouped with training op

def batch_normalization(input, trainable, name, **kwargs):
    input_shape = input.get_shape()
    shape = input_shape.as_list()[-1::]
    axis = list(range(len(input_shape) - 1))
    moving_mean = tf.get_variable(shape=shape, initializer=tf.zeros_initializer, trainable=trainable, name=name + "_mean")
    moving_variance = tf.get_variable(shape=shape, initializer=tf.ones_initializer, trainable=trainable, name=name + "_var")
    offset = tf.get_variable(shape=shape, initializer=tf.zeros_initializer, trainable=trainable, name=name + "_bias")
    scale = tf.get_variable(shape=shape, initializer=tf.ones_initializer, trainable=trainable, name=name + "_scale") if name != 'fc1' else None

    mean, variance = tf.nn.moments(input, axis)
    update_moving_mean = moving_averages.assign_moving_average(moving_mean, mean, BN_DECAY)
    update_moving_variance = moving_averages.assign_moving_average(moving_variance, variance, BN_DECAY)
    tf.add_to_collection(UPDATE_OPS_COLLECTION, update_moving_mean)
    tf.add_to_collection(UPDATE_OPS_COLLECTION, update_moving_variance)
    is_training = tf.convert_to_tensor(trainable, dtype='bool', name='is_training')
    mean, variance = control_flow_ops.cond(is_training,
        lambda: (mean, variance),
        lambda: (moving_mean, moving_variance))

    return tf.nn.batch_normalization(input, mean, variance, offset, scale, name=name, **kwargs)

def convolution(input, group, shape, trainable, name, **kwargs):
    w = tf.get_variable(initializer=tf.truncated_normal(shape, stddev=0.1), trainable=trainable, name=name + "_weight")
    if group == 1:
        layer = tf.nn.convolution(input, pruning.apply_mask(w, name + "_weight"), **kwargs)
    else:
        weight_groups = tf.split(w, num_or_size_splits=group, axis=-1)
        xs = tf.split(input, num_or_size_splits=group, axis=-1)
        convolved = [tf.nn.convolution(x, pruning.apply_mask(weight, name + "_weight_groups"), **kwargs) for
                     (x, weight) in zip(xs, weight_groups)]
        layer = tf.concat(convolved, axis=-1)

    if name.endswith('_sc'):
        b = tf.get_variable(initializer=tf.truncated_normal(input.get_shape().as_list()[-1::], stddev=0.1), trainable=trainable, name=name + "_bias")
        layer = layer + b
    return layer

def resnet(inputs, w_init, units, num_stages, filter_list, trainable, reuse=False):
    """Return ResNet symbol of
    Parameters
    ----------
    units : list
        Number of units in each stage
    num_stages : int
        Number of stage
    filter_list : list
        Channel size of each stage
    num_classes : int
        Ouput size of symbol
    dataset : str
        Dataset type, only cifar10 and imagenet supports
    """
    #version_se = kwargs.get('version_se', 1)
    #version_input = kwargs.get('version_input', 1)
    #assert version_input >= 0
    #version_output = kwargs.get('version_output', 'E')
    #version_unit = kwargs.get('version_unit', 3)
    #print(version_se, version_input, version_output, version_unit)
    num_unit = len(units)
    assert (num_unit == num_stages)
    inputs = inputs - 127.5
    inputs = inputs * 0.0078125

    with tf.variable_scope(variable_scope, reuse=reuse):
        net = tf.pad(inputs, paddings=[[0, 0], [1, 1], [1, 1], [0, 0]])
        net = convolution(net, group=1, strides=[1, 1], shape=[3, 3, 3, 64], padding='VALID', trainable=trainable, name='conv0')
        net = batch_normalization(net, variance_epsilon=2e-5, trainable=trainable, name='bn0')
        net = prelu(net, trainable=trainable, name='relu0')

        body = net
        for i in range(num_stages):
            body = residual_unit(body, filter_list[i + 1], (2, 2), False, trainable=trainable, name='stage%d_unit%d' % (i + 1, 1))
            for j in range(units[i] - 1):
                body = residual_unit(body, filter_list[i + 1], (1, 1), True, trainable=trainable, name='stage%d_unit%d' % (i + 1, j + 2))

        bn1 = batch_normalization(body, variance_epsilon=2e-5, trainable=trainable, name='bn1')
        bn1_shape = bn1.get_shape().as_list()
        bn1 = tf.reshape(bn1, shape=[-1, bn1_shape[1] * bn1_shape[2] * bn1_shape[3]], name='E_Reshapelayer')
        pre_fc1 = tf.layers.dense(bn1, units=512, kernel_initializer=w_init, use_bias=True)
        fc1 = batch_normalization(pre_fc1, variance_epsilon=2e-5, trainable=trainable, name='fc1')

    return fc1, pre_fc1

def get_resnet(inputs, w_init, num_layers, trainable, reuse=False):
    """
    Adapted from https://github.com/tornadomeet/ResNet/blob/master/train_resnet.py
    Original author Wei Wu
    """
    if num_layers >= 101:
        filter_list = [64, 256, 512, 1024, 2048]
        bottle_neck = True
    else:
        filter_list = [64, 64, 128, 256, 512]
        bottle_neck = False
    num_stages = 4
    if num_layers == 18:
        units = [2, 2, 2, 2]
    elif num_layers == 34:
        units = [3, 4, 6, 3]
    elif num_layers == 49:
        units = [3, 4, 14, 3]
    elif num_layers == 50:
        units = [3, 4, 14, 3]
    elif num_layers == 74:
        units = [3, 6, 24, 3]
    elif num_layers == 90:
        units = [3, 8, 30, 3]
    elif num_layers == 100:
        units = [3, 13, 30, 3]
    elif num_layers == 101:
        units = [3, 4, 23, 3]
    elif num_layers == 152:
        units = [3, 8, 36, 3]
    elif num_layers == 200:
        units = [3, 24, 36, 3]
    elif num_layers == 269:
        units = [3, 30, 48, 8]
    else:
        raise ValueError("no experiments done on num_layers {}, you can do it yourself".format(num_layers))

    return resnet(inputs=inputs,
                  w_init=w_init,
                  units=units,
                  num_stages=num_stages,
                  filter_list=filter_list,
                  trainable=trainable,
                  reuse=reuse)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--pretrained_model', type=str, help='Load a pretrained model before training starts.')
    parser.add_argument('--ckpt_path', type=str, help='the checkpoint path to save model.')
    args = parser.parse_args(sys.argv[1:])

    with tf.Graph().as_default():
        with tf.Session() as sess:
            input = tf.placeholder(dtype=tf.float32, shape=[None, 112, 112, 3], name='input')
            trainable_placeholder = tf.placeholder_with_default(tf.constant(False, dtype=tf.bool), shape=None, name='trainable')
            w_init_method = tf.contrib.layers.xavier_initializer(uniform=False)
            prelogits = get_resnet(input, w_init=w_init_method, num_layers=50, trainable=trainable_placeholder)

            embeddings = tf.identity(prelogits, name='embeddings')

            saver = tf.train.Saver(tf.trainable_variables(), max_to_keep=3)
            print(args.pretrained_model)
            ckpt = tf.train.get_checkpoint_state(args.pretrained_model)
            print(ckpt)
            saver.restore(sess, ckpt.model_checkpoint_path)
            saver.save(sess, args.ckpt_path, global_step=0)

    print('test finish!')


from collections import Counter
from .tiles import grid
from .tiles.start import GameWon

def process_move(move):
    move = move.upper()
    if move == 'N':
        return (0, 1)
    if move == 'S':
        return (0, -1)
    if move == 'W':
        return (-1, 0)
    if move == 'E':
        return (1, 0)
    print("Move %s not recognised" % move)
    return (0, 0)

def main():
    name = input("What is your name? ")
    inventory = Counter()
    x, y = 0, 0

    try:
        while True:
            tile = grid[x,y]
            move = tile.enter(name, inventory)
            dx, dy = process_move(move)
            new_locn = x+dx, y+dy
            if new_locn in grid:
                x, y = new_locn
            else:
                print("The undergrowth in that direction is impenetrable. "
                      "You turn back.")
                print()

    except GameWon:
        print("Congratulations!")


import cv2
import numpy as np

img = np.zeros((512, 512, 3), np.uint8)

# coloring image
# img[:] = 255, 0, 0

cv2.line(img, (0, 0), (img.shape[1], img.shape[0]), (0, 255, 0), 3)
# write cv2.FILLED in place of thickness to fill rectangle
cv2.rectangle(img, (0, 0), (250, 350), (0, 0, 255), 2)
cv2.circle(img, (400, 100), 70, (255, 255, 0), 2)
cv2.putText(img, " OPENCV ", (250, 200), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 150, 0), 2)

cv2.imshow("Image", img)

cv2.waitKey(0)


import re
import os

from bs4 import BeautifulSoup
from docx import Document
from docx.oxml.ns import qn
from docx.shared import Pt

from util import util

class Field:
    def __init__(self, name='', type='', dtype='', comment=''):
        self.name = name
        self.type = type
        self.dtype = dtype
        self.comment = comment
        self.is_not_null = False
        self.is_key = False
        self.is_auto_increase = False

    def __repr__(self):
        return "Field(name=%s, type=%s, dtype=%s, comment=%s, is_not_null=%s, is_key=%s, is_auto_increase=%s)" % \
               (self.name, self.type, self.dtype, self.comment, self.is_not_null, self.is_key, self.is_auto_increase)

class Table:
    def __init__(self):
        self.name = ''
        self.comment = ''
        self.fields = []

    def __repr__(self):
        return "Table(name=%s, comment=%s, fields=%s)" % (self.name, self.comment, repr(self.fields))

    def pprint(self):
        import pprint
        print("Table(\nname=%s,"% self.name)
        print("comment=%s," % self.comment)
        print("fields=")
        pprint.pprint(self.fields)
        print(")")

def parse_sql_table(sql_text):
    """
    sql文本转Table对象列表
    :param sql_text: sql文本
    :return: list of Table
    """
    tables = []
    ret = re.findall(r"""create\s+(?:external\s+|)table\s+
                    `{0,1}(.+?)`{0,1}\s*    #表名
                    \(([^;]+)\)           #表内容
                    ([^;]*?)          #表描述
                    ;""", sql_text, re.X | re.I)
    table_comm_re = re.compile(r"COMMENT='(.*?)'", re.I)
    for per_table_ret in ret:
        table_name = per_table_ret[0]
        table_body = per_table_ret[1]
        table_desc = per_table_ret[2]
        table_body_lines = list(map(lambda x: x.strip(), table_body.strip().splitlines()))
        new_table = Table()
        # 遍历( ... )里面的每一行
        key_names = []
        for line in table_body_lines:
            line_lower = line.lower()
            if 'primary key' in line_lower:
                key_names.append(line[line.find('(') + 1:line.find(')')])
            if 'key ' not in line_lower:
                ret_line = re.search(r'`{0,1}([\w\d_]+)`{0,1}\s+([^\s,]+)\s*(.*)', line)
                field_name = ret_line.group(1)
                field_type = ret_line.group(2)
                field_dtype = field_type.split("(")[0].strip()
                field_comment = ''
                if 'comment ' in line_lower:
                    field_comment = re.search(r"comment\s+'(.*?)'", line, re.I).group(1)
                new_field = Field(field_name, field_type, field_dtype, field_comment)
                if 'not null' in line_lower:
                    new_field.is_not_null = True
                if 'auto_increment' in line_lower:
                    new_field.is_auto_increase = True
                new_table.fields.append(new_field)
        # 处理primary key
        for per_field in new_table.fields:
            if per_field.name in key_names:
                per_field.is_key = True
        table_comment = ''
        ret_comment = table_comm_re.search(table_desc)
        if ret_comment is not None:
            table_comment = ret_comment.group(1)
        new_table.comment = table_comment
        new_table.name = table_name
        tables.append(new_table)
    return tables

def sql_to_javabean(sql_text, useWrapperClass=False):
    """
    sql文本转javabean，
    :param sql_text: sql文本
    :param useWrapperClass: 属性是否使用包装类
    :return: list of (class name, javaBean text)
    """
    tables = parse_sql_table(sql_text)
    return [table_to_javabean(table, useWrapperClass) for table in tables]

def sql_to_scalacase(sql_text):
    tables = parse_sql_table(sql_text)
    return [table_to_scalacase(table) for table in tables]

def sql_to_scalabean(sql_text):
    tables = parse_sql_table(sql_text)
    return [table_to_scalabean(table) for table in tables]

def sql_to_docx(sql_text,path="sql.docx",explorer=False):
    tables = parse_sql_table(sql_text)

    NORMAL_FONT = '微软雅黑'
    NORMAL_FONT_SIZE = 10
    TABLE_STYLE = 'Light Grid Accent 3'

    document = Document()
    # 样式设置
    document.styles['Normal'].font.name = NORMAL_FONT
    document.styles['Normal'].font.size = Pt(NORMAL_FONT_SIZE)
    # noinspection PyProtectedMember
    document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), NORMAL_FONT)
    # 1.Head生成
    doc_title = "数据库表"
    head_runs = document.add_heading(doc_title, 0).runs
    for per_run in head_runs:
        per_run.font.name = NORMAL_FONT
        # noinspection PyProtectedMember
        per_run._element.rPr.rFonts.set(qn('w:eastAsia'), NORMAL_FONT)
    # 2.Sql表格的生成
    for sql_table in tables:
        # 表Title生成
        tag_text = sql_table.name + '(' + sql_table.comment + ')' if not sql_table.comment == 'null' else sql_table.name
        label = document.add_paragraph()
        label_table_name = label.add_run(tag_text[0].upper() + tag_text[1:])
        label_table_name.font.size = Pt(14)
        # 表格生成
        row, col = len(sql_table.fields) + 1, 6
        docx_table = document.add_table(rows=row, cols=col, style=TABLE_STYLE)
        col_index = 0
        docx_table.cell(0, col_index).text = '字段名称'
        col_index += 1
        docx_table.cell(0, col_index).text = '数据类型'
        col_index += 1
        docx_table.cell(0, col_index).text = '主键'
        col_index += 1
        docx_table.cell(0, col_index).text = '不可空'
        col_index += 1
        docx_table.cell(0, col_index).text = '自增'
        col_index += 1
        docx_table.cell(0, col_index).text = '字段注释'
        for field, row_index in zip(sql_table.fields, range(len(sql_table.fields))):
            col_index = 0
            docx_table.cell(row_index + 1, col_index).text = field.name
            col_index += 1
            docx_table.cell(row_index + 1, col_index).text = field.type
            col_index += 1
            docx_table.cell(row_index + 1, col_index).text = str(field.is_key)
            col_index += 1
            docx_table.cell(row_index + 1, col_index).text = str(field.is_not_null)
            col_index += 1
            docx_table.cell(row_index + 1, col_index).text = str(field.is_auto_increase)
            col_index += 1
            docx_table.cell(row_index + 1, col_index).text = field.comment
        document.add_paragraph("\n")
    document.save(path)
    if explorer:
        os.system("explorer %s" % (path))

def sql_to_html(sql_text,path="sql.html",explorer=False):
    html_css = """
        th {
            background-color: rgb(81, 130, 187);
            color: #fff;
            border-bottom-width: 0;
        }
        td {
            color: #000;
        }
        tr, th {
            border-width: 1px;
            border-style: solid;
            border-color: rgb(81, 130, 187);
        }
        td, th {
            padding: 5px 10px;
            font-size: 12px;
            font-family: Verdana;
            font-weight: bold;
        }
        table {
            border-width: 1px;
            border-collapse: collapse;
            float: left;
            margin: 10px;
        }
    """
    html = """
    <title>PdmShow</title>
    """ % html_css
    tables = parse_sql_table(sql_text)

    html = BeautifulSoup(html, 'lxml')
    # 遍历数据表
    for table in tables:
        table1 = html.new_tag(name='table')
        # 标题行
        tr_head = html.new_tag(name='tr')
        td_head = html.new_tag(name='th', colspan="3")
        td_head.append(table.name + '(' + table.comment + ')')
        tr_head.append(td_head)
        table1.append(tr_head)
        # field行
        for field in table.fields:
            tr_field = html.new_tag(name='tr')
            td_name = html.new_tag(name='td')
            td_name.append(field.name)
            td_type = html.new_tag(name='td')
            td_type.append(field.type)
            td_comment = html.new_tag(name='td')
            td_comment.append(field.comment)
            tr_field.append(td_name)
            tr_field.append(td_type)
            tr_field.append(td_comment)
            table1.append(tr_field)
        html.body.append(table1)

    result_html = html.prettify()
    with open(path, "w", encoding="utf-8") as fp:
        fp.write(result_html)
    if explorer:
        os.system("explorer %s" % (path))

def table_to_javabean(table, useWrapperClass=False):
    """
    Table对象转为javaBean
    :param table: Table obj
    :return: (class name, javaBean text)
    """
    type_map = {"varchar": "String", "datetime": "Date", "bigint": "long", "smallint": "int",
                "tinyint": "int", "int": "int", "float": "float", "double": "double"}
    wrapper_class_map = {"int": "Integer", "long": "Long", "double": "Double"}
    class_fmt = """public class {class_name} {{
{field_content}
}}
    """
    field_fmt = """    private {type} {name};{comment}"""
    if useWrapperClass:
        type_map.update(wrapper_class_map)
    field_list = [(type_map.get(field.dtype, "String"), util.fieldname_under2camel(field.name), field.comment) for field in table.fields]
    class_name = util.fieldname_under2camel(table.name, True)
    field_content = "\n".join( [field_fmt.format(type=type,name=name,comment="//"+comment if comment else comment) for type,name,comment in field_list] )
    class_text = class_fmt.format(**{"class_name": class_name,
                                   "field_content": field_content })
    return class_name, class_text

def table_to_scalacase(table):
    type_map = {"varchar": "String", "datetime": "Date", "bigint": "Long", "smallint": "Int",
                "tinyint": "Int", "int": "Int", "float": "Float", "double": "Double"}
    class_fmt = """case class {}({})"""
    class_name = util.fieldname_under2camel(table.name, True)
    field_list = [(type_map.get(field.dtype, "String"), util.fieldname_under2camel(field.name), field.comment) for field in table.fields]
    class_text = class_fmt.format(class_name, ", ".join( ["{}:{}".format(name,type) for type,name,comment in field_list] ))
    return class_name, class_text

def table_to_scalabean(table):
    type_map = {"varchar": "String", "datetime": "Date", "bigint": "Long", "smallint": "Int",
                "tinyint": "Int", "int": "Int", "float": "Float", "double": "Double"}
    class_fmt = """class {class_name}{{
{field_content}
}}"""
    field_fmt = """  var {name}: {type} = _{comment}"""
    class_name = util.fieldname_under2camel(table.name, True)
    field_list = [(type_map.get(field.dtype, "String"), util.fieldname_under2camel(field.name), field.comment) for field
                  in table.fields]
    field_content = "\n".join([field_fmt.format(type=type, name=name, comment="//" + comment if comment else comment)
         for type, name, comment in field_list])
    class_text = class_fmt.format(class_name=class_name,field_content=field_content)
    return class_name, class_text

def sql_to_sqlalchemy(sql_text):
    table_texts = re.findall(r"""create\s+(?:external\s+|)table\s+
                        `{0,1}.+?`{0,1}\s*    #表名
                        \([^;]+\)           #表内容
                        [^;]*?              #表描述
                        ;""", sql_text, re.X | re.I)

    return [sql_table_to_sqlalchemy(table_text) for table_text in table_texts]

def sql_table_to_sqlalchemy(text):
    type_map = {"varchar": "String", "datetime": "DateTime", "bigint": "BigInteger", "smallint": "SmallInteger",
                "tinyint": "SmallInteger", "text": "Text", "int": "Integer", "double": "Float", "char": "String",
                "set": "Enum"}
    s = []
    primary_key_l = []
    lines = text.split("\n")  # 表设计行拆分
    for line in lines[::-1]:  # 遍历表设计行
        j = line.strip().split(" ")  # 倒序遍历，并按空格切分
        if len(j) > 2:  # 只关注行长度超过2的元素
            column = j[0].replace("`", "")
            i_type = j[1]
            if column == "PRIMARY":
                primary_key_l = re.sub(r'`|\(|\)', '', j[2]).split(",")  # 拿到主键key
                continue
            elif column == "CREATE":  # 获取表名
                table_name = j[2].replace("`", "")
                s.append("    " + '__tablename__ = "%s"' % table_name)
                s.append("class %s(Base):" % table_name)
                continue
            elif column in ("UNIQUE", ")", "KEY"):  # 非表列名，跳过
                continue
            if i_type in type_map.keys():  # 类型存在映射表中
                i_type = i_type.replace(i_type, type_map[i_type]) + "()"
            elif "(" in i_type and i_type.split("(")[0] in type_map.keys():  # 类型有长度声明，提取类型字段，找到映射表映射value，并替换
                old_type = i_type.split("(")[0]
                new_type = type_map[old_type]
                i_type = i_type.replace(old_type, new_type)
            else:
                i_type = i_type.replace(i_type, type_map[i_type]) + "()"
                print("Catch any case not in type_map:%s" % i_type)

            if column in primary_key_l:  # 列名存在主键数组中
                i_type = i_type + ", primary_key=True"
            s.append("    " + column + " = Column(" + i_type + ")")

    return table_name,"\n".join(s[::-1])  # 反序输出

if __name__ == '__main__':
    sql_text = """CREATE TABLE `test_rerm` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `ip` int(10) unsigned NOT NULL,
  `termType` varchar(32) NOT NULL DEFAULT '' comment '1111',
  `vendor` varchar(32) NOT NULL,
  `date` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3001 DEFAULT CHARSET=utf8 COMMENT='终端类型表';"""
    sql_to_html(sql_text)
    for name,text in sql_to_scalabean(sql_text):
        print(text)


# -*- coding:utf-8 -*-
# leetcode79:单词搜索
# newcoder上就是不通过
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        visited = [[False for _ in range(len(matrix[0]))] for _ in range(len(matrix))]
        for i in range(rows):
            # print()
            for j in range(cols):
                if self.dfs(matrix,path,i,j,0,visited):
                    # print("bbb")
                    return True
        return False

    def dfs(self,matrix,path,a,b,u,visited):
        # print("path",len(path))
        # print("u",u)
        # print("m:",matrix[a][b])
        # print("path",path[u])
        # print(matrix[a][b] == path[u])
        if matrix[a][b] != path[u]: return False
        if len(path) == u+1:return True
        dx = [-1,0,1,0]
        dy = [0,1,0,-1]
        for i in range(4):
            visited[a][b] = True
            x = a+dx[i]
            y = b+dy[i]
            if x>=0 and x<len(matrix) and y>=0 and y<len(matrix[0]) and not visited[x][y]:
                # print("yes")
                if self.dfs(matrix,path,x,y,u+1,visited):return True
        # print("q")
        visited[a][b] = False
        # print("a")
        return False

if __name__ == '__main__':
    matrix = [["a","b","c","e"],
              ['s','f','c','s'],
              ['a','d','e','e']]
    matrix = [["a"]]
    matrix = [["A",'B','C',"E"],
              ["S",'F','C',"S"],
              ["A",'D','E',"E"]]
    # print(matrix[2][3])
    # matrix[2][3] = "@"
    # print(matrix)
    # lucky = "abc"
    # lucky[1]="!"
    # print(lucky)
    # lucky[1]="!"
    # TypeError: 'str' object does not support item assignment
    row = 1
    col = 1
    row=3
    col=4
    path = "bcced"
    path = "abcb"
    path = "b"
    path = "ABCCED"
    print(Solution().hasPath(matrix,row,col,path))

23-矩阵中的路径.py


# coding=utf-8
"""
    This file has some auxiliary functions for Case Recommender. Method:
        - check_error_file: check if file exist
        - check_len_lists: check if the size of two list are equal
        - timed: measure the execution time of a function
        - print_header: print header in the algorithms

"""

# © 2018. Case Recommender (MIT License)

import sys
import time

__author__ = 'removed for double blind review'

def check_error_file(file_check):
    """
    Function to check if file exist

    :param file_check: File to check
    :type file_check: str

    """

    try:
        open(file_check)
    except TypeError:
        raise TypeError("File cannot be empty or file is invalid: " + str(file_check))

def check_len_lists(list1, list2):
    """
    Function to check if 2 have the same length

    :param list1: First list
    :type list1: list

    :param list2: Second list
    :type list2: list

    """

    if len(list1) != len(list2):
        print("Error: Number of files in train list and rank list must be equal!")
        sys.exit()

def timed(f):
    """
    Function to calculate the time of execution

    :param f: Function name without ()
    :type f: function name

    :return: Time of execution
    :rtype: float

    """
    start = time.time()
    f()
    elapsed = time.time() - start
    return elapsed

def print_header(header_info, test_info=None):
    """
    Function to print the header with information of the files

    :param header_info: Dictionary with information about dataset or train file
    :type header_info: dict

    :param test_info: Dictionary with information about test file
    :type test_info: dict

    """

    print("[Case Recommender: %s]\n" % header_info['title'])
    print("train data:: %d users and %d items (%d interactions) | sparsity:: %.2f%%" %
          (header_info['n_users'], header_info['n_items'], header_info['n_interactions'], header_info['sparsity']))

    if test_info is not None:
        print("test data:: %d users and %d items (%d interactions) | sparsity:: %.2f%%\n" %
              (test_info['n_users'], test_info['n_items'], test_info['n_interactions'], test_info['sparsity']))


def transform(old, mat):
	new = [0,0,0,0]
	new[0] = old[0]*mat[0][0] + old[1]*mat[0][1] + old[2]*mat[0][2] + old[3]*mat[0][3]
	new[1] = old[0]*mat[1][0] + old[1]*mat[1][1] + old[2]*mat[1][2] + old[3]*mat[1][3]
	new[2] = old[0]*mat[2][0] + old[1]*mat[2][1] + old[2]*mat[2][2] + old[3]*mat[2][3]
	new[3] = old[0]*mat[3][0] + old[1]*mat[3][1] + old[2]*mat[3][2] + old[3]*mat[3][3]
	return new

import math
n = int(input("Enter the number of vertices of the 3D shape: "))
x = list(map(int, input("Input a space-separated list for x-coordinates").split()))
y = list(map(int, input("Input a space-separated list for y-coordinates").split()))
z = list(map(int, input("Input a space-separated list for z-coordinates").split()))
q = int(input("Enter the number of transformation queries: "))
queries = []
for i in range(q):
	temp = list(map(int, input().split()))
	queries.append(temp)
# s = [[sx,0,0,0],[0,sy,0,0],[0,0,sz,0],[0,0,0,1]]
# t = [[1,0,0,tx],[0,1,0,ty],[0,0,1,tz],[0,0,0,1]]
# rx = [[1,0,0,0],[0,math.cos(theta),-math.sin(theta),0],[0,math.sin(theta),math.cos(theta),0],[0,0,0,1]]
# ry = [[math.cos(theta),0,math.sin(theta),0],[0,1,0,0],[-math.sin(theta),0,math.cos(theta),0],[0,0,0,1]]
# rz = [[math.cos(theta),-math.sin(theta),0,0],[math.sin(theta),math.cos(theta),0,0],[0,0,1,0],[0,0,0,1]]
for i in range(q):
	task = q[i]
	if (task[0] == 'S'):
		sx = task[1]
		sy = task[2]
		sz = task[3]
		s = [[sx,0,0,0],[0,sy,0,0],[0,0,sz,0],[0,0,0,1]]
		for i in range(len(x)):
			new = transform([x[i],y[i],z[i],1], s)
			x[i] = new[0]
			y[i] = new[1]
			z[i] = new[2]
	if (task[0] == 'T'):
		tx = task[1]
		ty = task[2]
		tz = task[3]
		t = [[1,0,0,tx],[0,1,0,ty],[0,0,1,tz],[0,0,0,1]]
		for i in range(len(x)):
			new = transform([x[i],y[i],z[i]], t)
			x[i] = new[0]
			y[i] = new[1]
			z[i] = new[2]
	if (task[0] == 'R'):
		axis = task[1]
		theta = task[2]
		if (axis == 'x'):
			mat = [[1,0,0,0],[0,math.cos(theta),-math.sin(theta),0],[0,math.sin(theta),math.cos(theta),0],[0,0,0,1]]
		if (axis == 'y'):
			mat = [[math.cos(theta),0,math.sin(theta),0],[0,1,0,0],[-math.sin(theta),0,math.cos(theta),0],[0,0,0,1]]
		if (axis == 'z'):
			mat = [[math.cos(theta),-math.sin(theta),0,0],[math.sin(theta),math.cos(theta),0,0],[0,0,1,0],[0,0,0,1]]
		for i in range(len(x)):
			new = transform([x[i],y[i],z[i]], mat)
			x[i] = new[0]
			y[i] = new[1]
			z[i] = new[2]
file = open('output.txt', 'w')
ans = "Input: "+"\n"
ans = ans+"n = "+str(n)+"\n"
ans = ans+"x = "+str(x)+"\n"
ans = ans+"y = "+str(y)+"\n"
ans = ans+"z = "+str(z)+"\n"
ans = ans+"q = "+str(q)+"\n"
ans = ans+"Output = "+"\n"
ans = ans+str(x) + '\n' + str(y) + '\n' +  str(z)
file.write(ans)
file.close()


from dataclasses import dataclass, field
from nonebot import get_driver
# from nonebot.rule import to_me
from nonebot.params import CommandArg, RawCommand
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.plugin import on_command
import datetime
from time import strftime
from functools import lru_cache
from typing import Optional
import os
import json
import string
import random
from utils import qq_image

from .config import Config

global_config = get_driver().config
config = Config.parse_obj(global_config)
PLUGIN_DIR = os.path.dirname(os.path.abspath(__file__))
IMAGE_TMP_PATH = "/tmp"

OLD_FLOWER_DICT = {  # deprecated?
    "アイビー": "公正と信頼",
    "アイビーゼラニウム": "新しいチャレンジ",
    "葵": "（一般）豊穣"+"\n（白）女性の野心",
    "アカシア": "魂の不死",
    "アガパンサス": "知的な装い",
    "アグリモニー": "多才",
    "アゲラタム": "深い信頼",
    "朝顔": "（一般）偉大なる友情"+"\n（白）喜び溢れ",
    "アザミ": "独立",
    "アザレア": "（一般）愛で満たされる"+"\n（白）節制",
    "紫陽花": "移り気",
    "アスター": "信じる心",
    "アスペン": "自信と勇気",
    "アッツ桜": "無意識",
    "アネモネ": "（一般）遊び"+"\n（赤）君を愛する",
    "アベリア": "謙虚",
    "アマリリス": "おしゃべり",
    "あやめ": "優雅",
    "アルストロメリア": "小悪魔的な思い",
    "アロエ": "万能",
    "杏": "臆病",
    "アンスリウム": "強い印象",
    "苺": "尊重と愛情",
    "イチゴノキ": "あなただけを愛します",
    "イベリス": "心を惹きつける",
    "インパチェンス": "流れるままに",
    "ウィンターグリーン": "際立った個性",
    "梅": "澄んだ心",
    "エーデルワイス": "尊い記憶",
    "エキナセア": "痛みを癒す",
    "エビネ": "真実",
    "エリカ": "（一般）自立"+"\n（クリスマスパレード）沈黙",
    "エレモフィラ": "あこがれの人",
    "オオイヌノフグリ": "神聖",
    "オーク": "（木）強さ"+"\n（葉）勇敢さ",
    "オシロイバナ": "臆病な愛",
    "オステオスペルマム": "心身の健康",
    "オダマキ": "（一般）勝利の誓い"+"\n（赤）素直",
    "オドントグロッサム": "特別な存在",
    "オニユリ": "富の蓄積",
    "オリーブ": "平和",
    "オレンジ": "花嫁の喜び",
    "カーネーション": "（一般）神の愛"+"\n（ピンク）母の愛"+"\n（黄）ユニークな視点"+"\n（白）安定",
    "ガーベラ": "（一般）神秘的な美しさ"+"\n（スパイダー咲）崇高な美しさ"+"\n（ピンク）崇高美の探求"+"\n（赤）神秘的な魅力"+"\n（白）律儀"+"\n（オレンジ）続ける力"+"\n（黄）究極美",
    "楓": "寡黙",
    "カキツバタ": "幸運は必ず来る",
    "ガザニア": "天才",
    "ガジュマル": "沢山の幸せ",
    "かすみ草": "夢見心地",
    "カタバミ": "光輝く心",
    "カトレア": "成熟した大人の魅力",
    "ガマズミ": "愛は死より強し",
    "カモミール": "逆境に負けぬ強さ",
    "カラー": "（色）情熱と勇敢さ"+"\n（白）清純さ",
    "カランコエ": "幸せを告げる",
    "カルミア": "大きな希望",
    "カンナ": "情熱と快活",
    "カンパニュラ": "高貴",
    "桔梗": "変わらぬ愛",
    "菊": "（一般）王侯にふさわしい壮麗さ"+"\n（うら菊）熟考"+"\n（大菊）あなたを心から愛します。"+"\n（黄）いつも満たされる"+"\n（白）真実を求める"+"\n（紅）ダイナミック"+"\n（ポンポン咲き）嬉しい夢"+"\n（紫紅）社会への愛",
    "夾竹桃": "親友",
    "金魚草": "世話好き",
    "金木犀": "志の高い人",
    "銀木犀": "気高い人",
    "グズマニア": "あなたは完璧",
    "クチナシ": "幸せでとてもうれしい",
    "クマツヅラ": "魔法",
    "グラジオラス": "準備",
    "クリスマスベゴニア": "愛の告白",
    "クリスマスローズ": "私の心配をやわらげて",
    "クルクマ": "酔いしれる",
    "クレマチス": "心の美しさ",
    "クロッカス": "天真爛漫",
    "クロッサンドラ": "仲良し",
    "クローバー": "（一般）私のことを考えて"+"\n（四つ葉）望みがかなう",
    "黒百合": "独創的",
    "グロリオサ": "栄光に満ちた世界",
    "ケイトウ": "色褪せぬ恋",
    "月下美人": "ただ一度だけ会いたくて",
    "月桂樹": "栄光と勝利",
    "胡蝶蘭": "幸福が飛んでくる",
    "ゴールデンロッド": "用心",
    "コスモス": "乙女の心",
    "コデマリ": "品格",
    "ごぼう": "解放",
    "コリアンダー": "秘密の富",
    "桜": "精神美",
    "さくらんぼ": "真実の心",
    "ザクロ": "（花）円熟の美"+"\n（実）希望の成就",
    "山茶花": "ひたむきに愛します",
    "サフラン": "歓喜",
    "サボテン": "燃える心",
    "百日紅": "雄弁",
    "サルビア": "（赤）燃ゆる思い"+"\n（紫）尊敬",
    "サンセベリア": "永久",
    "サンビタリア": "私を見つめて",
    "シクラメン": "（一般）はにかみ"+"\n（赤）感情の手放し"+"\n（ピンク）憧れ",
    "杉": "雄大",
    "シネラリア": "快活",
    "シャクナゲ": "壮厳",
    "芍薬": "必ず来る幸福",
    "シャコバサボテン": "冒険心",
    "ジャスミン": "（アラビアンジャスミン・茉莉花）清浄無垢"+"\n（シルクジャスミン・ゲッキツ）正当な道"+"\n（一般）愛想の良さ"+"\n（マダガスカルジャスミン）私はあなたについていく",
    "ジュニパー": "長寿",
    "菖蒲（しょうぶ）": "適合",
    "ジンジャー": "信頼しています",
    "沈丁花": "栄光と不滅",
    "シンビジウム": "（白）高貴な人"+"\n（ピンク）気取らない心",
    "スイートアリッサム": "価値あるもの",
    "スイートピー": "私を覚えていて",
    "水仙": "自己愛",
    "睡蓮": "清純な心",
    "スウィートチェストナット": "正当な扱い",
    "スカビオサ": "風情",
    "杉": "雄大",
    "すずらん": "純潔、自然な美しさ",
    "スターチス": "永遠に変わらぬ愛",
    "ステルンベルギア": "粘り強さ",
    "ストック": "（八重咲き）永遠の美"+"\n（一重咲き）逆境を克服",
    "ストレリチア": "気取った恋",
    "スノードロップ": "希望",
    "スノーフレーク": "汚れ無き心",
    "スミレ": "（青）直観に誠実"+"\n（黄）希少価値"+"\n（白）無垢"+"\n（紫）誠実"+"\n（野生）つれづれの恋",
    "スモモ": "約束を守って",
    "セージ": "家庭の徳",
    "セツブンソウ": "光輝",
    "ゼラニウム": "（一般）決心"+"\n（葉）努力家"+"\n（緋）好奇心",
    "セントジョーンズワート": "預言者",
    "セントポーリア": "小さな愛",
    "千日紅": "不滅の愛",
    "タイム": "勇気ある行動",
    "竹": "高い目標",
    "ダリア": "栄華と移り気",
    "タンジー": "滅びることのない愛",
    "ダンデライオン": "思わせぶり",
    "チコリ": "質素",
    "茶ノ木": "ユーモア",
    "チューブローズ": "危険な楽しみ",
    "チューリップ": "（白）観察力"+"\n（紫）この世の成功"+"\n（黄）名声"+"\n（一般）美しい瞳"+"\n（赤）永遠の愛"+"\n（パーロット咲）愛の表現",
    "チョコレートコスモス": "新しい恋のはじまり",
    "椿": "（赤）生来の価値"+"\n（寒椿）愛嬌"+"\n（白椿）愛らしさ",
    "露草": "波乱万丈",
    "ディアスキア": "私を許して",
    "デイジー": "（一般）無邪気"+"\n（黄）ありのまま"+"\n（白）自由で無邪気",
    "デルフィニウム": "変わりやすい心",
    "デンドロビウム": "わがままな美人",
    "デンファレ": "お似合いの二人",
    "トケイソウ": "聖なる愛",
    "トリカブト": "致命的なこと",
    "トルコキキョウ": "良い語らい",
    "トレニア": "魅力と誘惑",
    "梨の花": "愛の基盤",
    "ナズナ": "私のすべてをあなたに捧げます",
    "撫子": "内気",
    "菜の花": "前向き",
    "ニオイヒバ": "固い友情",
    "ニゲラ": "夢の中の恋",
    "ニチニチソウ": "楽しい思い出",
    "楡": "感受性",
    "ネメシア": "偽りのない心",
    "ネモフィラ": "愛国心",
    "ノウゼンカズラ": "花のある人生",
    "ノースポール": "自分に誠実",
    "バーベナ": "（一般）家族の和合"+"\n（赤）団結"+"\n（紫）真実を守る"+"\n（ピンク）未来",
    "ハイビスカス": "常に新しい美",
    "萩": "思案",
    "パキラ": "幸運",
    "ハクモクレン": "慈悲心",
    "バジル": "忍耐力と勇気",
    "蓮": "動じない心",
    "パセリ": "逆境からの勝利",
    "バッカリス": "開拓",
    "花菖蒲": "優美",
    "花虎ノ尾": "輝かしい実績",
    "ハナニラ": "出会い",
    "ハナミズキ": "私の思いを受け入れて",
    "ハニーサックル": "崇拝",
    "パフィオペディラム": "ユニークな視点",
    "葉牡丹": "利益",
    "薔薇": "（ダマスクローズ）照り映える容色"+"\n（蕾）希望、夢"+"\n（黒赤色）神秘"+"\n（バーガンディー）秘められた美"+"\n（白）私はあなたにふさわしい"+"\n（ベージュ）成熟した愛"+"\n（赤）愛、美"+"\n（黄）君のすべてが可憐"+"\n（ピンク）愛を誓う",
    "ハルジオン": "追憶の愛",
    "バレリアン": "善良",
    "パンジー": "（一般）私の胸はあなたのことでいっぱいです"+"\n（白）温順"+"\n（アプリコット）楽しい気分"+"\n（紫）愛の使者"+"\n（オレンジ）明朗快活"+"\n（黄）慎ましい幸せ",
    "バンダ": "ユニーク",
    "柊": "先見性がある",
    "ヒイラギモチ": "清廉",
    "ビオラ": "（白）真実に光を当てる"+"\n（紫）ゆるぎない魂",
    "彼岸花": "思い出",
    "ヒソップ": "聖性",
    "ビデンス": "美しい調和",
    "ひまわり": "（一般）光輝、尊敬"+"\n（イタリアンホワイト）あなたを思い続けます。",
    "百日草": "遠く離れた友",
    "ヒヤシンス": "（青）想像力"+"\n（黄）勝負"+"\n（白）心静かな愛"+"\n（ピンク）スポーツ、ゲーム"+"\n（紫）悲哀",
    "昼顔": "優しい愛情",
    "フィーバーフュー": "不死",
    "ブーゲンビリア": "ドラマチックな恋",
    "フェンネル": "称賛",
    "フクシア": "趣味",
    "福寿草": "幸福をつかむ",
    "藤の花": "あなたに夢中",
    "ブッドレア": "信仰心",
    "葡萄": "元気",
    "芙蓉": "繊細な美",
    "ブラキカム": "自由な美",
    "フリージア": "（一般）あどけなさ"+"\n（黄）澄んだ心",
    "ブリオニア": "幸せの選択",
    "プリムラ": "（一般）初恋"+"\n（赤）美の秘密"+"\n（白）正当"+"\n（オブコニカ）少年時代の希望"+"\n（ジュリアン）神秘的な心"+"\n（ポリアンサ）運命を切り開く"+"\n（桜草）若い時代と苦悩",
    "ブルーデイジー": "協力的",
    "プルメリア": "恵まれた人",
    "プルンバゴ": "美意識",
    "フロックス": "温和",
    "ベゴニア": "好きな人",
    "ヘザー": "（赤）頼もしい"+"\n（白）追求者",
    "ヘーゼル": "和解",
    "ペチュニア": "君といると心和む",
    "ベラドンナリリー": "美しさ",
    "ヘリオトロープ": "献身",
    "ペンタス": "希望の実現",
    "ポインセチア": "（赤）祝福する"+"\n（一般）私の心は燃えている"+"\n（白）洞察力",
    "鳳仙花": "エネルギッシュ",
    "ほおずき": "自然美",
    "ポーチュラカ": "チャーミング",
    "ボケ": "日々の幸せ",
    "牡丹": "富貴",
    "ポトス": "永遠の富",
    "ポピー": "デリケートな美",
    "ボリジ": "才能",
    "マーガレット": "（一般）恋の予言"+"\n（白）恋の行方"+"\n（ピンク）真実の愛"+"\n（黄）美しい容姿",
    "マロウ": "柔和な心",
    "マジョラム": "恥じらい",
    "マスタード": "チャレンジと成長",
    "松": "不老長寿",
    "マドンナリリー": "天界の美",
    "マネッチア": "沢山の話",
    "マリーゴールド": "太陽",
    "マンサク（満作・万作）": "ひらめき",
    "ミムラス": "援助の申し出",
    "ミモザ（ミモザアカシア）": "秘密の愛",
    "ミント": "有徳の人",
    "ムスカリ": "黙っていても通じる私の心",
    "メドウスイート": "心の支え",
    "木蓮": "崇高",
    "モミ": "高尚",
    "桃": "恋のとりこ",
    "モンステラ": "一途な幸せ",
    "ヤグルマギク": "天上の人",
    "矢車薄荷": "柔らかな心",
    "柳": "（一般）従順"+"\n（シダレヤナギ）嘆き",
    "山吹": "ずっと待っていました",
    "ヤロウ": "治癒",
    "ユーカリ": "記憶",
    "雪割草": "信頼",
    "ユーフォルビア": "協力を得る",
    "百合": "純粋さ",
    "ユリオプスデイジー": "円満",
    "夜顔": "夕暮れの思い出",
    "ライム": "刺激",
    "ライラック": "（一般）私をまだ愛してますか"+"\n（白）美しい契り",
    "ラナンキュラス": "輝く魅力",
    "ラブダナム": "注目",
    "ラベンダー": "期待",
    "蘭": "勤勉",
    "ランタナ": "心変わり",
    "リカステ": "汚れなき人",
    "リナリア": "私の恋を知って",
    "りんご": "偉大",
    "リンコスティリス": "大胆",
    "リンドウ": "甘い夢",
    "ルドベキア": "公平",
    "ルバーブ": "忠告",
    "ルピナス": "多くの仲間",
    "レディースマントル": "ファッション",
    "レモン": "愛の忠誠",
    "レモンバーベナ": "神聖",
    "蝋梅": "慈愛",
    "ローズマリー": "あなたは私を蘇らせる",
    "ローダンセ": "ロマンチックな愛",
    "ロベリア": "いつも可愛らしい",
    "ワイルドストロベリー": "徳の成果",
    "勿忘草 （忘れな草）": "私を忘れないで",
    "吾亦紅（ワレモコウ）": "移り行く日々",
}

def random_str(length):  # FIXME: duplicated, moved to help_func.py
    """Generate random a string consists with a-zA-z0-9 with a given length"""
    letters = string.ascii_lowercase + string.ascii_uppercase + string.digits
    return ''.join(random.choice(letters) for _ in range(length))

@dataclass
class Flower:
    image: str | bytes = ""
    name: str = ""
    desc: str = ""
    kotoba: list[str] = field(default_factory=lambda: [])
    aliases: str = ""
    familia: str = ""
    period: str = ""
    birthday: str = ""

with open(os.path.join(PLUGIN_DIR, "flowers.json"), "r", encoding="utf8") as f:
    flowers_json = json.load(f)

FLOWERS: dict[str|int,Flower] = {
    k:Flower(**v, image=os.path.join(PLUGIN_DIR, "images", f"hana_{k}.jpg")) for k, v in flowers_json.items()}
# print(FLOWERS)

hnktb = on_command("花语", aliases={"hanakotoba", "花言叶", "花言葉", "今日花语"})

def day_hash(day: datetime.date | None = None) -> int:
    if day is None:
        day = datetime.date.today()
    hash = day.strftime('%y%m%d')
    return int(hash*37)

@hnktb.handle()
async def handle_hnktb(matcher: Matcher, arg: Message = CommandArg(), command = RawCommand()):
    # FIXME: duplicated to zju_info plugins
    def show_if_exist(obj, template: str = "{}") -> str:
        return template.format(obj) if obj else ""
    flower = arg.extract_plain_text()
    if flower:
        if flower in OLD_FLOWER_DICT:
            send_text = f"「{flower}」の花言葉：\n{OLD_FLOWER_DICT.get(flower)}"
        else:
            send_text = "未找到对应花语：请尽量使用片假名哦"
    else:
        index = day_hash() if "今日" in command else random.randint(0, len(FLOWERS)-1)
        today_flower = FLOWERS.get(list(FLOWERS.keys())[index % len(FLOWERS)], Flower())
        image = qq_image.handlers['hanakotoba'](
            image=today_flower.image,
            kotobas=today_flower.kotoba,
            name=today_flower.name,
            desc=show_if_exist(today_flower.aliases, "別名：{}\n") +
            show_if_exist(today_flower.birthday, "誕生日{}の花\n") +
            show_if_exist(today_flower.period, "開花期：{}\n") +
            show_if_exist(today_flower.familia, "科名：{}\n") +
            show_if_exist(today_flower.desc, "{}"))
        # today_hash = day_hash()
        # today_flower = list(OLD_FLOWER_DICT.keys())[
        #     today_hash % len(OLD_FLOWER_DICT)]
        # send_text = f"今日花语\n{today_flower}:{OLD_FLOWER_DICT.get(today_flower)}"
        image_path = f"{IMAGE_TMP_PATH}/tmp_{random_str(6)}.png"
        # TODO: using a context manager to delete tmp file
        image.save(image_path)
        await matcher.send(MessageSegment.image("file://" + image_path))
        os.remove(image_path)
        return
    send_text = str(send_text)
    await hnktb.send(message=send_text)


"""
    settings.py
"""

# Game field (half) size
HALF_SIZE_X = 20
HALF_SIZE_Y = 12
# field layout settings
BRICK_FRACTION = 0.025
NUM_FOOD_ITEMS = 3

# Timeouts and waiting times
RECEIVE_TIMEOUTS_MS = 5
SLEEP_BETWEEN_READS_MS = 1


import json, re, random

def preprocess_input(input_text):
    # Tokenize and preprocess the input by converting to lowercase and removing punctuation
    return re.sub(r'[^\w\s]', '', input_text.lower()).split()

def identify_intent(input_tokens, intents_data):
    # Iterate through each intent and its patterns
    for intent in intents_data["intents"]:
        for pattern in intent["patterns"]:
            pattern_tokens = preprocess_input(pattern)
            # Check if the input_tokens contain all the tokens in the pattern
            if all(token in input_tokens for token in pattern_tokens):
                return intent["tag"], intent["follow_up_questions"]

    # If no intent is matched, return a default intent
    return "default", []

# Load the intents data from intents.json
with open("mysite/chatbotFiles/intents.json", "r") as file:
    intents_data = json.load(file)

def get_response(intent_tag):
    # Get the appropriate response for the identified intent
    for intent in intents_data["intents"]:
        if intent["tag"] == intent_tag:
            response = intent["responses"]
            return response
            break

# If there are follow-up questions, ask them
#if follow_up_questions:
#    for question in follow_up_questions:
#        user_response = input("Bot: " + question + " ")
#        # Process user's response to follow-up questions as needed

def get_cr_ev_followup_questions():
    cr_ev_followup_questions = ['What do you want your Event Title to be?',
                                'What is the Date for this Event?',
                                'What is the start time for this event? Include AM/PM',
                                'What is the end time for this event? Include AM/PM',
                                'You can customize your event more in a few seconds...']
    return cr_ev_followup_questions

def get_help_login_followup_questions():
    help_login_followup_questions = [
            "What is your email?",
            "What is your password?"
        ]
    return help_login_followup_questions

def get_intent_tag(message):
    input_tokens = preprocess_input(message)
    intent_tag, follow_up_questions = identify_intent(input_tokens, intents_data)
    return intent_tag

def user_input(message, page):
    intent_tag = get_intent_tag(message)
    if page != 'login_page':
        if intent_tag != 'create_event' and intent_tag != 'default':
            possible_responses = get_response(intent_tag)
            return random.choice(possible_responses)
        else:
            return 'null'
    elif page == 'login_page':
        if intent_tag == 'create_event':
            return "You can only create events after you have logged in to your home page"
        if intent_tag == 'help':
            return "I can only assist you with logging in. Type 'log in' for my assistance"
        elif intent_tag == 'default':
            return "null"
        else:
            possible_responses = get_response(intent_tag)
            return random.choice(possible_responses)


class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        N = len(grid)
        M = len(grid[0])
        ans = 0

        def dfs(r,c):
            if r < 0 or c < 0 or r >= N or c >= M or grid[r][c] == 0:
                return 0
            grid[r][c] = 0
            return 1 + dfs(r-1,c) + dfs(r+1,c) + dfs(r, c-1) + dfs(r, c+1)

        for i in range(N):
            for j in range(M):
                if grid[i][j] == 0:
                    continue
                ans = max(ans, dfs(i,j))
        return ans


from .astronomy_object_type import AstronomyObjectType
from .astronomy_day import AstronomyDay
from .astronomy_current import AstronomyCurrent
from libtad.common.exceptions import MalformedXMLException
import xml.etree.ElementTree as ET
from typing import List

class AstronomyObjectDetails:
    """
    A class used to store astronomy objects

    ...

    Attributes
    ----------
    name : AstronomyObjectType
        Object name.
    days : list of AstronomyDay
        astronomy service: Lists all the requested days where events are happening.

        astrodata service: N/A
    current : AstronomyCurrent
        astronomy service: The current data for the object. Only if requested.

        astrodata service: N/A
    current : list of AstronomyCurrent
        astronomy service: N/A

        astrodata service: The specific data for the object at isotime/utctime.

    """

    def __init__(self, node: ET.Element):
        self.name: AstronomyObjectType = AstronomyObjectType(0)
        self.days: List[AstronomyDay] = None
        self.current: AstronomyCurrent = None
        self.result: List[AstronomyCurrent] = None

        name = node.get("name")
        days = node.findall("day")
        current = node.find("current")
        results = node.findall("result")

        if name and name.capitalize() in AstronomyObjectType.__members__:
            self.name = AstronomyObjectType[name.capitalize()]
        else:
            raise MalformedXMLException(name)

        if days:
            self.days = [AstronomyDay(day) for day in days]

        if current is not None:
            self.current = AstronomyCurrent(current)

        if results:
            self.result = [AstronomyCurrent(result) for result in results]


#!/usr/bin/env python3
import math
import argparse
import random
import credb
import traceback
from multiprocessing import Process
from test import *

parser = argparse.ArgumentParser()
parser.add_argument("--server_port", type=int, default=5042)
parser.add_argument("--no_server", action="store_true")
parser.add_argument("--num_calls", type=int, default=1000)
parser.add_argument("--num_clients", type=int, default=10)
parser.add_argument("--verbose", action="store_true")

args = parser.parse_args()

if args.no_server:
    server = None
else:
    server = Testserver()
    server.start(args.server_port, quiet=(not args.verbose))

func = """
val = int(argv[0])
return (val % 2) == 0"""

def run_calls(pos):
    conn = create_test_client(server="localhost", port=args.server_port, name="testclient" + str(pos))
    c = conn.get_collection('test')

    for i in range(args.num_calls):
        res = c.call("func", [str(i)])
        assert_equals(res, i % 2 == 0)

def setup_server():
    conn = credb.create_client("c", "testserver", "localhost", port=args.server_port)
    c = conn.get_collection('test')
    c.put_code("func", func)

def run_test():
    print("Setting up server")
    p0 = Process(target=setup_server)
    p0.start()
    p0.join()
    print("Running call operations")
    processes = []
    count = 0

    for i in range(args.num_clients):
        p = Process(target=run_calls, args=[i])
        p.start()
        processes.append(p)

    exitcode = 0
    for p in processes:
        count += 1
        p.join()
        if p.exitcode:
            exitcode = p.exitcode
    return exitcode

p = Process(target=run_test)
p.start()
p.join()

if server:
    server.stop()
exit(p.exitcode)


## the attack on the genome data
from util import Embedder
import numpy as np
from sklearn.svm import SVC, LinearSVC
from sklearn import linear_model
import torch
import torch.utils.data as data_utils
import torch.optim as optim
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import GRU, Embedding, Linear
import random
from tqdm import tqdm
from pathlib import Path
from sklearn.ensemble import RandomForestClassifier
import argparse
from pytorch_revgrad import RevGrad
from sklearn.decomposition import PCA
from scipy.stats import describe
from scipy.spatial.distance import pdist
from scipy.spatial import cKDTree
from sklearn.manifold import MDS
from numpy import linalg as LA
from defense import initialize_defense

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()

parser = argparse.ArgumentParser(description='Genome Attack')
parser.add_argument("-p", type=int, default= 5555, help = 'the comm port the client will use')
parser.add_argument("-c", action='store_true', help = 'whether to use cached model')
parser.add_argument("-t", action='store_true', help = "to switch between training or testing")
parser.add_argument("--save_p", type=str, default="default", help = 'the place to store the model')
parser.add_argument("-a", type=str, default='bert', help = 'targeted architecture')
parser.add_argument("-d", type=str, default='none', help = 'the type of defense to do')
ARGS = parser.parse_args()

TOTAL_LEN = 20

# The attacker model, which is used to infer the genetic subsequence at a fixed interval (a 4)
TABLE = {
    "A": 0,
    "G": 1,
    "C": 2,
    "T": 3
    }
REVERSE_TABLE  = ["A", "G", "C", "T"]
EMB_DIM_TABLE = {
    "bert": 768,
    'bert-large': 1024,
    'gpt' : 768,
    'gpt-2': 768,
    'transformer-xl': 1024,
    'xlnet': 768,
    'xlm': 1024,
    'roberta': 768,
    'ernie': 768,
    "gpt-2-medium": 1024,
    "gpt-2-large": 1280
    }
INTERVAL_LEN = 1

ARCH = ARGS.a

POS_EMBED_DIM = EMB_DIM_TABLE[ARCH]

#

TRUNCATE_RATIO = 0.1

embedder = Embedder(ARGS.p)
embedding = embedder.embedding # export the functional port

COUNTER = 0

offline_archs = ['transformer-xl']
# offline_archs = []

if(ARCH in offline_archs):
    # construct the transformer
    batch_size = 512
    z = torch.FloatTensor(np.load('{}.z.npy'.format(ARCH)))
    y = torch.LongTensor(np.load('{}.y.npy'.format(ARCH)))
    # to do some truncating
    batch_num = z.shape[0] // batch_size
    print(batch_num)
    ARGS.save_p += ".{:.1f}".format(TRUNCATE_RATIO)
    current_batch_num = int(batch_num * TRUNCATE_RATIO)
    print("Batch Size {}/{}".format(current_batch_num, batch_num))
    #

    xl_dataset = data_utils.TensorDataset(z, y)
    xl_dataloader = data_utils.DataLoader(xl_dataset, batch_size = batch_size, shuffle = True)
    xl_dataloader = [(z, y) for z, y in xl_dataloader]
    print(len(xl_dataloader))

def explate(seq):
    out = ""
    for c in seq:
        out = out + c + ' '
    return out[:-1]

def extract_genomes(path):
    f = open(path, 'r')
    out = []
    for i in range(4): next(f)
    for line in f:
        line = line.split(' ')
        out.append(line[-1][:TOTAL_LEN])
    return out
## extraction
def _extract_genomes(path):
    f = open(path, 'r')
    out = []
    for i in range(4): next(f)
    for line in f:
        line = line.split(' ')
        out.append(line[-1][:TOTAL_LEN])
    return out

def dump(sents, path):
    f = open(path, 'w+')
    for sent in sents:
        f.write(sent + '\n')
    f.close()

def prepare_raw_datasets():
    TRUE_PATH = "data/acceptor_hs3d/IE_true.seq"
    F_PATH_PAT = "data/acceptor_hs3d/IE_false.seq.00{}"
    true_akpt = extract_genomes(TRUE_PATH)
    false_akpt = []
    for i in range(1, 5):
        false_akpt.extend(extract_genomes(F_PATH_PAT.format(i)))
    # random select 1:10 false samples
    false_akpt = np.random.choice(false_akpt, size = 10 * len(true_akpt), replace = False).tolist()
    print("# of Positive Samples: {}".format(len(true_akpt)))
    print("# of Negative Samples: {}".format(len(false_akpt)))
    print(len(true_akpt[0]))
    print(len(false_akpt[0]))
    # dump(true_akpt, "data/acceptor_hs3d/genome.1.txt")
    # dump(false_akpt, "data/acceptor_hs3d/genome.0.txt")
    return true_akpt, false_akpt

def load_raw_datasets():
    true_akpt = [s[:-1] for s in open("data/acceptor_hs3d/genome.1.txt", 'r')]
    false_akpt = [s[:-1] for s in open("data/acceptor_hs3d/genome.0.txt", 'r')]
    return true_akpt, false_akpt

def train_test_split(embs, ratio = 0.9):
    np.random.shuffle(embs)
    train = embs[:int(ratio * len(embs))]
    test = embs[int(ratio*len(embs)):]
    return train, test

def construct_datasets(arch = 'bert'):
    embedding_path = "data/acceptor_hs3d/IE.{}"
    true_akpt, false_akpt = load_raw_datasets() # prepare_raw_datasets()

    true_embeddings = embedding(true_akpt, embedding_path.format(1), arch, False)
    false_embeddings = embedding(false_akpt, embedding_path.format(0), arch, False)
    return

class GenomeClassifier(nn.Module):
    def __init__(self, embedding_size):
        super(GenomeClassifier, self).__init__()
        hidden_size = 200
        self.mlp = nn.Sequential(Linear(embedding_size, hidden_size),
                                     nn.Sigmoid(),
                                     Linear(hidden_size, 2))
        self.criterion = nn.CrossEntropyLoss()

    def forward(self, x):
        return self.mlp(x)

    def predict(self, x):
        outputs = self(x)
        _, preds = torch.max(outputs, 1)
        return preds.cpu().numpy()

    def train(self, X, Y, test_X, test_Y):
        X = torch.FloatTensor(X)
        Y = torch.LongTensor(Y)
        test_X = torch.FloatTensor(test_X).cuda()
        dataset = data_utils.TensorDataset(X, Y)
        dataloader = data_utils.DataLoader(dataset, batch_size = 128, shuffle = True)
        optimizer = optim.Adam(self.parameters(), lr = 0.001)
        self.cuda()
        running_loss = 0.0
        PRINT_FREQ = 100
        counter = 0
        max_epoch = 100
        best_acc = 0.5
        for i in range(max_epoch):
            for x, y in dataloader:
                x, y = x.cuda(), y.cuda()
                loss = self.criterion(self(x), y)
                # print(loss)
                running_loss += loss.data
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                counter += 1
                if(counter % PRINT_FREQ == 0):
                    running_loss /= PRINT_FREQ
                    preds = self.predict(test_X)
                    acc = np.mean(preds == test_Y)
                    print("Iteration {}: Loss {:.4f} Acc: {:.4f}".format(counter, running_loss, acc))
                    running_loss = 0.0
                    if(acc > best_acc):
                        best_acc = acc
                        torch.save(self.state_dict(), "functional.genome.{}.cpt".format(ARCH))
                        print("save best acc. {:.4f}".format(best_acc))

# let us just test svm
def predict(embedding_path = "data/acceptor_hs3d/IE.{}"):
    true_akpt, false_akpt = load_raw_datasets()
    if(ARCH == 'transformer-xl'):
        true_akpt = [explate(x) for x in true_akpt]
        false_akpt = [explate(x) for x in false_akpt]
    true_embeddings = embedding(true_akpt, embedding_path.format(1), ARCH)
    false_embeddings = embedding(false_akpt, embedding_path.format(0), ARCH)[:len(true_embeddings),:]
    print(true_embeddings)
    print(false_embeddings)
    # do a train test split
    train_1, test_1 = train_test_split(true_embeddings)
    train_0, test_0 = train_test_split(false_embeddings)
    print("# of train_0: {}".format(len(train_0)))
    print("# of train_1: {}".format(len(train_1)))
    print("# of test_0: {}".format(len(test_0)))
    print("# of test_1: {}".format(len(test_1)))
    # clf = linear_model.SGDClassifier(max_iter=1000, tol=1e-5, verbose = 1)
    # clf = LinearSVC(verbose = 1, max_iter = 5000)
    clf = GenomeClassifier(true_embeddings.shape[1])
    train_x = np.concatenate([train_0, train_1], axis = 0)
    test_x = np.concatenate([test_0, test_1], axis = 0)
    train_y = np.array([0] * len(train_0) + [1] * len(train_1))
    test_y = np.array([0] * len(test_0) + [1] * len(test_1))
    clf.train(train_x, train_y, test_x, test_y)
    # clf.fit(train_x, train_y)
    # preds = clf.predict(test_x)
    # print(np.sum(preds))
    # true_p = np.mean(preds[test_y == 1])
    # false_p = np.mean(1 - preds[test_y == 1])
    # print('ACC: {:.4f} TP: {:.4f} FP: {:.4f}'.format(np.mean(preds == test_y), true_p, false_p))

def get_positional_embedding(d_pos_vec, n_position):
    position_enc = np.array([
    [pos / np.power(10000, 2*i/d_pos_vec) for i in range(d_pos_vec)]
    if pos != 0 else np.zeros(d_pos_vec) for pos in range(n_position)])

    position_enc[1:, 0::2] = np.sin(position_enc[1:, 0::2]) # dim 2i
    position_enc[1:, 1::2] = np.cos(position_enc[1:, 1::2]) # dim 2i+1
    return position_enc

POS_EMBEDDING = get_positional_embedding(POS_EMBED_DIM, TOTAL_LEN)

def seq2id(s):
    return TABLE[s]

def id2seq(val):
    s = np.base_repr(val, base = 4).zfill(INTERVAL_LEN)
    return "".join([REVERSE_TABLE[int(c)] for c in s])

def gen(target = 0):
    # @param target: which specifies the inverval to infer (i.e. [target, target + inverval_LEN))
    # key = [random.choice(REVERSE_TABLE) for i in range(target, target+INTERVAL_LEN)]
    seq = [random.choice(REVERSE_TABLE) for i in range(TOTAL_LEN)]
    return [("".join(seq), seq2id(seq[target])), target]

CENTERS = []
PLOTTED = False
CONCAT = True

def generate_offline_training_data(total_number, batch_size = 64, pos_embedding = POS_EMBEDDING):
    z = []
    y = []

    for idx in tqdm(range(total_number // batch_size)):
        batch = []
        TARGETS = list(range(TOTAL_LEN))
        for i in range(batch_size):
            target = random.choice(TARGETS)
            batch.append(gen(target))
        z_ = embedding([explate(b[0][0]) for b in batch], "tmp", ARCH, cached = False)
        y.extend([b[0][1] for b in batch])
        pos_embeddings = np.array([pos_embedding[b[1]] for b in batch])
        if(CONCAT):
            z_ = np.concatenate([z_, pos_embeddings], axis = 1)
        else:
            z_ = z_ + pos_embeddings
        z.append(z_)
    z = np.concatenate(z, axis = 0)
    y = np.array(y)
    # save the numpy file
    np.save(open("{}.z.npy".format(ARCH), 'w+b'), z)
    np.save(open("{}.y.npy".format(ARCH), 'w+b'), y)

    return z, y

"""
Now the batch consists of (seq, id, positional_embedding)
"""
def get_batch(batch_size = 10, is_offline = False, dataloader = None, pos_embedding = POS_EMBEDDING):
    global COUNTER
    if(is_offline):
        z, y = dataloader[COUNTER]
        COUNTER = (COUNTER+1) % len(dataloader)
        z, y = random.choice(dataloader)
        return z, y, None
    batch = []
    TARGETS = list(range(TOTAL_LEN))
    for i in range(batch_size):
        target = random.choice(TARGETS)
        batch.append(gen(target))
    # for i in range(batch_size):
    #     target = random.choice(TARGETS)
    #     batch.append([gen(target), target])
    z = embedding([b[0][0] for b in batch], "tmp", ARCH, cached = False)
    pos_embeddings = np.array([pos_embedding[b[1]] for b in batch])
    if(CONCAT):
        z = np.concatenate([z, pos_embeddings], axis = 1)
    else:
        z = z + pos_embeddings
    # z = z + pos_embeddings
    # to centralize the embeddings
    y = [b[0][1] for b in batch]
    z = torch.FloatTensor(z)
    y = torch.LongTensor(y)
    # print(z.shape)
    return z, y, [b[0][0] for b in batch]

def get_batch_ground_truth(target = 0, batch_size = 10, use_defense = False ,defense = None, arch = ARCH, pos_embedding = POS_EMBEDDING):
    embedding_path = "data/acceptor_hs3d/IE.{}"
    # TRUE_PATH = "data/acceptor_hs3d/IE_true.seq"
    y_1 = [s[:-1] for s in open("data/acceptor_hs3d/genome.1.txt", 'r')]
    y_0 = [s[:-1] for s in open("data/acceptor_hs3d/genome.0.txt", 'r')]
    y_1 = y_1[:batch_size]
    y_0 = y_0[:batch_size]
    y = y_1 + y_0

    if(arch == 'transformer-xl'):
        y_0 = [explate(x) for x in y_0]
        y_1 = [explate(x) for x in y_1]
    # print(len(y))
    z_1 = embedding(y_1, embedding_path.format(1), arch)[:batch_size, :]
    z_0 = embedding(y_0, embedding_path.format(0), arch)[:batch_size, :]
    # print(z_1.shape)
    # print(z_0.shape)
    z = np.concatenate([z_1, z_0], axis = 0)

    utility_y = np.array([1]*batch_size + [0]*batch_size)

    # the sensitive y
    y = [seq2id(x[target:target+INTERVAL_LEN]) for x in y]

    # seems a bug here
    if(use_defense):
        z = defense(z, y) # add the defense
    raw_z = z
    ## obtain the correposnding positional embedding
    pos_embeddings = np.array([pos_embedding[target] for i in range(2*batch_size)])
    if(CONCAT):
        z = np.concatenate([z, pos_embeddings], axis = 1)
    else:
        z = z + pos_embeddings
    # y = _extract_genomes(TRUE_PATH)[:batch_size]

    z = torch.FloatTensor(z)
    y = torch.LongTensor(y)
    return z, y, utility_y, raw_z

class Classifier(nn.Module):
    def __init__(self, embedding_size, hidden_size, cls_num = 12, device = torch.device('cuda:0')):
        super(Classifier, self).__init__()
        self.encoder = nn.Sequential(Linear(embedding_size, 400),
                                     nn.BatchNorm1d(400),
                                        nn.Sigmoid(),
                                     Linear(400, 100),
                                        nn.Sigmoid(),
                                     nn.BatchNorm1d(100))

        self.classifier = Linear(100, cls_num)
        self.device = device
        self.criterion = nn.CrossEntropyLoss()
        print(cls_num)

    def forward(self, x):
        x = self.classifier(self.encoder(x))
        return x

    def predict(self, x):
        outputs = self(x)
        _, preds = torch.max(outputs, 1)
        return preds.cpu().numpy()

    def predict_topk(self, x, k = 5):
        with torch.no_grad():
            probs = self(x)
            _, topk = torch.topk(probs, k)
        return topk.cpu().numpy()

    def loss(self, x, y):
        x = self(x)
        _loss = self.criterion(x, y)
        return _loss

    def evaluate(self, x, y):
        with torch.no_grad():
            preds = self.predict(x)
            y = y.numpy()
            # print(np.histogram(y))
            # print(np.histogram(preds))
        return np.mean(preds == y)

    def evaluate_topk(self, x, y, k = 5):
        y = y.numpy()
        with torch.no_grad():
            probs = self(x)
            _, topk = torch.topk(probs, k)
            topk = topk.cpu().numpy()
            acc = [int(y[i] in topk[i, :]) for i in range(len(y))]
        return np.mean(acc)

DEVICE = torch.device('cuda:0')

def train_attacker(target = 0, path = None):
    TARGET = target
    CLS_NUM = 4 ** INTERVAL_LEN
    print("INFER GENE SUBSEQ [{}, {}) CLS NUMBER {}".format(TARGET, TARGET + INTERVAL_LEN, CLS_NUM))
    MAX_ITER = 100000
    CACHED = False
    PRINT_FREQ = 10000

    TEST_SIZE = 1000
    HIDDEN_DIM = 200
    BATCH_SIZE = 128 # 128 #64
    TRUTH = True
    EMB_DIM = EMB_DIM_TABLE[ARCH]
    PATH = path
    best_acc = 0.0
    K = 2
    if(CONCAT):
        emb_dim = EMB_DIM + POS_EMBED_DIM
    else:
        emb_dim = EMB_DIM
    classifier = Classifier(emb_dim, HIDDEN_DIM, CLS_NUM, DEVICE)
    if(CACHED and Path(PATH).exists()):
        print("Loading Model...")
        classifier.load_state_dict(torch.load(PATH, map_location = DEVICE))
    classifier = classifier.cuda()

    if(TRUTH):
        test_x, test_y, _, _ = get_batch_ground_truth(TARGET, TEST_SIZE)
    else:
        test_x, test_y, _ = get_batch(TEST_SIZE)

    test_x = test_x.cuda()
    # optimizer = optim.SGD(classifier.parameters(), lr = 0.01)
    optimizer = optim.Adam(classifier.parameters(), lr = 0.001)
    running_loss = 0.0

    acc = classifier.evaluate(test_x, test_y)
    topk_acc = classifier.evaluate_topk(test_x, test_y, k = K)
    print("Iteration {} Loss {:.4f} Acc.: {:.4f} Top-{} Acc.: {:.4f}".format(0, running_loss/PRINT_FREQ, acc, K, topk_acc))
    evaluate("", ARCH, None, given_clf = True, clf = classifier)
    for i in tqdm(range(MAX_ITER)):
        if(not ARCH in offline_archs):
            x, y, _ = get_batch(BATCH_SIZE)
        else:
            x, y, _ = get_batch(BATCH_SIZE, is_offline = True, dataloader = xl_dataloader)
        x, y = x.cuda(), y.cuda()
        optimizer.zero_grad()
        loss = classifier.loss(x, y)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()

        if((i + 1) % PRINT_FREQ == 0):
            acc = classifier.evaluate(test_x, test_y)
            topk_acc = classifier.evaluate_topk(test_x, test_y, k = K)
            print("Iteration {} Loss {:.4f} Acc.: {:.4f} Top-{} Acc.: {:.4f}".format(i+1, running_loss/PRINT_FREQ, acc, K, topk_acc))
            evaluate("", ARCH, None, given_clf = True, clf = classifier)
            running_loss = 0.0
            # print(raw[:4])
            # print(y[:4])
            if(acc >= best_acc):
                best_acc = acc
                torch.save(classifier.state_dict(), PATH)
                print("save model acc. {:.4f}".format(best_acc))
                if(best_acc > 0.99):
                    break
    return best_acc

def train_random_forest(target = 0):
    train_sample_num = 10000
    test_sample_num = 1000
    test_x, test_y, _ = get_batch_ground_truth(target, test_sample_num)
    x, y, _ = get_batch(target, train_sample_num)
    x, y = x.numpy(), y.numpy()
    test_x, test_y = test_x.numpy(), test_y.numpy()
    clf = RandomForestClassifier(n_estimators = 100)
    # clf = SVC()
    clf.fit(x, y)
    preds = clf.predict(test_x)
    acc = np.mean(preds == test_y)
    print("Target {} -- Top-1 Acc. {:.4f}".format(target, acc))
    return acc

def evaluate(path, arch, defense = None, given_clf = False, clf = None):
    pos_embed_dim = EMB_DIM_TABLE[arch]
    local_pos_embedding =  get_positional_embedding(pos_embed_dim, TOTAL_LEN)
    TEST_SIZE = 1000
    EMB_DIM = EMB_DIM_TABLE[arch]

    if(CONCAT):
        emb_dim = EMB_DIM + pos_embed_dim
    else:
        emb_dim = EMB_DIM
    # print(emb_dim)
    CLS_NUM = 4
    if(not given_clf):
        classifier = Classifier(emb_dim, 0, CLS_NUM, DEVICE)
        classifier.load_state_dict(torch.load(path, map_location = DEVICE))
        print("Loading Model from {} ...".format(path))
        classifier = classifier.cuda()
        classifier.eval() # this line is important, to deactivate the effect of the batch normalization
    else:
        classifier = clf
        clf.eval()

    average_acc = 0.0
    average_topk_acc =0.0
    avg_util  = 0.0
    protected_avg_acc = 0.0
    protected_avg_topk_acc = 0.0
    protected_avg_util = 0.0

    print("Loading the Utility Model ")
    genome_clf_path = "checkpoints/functional.genome.{}.cpt".format(arch)

    genome_clf = GenomeClassifier(EMB_DIM)
    # print(EMB_DIM)

    # genome_clf.load_state_dict(torch.load(genome_clf_path, map_location = DEVICE))
    genome_clf.cuda()

    # defense = initialize_defense('rounding', decimals = 1)
    # defense = initialize_defense('dp', delta = 12.0, eps = 20.0)
    # defense = initialize_defense('minmax', cls_num = 2, eps = 0.001)
    atk_acc_arr = []
    protected_acc_arr = []
    baseline_acc = []

    for target in range(0, TOTAL_LEN):
        test_x, test_y, test_util_y, raw_x = get_batch_ground_truth(target, TEST_SIZE, arch = arch, pos_embedding = local_pos_embedding)
        # impose the defense with raw_x and the test util_y
        histg = np.histogram(test_y, bins = 4)
        baseline_acc.append(max(histg[0] / np.sum(histg[0])))

        test_x = test_x.cuda()
        acc = classifier.evaluate(test_x, test_y)
        topk_acc = classifier.evaluate_topk(test_x, test_y, k = 2)
        average_acc += acc
        average_topk_acc += topk_acc
        raw_x = torch.FloatTensor(raw_x).cuda()
        preds = genome_clf.predict(raw_x)
        util_acc = np.mean(preds == test_util_y)
        avg_util += util_acc

        atk_acc_arr.append(acc)

        protected_util_acc, protected_acc, protected_topk_acc = 0.0, 0.0, 0.0
        if(defense):
            protected_test_x, _, _, protected_raw_x = get_batch_ground_truth(target, TEST_SIZE, True, defense, arch = arch, pos_embedding = local_pos_embedding)
            protected_test_x = torch.FloatTensor(protected_test_x).cuda()
            protected_acc = classifier.evaluate(protected_test_x, test_y)
            protected_topk_acc = classifier.evaluate_topk(protected_test_x, test_y, k = 2)
            protected_avg_acc += protected_acc
            protected_avg_topk_acc += protected_topk_acc
            protected_raw_x = torch.FloatTensor(protected_raw_x).cuda()
            preds = genome_clf.predict(protected_raw_x)
            protected_util_acc = np.mean(preds == test_util_y)
            protected_avg_util += protected_util_acc
            protected_acc_arr.append(protected_acc)

        # print("Util Acc: {:.4f} Protected Util Acc.: {:.4f} TARGET INDEX {} ACC: {:.4f} TOP-2: {:.4f} Protected: {:.4f} Protected Top-2: {:.4f}".format(util_acc, protected_util_acc, target, acc, topk_acc, protected_acc, protected_topk_acc))
    # print("Average Acc: {:.4f} Average Top-2 Acc.: {:.4f} Avergage Util: {:.4f} Protected: {:.4f} {:.4f} {:.4f}".format(average_acc/TOTAL_LEN, average_topk_acc/TOTAL_LEN, avg_util/TOTAL_LEN, protected_avg_acc/TOTAL_LEN, protected_avg_topk_acc/TOTAL_LEN, protected_avg_util/TOTAL_LEN))

    """
    # THE ADV. Utility
    # print(atk_acc_arr)
    # print(average_acc /  TOTAL_LEN)
    # print(average_topk_acc / TOTAL_LEN)
    """
    protected_avg_acc  /= TOTAL_LEN
    avg_util /= TOTAL_LEN
    protected_avg_util /= TOTAL_LEN

    print("{},{}".format(atk_acc_arr, np.array(atk_acc_arr).mean()))
    # print(avg_util)
    # print(protected_avg_util)
    # print(protected_acc_arr)
    # print(protected_avg_acc)
    # for
    # print(baseline_acc)
    # print()

    classifier.train()
    return (protected_acc_arr, [avg_util, protected_avg_util]) # protected_acc_arr

if __name__ == '__main__':
    # generate_offline_training_data(102400)

    # predict()
    # import sys; sys.exit()
    TRAIN = (not ARGS.t)
    DEFENSE = ARGS.d
    TEST_ARCHS = ["bert", "gpt", "gpt-2", "xlm", "xlnet", "roberta", "transformer-xl", "ernie"]
    # TEST_ARCHS = TEST_ARCHS[:1]

    # TEST_ARCHS = ["transformer-xl"]
    # prepare_raw_datasets()
    DELTA_TABLE = {
    "bert": 81.82,
    'gpt' : 73.19,
    'gpt-2': 110.2,
    'transformer-xl': 17.09,
    'xlnet': 601.5,
    'xlm': 219.4,
    'roberta': 4.15,
    'ernie': 28.20
    }

    # predict()
    # import sys; sys.exit()
    # acc = 1.0

    # prepare_raw_datasets()
    # predict()
    # import sys; sys.exit()
    TEMPLATE = "checkpoints/genome_{}_{}.cpt"
    PATH = "checkpoints/genome_{}_{}.cpt".format(ARGS.save_p, ARCH)

    if(TRAIN):
        # generate_offline_training_data(102400)
        acc = train_attacker(0, PATH)
    elif(DEFENSE != 'none'):
        # construct_datasets(ARCH)
        defenses = []
        if(DEFENSE == 'rounding'):
            for i in range(10):
                defenses.append((i, "rounding to {} decimals".format(i), initialize_defense('rounding', decimals = i)))
            RESULTS = []
            for param, descript, _def in defenses:
                RESULT = dict()
                for arch in TEST_ARCHS:
                    print("EVALUATE {} With Defense {}".format(arch, descript))
                    RESULT[arch] = evaluate(TEMPLATE.format(ARGS.save_p, arch), arch, _def)
                    # RESULT.append()
                RESULTS.append((param, RESULT))
            print(RESULTS)
        elif(DEFENSE == 'dp'):
            eps_list = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]
            RESULTS = [dict() for _ in eps_list]
            for i, arch in enumerate(TEST_ARCHS):
                defenses = []
                for eps in eps_list:
                    defenses.append((eps, "laplace with eps {}".format(eps), initialize_defense("dp", delta = DELTA_TABLE[arch], eps = eps)))
                for j, defense in enumerate(defenses):
                    param, descript, _def = defense
                    print("Evaluate {} with Defense {}".format(arch, descript))
                    RESULTS[j][arch] = evaluate(TEMPLATE.format(ARGS.save_p, arch), arch, _def)
            RESULTS = [(eps_list[i], RESULTS[i]) for i in range(len(RESULTS))]
            print(RESULTS)
        elif(DEFENSE == 'minmax'):
            eps_list = [0.001, 0.005, 0.01, 0.1, 0.5, 1.0]
            RESULTS = [dict() for _ in eps_list]
            # defenses = []
            for i, arch in enumerate(TEST_ARCHS):
                defenses = []
                for eps in eps_list:
                    defenses.append((eps, "minmax with eps {}".format(eps), initialize_defense("minmax", cls_num = 4, eps = eps)))
                for j, defense in enumerate(defenses):
                    param, descript, _def = defense
                    print("Evaluate {} with Defense {}".format(arch, descript))
                    RESULTS[j][arch] = evaluate(TEMPLATE.format(ARGS.save_p, arch), arch, _def)
            RESULTS = [(eps_list[i], RESULTS[i]) for i in range(len(RESULTS))]
            print(RESULTS)
    else:
        evaluate(TEMPLATE.format(ARGS.save_p, ARGS.a), ARGS.a)
        # evaluate(PATH)

    # z, y = generate_offline_training_data(1024 * 100)

    # print(z.shape)
    # print(y.shape)


import unittest
import threading
import traceback

from nose.plugins.skip import SkipTest

from test.utils import (joinall, remove_all_users,
                        server_started_with_auth, RendezvousThread)
from test.test_client import get_client
from test.utils import get_pool
from pymongo.pool import SocketInfo, _closed
from pymongo.errors import AutoReconnect, OperationFailure

class AutoAuthenticateThreads(threading.Thread):

    def __init__(self, collection, num):
        threading.Thread.__init__(self)
        self.coll = collection
        self.num = num
        self.success = True
        self.setDaemon(True)

    def run(self):
        try:
            for i in xrange(self.num):
                self.coll.insert({'num':i})
                self.coll.find_one({'num':i})
        except Exception:
            traceback.print_exc()
            self.success = False

class SaveAndFind(threading.Thread):

    def __init__(self, collection):
        threading.Thread.__init__(self)
        self.collection = collection
        self.setDaemon(True)

    def run(self):
        sum = 0
        for document in self.collection.find():
            sum += document["x"]
        assert sum == 499500, "sum was %d not 499500" % sum

class Insert(threading.Thread):

    def __init__(self, collection, n, expect_exception):
        threading.Thread.__init__(self)
        self.collection = collection
        self.n = n
        self.expect_exception = expect_exception
        self.setDaemon(True)

    def run(self):
        for _ in xrange(self.n):
            error = True

            try:
                self.collection.insert({"test": "insert"})
                error = False
            except:
                if not self.expect_exception:
                    raise

            if self.expect_exception:
                assert error

class Update(threading.Thread):

    def __init__(self, collection, n, expect_exception):
        threading.Thread.__init__(self)
        self.collection = collection
        self.n = n
        self.expect_exception = expect_exception
        self.setDaemon(True)

    def run(self):
        for _ in xrange(self.n):
            error = True

            try:
                self.collection.update({"test": "unique"},
                                       {"$set": {"test": "update"}})
                error = False
            except:
                if not self.expect_exception:
                    raise

            if self.expect_exception:
                assert error

class IgnoreAutoReconnect(threading.Thread):

    def __init__(self, collection, n):
        threading.Thread.__init__(self)
        self.c = collection
        self.n = n
        self.setDaemon(True)

    def run(self):
        for _ in range(self.n):
            try:
                self.c.find_one()
            except AutoReconnect:
                pass

class FindPauseFind(RendezvousThread):
    """See test_server_disconnect() for details"""
    def __init__(self, collection, state):
        """Params:
          `collection`: A collection for testing
          `state`: A shared state object from RendezvousThread.shared_state()
        """
        super(FindPauseFind, self).__init__(state)
        self.collection = collection

    def before_rendezvous(self):
        # acquire a socket
        list(self.collection.find())

        pool = get_pool(self.collection.database.connection)
        socket_info = pool._get_request_state()
        assert isinstance(socket_info, SocketInfo)
        self.request_sock = socket_info.sock
        assert not _closed(self.request_sock)

    def after_rendezvous(self):
        # test_server_disconnect() has closed this socket, but that's ok
        # because it's not our request socket anymore
        assert _closed(self.request_sock)

        # if disconnect() properly replaced the pool, then this won't raise
        # AutoReconnect because it will acquire a new socket
        list(self.collection.find())
        assert self.collection.database.connection.in_request()
        pool = get_pool(self.collection.database.connection)
        assert self.request_sock != pool._get_request_state().sock

class BaseTestThreads(object):
    """
    Base test class for TestThreads and TestThreadsReplicaSet. (This is not
    itself a unittest.TestCase, otherwise it'd be run twice -- once when nose
    imports this module, and once when nose imports
    test_threads_replica_set_connection.py, which imports this module.)
    """
    def setUp(self):
        self.db = self._get_client().pymongo_test

    def tearDown(self):
        # Clear client reference so that RSC's monitor thread
        # dies.
        self.db = None

    def _get_client(self):
        """
        Intended for overriding in TestThreadsReplicaSet. This method
        returns a MongoClient here, and a MongoReplicaSetClient in
        test_threads_replica_set_connection.py.
        """
        # Regular test client
        return get_client()

    def test_threading(self):
        self.db.drop_collection("test")
        for i in xrange(1000):
            self.db.test.save({"x": i})

        threads = []
        for i in range(10):
            t = SaveAndFind(self.db.test)
            t.start()
            threads.append(t)

        joinall(threads)

    def test_safe_insert(self):
        self.db.drop_collection("test1")
        self.db.test1.insert({"test": "insert"})
        self.db.drop_collection("test2")
        self.db.test2.insert({"test": "insert"})

        self.db.test2.create_index("test", unique=True)
        self.db.test2.find_one()

        okay = Insert(self.db.test1, 2000, False)
        error = Insert(self.db.test2, 2000, True)

        error.start()
        okay.start()

        error.join()
        okay.join()

    def test_safe_update(self):
        self.db.drop_collection("test1")
        self.db.test1.insert({"test": "update"})
        self.db.test1.insert({"test": "unique"})
        self.db.drop_collection("test2")
        self.db.test2.insert({"test": "update"})
        self.db.test2.insert({"test": "unique"})

        self.db.test2.create_index("test", unique=True)
        self.db.test2.find_one()

        okay = Update(self.db.test1, 2000, False)
        error = Update(self.db.test2, 2000, True)

        error.start()
        okay.start()

        error.join()
        okay.join()

    def test_server_disconnect(self):
        # PYTHON-345, we need to make sure that threads' request sockets are
        # closed by disconnect().
        #
        # 1. Create a client with auto_start_request=True
        # 2. Start N threads and do a find() in each to get a request socket
        # 3. Pause all threads
        # 4. In the main thread close all sockets, including threads' request
        #       sockets
        # 5. In main thread, do a find(), which raises AutoReconnect and resets
        #       pool
        # 6. Resume all threads, do a find() in them
        #
        # If we've fixed PYTHON-345, then only one AutoReconnect is raised,
        # and all the threads get new request sockets.
        cx = get_client(auto_start_request=True)
        collection = cx.db.pymongo_test

        # acquire a request socket for the main thread
        collection.find_one()
        pool = get_pool(collection.database.connection)
        socket_info = pool._get_request_state()
        assert isinstance(socket_info, SocketInfo)
        request_sock = socket_info.sock

        state = FindPauseFind.create_shared_state(nthreads=10)

        threads = [
            FindPauseFind(collection, state)
            for _ in range(state.nthreads)
        ]

        # Each thread does a find(), thus acquiring a request socket
        for t in threads:
            t.start()

        # Wait for the threads to reach the rendezvous
        FindPauseFind.wait_for_rendezvous(state)

        try:
            # Simulate an event that closes all sockets, e.g. primary stepdown
            for t in threads:
                t.request_sock.close()

            # Finally, ensure the main thread's socket's last_checkout is
            # updated:
            collection.find_one()

            # ... and close it:
            request_sock.close()

            # Doing an operation on the client raises an AutoReconnect and
            # resets the pool behind the scenes
            self.assertRaises(AutoReconnect, collection.find_one)

        finally:
            # Let threads do a second find()
            FindPauseFind.resume_after_rendezvous(state)

        joinall(threads)

        for t in threads:
            self.assertTrue(t.passed, "%s threw exception" % t)

class BaseTestThreadsAuth(object):
    """
    Base test class for TestThreadsAuth and TestThreadsAuthReplicaSet. (This is
    not itself a unittest.TestCase, otherwise it'd be run twice -- once when
    nose imports this module, and once when nose imports
    test_threads_replica_set_connection.py, which imports this module.)
    """
    def _get_client(self):
        """
        Intended for overriding in TestThreadsAuthReplicaSet. This method
        returns a MongoClient here, and a MongoReplicaSetClient in
        test_threads_replica_set_connection.py.
        """
        # Regular test client
        return get_client()

    def setUp(self):
        client = self._get_client()
        if not server_started_with_auth(client):
            raise SkipTest("Authentication is not enabled on server")
        self.client = client
        self.client.admin.add_user('admin-user', 'password',
                                   roles=['clusterAdmin',
                                          'dbAdminAnyDatabase',
                                          'readWriteAnyDatabase',
                                          'userAdminAnyDatabase'])
        self.client.admin.authenticate("admin-user", "password")
        self.client.auth_test.add_user("test-user", "password",
                                       roles=['readWrite'])

    def tearDown(self):
        # Remove auth users from databases
        self.client.admin.authenticate("admin-user", "password")
        remove_all_users(self.client.auth_test)
        self.client.drop_database('auth_test')
        remove_all_users(self.client.admin)
        # Clear client reference so that RSC's monitor thread
        # dies.
        self.client = None

    def test_auto_auth_login(self):
        client = self._get_client()
        self.assertRaises(OperationFailure, client.auth_test.test.find_one)

        # Admin auth
        client = self._get_client()
        client.admin.authenticate("admin-user", "password")

        nthreads = 10
        threads = []
        for _ in xrange(nthreads):
            t = AutoAuthenticateThreads(client.auth_test.test, 100)
            t.start()
            threads.append(t)

        joinall(threads)

        for t in threads:
            self.assertTrue(t.success)

        # Database-specific auth
        client = self._get_client()
        client.auth_test.authenticate("test-user", "password")

        threads = []
        for _ in xrange(nthreads):
            t = AutoAuthenticateThreads(client.auth_test.test, 100)
            t.start()
            threads.append(t)

        joinall(threads)

        for t in threads:
            self.assertTrue(t.success)

class TestThreads(BaseTestThreads, unittest.TestCase):
    pass

class TestThreadsAuth(BaseTestThreadsAuth, unittest.TestCase):
    pass

if __name__ == "__main__":
    unittest.main()


import subprocess
import argparse
from pathlib import Path

def submit_experiment_on_slurm(python_script_name, data_dir, experiment_type, argdict):
    command = "sbatch slurm_job {} {} {}".format(
        python_script_name, data_dir, experiment_type
    )
    argstring = " ".join(
        ["--{} {}".format(argname, str(argdict[argname])) for argname in argdict]
    )
    command = command + " " + argstring
    print(command)
    process = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
    output, error = process.communicate()
    del output, error

def ablation(experiment_type, report_path, data_dir):
    main_argdict = {
        "nepochs": 20,
        "lr": 0.2,
        "batch_size": 512,
        "compare_models_by_loss": False,
        "nbins": 20,
        "npows": 5,
        "nhops": 3,
        "calib_before_lp_method": "local",
        "calib_after_lp_method": "global",
        "learn_node_importance": True,
        "normalize_by_degrees": False,
        "use_cumsum": False,
    }
    report_path_for_type = Path(report_path) / experiment_type
    report_path_for_type.mkdir(parents=True, exist_ok=True)
    for argdict_changes in [
        {
            "exp_name": "Ours_(nhops_1)",
            "nhops" :1,
        },
        {
            "exp_name": "Ours_(nhops_2)",
            "nhops" :2,
        },
        {
            "exp_name": "Ours_(nhops_3)",
            "nhops" :3,
        },
        {
            "exp_name": "Ours_(nhops_4)",
            "nhops" :4,
        },
        {
            "exp_name": "Ours_(nhops_5)",
            "nhops" :5,
        },
        {
            "exp_name": "Ours_(only_calib_1)",
            "calib_after_lp_method": "none",
        },
        {
            "exp_name": "Ours_(no_calib)",
            "calib_after_lp_method": "none",
            "calib_before_lp_method": "none",
        },
        {
            "exp_name": "Ours_(both_global)",
            "calib_after_lp_method": "global",
            "calib_before_lp_method": "global",
        },
        {
            "exp_name": "Ours_(no_node_iw)",
            "learn_node_importance": False,
            "normalize_by_degrees": True,
        },
        {
            "exp_name": "Ours_(merged_loss)",
            "separate_loss_per_hop": False,
        },
    ]:
        argdict = {argname: main_argdict[argname] for argname in main_argdict}
        argdict.update(argdict_changes)
        argdict["report_path"] = report_path_for_type / "{}.txt".format(
            argdict["exp_name"]
        )
        submit_experiment_on_slurm(
            python_script_name="run_main_experiment.py",
            data_dir=data_dir,
            experiment_type=experiment_type,
            argdict=argdict,
        )

def baselines(experiment_type, report_path, data_dir):
    report_path_for_type = Path(report_path) / experiment_type
    report_path_for_type.mkdir(parents=True, exist_ok=True)
    for argdict in [
        {
            "exp_name": "classic_lp",
            "model": "classic_lp",
            "alpha": 0.001,
            "cutoff": 0.0,
        },
        {
            "exp_name": "hpolabeler_lr",
            "model": "hpolabeler_lr",
        },
        {
            "exp_name": "hpolabeler_nn",
            "model": "hpolabeler_nn",
        },
    ]:
        argdict["report_path"] = report_path_for_type / "{}.txt".format(
            argdict["exp_name"]
        )
        submit_experiment_on_slurm(
            python_script_name="run_baseline_experiment.py",
            data_dir=data_dir,
            experiment_type=experiment_type,
            argdict=argdict,
        )

def main():
    parser = argparse.ArgumentParser(
        description="Download data for protein function prediction."
    )
    parser.add_argument("report_path", help="Path to the report directory.")
    parser.add_argument("data_dir", help="Path to the data directory.")
    args = parser.parse_args()
    data_path = Path(args.data_dir)
    for experiment_type in ["temporal", "cv"]:
        ablation(experiment_type, args.report_path, data_path / f"ppi_hpo_string_{experiment_type}/")
        baselines(experiment_type, args.report_path, data_path / f"ppi_hpo_string_{experiment_type}/")

if __name__ == "__main__":
    main()


from airflow import DAG
from airflow.operators.python import PythonOperator
from airflow.providers.postgres.operators.postgres import PostgresOperator
from airflow.providers.postgres.hooks.postgres import PostgresHook
from datetime import datetime

default_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime(2023, 3, 16),
}

def extract_data_to_nested(**kwargs):
    def clean_input(data_type, data_value):
        if data_type == 'string':
            return 'null' if not data_value else f'\"{data_value}\"'
        elif data_type == 'datetime':
            return 'null' if not data_value else f'CAST(\'{data_value}\' As TIMESTAMP)'
        else:
            return data_value

    pg_hook = PostgresHook(postgres_conn_id='postgres_result_db')
    pg_conn = pg_hook.get_conn()
    pg_cursor = pg_conn.cursor()
    ti = kwargs['ti']
    transform_data_output = ti.xcom_pull(task_ids='transform_data')
    for transform_row in transform_data_output:
        pg_cursor.execute(
            'INSERT INTO group_sessions (table_unique_key, meeting_id, '
            'booked_by_id, mentee_user_id, child_video_session,'
            'course_id, actual_duration, created_at, start_timestamp, end_timestamp, '
            'end_via_api,hash, participants_count, reports_pulled, '
            'title, video_session_using, with_mentees, is_deleted,'
            'deleted_by_id, should_redirect, cancel_reason, meeting_status)'
            'VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'
            'on conflict (table_unique_key) do update set meeting_id = EXCLUDED.meeting_id,'
            'booked_by_id = EXCLUDED.booked_by_id,'
            'mentee_user_id = EXCLUDED.mentee_user_id,'
            'child_video_session = EXCLUDED.child_video_session,'
            'course_id = EXCLUDED.course_id,'
            'actual_duration = EXCLUDED.actual_duration,'
            'created_at = EXCLUDED.created_at,'
            'start_timestamp = EXCLUDED.start_timestamp,'
            'end_timestamp = EXCLUDED.end_timestamp,'
            'end_via_api = EXCLUDED.end_via_api,'
            'hash = EXCLUDED.hash,'
            'participants_count = EXCLUDED.participants_count,'
            'reports_pulled = EXCLUDED.reports_pulled,'
            'title = EXCLUDED.title,'
            'video_session_using = EXCLUDED.video_session_using,'
            'with_mentees = EXCLUDED.with_mentees,'
            'is_deleted = EXCLUDED.is_deleted,'
            'deleted_by_id = EXCLUDED.deleted_by_id,'
            'should_redirect = EXCLUDED.should_redirect,'
            'cancel_reason = EXCLUDED.cancel_reason,'
            'meeting_status = EXCLUDED.meeting_status ;',
            (
                transform_row[0],
                transform_row[1],
                transform_row[2],
                transform_row[3],
                transform_row[4],
                transform_row[5],
                transform_row[6],
                transform_row[7],
                transform_row[8],
                transform_row[9],
                transform_row[10],
                transform_row[11],
                transform_row[12],
                transform_row[13],
                transform_row[14],
                transform_row[15],
                transform_row[16],
                transform_row[17],
                transform_row[18],
                transform_row[19],
                transform_row[20],
                transform_row[21],
            )
        )
    pg_conn.commit()

dag = DAG(
    'group_sessions_dag',
    default_args=default_args,
    description='Group Sessions mentor and mentee data',
    schedule_interval='35 20 * * *',
    catchup=False,
    max_active_runs=1
)

create_table = PostgresOperator(
    task_id='create_table',
    postgres_conn_id='postgres_result_db',
    sql='''CREATE TABLE IF NOT EXISTS group_sessions (
            id serial,
            table_unique_key text not null PRIMARY KEY,
            meeting_id int,
            booked_by_id bigint,
            mentee_user_id bigint,
            child_video_session boolean,
            course_id int,
            actual_duration int,
            created_at TIMESTAMP,
            start_timestamp TIMESTAMP,
            end_timestamp TIMESTAMP,
            end_via_api boolean,
            hash varchar(256),
            participants_count int,
            reports_pulled boolean,
            title varchar(256),
            video_session_using int,
            with_mentees boolean,
            is_deleted boolean,
            deleted_by_id bigint,
            should_redirect boolean,
            cancel_reason varchar(256),
            meeting_status int
        );
    ''',
    dag=dag
)

transform_data = PostgresOperator(
    task_id='transform_data',
    postgres_conn_id='postgres_read_replica',
    sql='''select
                concat(video_sessions_meeting.id, video_sessions_meeting_booked_with.user_id) as table_unique_key,
                video_sessions_meeting.id as meeting_id,
                booked_by_id,
                video_sessions_meeting_booked_with.user_id as mentee_user_id,
                child_video_session,
                course_id,
                actual_duration,
                created_at,
                start_timestamp,
                end_timestamp,
                end_via_api,
                hash,
                participants_count,
                reports_pulled,
                title,
                video_session_using,
                with_mentees,
                is_deleted,
                deleted_by_id,
                should_redirect,
                cancel_reason,
                meeting_status
            from
                video_sessions_meeting
            LEFT JOIN video_sessions_meeting_booked_with
                on video_sessions_meeting_booked_with.meeting_id = video_sessions_meeting.id;
        ''',
    dag=dag
)

extract_python_data = PythonOperator(
    task_id='extract_python_data',
    python_callable=extract_data_to_nested,
    provide_context=True,
    dag=dag
)
create_table >> transform_data >> extract_python_data


binaryNumber = []

def convertToBinary(iNumber:int):
    resto = round(iNumber%2);
    binaryNumber.append(resto)
    iNumber = int(iNumber/2)
    if(iNumber > 1):
        convertToBinary(iNumber)
    else:
        binaryNumber.append(iNumber)
    #for x in range(iNumber, 0,-1):
    #    print(x)
    binaryNumber.reverse()

print("Conversion Decimal to Binary")

iNumber = input("Enter the number")
TheNumber = int(iNumber)
convertToBinary(TheNumber)
print(binaryNumber);
#print(str(int(5/2)));