from collections import OrderedDict
from sklearn.ensemble import GradientBoostingClassifier, RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.neural_network import MLPClassifier

from pprint import pprint

from sklearn.model_selection import train_test_split

from utils.data import HeartDataset, HousingDataset, RainDataset, CampusDataset

from time import perf_counter as time
import polars as pl
import numpy as np
import os

import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, precision_recall_fscore_support

def train_gradient_boosting_classifier(X, y, n_estimators=100):
    """
    Train a Gradient Boosting Classifier.

    Parameters:
    X: array-like, shape = [n_samples, n_features]
       Training vectors, where n_samples is the number of samples and
       n_features is the number of features.
    y: array-like, shape = [n_samples]
       Target values (class labels in classification).

    Returns:
    model: The trained Gradient Boosting Classifier model.
    """

    # Create a Gradient Boosting Classifier
    gbc = GradientBoostingClassifier(n_estimators=n_estimators, learning_rate=1e0, max_depth=1, random_state=42)

    # Train the classifier
    gbc.fit(X, y)

    return gbc

def train_logistic_regression(X, y):
    """
    Train a Logistic Regression Classifier.

    Parameters:
    X: array-like, shape = [n_samples, n_features]
       Training vectors, where n_samples is the number of samples and
       n_features is the number of features.
    y: array-like, shape = [n_samples]
       Target values (class labels in classification).

    Returns:
    model: The trained Logistic Regression Classifier model.
    """

    # Create a Logistic Regression Classifier
    lrc = LogisticRegression(max_iter=2_000, random_state=42)

    # Train the classifier
    lrc.fit(X, y)

    return lrc

def train_random_forest_classifier(X, y, n_estimators=100):
    """
    Train a Random Forest Classifier.

    Parameters:
    X: array-like, shape = [n_samples, n_features]
       Training vectors, where n_samples is the number of samples and
       n_features is the number of features.
    y: array-like, shape = [n_samples]
       Target values (class labels in classification).

    Returns:
    model: The trained Random Forest Classifier model.
    """

    # Create a Random Forest Classifier
    rfc = RandomForestClassifier(n_estimators=n_estimators, random_state=42)

    # Train the classifier
    rfc.fit(X, y)

    return rfc

def train_support_vector_classifier(X, y, kernel):
    """
    Train a Support Vector Classifier.

    Parameters:
    X: array-like, shape = [n_samples, n_features]
       Training vectors, where n_samples is the number of samples and
       n_features is the number of features.
    y: array-like, shape = [n_samples]
       Target values (class labels in classification).

    Returns:
    model: The trained Support Vector Classifier model.
    """

    # Create a Support Vector Classifier
    svc = SVC(kernel=kernel, gamma='auto', random_state=42)

    # Train the classifier
    svc.fit(X, y)

    return svc

def train_neural_network_classifier(X, y):
    """
    Train a Neural Network Classifier.

    Parameters:
    X: array-like, shape = [n_samples, n_features]
       Training vectors, where n_samples is the number of samples and
       n_features is the number of features.
    y: array-like, shape = [n_samples]
       Target values (class labels in classification).

    Returns:
    model: The trained Neural Network Classifier model.
    """

    # Create a Neural Network Classifier
    nnc = MLPClassifier(solver='lbfgs', alpha=1e-5, hidden_layer_sizes=(5, 5, 5), max_iter=2_000, random_state=42)

    # Train the classifier
    nnc.fit(X, y)

    return nnc

def train_all_classifiers(X, y, n_estimators=100, kernel='rbf'):
    """
    Train all the classifiers on the given dataset.

    Parameters:
    X: array-like, shape = [n_samples, n_features]
       Training vectors, where n_samples is the number of samples and
       n_features is the number of features.
    y: array-like, shape = [n_samples]
       Target values (class labels in classification).

    Returns:
    models: A dictionary of all the trained models.
    """

    training_times = {}

    start_time = time()
    gbc = train_gradient_boosting_classifier(X, y, n_estimators=n_estimators)
    training_times['GradientBoosting'] = time() - start_time

    start_time = time()
    lrc = train_logistic_regression(X, y)
    training_times['LogisticRegression'] = time() - start_time

    start_time = time()
    rfc = train_random_forest_classifier(X, y, n_estimators=n_estimators)
    training_times['RandomForest'] = time() - start_time

    start_time = time()
    svc = train_support_vector_classifier(X, y, kernel)
    training_times['SupportVector'] = time() - start_time

    start_time = time()
    nnc = train_neural_network_classifier(X, y)
    training_times['NeuralNetwork'] = time() - start_time

    return gbc, lrc, rfc, svc, nnc, training_times

def get_accuracy(X_train, y_train, X_test, y_test, gbc, lrc, rfc, svc, nnc, training_times):

    metrics = OrderedDict(
        accuracy = ['Test CCR', 'Train CCR', 'Test Precision', 'Test Recall', 'F1 score', 'Training Time'],
        grad_boost = [
            gbc.score(X_test, y_test),
            gbc.score(X_train, y_train),
            *precision_recall_fscore_support(y_test, gbc.predict(X_test), average='weighted')[:-1],
            training_times['GradientBoosting']
        ],
        log_reg = [
            lrc.score(X_test, y_test),
            lrc.score(X_train, y_train),
            *precision_recall_fscore_support(y_test, lrc.predict(X_test), average='weighted')[:-1],
            training_times['LogisticRegression']
        ],
        rand_forest = [
            rfc.score(X_test, y_test),
            rfc.score(X_train, y_train),
            *precision_recall_fscore_support(y_test, rfc.predict(X_test), average='weighted')[:-1],
            training_times['RandomForest']
        ],
        svc = [
            svc.score(X_test, y_test),
            svc.score(X_train, y_train),
            *precision_recall_fscore_support(y_test, svc.predict(X_test), average='weighted')[:-1],
            training_times['SupportVector']
        ],
        neural_net = [
            nnc.score(X_test, y_test),
            nnc.score(X_train, y_train),
            *precision_recall_fscore_support(y_test, nnc.predict(X_test), average='weighted')[:-1],
            training_times['NeuralNetwork']
        ]
    )

    return pl.DataFrame(metrics)

def plot_confusion_matrix(X_test, y_test, basedir, labels, *models):
    """
    Generate a Polars DataFrame representation of the confusion matrix.

    Parameters:
    - model: The trained classification model.
    - X_test: Test features.
    - y_test: True labels for the test set.

    Returns:
    - Confusion matrix table as a Polars DataFrame.
    """

    plt.figure()

    os.makedirs(f'{basedir}/confusion', exist_ok=True)

    for model, name in zip(models, ['GradientBoosting', 'LogisticRegression', 'RandomForest', 'SupportVector', 'NeuralNetwork']):

        # Predictions
        y_pred = model.predict(X_test)

        y_pred_final = [labels[i] for i in y_pred]
        y_test_final = [labels[i] for i in y_test]

        # Calculate confusion matrix
        cm = confusion_matrix(y_test_final, y_pred_final, labels=labels)

        # Convert to Polars DataFrame for better visualization
        cm_df = ConfusionMatrixDisplay(cm, display_labels=labels)

        cm_df.plot()

        plt.savefig(f'{basedir}/confusion/{name}.png')

def plot_class_balance(Y, basedir, xlabel, xlabel_ticks):
    """
    Plot the class balance of the given dataset.

    Parameters:
    - Y: The target variable.
    """

    plt.figure()

    y_in = Y.to_list()

    counts, bins, patches = plt.hist(y_in, bins=np.arange(min(y_in)-0.5, max(y_in)+1, 1), rwidth=0.5)

    # Add count annotations above each bar
    for count, bin, patch in zip(counts, bins, patches):
        if count > 0:
            plt.text(bin+0.5, patch.get_height(), str(int(count)), ha='center', va='bottom')

    plt.ylabel('Count')
    plt.xlabel(xlabel)
    plt.xticks(np.arange(len(Y.unique())), labels=xlabel_ticks)

    plt.savefig(f'{basedir}/class_balance.png')

def train_campus():

    os.makedirs('results/campus', exist_ok=True)

    dataset = CampusDataset()

    target = 'degree_t'
    features = list(set(dataset.df.columns) - set([target, 'salary']))

    y, X = dataset.get(features, target, ommit_nan=True)

    xlabel_ticks = [dataset.categorical[target][i] for i in sorted(y.unique().to_list())]
    plot_class_balance(y, 'results/campus', 'Degree placement', xlabel_ticks)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    classifiers = train_all_classifiers(X_train, y_train, kernel='linear')

    metrics = get_accuracy(X_train, y_train, X_test, y_test, *classifiers)

    plot_confusion_matrix(X_test, y_test, 'results/campus', xlabel_ticks, *classifiers)

    metrics.write_csv('results/campus/metrics.csv')

    print('Campus Placement Dataset')
    print(metrics)
    print()
    print()

def train_heart():

    os.makedirs('results/heart', exist_ok=True)

    dataset = HeartDataset()

    target = 'output'
    features = list(set(dataset.df.columns) - set([target]))

    y, X = dataset.get(features, target, ommit_nan=True)

    xlabel_ticks = [dataset.categorical[target][i] for i in sorted(y.unique().to_list())]
    plot_class_balance(y, 'results/heart', 'Heart Attack Risk', xlabel_ticks)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    classifiers = train_all_classifiers(X_train, y_train, kernel='poly')

    metrics = get_accuracy(X_train, y_train, X_test, y_test, *classifiers)

    plot_confusion_matrix(X_test, y_test, 'results/heart', xlabel_ticks, *classifiers)

    metrics.write_csv('results/heart/metrics.csv')

    print('Heart Disease Dataset')
    print(metrics)
    print()
    print()

def train_rain():

    os.makedirs('results/rain', exist_ok=True)

    dataset = RainDataset()

    target = 'RainTomorrow'
    features = list(set(dataset.df.columns) - set([target]))

    y, X = dataset.get(features, target, ommit_nan=True)

    xlabel_ticks = [dataset.categorical[target][i] for i in sorted(y.unique().to_list())]
    plot_class_balance(y, 'results/rain', 'Rain Tomorrow', xlabel_ticks)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    classifiers = train_all_classifiers(X_train, y_train, n_estimators=500, kernel='linear')

    metrics = get_accuracy(X_train, y_train, X_test, y_test, *classifiers)

    plot_confusion_matrix(X_test, y_test, 'results/rain', xlabel_ticks, *classifiers)

    metrics.write_csv('results/rain/metrics.csv')

    print('Rain Dataset')
    print(metrics)
    print()
    print()

def train_housing():

    os.makedirs('results/housing', exist_ok=True)

    dataset = HousingDataset()

    target = 'Beds'
    features = list(set(dataset.df.columns) - set([target]))

    y, X = dataset.get(features, target, ommit_nan=True)

    xlabel_ticks = [dataset.categorical[target][i] for i in sorted(y.unique().to_list())]
    plot_class_balance(y, 'results/housing', 'Number of Beds', xlabel_ticks)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    classifiers = train_all_classifiers(X_train, y_train, kernel='rbf')

    metrics = get_accuracy(X_train, y_train, X_test, y_test, *classifiers)

    plot_confusion_matrix(X_test, y_test, 'results/housing', xlabel_ticks, *classifiers)

    metrics.write_csv('results/housing/metrics.csv')

    print('Housing Dataset')
    print(metrics)
    print()
    print()

def train_all():
    train_campus()
    train_heart()
    train_rain()
    train_housing()


import itertools
import math
import requests
import re
import asyncio
import functools
import datetime
import shlex
import getopt
from pebble import concurrent, ThreadPool
from concurrent.futures import TimeoutError, ThreadPoolExecutor, _base
from wand.image import Image
from wand.drawing import Drawing
from wand.color import Color
import os
import json
from matplotlib import pyplot
import numpy
from . import config
from nonebot import CommandSession, get_bot, permission
from nonebot.message import escape
from .helper.function.function import parser, ParserError
from .inject import on_command
#pylint: disable=no-member

async def latex(s, hsh=()):
    loop = asyncio.get_event_loop()
    ipt = re.sub('&', '%26', re.sub('\+', '%2B', s))
    url = await loop.run_in_executor(None, functools.partial(requests.get,
        'https://www.zhihu.com/equation?tex=' + ipt,
        headers={'user-agent': config.user_agent}))
    name = str(hash((s,) + hsh))
    with open(config.img(name + '.svg'), 'wb') as f:
        f.write(url.content)
    with Image(filename=config.img(name + '.svg')) as image:
        with image.convert('png') as converted:
            converted.background_color = Color('white')
            converted.alpha_channel = 'remove'
            converted.save(filename=config.img(name + '.png'))
    return name + '.png'

config.CommandGroup('tools', short_des='数理小工具。')

@on_command(('tools', 'Julia'), only_to_me=False, short_des="绘制Julia集。", args=("x", "y"))
@config.ErrorHandle
async def Julia(session: CommandSession):
    """绘制以c=x+yi为参数，z→z^2+c的Julia集。
    Julia集为在复平面上，使得无限迭代z→z^2+c不发散的初值z_0的集合。
    Ref：https://en.wikipedia.org/wiki/Julia_set"""
    c = session.current_arg_text.split(' ')
    if len(c) != 2:
        await session.send("使用格式：-tools.Julia x y\n绘制Julia set，使得c=x+yi")
        return
    x = float(c[0])
    y = float(c[1])
    height = 600
    dx = 0.005
    MAX = 80
    color_in = (128, 48, 10)
    name = 'Julia_%f_%f.png' % (x, y)
    if not os.path.exists(config.img(name)):
        f = lambda i, x: math.log(i + math.log(abs(x) + 3) + 2)
        await session.send("少女计算中...请耐心等待...")
        with Drawing() as draw:
            for x1, y1 in itertools.product(range(height), range(height)):
                x2, y2 = (x1 - height / 2) * dx, (y1 - height / 2) * dx
                for i in range(MAX):
                    x3, y3 = (x2 ** 2 - y2 ** 2 + x, 2 * x2 * y2 + y)
                    if (x2 - x3) ** 2 + (y2 - y3) ** 2 >= 100:
                        break
                    x2, y2 = x3, y3
                else:
                    i += 1
                r2 = math.sqrt(x2 ** 2 + y2 ** 2)
                color = tuple(map(lambda c: c[0] * c[1], zip(color_in, (f(i, x2), f(i, y2), f(i, r2)))))
                draw.fill_color = Color('rgb(%i, %i, %i)' % color)
                draw.point(x1, y1)
            with Image(width=height, height=height) as image:
                draw(image)
                image.save(filename=config.img(name))
    await session.send(config.cq.img(name))

@on_command(('tools', 'Mandelbrot'), only_to_me=False, short_des="绘制Mandelbrot集。", args=("x", "y"), hide=True)
@config.ErrorHandle
async def Mandelbrot(session: CommandSession):
    """绘制以z_0=x+yi为初值，z→z^2+c的Mandelbrot集。
    Mandelbrot集为在复平面上，使得无限迭代z→z^2+c不发散的参数c的集合。
    Ref：https://en.wikipedia.org/wiki/Mandelbrot_set"""
    c = session.current_arg_text.split(' ')
    if len(c) != 2:
        await session.send("使用格式：-tools.Mandelbrot x y\n绘制Mandelbrot set，使得z0=x+yi")
        return
    x = float(c[0])
    y = float(c[1])
    height = 600
    dx = 0.005
    MAX = 80
    color_in = (128, 48, 10)
    name = 'Mandelbrot_%f_%f.png' % (x, y)
    if not os.path.exists(config.img(name)):
        f = lambda i, x: math.log(i + math.log(abs(x) + 3) + 2)
        await session.send("少女计算中...请耐心等待...")
        with Drawing() as draw:
            for x1, y1 in itertools.product(range(height), range(height)):
                x2, y2 = (x1 - height / 2) * dx, (y1 - height / 2) * dx
                x4, y4 = x, y
                for i in range(MAX):
                    x3, y3 = (x4 ** 2 - y4 ** 2 + x2, 2 * x4 * y4 + y2)
                    if (x4 - x3) ** 2 + (y4 - y3) ** 2 >= 100:
                        break
                    x4, y4 = x3, y3
                else:
                    i += 1
                r4 = math.sqrt(x4 ** 2 + y4 ** 2)
                color = tuple(map(lambda c: c[0] * c[1], zip(color_in, (f(i, x4), f(i, y4), f(i, r4)))))
                draw.fill_color = Color('rgb(%i, %i, %i)' % color)
                draw.point(x1, y1)
            with Image(width=height, height=height) as image:
                draw(image)
                image.save(filename=config.img(name))
    await session.send(config.cq.img(name))

@on_command(('tools', 'oeis'), only_to_me=False, short_des="查询oeis（整数序列在线百科全书）。", args=("[Anumber]", "[a_1, a_2, ...]"))
@config.ErrorHandle
async def oeis(session: CommandSession):
    """查询oeis（整数序列在线百科全书）。
    参数为序列中的几项，使用逗号分隔。或为oeis编号如A036057。"""
    if re.match('A\d+', session.current_arg_text):
        result = await oeis_id(session.current_arg_text)
        if type(result) == str:
            await session.send(result)
        else:
            await session.send('%s\nDESCRIPTION: %s\n%s\nEXAMPLE: %s' % \
                    (result['Id'], result['description'], result['numbers'], result['example']))
    elif re.fullmatch('(-?\d+, ?)*-?\d+', session.current_arg_text):
        loop = asyncio.get_event_loop()
        response = await loop.run_in_executor(None, requests.get,
                'http://oeis.org/search?q=' + session.current_arg_text + '&sort=&language=&go=Search')
        if response.status_code != 200:
            await session.send('sequence not found!')
            return
        match = re.search('A\d+', response.text)
        if not match:
            await session.send('sequence not found!')
            return
        s = match.group()
        result = await oeis_id(s)
        if type(result) == str:
            await session.send(result)
        else:
            await session.send('%s\nDESCRIPTION: %s\n%s\nEXAMPLE: %s' % \
                    (result['Id'], result['description'], result['numbers'], result['example']))
    else:
        await session.send("I don't know what you mean.")

async def oeis_id(s):
    loop = asyncio.get_event_loop()
    try:
        response = await asyncio.wait_for(loop.run_in_executor(None, requests.get,
            'http://oeis.org/' + s), timeout=600.0)
    except asyncio.TimeoutError:
        return "time out!"
    if response.status_code != 200:
        return 'Name not found!'
    text = response.text
    begin_pos = 0
    match = re.search('<title>(A\d+)', text[begin_pos:])
    if not match:
        return 'Title not found!'
    begin_pos += match.span()[1]
    Id = match.group(1)
    match = re.search('\n(.*)\n', text[begin_pos:])
    if not match:
        return 'Description not found!'
    begin_pos += match.span()[1]
    description = match.group(1).strip()
    match = re.search('', text[begin_pos:])
    if not match:
        return 'Numbers not found!'
    begin_pos += match.span()[1]
    match = re.search('<tt>(.*?)</tt>', text[begin_pos:])
    if not match:
        return 'Numbers not found!'
    numbers = match.group(1)
    match = re.search('EXAMPLE', text[begin_pos:])
    if not match:
        example = None
    else:
        example_pos = begin_pos + match.span()[1]
        match2 = re.search('<font size=', text[example_pos:])
        match3 = re.search('
', text[example_pos:])
        if not match2:
            match2 = match3
        if not match3:
            example = None
        else:
            example_end = example_pos + match2.span()[1]
            example_list = []
            while 1:
                match2 = re.search('<tt>(.*)</tt>', text[example_pos:example_end])
                if not match2:
                    break
                example_pos += match2.span()[1]
                example_list.append(re.sub(' ', '\t', re.sub('<.*?>', '', match2.group(1))).strip())
            example = '\n'.join(example_list)
    result = {'Id': Id, 'description': description, 'numbers': numbers, 'example': example}
    return result

@on_command(('tools', 'quiz'), only_to_me=False, shell_like=True, short_des="每月趣题。", args=("[-t YYYYMM]", "[-a]"))
@config.ErrorHandle
async def quiz(session: CommandSession):
    """每月趣题。
    可用选项：
        -t, --time 接六位月份码查看历史趣题。
        -a, --answer 查看答案。
    欢迎提交好的东方化（或其他IP化也欢迎~）的趣题至维护者邮箱shedarshian@gmail.com（难度至少让维护者能看懂解答）"""
    opts, args = getopt.gnu_getopt(session.state['argv'], 't:a', ['time=', 'answer'])
    d = datetime.date.today()
    s, ans = None, False
    for o, a in opts:
        if o in ('-t', '--time'):
            s = a
            print(a)
            if not re.match('\d{6,}', s):
                session.finish('请使用YYYYMM（四位年份加两位月份）来获取往年试题')
            if int(s[0:4]) > d.year or int(s[0:4]) == d.year and int(s[4:6]) > d.month:
                session.finish('未发现该月题目，题目自201910开始')
        elif o in ('-a', '--answer'):
            ans = True
    if s is None:
        s = f'{d.year}{d.month:02}'
    try:
        print(s)
        with open(config.rel("games\\quiz.json"), encoding='utf-8') as f:
            await session.send(json.load(f)["math"][s][int(ans)], ensure_private=ans)
    except KeyError:
        await session.send('未发现该月题目，题目自201910开始')

@on_command(('tools', 'quiz_submit'), only_to_me=False, shell_like=True, args=("content",))
@config.ErrorHandle
async def quiz_submit(session: CommandSession):
    """提交每月趣题答案。"""
    for group in config.group_id_dict['aaa']:
        await get_bot().send_group_msg(group_id=group, message=f'用户{session.ctx["user_id"]} 提交答案：\n{session.current_arg}')
    await session.send('您已成功提交答案')

@concurrent.process(timeout=30)
def calculate(s):
    parser.reset()
    parser.max_sum = 10000
    try:
        return parser.parse(s)
    except ParserError as e:
        return 'SyntaxError: ' + str(e)
    except Exception as e:
        return type(e).__name__ + ': ' + str(e)

@on_command(('tools', 'calculator'), only_to_me=False, aliases=('cal',), short_des="计算器。别名：-cal")
@config.ErrorHandle
async def calculator(session: CommandSession):
    """计算器。计算给定式子的结果。别名：-cal
    运算过程中有浮点布尔列表三种类型，计算结果必须为浮点数。
    可以使用的运算符：
        列表 {1,2,3,4}
        C++中的一元与二元运算符 + - * / ^ == != < <= > >= && || ! 下标[] 下标slice[i:j]
        括号 ( )
        C++中的三目运算符 ? :
        定义临时变量的运算符 := （使用例：(t:=2^3+1)*(t^2-2)
        优先级最低的分隔符 $
        求和 sum[变量名](下限，上限，表达式)或者sum[变量名](列表，表达式) （使用例：sum[t](1,100,sum[n](1,t,2^n/Gamma(n+1)))+sum[t](L:={2,3,5,7},t)/sum[t](L,1))
    可以使用的函数名：
        指数函数exp 自然对数ln 常用对数lg 绝对值abs 开根号sqrt 向下取整floor
        六种三角函数（sin等） 六种反三角函数（asin等） 六种双曲三角函数（sinh等） 六种反双曲三角函数（asinh等）
        误差函数erf 伽马函数Gamma 贝塔函数Beta 双伽马函数psi 不完全伽马函数Gammainc
        黎曼zeta函数或赫尔维茨zeta函数zeta（重载）
        雅克比椭圆函数ellipse_sn ellipse_cn ellipse_dn
        贝塞尔函数BesselJ BesselY BesselK BesselI
        球贝塞尔函数Besselj Bessely Besselk Besseli
        艾里函数Airy Biry
        均匀分布随机数random 高斯分布随机数gauss
    可以使用的常量：
        圆周率pi 自然对数的底e 欧拉常数gamma"""
    try:
        loop = asyncio.get_event_loop()
        future = calculate(session.current_arg_text)
        with ThreadPoolExecutor() as pool:
            result = await loop.run_in_executor(pool, future.result)
    except (TimeoutError, _base.CancelledError):
        session.finish("time out!")
    if type(result) is float:
        await session.send(escape(str(result)))
    elif type(result) is str:
        await session.send(escape(result))
    else:
        await session.send(escape('TypeError ' + str(result)))

@on_command(('tools', 'function'), only_to_me=False, short_des="绘制函数。", args=("[-b begin=0]", "[-e end=10]", "[-s step=0.01]"))
@config.ErrorHandle
async def plot_function(session: CommandSession):
    """绘制函数。语法见-tools.calculator的帮助。
    可用选项：
        -b, --begin: 起始范围，默认为0。
        -e, --end: 结束范围，默认为10。
        -s, --step: 步长，默认为0.01。
        以上三个选项均可以输入表达式，但是在包含空格时需要用引号包裹。
    函数自变量符号为x。
    函数不可包含换行符。在函数包含空格时，请用引号包裹函数体部分。
    也可以在第一行输入选项，换行后输入函数体。"""
    opt_str, *els = session.current_arg_text.split('\n')
    print(session.current_arg_text, session.current_arg_text[0])
    if len(els) >= 2:
        await session.send('函数不可包含换行符。')
        return
    begin, end, step = 0, 10, 0.01
    opts, args = getopt.gnu_getopt(shlex.split(opt_str.strip()), 'b:e:s:', ['begin=', 'end=', 'step='])
    loop = asyncio.get_event_loop()
    try:
        with ThreadPoolExecutor() as pool:
            for o, a in opts:
                if o in ('-b', '--begin'):
                    future = calculate(a)
                    begin = await loop.run_in_executor(pool, future.result)
                    if type(begin) is str:
                        session.finish(escape(begin))
                elif o in ('-e', '--end'):
                    future = calculate(a)
                    end = await loop.run_in_executor(pool, future.result)
                    if type(end) is str:
                        session.finish(escape(end))
                elif o in ('-s', '--step'):
                    step = calculate(a)
                    begin = await loop.run_in_executor(pool, future.result)
                    if type(step) is str:
                        session.finish(escape(step))
    except (TimeoutError, _base.CancelledError):
        session.finish("time out!")
    if len(els) == 1:
        func_str = els[0].strip()
    elif len(args) != 0:
        func_str = args[0].strip()
    else:
        await session.send('请输入函数。')
    num = math.ceil((end - begin) / step)
    if num > 10000:
        session.finish('点数不能大于10000。')
    parser.reset()
    parser.setstate('x')
    try:
        result = parser.parse(func_str)
        if type(result) is float:
            result2 = result
            result = lambda *args: result2
        result(begin)
        x = numpy.linspace(begin, end, num)
        loop = asyncio.get_event_loop()
        # ufunc = numpy.frompyfunc(result, 1, 1)
        # future = _f(ufunc, x)
        with ThreadPool() as pool:
            future = pool.map(result, x, timeout=30)
            y = await loop.run_in_executor(None, lambda: list(future.result()))
    except (TimeoutError, _base.CancelledError):
        session.finish("time out!")
    except IndexError:
        session.finish('请输入一元函数。')
    except ParserError as e:
        session.finish('SyntaxError: ' + str(e))
    except Exception as e:
        session.finish(type(e).__name__ + ': ' + str(e))
    pyplot.clf()
    pyplot.plot(x, y)
    name = f'func_{hash(session.current_arg_text)}.png'
    pyplot.savefig(config.img(name))
    await session.send(config.cq.img(name))


'''
listy możemy modyfikować !
list[2] = x spowoduje zapisanie w list pod indeksem 2 wartość x
listy mogą mieć dowolne typy w liście ale przyjmuje się że są to dane tego samego typy !
do zamiany na liste urzywamy list(typ...)
jeżeli nie dajemy nawiasów [ ] domyślnie definuijemy tuple !!!
przy list musimy zawsze podać nawiasy [ ...,...]

'''
list1 = [] # tworzymy pustą listę którą możemy np: uzupełnić wartościami urzywając list1.append(value)
fruits = ['owoc', 'aple', 'lemon', 'aple'] #musimu! podać nawiasy kwaratowe ponieważ nie podanie domyslnie definiuje tuple a to jest lista
list(fruits) # do rzutowania na liste
tuple(fruits) # do tzutowania na tuple
word = 'samuraj'
a = list(word)
print(a)
b = tuple(word)
print(b)
# listy są mutowalne i kolejność jest zachowana
fruits.append('orange')
print(fruits)
fruits.remove('aple')
print(fruits)
del fruits[1]
print(fruits)


'''Module for rule-based phoneme to grapheme conversion (simple 1:1 alignment)'''
from dpgc import preprocessing
from dpgc import logger

# mappings according to consonant & vowel mappings in Eisenberg (2020) https://doi.org/10.1007/978-3-476-05096-0
# phonemes are encoded in DISC format (cf. CELEX German User Guide https://catalog.ldc.upenn.edu/docs/LDC96L14/gug_a4.pdf

CONVERSION_STRATEGIES = ["ignore_unknown"]

PGC = {
    # consonants
    "p": "p",
    "t": "t",
    "k": "k",
    "b": "b",
    "d": "d",
    "x": "ch",
    "v": "w",
    "j": "j",
    "h": "h",
    "m": "m",
    "g": "g",
    "f": "f",
    # note: Gla[s] not captured by context-free rules
    "z": "s",
    "s": "ß",
    "S": "sch",
    "n": "n",
    "N": "ng",
    "l": "l",
    "r": "r",

    # complex consonants
    "kv": "qu",
    "=": "z",
    "ks": "x",

    # vocals (stressed)
    "i": "ie",
    "y": "ü",
    "e": "e",
    "|": "ö",
    ")": "ä",
    "ɑ": "a",
    "o": "o",
    "u": "u",

    # vocals (unstressed)
    "I": "i",
    "Y": "ü",
    "E": "e",
    "/": "ö",
    "&": "a",
    "O": "o",
    "U": "u",

    # vocals (reduced)
    "@": "e",

    # diphthongs
    "W": "ei",
    "B": "au",
    "X": "eu"

}

def convert_phonemes2graphemes_pgc(phon_seq: str,
                                   strategy: str=CONVERSION_STRATEGIES[0],
                                   pgc_dict: dict = PGC,
                                   **kwargs):
    phon_seq_list_out = preprocessing.extract_tokens_list(phon_seq, **kwargs)

    if strategy:

        if strategy == CONVERSION_STRATEGIES[0]:
            graph_seq = ""

            for phon in phon_seq_list_out:
                try:
                    graph_seq += pgc_dict[phon]

                except KeyError:
                    pass

            return graph_seq

    elif not strategy:
        raise ValueError("No valid conversion strategy has been defined.")

if __name__ == "__main__":
    phonemes = "'&p-ve-z@nt"
    graphemes = convert_phonemes2graphemes_pgc(phonemes, complex_tokens = preprocessing.COMPLEX_PHONEMES,
                                               non_token_chars = preprocessing.NON_PHONEME_CHARS)
    logger.info(graphemes)


import argparse
from collections import OrderedDict
import glob
import os

import torch

from vidar.core.wrapper import Wrapper
from vidar.utils.config import read_config

from vidar.arch.networks.layers.selffsm.metrics import *
from vidar.arch.networks.layers.selffsm.implemented_dataset_cfg import \
    (DATASET2FRONT_IMG_PATH_UNDER_SCENARIO, DATASET2IMG_EXT,
     DATASET2DEFAULT_HW, DATASET2DEFAULT_VIEW_KEY, DATASET2DEFAULT_SCENARIO
     )

from vidar.utils.config import cfg_has
from vidar.utils.data import make_batch

def parser(feed_by_lst=None):
    """Parser for config"""
    parser = argparse.ArgumentParser(description='Project trained model ')
    parser.add_argument('cfg', type=str, help='Data downloaded directory')
    if feed_by_lst is not None:
        args = parser.parse_args(feed_by_lst)
    else:
        args = parser.parse_args()
    return args

class SescInference:
    """
    Wrapper for SESC to visualize the calibrated extrinsics and point clouds

    Parameters
    ----------
    cfg : Config
        Configuration file for model generation
    """

    def __init__(self, cfg, **kwargs):
        super().__init__()

        # Same to the run.py
        os.environ['DIST_MODE'] = 'gpu' if torch.cuda.is_available() else 'cpu'
        cfg = read_config(cfg, **kwargs)
        wrapper = Wrapper(cfg, verbose=True)
        wrapper.eval()

        # Set appropriately
        dataset_mode = "train"
        searched_scenario_from_path = cfg.arch.networks.extrinsics_net.search_scenario_from_path
        rgb_stored_under_scenario = DATASET2FRONT_IMG_PATH_UNDER_SCENARIO[cfg.arch.model.dataset]
        img_extension = DATASET2IMG_EXT[cfg.arch.model.dataset]
        self.ctx = cfg.arch.model.context
        self.use_gt_pose = cfg_has(cfg.arch.model, "use_gt_pose", False)

        # Process
        self.dataset_with_mode = wrapper.datasets[dataset_mode]
        scenarios = self._get_scenario_from_dict(searched_scenario_from_path)

        self.scenario2image_num = self._get_scenario2image(searched_scenario_from_path,
                                                           scenarios, rgb_stored_under_scenario, img_extension
                                                           )
        self.scenario2serial_num = OrderedDict({key: i for i, key in enumerate(scenarios)})
        self.bacth_id_now = None
        self.set_scenario = None
        self.fsm = wrapper.arch  # arch must be inheritance of the vidar.arch.models.perceiver.BaseFSM

        # set variables to pass CamViz
        self.hw = DATASET2DEFAULT_HW[cfg.arch.model.dataset]
        self.keys = DATASET2DEFAULT_VIEW_KEY[cfg.arch.model.dataset]
        self.first_scenario = DATASET2DEFAULT_SCENARIO[cfg.arch.model.dataset]

    def forward_fsm(self, batch: dict) -> dict:
        """Forward pass of the model, using a batch of data"""
        out = self.fsm.forward_scfsm(batch)

        self._print_extrinsics_errors(
            gt_transformation=out.extrinsics_gt[:, 1:, :, :],
            pred_transformation=out.ext_pred_forward[:, 1:, :, :]
        )

        return {
            "rgb": out.rgb,  # BrokenDict{ (ctx, cam_id): torch.Tensor(b, 1, h, w) }
            "intrinsics": out.intrinsics,
            "pred_depth": out.pred_depth,  # BrokenDict{ (ctx, cam_id): ScaleList[ torch.Tensor(b, 1, h, w) ] }
            "pred_pose": out.pred_from_main_cam,  # BrokenDict{ (ctx, cam_id): torch.Tensor(b, 4, 4) }
            "gt_pose": out.pose_gt_broken,  # BrokenDict{ (ctx, cam_id): torch.Tensor(b, 4, 4) }
        }

    def reload_batch(self, scenario: str, to=0) -> dict:
        """ Get batch from the scenario ID such as "000000" and "000150", ... """
        self.set_scenario = self._step_scenario(now_scenario=scenario, to=to)
        self.bacth_id_now = self._scenario2first_batch_idx(scenario=self.set_scenario)
        return self.__reload_batch_from_serial_num(self.bacth_id_now)

    def reload_next_scenario(self):
        """ Return next scenario's batch (e.g. "000016" -> "000017") """
        return self.reload_batch(scenario=self.set_scenario, to=1)

    def reload_previous_scenario(self):
        """ Return next scenario's batch (e.g. "000016" -> "000015") """
        return self.reload_batch(scenario=self.set_scenario, to=-1)

    @staticmethod
    def _get_scenario_from_dict(root_path: str):
        """
        Get scenario directory name each of which gives different extrinsics
        [NOTICE]
        * If scenario is also set by scene_id, it is ignored
        * All scenario is supposed to different extrinsics.
        * If you share the extrinsics to two or more scenario, use scene_id

        Parameters
        ----------
        root_path : str
            Path to get the scenario names

        Returns
        -------
        List[str]
            scenario list like ["000150", "000151", ..., ]
        """
        return [elem for elem in sorted(os.listdir(root_path)) if
                os.path.isdir(os.path.join(root_path, elem))]

    @staticmethod
    def _get_scenario2image(scenario_root: str, scenario_lst: list, under_scenario_path: str, ext=".png"):
        """Sample the image from the scenario, to visualize colored point clouds"""
        all_png_file_num = [len(glob.glob(os.path.join(scenario_root, scenario, under_scenario_path, "*" + ext))) for
                            scenario in scenario_lst]
        return OrderedDict({scenario: rgb_num for scenario, rgb_num in zip(scenario_lst, all_png_file_num)})

    def _step_scenario(self, now_scenario: str, to: int) -> str:
        """ Get the scenario name based on the key input """
        now_scenario_serial = self.scenario2serial_num[now_scenario]
        new_int = min(max(now_scenario_serial + to, 0), len(self.scenario2serial_num) - 1)
        if (new_int == 0 or new_int == len(self.scenario2serial_num) - 1):
            print("Skip scenario slide because it is the last one")
        serial2scenario = {v: k for k, v in self.scenario2serial_num.items()}  # swap the key and val
        next_str = serial2scenario[new_int]
        return next_str

    def _scenario2first_batch_idx(self, scenario: str):
        """
        Get the ID of the first timestep in each scenarion from the serial number of batch, such as
        {'000000': 50, '000001': 100, '000002': 100, }
        """
        scenario_id = list(self.scenario2image_num.keys()).index(scenario)
        stack_image_nums = list(self.scenario2image_num.values())[0:scenario_id]
        scenario_start_id = sum(stack_image_nums) - len(self.ctx) * scenario_id
        return scenario_start_id

    def __reload_batch_from_serial_num(self, idx):
        """Get desired batch based on the serial ID of all batche"""
        return make_batch(self.dataset_with_mode[idx])

    @staticmethod
    def _print_extrinsics_errors(gt_transformation: torch.Tensor, pred_transformation: torch.Tensor):
        """Print extrinsic relating errors on the terminal"""
        gt_tgts = gt_transformation
        pred_tgts = pred_transformation
        print("%%% EXTRINSICS %%%")
        print("GT-norm\t\t", multicam_norm(gt_tgts)[0].data)
        print("Pred-norm\t", multicam_norm(pred_tgts)[0].data)
        print("t\t\t", define_metrics()["t"](gt=gt_tgts, pred=pred_tgts)[0].data)
        print("tn\t\t", define_metrics()["tn"](gt=gt_tgts, pred=pred_tgts)[0].data)
        print("ta\t\t", define_metrics()["ta"](gt=gt_tgts, pred=pred_tgts)[0].data)
        print("ts\t\t", define_metrics()["ts"](gt=gt_tgts, pred=pred_tgts)[0].data)
        print("rot\t\t", define_metrics()["rot"](gt=gt_tgts, pred=pred_tgts)[0].data)

        pass


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu May 14 20:58:35 2020

@author: shawvey
"""

# calculate the estimate firing rate for 'on' and 'off'
import matplotlib.pyplot as plt
import numpy as np
import random as rand
import math

def Simulation_on(t, Tau_m, Tau_s, El, Vrest, Vth, Rm, Ie, g , Es, delta_s, delta_t, fire_rate, N, A_plus, A_minus, Tau_plus, Tau_minus, flag):
    S = [0]*N
    pre_st = [0]*N
    g_bar = [g]*N
    post_st = -1500
    timeSteps = int(t/delta_t)
    Vol=[0]*timeSteps
    Vol[0] = Vrest
    g_ = g
    count=0
    for i in range(0, timeSteps-1):
        for r in range(0, N):
            S[r]=S[r]-S[r]*delta_t/Tau_s
            randnum = rand.uniform(0,1)
            if (randnum < fire_rate * delta_t and flag == 'on'): # pre_s
                S[r]+=delta_s
                time_diff = post_st - i*delta_t
                if(time_diff > 0):
                    g_bar[r] = g_bar[r] + A_plus * math.exp(-1*abs(time_diff)/Tau_plus)
                else:
                    g_bar[r] = g_bar[r] - A_minus * math.exp(-1*abs(time_diff)/Tau_minus)
                if(g_bar[r] < 0):
                    g_bar[r] = 0
                pre_st[r] = i*delta_t

        if(Vol[i] > Vth and flag == 'on'):  # post
            if(i>1079999):
                count+=1
            Vol[i] = Vrest
            for j in range(0,N):
                time_diff = i*delta_t - pre_st[j]
                if(time_diff > 0):
                    g_bar[j] = g_bar[j] + A_plus * math.exp(-1*abs(time_diff)/Tau_plus)
                else:
                    g_bar[j] = g_bar[j] - A_minus * math.exp(-1*abs(time_diff)/Tau_minus)
                if(g_bar[j] > g_):
                    g_bar[j] = g_
            post_st = i*delta_t

        gsst = 0

        for q in range(0,N):
            gsst += S[q]*g_bar[q]

        Vol[i+1] = Vol[i]+(El-Vol[i]+Rm*Ie+Rm*gsst*(Es-Vol[i]))*delta_t/Tau_m
    g_mean = np.mean(g_bar)
    return count/30,g_mean

def Simulation_off(t, Tau_m, Tau_s, El, Vrest, Vth, Rm, Ie, g , Es, delta_s, delta_t, fire_rate, N, A_plus, A_minus, Tau_plus, Tau_minus, flag):
    S = [0]*N
    timeSteps = int(t/delta_t)
    Vol=[0]*timeSteps
    Vol[0] = Vrest
    count=0
    for i in range(0, timeSteps-1):
        for r in range(0, N):
            S[r]=S[r]-S[r]*delta_t/Tau_s
            randnum = rand.uniform(0,1)
            if (randnum < fire_rate * delta_t): # pre_s
                S[r]+=delta_s
        if(Vol[i] > Vth):  # post
            if(i>1079999): # last 30seconds
                count+=1
            Vol[i] = Vrest
        sums = np.sum(S)
        Vol[i+1] = Vol[i]+(El-Vol[i]+Rm*Ie+Rm*g*sums*(Es-Vol[i]))*delta_t/Tau_m
    return count/30

######### Part B

#### Question 2

t = 300*1000
Tau_m = 10
El = -65
Vrest = -65
Vth = -50
Rm = math.pow(10, 11)
Ie = 0
N = 40
g = 4*math.pow(10, -12)
delta_s = 0.5
Tau_s = 2
Es = 0
delta_t = 0.25
fire_rate = 15*math.pow(10, -3)
A_plus = 0.2*math.pow(10, -12)
A_minus = 0.25*math.pow(10, -12)
Tau_plus = 20
Tau_minus = 20

### flag = on
flag = 'on'
print('------ flag = on ------')
fire_rate_on = 0
g_off = 0

for x in range(0,4):
    fire_rate1, g_mean = Simulation_on(t, Tau_m, Tau_s, El, Vrest, Vth, Rm, Ie, g , Es, delta_s, delta_t, fire_rate, N, A_plus, A_minus, Tau_plus, Tau_minus, flag)
    fire_rate_on += fire_rate1
    g_off += g_mean
print(fire_rate_on/4)
print(g_off/4)
g_off = g_off/4
### flag = off
flag = 'off'
print('------ flag = off ------')
fire_rate2 = 0
for x in range(0,4):
    fire_rate2 += Simulation_off(t, Tau_m, Tau_s, El, Vrest, Vth, Rm, Ie, g_off , Es, delta_s, delta_t, fire_rate, N, A_plus, A_minus, Tau_plus, Tau_minus, flag)
print(fire_rate2/4)


from plumbum import local
import dendropy
import pandas as pd
from sequencing.phylo.utils import fix_directories, add_root_to_dict

symbols = ['A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 'S', 'T', 'W', 'Y', 'V']
symbol_map = {i+7: s for i, s in enumerate(symbols)}
fasttree = local["/home/dcsoft/s/ron/usefull_apps/fasttree_new/FastTree"]
fasttree_trans_noa = fasttree['-trans', '/home/dcsoft/s/Ofir/noa_for_fasttree_scientific.mat']
fasttree_pseudo = fasttree['-pseudo']
fasttree_pseudo_trans_noa = fasttree_pseudo['-trans', '/home/dcsoft/s/Ofir/noa_for_fasttree_scientific.mat']
fasttree_pseudo_trans_unified = fasttree_pseudo['-trans', '/home/dcsoft/s/Ofir/unified_for_fastree_asaf.mat']
fasttree_trans_unifed = fasttree['-trans', '/home/dcsoft/s/Ofir/unified_for_fastree_asaf.mat']

def create_FastTree_fasta_file(td, rldr, ind_name, title, min_group_size, rldr_group):
    td_with_root = add_root_to_dict(td, rldr)
    df = pd.DataFrame.from_dict(td_with_root)
    vs = list(v for vs in td_with_root.values() for v in vs.values())
    for i in range(min(vs), max(vs) + 4):
        if i not in symbol_map:
            symbol_map[i] = '-'

    df.replace(symbol_map, inplace=True)
    df.fillna("-", inplace=True)
    normalized_fasta_dir = fix_directories("/home/dcsoft/s/trees", ind_name)
    normalized_fasta_path = '{}/{}_{}_FastTree_g{}_root_{}.fasta'.format(normalized_fasta_dir, title, ind_name,
                                                                   min_group_size, rldr_group)
    with open(normalized_fasta_path, 'w') as f:
        for sr, row in df.iterrows():
            f.write('>{}\r\n{}\r\n'.format(sr, ''.join(row.values)))

    return normalized_fasta_path

def run_fasttree_binary(newick_output_file, mutations_fasta_path, variation=fasttree_pseudo_trans_noa):
    variation('-out', newick_output_file, mutations_fasta_path)
    good_tree = dendropy.Tree.get_from_path(
        newick_output_file,
        "newick")
    return good_tree

def run_fastree(fasta_path, ind_name, title, min_group_size, rldr_group):
    newick_output_files = []
    normalized_newick_dir = fix_directories("/home/dcsoft/s/trees", ind_name)
    for name, method, kwargs in [
        ('FTPU', 'fasttree_pseudo_trans_unified', {'variation': fasttree_pseudo_trans_unified}),
    ]:
        newick_output_file = '{}/{}_{}_g{}_{}_root_{}.newick'.format(normalized_newick_dir, title, ind_name,
                                                                     min_group_size, method, rldr_group)
        ret_tree = run_fasttree_binary(newick_output_file, fasta_path, list(kwargs.values())[0])
        newick_output_files.append(newick_output_file)

    return newick_output_files

def unroot_FastTree_tree(newick_output_file):
    rooted_tree = dendropy.Tree.get_from_path(newick_output_file, "newick")
    rooted_tree.reroot_at_node(rooted_tree.find_node_with_taxon_label('root'), update_bipartitions=False)
    tree = dendropy.Tree.get_from_string(rooted_tree.as_string('newick', suppress_rooting=False).replace('root', ''), 'newick')
    tree.ladderize(ascending=False)
    return tree


import matplotlib.pyplot as plt
import networkx as nx
import matplotlib.colors as mcolors
import numpy as np
import matplotlib.cm as cm

def draw(G, pos, measures, measure_name):

    nodes = nx.draw_networkx_nodes(G, pos, node_size=250, cmap=plt.cm.plasma,
                                   node_color=list(measures.values()),
                                   nodelist=measures.keys())
    nodes.set_norm(mcolors.SymLogNorm(linthresh=0.01, linscale=1, base=10))
    # labels = nx.draw_networkx_labels(G, pos)
    edges = nx.draw_networkx_edges(G, pos)

    plt.title(measure_name)
    plt.colorbar(nodes)
    plt.axis('off')
    plt.show()
G=nx.powerlaw_cluster_graph(10,2,0.5)
pos = nx.spring_layout(G, seed=675)
draw(G,pos, nx.degree_centrality(G), 'Degree Centrality')
draw(G, pos, nx.pagerank(G), 'PageRank Centrality')
draw(G, pos, nx.betweenness_centrality(G), 'Betweenness Centrality')
draw(G, pos, nx.eigenvector_centrality(G), 'Eigenvector Centrality')


from ckan.exceptions import CkanConfigurationException

import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit

class Example_ThemePlugin(plugins.SingletonPlugin):
    plugins.implements(plugins.IConfigurer, inherit=True)

    def update_config(self, config):
        plugins = config['ckan.plugins'].split(' ')
        if 'recline_view' not in plugins:
            raise CkanConfigurationException(
                'You provided an invalid value for ckan.plugins. '
                'The "example_theme" plugin requires the "recline_view" plugin. '
                'Add "recline_view" to ckan.plugins.'
            )
        if plugins.index('example_theme') > plugins.index('recline_view'):
            raise CkanConfigurationException(
                'You provided an invalid value for ckan.plugins. '
                'The "example_theme" plugin must be before "recline_view". Change the order of the plugins.'
                'Move "recline_view" after "example_theme" in ckan.plugins.'
            )
        toolkit.add_template_directory(config, 'templates')
        toolkit.add_resource('public', 'example_theme')


#최신영화 뽑아내보기...
import requests

def open_name():
    pass
    #영화진흥위원회에서 일별 박스오피스 서비스 데이터를 받아온다
    URL = 'http://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=f5eef3421c602c6cb7ea224104795888&targetDt=20120101'

    response = requests.get(URL).json()
    print(response)
    # 받아온 데이터에서 dict(boxOfficeResult) 자료에서 dict(dailyBoxOfficeList)를 추출한다.
    daily_list = response.get('boxOfficeResult').get('dailyBoxOfficeList')
    # print(daily_list)
   # 필요한 변수값 초기화
    open = []
    name = []
    new_list = []
    movie_new = {}

    for i in range(len(daily_list)):
        open.append(daily_list[i]['openDt'])    # 받아온자료에서 오픈날자만 뽑아서 리스트화
    # print(open)
    for i in range(len(daily_list)):
        name.append(daily_list[i]['movieNm'])   # 받아온자료에서 이름만 뽑아서 리스트화
    # print(name)
    for j in range(len(daily_list)):
        year, mon, day =map(int, open[j].split('-'))    #날짜를 년 월 일 로 나누어
    for k in range(len(open)):                          #날짜 : 이름 형식으로 딕셔너리에 넣는다
        movie_new[open[k]] = name[k]

    for date in open:                       # 2011년 미만이면 최신영화 아닌걸로 판단하고 제거
        year, mon, day = map(int, date.split('-'))
        if year < 2011:
            movie_new.pop(date)
    # print(movie_new)
    final = list(movie_new.values())        # 남은 자료들중 제목만 추출
    return final

# 아래의 코드는 수정하지 않습니다.
if __name__ == '__main__':
    """
    open_name 최신영화 제목 반환
    """
    print(open_name())


from django.http import HttpResponse
from django.http import Http404
from django.shortcuts import render,render_to_response
from django.forms.models import model_to_dict

from models import Genesets,GenesetsTable

# Construct verbosename/name pair
GenesetFields = []
for f in Genesets._meta.fields:
    GenesetFields.append((f.verbose_name, f.name))

excludeFields = ['label']

def geneset(request, gs):
    '''Handles requests for a particular geneset specified by the gs
    parameter.
    '''
    try:
        #g = Genesets.objects.filter(label=gs)
        g = Genesets.objects.get(label=gs)
    except Genesets.DoesNotExist:
        raise Http404

#    g = Genesets.objects.get(label=gs)
#    if (g.count() == 0):
#        raise Http404

    if g.detailsurl:
        g.detailsurl = 'Link'

    if g.pubmed:
        g.pubmed = r'' + g.pubmed + ''

    exportFields = []
    for f in GenesetFields:
        val = eval('g.%s' % (f[1],))
        if (not val) or \
            (f[1] in excludeFields): # Skip empty columns and some fields
            continue
        exportFields.append((f[0], val))

    return render(request, 'genesets/geneset.html', locals())


from __future__ import print_function
import argparse
import requests
import json
import sys
from datetime import datetime
from dateutil.parser import parse

def parse_cmdline_args():
    """Parse the command line options and set some useful defaults"""
    parser = argparse.ArgumentParser(
        description='Download raw flows from SP Insight to a CSV file',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '-s', '--start_time',
        dest='start',
        required=True,
        help='Start date and time for rawflows')
    parser.add_argument(
        '-e', '--end_time',
        dest='end',
        required=True,
        help='End date and time for rawflows')
    parser.add_argument(
        '-l', '--sp_leader',
        dest='leader',
        required=True,
        help='Hostname or IP address of the SP leader')
    parser.add_argument(
        '-k', '--api_key',
        dest='apikey',
        required=True,
        help='SP REST API key for the leader')
    parser.add_argument(
        '-n', '--number_of_raw_flow_records',
        type=int,
        default=5000,
        dest='num_records',
        help='Maximum number of raw flows records to return')
    parser.add_argument(
        '-p', '--perspective',
        default='network',
        dest='perspective',
        help='Perspective from which to get the raw flows')
    parser.add_argument(
        '-v', '--view',
        default='Network',
        dest='view',
        help='View from which to get the raw flows')
    parser.add_argument(
        '-o', '--output_file',
        default='raw_flows.csv',
        dest='output_file',
        help='Path and filename for rawflows CSV data')
    parser.add_argument(
        '-c', '--cert_file',
        default='/Users/acaird/certfile',
        dest='certfile',
        help='Path to and name of the SSL certificate file')

    return parser.parse_args()

if __name__ == '__main__':

    args = parse_cmdline_args()

    leaderurl = 'https://{}/api/sp/insight/rawflows'.format(args.leader)

    # Use Python's parse/fuzzy date interpreter to try to get useful dates
    try:
        start = parse(args.start, fuzzy=True).isoformat()
        end = parse(args.end, fuzzy=True).isoformat()
    except ValueError:
        print ("ERROR: I couldn't parse the dates you provided ("
               "start: {}, end: {}), please try another format.".format(
                   args.start, args.end))
        sys.exit(1)

    query = {
        "start": start,
        "end": end,
        "dimensions": [
            "IP_Protocol",
            "Source_IPv4_Address",
            "Source_Port",
            "Destination_IPv4_Address",
            "Destination_Port"
        ],
        "limit": args.num_records,
        "perspective": args.perspective,
        "view": args.view
    }

    print ("  Querying {} for {} raw flows records between {} and {}...".
           format(
               args.leader,
               args.num_records,
               start,
               end))

    query_start = datetime.now()
    answer = requests.post(leaderurl,
                           headers={"X-Arbux-APIToken": args.apikey,
                                    "Content-Type": "application/vnd.api+json",
                                    "Accept": "text/csv"},
                           data=json.dumps(query), verify=args.certfile,
                           stream=True)
    query_end = datetime.now()
    with open(args.output_file, "wb") as f:
        for i, chunk in enumerate(answer.iter_content(chunk_size=262144)):
            print ("  Writing chunk #{} to {}".format(i, args.output_file),
                   end='\r')
            f.write(chunk)

    write_end = datetime.now()

    # Print some timing information
    print ('')
    print ("Query time: {0:10.1f} seconds".format(
        ((query_end-query_start).total_seconds())))
    print ("Write time: {0:10.1f} seconds".format(
        ((write_end-query_end).total_seconds())))
    print ("Total time: {0:10.1f} seconds".format(
        ((write_end-query_start).total_seconds())))


import logging
import pytest
import os
from datetime import datetime
from lib389._constants import DEFAULT_SUFFIX, INSTALL_LATEST_CONFIG
from lib389.properties import BACKEND_SAMPLE_ENTRIES, TASK_WAIT
from lib389.topologies import topology_st as topo
from lib389.backend import Backend
from lib389.tasks import BackupTask, RestoreTask
from lib389.config import BDB_LDBMConfig
from lib389 import DSEldif
from lib389.utils import ds_is_older, get_default_db_lib
import tempfile

pytestmark = pytest.mark.tier1

DEBUGGING = os.getenv("DEBUGGING", default=False)
if DEBUGGING:
    logging.getLogger(__name__).setLevel(logging.DEBUG)
else:
    logging.getLogger(__name__).setLevel(logging.INFO)
log = logging.getLogger(__name__)

def test_missing_backend(topo):
    """Test that an error is returned when a restore is performed for a
    backend that is no longer present.

    :id: 889b8028-35cf-41d7-91f6-bc5193683646
    :setup: Standalone Instance
    :steps:
        1. Create a second backend
        2. Perform a back up
        3. Remove one of the backends from the config
        4. Perform a restore
    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Failure
    """

    # Create a new backend
    BE_NAME = 'backupRoot'
    BE_SUFFIX = 'dc=back,dc=up'
    props = {
        'cn': BE_NAME,
        'nsslapd-suffix': BE_SUFFIX,
        BACKEND_SAMPLE_ENTRIES: INSTALL_LATEST_CONFIG
    }
    be = Backend(topo.standalone)
    backend_entry = be.create(properties=props)

    # perform backup
    backup_dir_name = "backup-%s" % datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
    archive = os.path.join(topo.standalone.ds_paths.backup_dir, backup_dir_name)
    backup_task = BackupTask(topo.standalone)
    task_properties = {'nsArchiveDir': archive}
    backup_task.create(properties=task_properties)
    backup_task.wait()
    assert backup_task.get_exit_code() == 0

    # Remove new backend
    backend_entry.delete()

    # Restore the backup - it should fail
    restore_task = RestoreTask(topo.standalone)
    task_properties = {'nsArchiveDir': archive}
    restore_task.create(properties=task_properties)
    restore_task.wait()
    assert restore_task.get_exit_code() != 0

@pytest.mark.bz1851967
@pytest.mark.ds4112
@pytest.mark.skipif(ds_is_older('1.4.1'), reason="Not implemented")
@pytest.mark.skipif(get_default_db_lib() == "mdb", reason="Not supported over mdb")
def test_db_home_dir_online_backup(topo):
    """Test that if the dbhome directory is set causing an online backup to fail,
    the dblayer_backup function should go to error processing section.

    :id: cfc495d6-2a58-4e4e-aa40-39a15c71f973
    :setup: Standalone Instance
    :steps:
        1. Change the dbhome to directory to eg-/tmp/test
        2. Perform an online back-up
        3. Check for the correct errors in the log
    :expectedresults:
        1. Success
        2. Failure
        3. Success
    """
    bdb_ldbmconfig = BDB_LDBMConfig(topo.standalone)
    dseldif = DSEldif(topo.standalone)
    topo.standalone.stop()
    with tempfile.TemporaryDirectory() as backup_dir:
        dseldif.replace(bdb_ldbmconfig.dn, 'nsslapd-db-home-directory', f'{backup_dir}')
        topo.standalone.start()
        topo.standalone.tasks.db2bak(backup_dir=f'{backup_dir}', args={TASK_WAIT: True})
        assert topo.standalone.ds_error_log.match(f".*Failed renaming {backup_dir}.bak back to {backup_dir}")

if __name__ == '__main__':
    # Run isolated
    # -s for DEBUG mode
    CURRENT_FILE = os.path.realpath(__file__)
    pytest.main(["-s", CURRENT_FILE])


from typing import Any, Dict, Optional, Type, TypeVar, Union

import pydantic
from pydantic import schema_of
from pydantic.error_wrappers import ErrorWrapper, ValidationError
from pydantic.main import ROOT_KEY
from pydantic.tools import NameFactory, parse_obj_as
from simdjson import Parser

from simdjson_schemaful import loads
from simdjson_schemaful.parser import Schema

class ModelMetaclass(pydantic.main.ModelMetaclass):
    def __new__(cls, *args: Any, **kwargs: Any) -> type:
        ret = super().__new__(cls, *args, **kwargs)
        _REGISTRY[ret] = ret.schema()
        return ret

T = TypeVar("T")
_REGISTRY: Dict[ModelMetaclass, Schema] = {}

class BaseModel(pydantic.BaseModel, metaclass=ModelMetaclass):
    @classmethod
    def parse_raw_simdjson(
        cls,
        b: Union[str, bytes],
        parser: Optional[Parser] = None,
    ) -> "BaseModel":
        try:
            obj = loads(b, schema=_REGISTRY[cls], parser=parser)
        except (ValueError, TypeError, UnicodeDecodeError) as e:
            raise ValidationError([ErrorWrapper(e, loc=ROOT_KEY)], cls)
        return cls.parse_obj(obj)

def parse_raw_simdjson_as(
    type_: Type[T],
    b: Union[str, bytes],
    *,
    parser: Optional[Parser] = None,
    type_name: Optional[NameFactory] = None,
    **_: Any,
) -> T:
    schema = schema_of(type_)  # already cached in pydantic
    obj = loads(b, schema=schema, parser=parser)
    return parse_obj_as(type_, obj, type_name=type_name)


def is_index_in_range(idx, seq):
    if 0 <= idx < len(seq):
        return True
    return False

pirate_ship = [int(x) for x in input().split(">")]
warship = [int(x) for x in input().split(">")]
max_health = int(input())

is_running = True
while is_running:
    line = input()
    if line == "Retire":
        break

    command_args = line.split()
    command = command_args[0]

    if command == "Fire":
        idx = int(command_args[1])
        damage = int(command_args[2])
        if not is_index_in_range(idx, warship):
            continue
        warship[idx] -= damage
        if warship[idx] <= 0:
            is_running = False
            print("You won! The enemy ship has sunken.")

    elif command == "Defend":
        start_idx = int(command_args[1])
        end_idx = int(command_args[2])
        damage = int(command_args[3])
        if not is_index_in_range(start_idx, pirate_ship) or not is_index_in_range(end_idx, pirate_ship):
            continue
        for idx in range(start_idx, end_idx + 1):
            pirate_ship[idx] -= damage
            if pirate_ship[start_idx] <= 0:
                is_running = False
                print("You lost! The pirate ship has sunken.")
                break

    elif command == "Repair":
        idx = int(command_args[1])
        health = int(command_args[2])
        if not is_index_in_range(idx, pirate_ship):
            continue
        pirate_ship[idx] = min(max_health, pirate_ship[idx] + health)

    elif command == "Status":
        counter = 0
        for idx in pirate_ship:
            if idx < 0.2 * max_health:
                counter += 1
        print(f"{counter} sections need repair.")

if is_running:
    print(f"Pirate ship status: {sum(pirate_ship)}")
    print(f"Warship status: {sum(warship)}")