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

from collections import OrderedDict

from paddle import fluid
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.regularizer import L2Decay

__all__ = ['MultiClassNMS', 'YOLOv3Head']

class MultiClassNMS(object):
    # __op__ = fluid.layers.multiclass_nms
    def __init__(self, background_label, keep_top_k, nms_threshold, nms_top_k, normalized, score_threshold):
        super(MultiClassNMS, self).__init__()
        self.background_label = background_label
        self.keep_top_k = keep_top_k
        self.nms_threshold = nms_threshold
        self.nms_top_k = nms_top_k
        self.normalized = normalized
        self.score_threshold = score_threshold

class YOLOv3Head(object):
    """Head block for YOLOv3 network

    Args:
        norm_decay (float): weight decay for normalization layer weights
        num_classes (int): number of output classes
        ignore_thresh (float): threshold to ignore confidence loss
        label_smooth (bool): whether to use label smoothing
        anchors (list): anchors
        anchor_masks (list): anchor masks
        nms (object): an instance of `MultiClassNMS`
    """

    def __init__(self,
                 norm_decay=0.,
                 num_classes=80,
                 ignore_thresh=0.7,
                 label_smooth=True,
                 anchors=[[10, 13], [16, 30], [33, 23], [30, 61], [62, 45], [59, 119], [116, 90], [156, 198],
                          [373, 326]],
                 anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]],
                 nms=MultiClassNMS(
                     background_label=-1,
                     keep_top_k=100,
                     nms_threshold=0.45,
                     nms_top_k=1000,
                     normalized=True,
                     score_threshold=0.01),
                 weight_prefix_name=''):
        self.norm_decay = norm_decay
        self.num_classes = num_classes
        self.ignore_thresh = ignore_thresh
        self.label_smooth = label_smooth
        self.anchor_masks = anchor_masks
        self._parse_anchors(anchors)
        self.nms = nms
        self.prefix_name = weight_prefix_name

    def _conv_bn(self, input, ch_out, filter_size, stride, padding, act='leaky', is_test=True, name=None):
        conv = fluid.layers.conv2d(
            input=input,
            num_filters=ch_out,
            filter_size=filter_size,
            stride=stride,
            padding=padding,
            act=None,
            param_attr=ParamAttr(name=name + ".conv.weights"),
            bias_attr=False)

        bn_name = name + ".bn"
        bn_param_attr = ParamAttr(regularizer=L2Decay(self.norm_decay), name=bn_name + '.scale')
        bn_bias_attr = ParamAttr(regularizer=L2Decay(self.norm_decay), name=bn_name + '.offset')
        out = fluid.layers.batch_norm(
            input=conv,
            act=None,
            is_test=is_test,
            param_attr=bn_param_attr,
            bias_attr=bn_bias_attr,
            moving_mean_name=bn_name + '.mean',
            moving_variance_name=bn_name + '.var')

        if act == 'leaky':
            out = fluid.layers.leaky_relu(x=out, alpha=0.1)
        return out

    def _detection_block(self, input, channel, is_test=True, name=None):
        assert channel % 2 == 0, \
            "channel {} cannot be divided by 2 in detection block {}" \
            .format(channel, name)

        conv = input
        for j in range(2):
            conv = self._conv_bn(
                conv, channel, filter_size=1, stride=1, padding=0, is_test=is_test, name='{}.{}.0'.format(name, j))
            conv = self._conv_bn(
                conv, channel * 2, filter_size=3, stride=1, padding=1, is_test=is_test, name='{}.{}.1'.format(name, j))
        route = self._conv_bn(
            conv, channel, filter_size=1, stride=1, padding=0, is_test=is_test, name='{}.2'.format(name))
        tip = self._conv_bn(
            route, channel * 2, filter_size=3, stride=1, padding=1, is_test=is_test, name='{}.tip'.format(name))
        return route, tip

    def _upsample(self, input, scale=2, name=None):
        out = fluid.layers.resize_nearest(input=input, scale=float(scale), name=name)
        return out

    def _parse_anchors(self, anchors):
        """
        Check ANCHORS/ANCHOR_MASKS in config and parse mask_anchors

        """
        self.anchors = []
        self.mask_anchors = []

        assert len(anchors) > 0, "ANCHORS not set."
        assert len(self.anchor_masks) > 0, "ANCHOR_MASKS not set."

        for anchor in anchors:
            assert len(anchor) == 2, "anchor {} len should be 2".format(anchor)
            self.anchors.extend(anchor)

        anchor_num = len(anchors)
        for masks in self.anchor_masks:
            self.mask_anchors.append([])
            for mask in masks:
                assert mask < anchor_num, "anchor mask index overflow"
                self.mask_anchors[-1].extend(anchors[mask])

    def _get_outputs(self, input, is_train=True):
        """
        Get YOLOv3 head output

        Args:
            input (list): List of Variables, output of backbone stages
            is_train (bool): whether in train or test mode

        Returns:
            outputs (list): Variables of each output layer
        """

        outputs = []

        # get last out_layer_num blocks in reverse order
        out_layer_num = len(self.anchor_masks)
        if isinstance(input, OrderedDict):
            blocks = list(input.values())[-1:-out_layer_num - 1:-1]
        else:
            blocks = input[-1:-out_layer_num - 1:-1]
        route = None
        for i, block in enumerate(blocks):
            if i > 0:  # perform concat in first 2 detection_block
                block = fluid.layers.concat(input=[route, block], axis=1)
            route, tip = self._detection_block(
                block, channel=512 // (2**i), is_test=(not is_train), name=self.prefix_name + "yolo_block.{}".format(i))

            # out channel number = mask_num * (5 + class_num)
            num_filters = len(self.anchor_masks[i]) * (self.num_classes + 5)
            block_out = fluid.layers.conv2d(
                input=tip,
                num_filters=num_filters,
                filter_size=1,
                stride=1,
                padding=0,
                act=None,
                param_attr=ParamAttr(name=self.prefix_name + "yolo_output.{}.conv.weights".format(i)),
                bias_attr=ParamAttr(
                    regularizer=L2Decay(0.), name=self.prefix_name + "yolo_output.{}.conv.bias".format(i)))
            outputs.append(block_out)

            if i < len(blocks) - 1:
                # do not perform upsample in the last detection_block
                route = self._conv_bn(
                    input=route,
                    ch_out=256 // (2**i),
                    filter_size=1,
                    stride=1,
                    padding=0,
                    is_test=(not is_train),
                    name=self.prefix_name + "yolo_transition.{}".format(i))
                # upsample
                route = self._upsample(route)

        return outputs, blocks

    def get_prediction(self, outputs, im_size):
        """
        Get prediction result of YOLOv3 network

        Args:
            outputs (list): list of Variables, return from _get_outputs
            im_size (Variable): Variable of size([h, w]) of each image

        Returns:
            pred (Variable): The prediction result after non-max suppress.

        """
        boxes = []
        scores = []
        downsample = 32
        for i, output in enumerate(outputs):
            box, score = fluid.layers.yolo_box(
                x=output,
                img_size=im_size,
                anchors=self.mask_anchors[i],
                class_num=self.num_classes,
                conf_thresh=self.nms.score_threshold,
                downsample_ratio=downsample,
                name=self.prefix_name + "yolo_box" + str(i))
            boxes.append(box)
            scores.append(fluid.layers.transpose(score, perm=[0, 2, 1]))

            downsample //= 2

        yolo_boxes = fluid.layers.concat(boxes, axis=1)
        yolo_scores = fluid.layers.concat(scores, axis=2)
        pred = fluid.layers.multiclass_nms(
            bboxes=yolo_boxes,
            scores=yolo_scores,
            score_threshold=self.nms.score_threshold,
            nms_top_k=self.nms.nms_top_k,
            keep_top_k=self.nms.keep_top_k,
            nms_threshold=self.nms.nms_threshold,
            background_label=self.nms.background_label,
            normalized=self.nms.normalized,
            name="multiclass_nms")
        return pred


# In this program, if we are given any number in binary form,
# then we will learn to convert that number in decimal form.xx
# content.

a = [1, 0, 0, 1, 1, 0, 1, 1]

i=1
c=0
sum=0
while i<=len(a):
    b=a[-i]
    sum+=(a[-i]*(2**c))
    c=c+1
    i=i+1
    print(sum)


import scrapy
import os

class MainSpider(scrapy.Spider):

    name = "example"

    base_url = "https://www.springfieldspringfield.co.uk/episode_scripts.php?tv-show="

    series = ["how-i-met-your-mother",
              "disenchantment-2018"
              ]
    start_urls = []

    for e in series:
        start_urls.append(base_url+e);

    def parse(self,response):

        for url in response.css(".season-episodes > "
                                ".season-episode-title"
                                "::attr('href')").extract():
            yield scrapy.Request(response.urljoin(url),self.parse_script)

    def parse_script(self,response):

        series_name = response.url.split("tv-show=")[1].split("&")[0]

        if not os.path.exists(series_name):
            os.mkdir(series_name)
        filename = response.url.split("&")[1]

        result = "\n".join(response.css("#content_container > div.main-content > "
                                        "div.main-content-left > div.episode_script > "
                                        "div.scrolling-script-container::text").getall())
        self.write_to_file(f"{series_name}/{filename}.txt",result)

    def write_to_file(self,filename,result):
        with open(filename,"w") as f:
            f.write(result)


"""
Create functions that double, triple, quadruple the number received as a parameter.
"""

def multiplier(mult):
    def multi(number):
        return number * mult
    return multi

double = multiplier(2)
triple = multiplier(3)
quadruple = multiplier(4)

print(double(7))
print(triple(7))
print(quadruple(7))


class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        # https://walkccc.me/LeetCode/problems/0169/

        # https://youtu.be/7pnhv842keE

        res = None
        count = 0

        for num in nums:
            if count == 0:
                res = num
            count += (1 if num == res else -1)
        return res


import torch.nn as nn
import torch
import numpy as np
import string
from utils import jaccard, AverageMeter, cal_jaccard, cal_accucary, load_model
from tqdm import tqdm
import time
from scipy.special import softmax

def KSLoss(preds, target):
    pred_cdf = torch.cumsum(torch.softmax(preds, dim=1), dim=1)
    target_cdf = torch.cumsum(target, dim=1)
    error = (target_cdf - pred_cdf)**2
    return torch.mean(error)

def custLoss(preds, target):
    pred = torch.argmax(torch.softmax(preds, axis=1), axis=1)
    target = torch.argmax(target, axis=1)
    return torch.sum((target-pred)**2)

def EntropyLoss(o1, o2, t1, t2):
    t1 = torch.argmax(t1, axis=1)
    t2 = torch.argmax(t2, axis=1)
    CE = nn.CrossEntropyLoss()
    l1 = CE(o1, t1)
    l2 = CE(o2, t2)

    return l1 + l2

def BcwLoss(o1, o2, t1, t2):
    bcw = nn.BCEWithLogitsLoss()
    l1 = bcw(o1, t1)
    l2 = bcw(o2, t2)
    return l1 + l2

def loss_fn(*loss):
    return sum(loss)

def trn_loop_fn(data_loader, model, optimzer, device):
    model.train()
    tk = tqdm(data_loader, total=len(data_loader))
    losses = AverageMeter()

    for i, d in enumerate(tk):
        ids = d['ids']
        mask_ids = d['mask_ids']
        token_type_ids = d['token_type_ids']
        target_start_idx = d['target_start_idx']
        target_end_idx = d['target_end_idx']
        offsets = d['offsets']
        orig_sentiment = d['orig_sentiment']
        orig_sele_text = d['orig_sele_text']
        orig_text = d['orig_text']
        targ_sentiment = d['targ_sentiment']

        ids = ids.to(device, dtype=torch.long)
        mask_ids = mask_ids.to(device, dtype=torch.long)
        token_type_ids = token_type_ids.to(device, dtype=torch.long)
        target_start_idx = target_start_idx.to(device, dtype=torch.float)
        target_end_idx = target_end_idx.to(device, dtype=torch.float)
        targ_sentiment = targ_sentiment.to(device, dtype=torch.long)

        optimzer.zero_grad()
        o1, o2 = model(ids, mask_ids, token_type_ids)

        #loss = EntropyLoss(o1, o2, target_start_idx, target_end_idx)
        loss = BcwLoss(o1, o2, target_start_idx, target_end_idx)
        #loss = loss_fn(loss1, loss2)

        loss.backward()
        optimzer.step()
        losses.update(loss.item(), ids.size(0))
        tk.set_postfix(loss=losses.avg)

def eval_loop_fn(data_loader, model,  device, df_type, rm_length):
    model.eval()

    fin_output_start = []
    fin_output_end = []
    fin_output_sentiment = []
    fin_offset = []
    fin_orig_sentiment = []
    fin_orig_selected = []
    fin_orig_text = []
    fin_targ_sentiment = []

    for bi, d in enumerate(data_loader):
        ids = d['ids']
        mask_ids = d['mask_ids']
        token_type_ids = d['token_type_ids']
        target_start_idx = d['target_start_idx']
        target_end_idx = d['target_end_idx']
        offsets = d['offsets']
        orig_sentiment = d['orig_sentiment']
        orig_sele_text = d['orig_sele_text']
        orig_text = d['orig_text']
        targ_sentiment = d['targ_sentiment']

        with torch.no_grad():
            ids = ids.to(device, dtype=torch.long)
            mask_ids = mask_ids.to(device, dtype=torch.long)
            token_type_ids = token_type_ids.to(device, dtype=torch.long)
            target_start_idx = target_start_idx.to(device, dtype=torch.long)
            target_end_idx = target_end_idx.to(device, dtype=torch.long)
            targ_sentiment = targ_sentiment.to(device, dtype=torch.long)

            o1, o2 = model(ids, mask_ids, token_type_ids)
            fin_output_start.append(o1.cpu().detach().numpy())
            fin_output_end.append(o2.cpu().detach().numpy())

            fin_offset.append(offsets)
            fin_orig_sentiment.extend(orig_sentiment)
            fin_orig_selected.extend(orig_sele_text)
            fin_orig_text.extend(orig_text)
            fin_targ_sentiment.append(targ_sentiment.cpu().detach().numpy())

    fin_output_start = np.vstack(fin_output_start)
    fin_output_end = np.vstack(fin_output_end)
    fin_offset = np.vstack(fin_offset)
    fin_targ_sentiment = np.concatenate(fin_targ_sentiment)

    if df_type == 'val' or df_type == 'trn':
        jaccard_score = cal_jaccard(fin_output_start, fin_output_end, fin_offset, fin_orig_sentiment, fin_orig_selected, fin_orig_text, rm_length)
        return jaccard_score, fin_output_start, fin_output_end

def pred_loop_fn(data_loader, device, file_path):
    fin_output_start = []
    fin_output_end = []
    fin_offset = []
    fin_orig_sentiment = []
    fin_orig_selected = []
    fin_orig_text = []

    tk = tqdm(data_loader, total=len(data_loader))
    fin_output_string = []

    for bi, d in enumerate(tk):
        ids = d['ids']
        mask_ids = d['mask_ids']
        token_type_ids = d['token_type_ids']
        offsets = d['offsets']
        orig_sentiment = d['orig_sentiment']
        orig_text = d['orig_text']

        with torch.no_grad():
            ids = ids.to(device, dtype=torch.long)
            mask_ids = mask_ids.to(device, dtype=torch.long)
            token_type_ids = token_type_ids.to(device, dtype=torch.long)

            model1, model2, model3, model4, model5 = load_model(file_path)
            output_start1, output_end1 = model1(ids, mask_ids, token_type_ids)
            output_start2, output_end2 = model2(ids, mask_ids, token_type_ids)
            output_start3, output_end3 = model3(ids, mask_ids, token_type_ids)
            output_start4, output_end4 = model4(ids, mask_ids, token_type_ids)
            output_start5, output_end5 = model5(ids, mask_ids, token_type_ids)

            output_start = output_start1 + output_start2 + output_start3 + output_start4 + output_start5
            output_end = output_end1 + output_end2 + output_end3 + output_end4 + output_end5

            output_start = softmax(output_start.cpu().detach().numpy(), axis=1)
            output_end = softmax(output_end.cpu().detach().numpy(), axis=1)

            fin_output_start.append(output_start)
            fin_output_end.append(output_end)
            fin_offset.append(offsets)
            fin_orig_sentiment.extend(orig_sentiment)
            fin_orig_text.extend(orig_text)

    fin_output_start = np.vstack(fin_output_start)
    fin_output_end = np.vstack(fin_output_end)
    fin_offset = np.vstack(fin_offset)

    for i in range(fin_output_start.shape[0]):
        output_start = fin_output_start[i]
        output_start = np.argmax(output_start)
        output_end = fin_output_end[i]
        output_end = np.argmax(output_end)
        offset = fin_offset[i]
        orig_sentiment = fin_orig_sentiment[i]
        orig_text = fin_orig_text[i]

        if output_start > output_end:
            output_end = output_start

        output_string = ""
        for j in range(output_start, output_end+1):
            output_string += orig_text[offset[j][0]:offset[j][1]]
            if (ix+1) < len(offset) and offset[ix][1] < offset[ix+1][0]:
               final_output += " "

        if orig_sentiment == 'neutral':
            output_string = orig_text

        fin_output_string.append(output_string)

    return fin_output_string


# encoding: UTF-8

import os
from datetime import datetime
import json

from ctaBase import *
from vnpy.trader.vtConstant import *

DEBUGCTALOG = True

"""
    网格交易，用于套利单
    作者：李来佳，QQ/Wechat:28888502
ChangeLog:
    0713,修改closeGrid，增加volume字段，关闭网格时，根据价格和交易量进行双重匹配.
    0715,增加保存json和重启后加载本地json文件
"""

class CtaGrid(object):
    """网格类
    它是网格交易的最小单元
    包括交易方向，开仓价格，平仓价格，止损价格，开仓状态，平仓状态

    """

    def __init__(self, direction, openprice, closeprice, stopprice=EMPTY_FLOAT, volume=1):

        self.direction = direction      # 交易方向（LONG：多，正套；SHORT：空，反套）
        self.openPrice = openprice      # 开仓价格
        self.closePrice = closeprice    # 平仓价格
        self.stopPrice = stopprice      # 止损价格

        self.volume = volume            # 开仓数量
        self.tradedVolume = EMPTY_INT   # 成交数量 开仓时，为开仓数量，平仓时，为平仓数量

        self.orderStatus = False        # 挂单状态: True,已挂单，False，未挂单
        self.orderRef = EMPTY_STRING    # OrderId
        self.openStatus = False         # 开仓状态
        self.closeStatus = False        # 平仓状态

        self.openDatetime = None
        self.orderDatetime = None       # 委托时间

        self.lockGrids = []             # 锁单的网格，[openPrice,openPrice]

    def toJson(self):
        """输出JSON"""

        j = {}
        j['direction'] = self.direction
        j['openPrice'] = self.openPrice      # 开仓价格
        j['closePrice'] = self.closePrice    # 平仓价格
        j['stopPrice'] = self.stopPrice      # 止损价格

        j['volume'] = self.volume            # 开仓数量

        j['tradedVolume'] = self.tradedVolume # 成交数量

        j['orderStatus'] = self.orderStatus        # 挂单状态: True,已挂单，False，未挂单
        j['orderRef'] = self.orderRef           # OrderId
        j['openStatus'] = self.openStatus         # 开仓状态
        j['closeStatus'] = self.closeStatus        # 平仓状态
        j['lockGrids'] = self.lockGrids         # 对锁的网格

        if type(self.openDatetime) == type(None):
            j['openDatetime'] = EMPTY_STRING
        else:
            try:
                j['openDatetime'] = self.openDatetime.strftime('%Y-%m-%d %H:%M:%S')
            except Exception:
                j['openDatetime'] = EMPTY_STRING

        return j

    def toStr(self):
        """输入字符串"""

        str = u'o:{0}/{1};c:{2}/{3},r:{4}/opentime:{5}/ordertime:{6}'\
            .format(self.openPrice, self.openStatus, self.closePrice,
                    self.closeStatus, self.orderRef, self.openDatetime, self.orderDatetime)
        return str

class CtaGridTrade(object):
    """网格交易类
    包括两个方向的网格队列，
    v1, 基本版
    v2，增加更新最小价格跳动，增加动态上下网格间距
    """

    def __init__(self, strategy, maxlots=5, height=2, win=2, vol=1, minDiff = 1):
        """初始化
        maxlots,最大网格数
        height，网格高度（绝对值，包含minDiff）
        win，盈利数（包含minDiff）
        vol，网格开仓数
        minDiff, 最小价格跳动
        """
        self.minDiff = minDiff

        self.strategy = strategy

        self.jsonName = self.strategy.name  #策略名称

        self.maxLots = maxlots      # 缺省网格数量
        self.gridHeight = height    # 最小网格高度
        self.gridWin = win          # 最小止盈高度

        self.volume = vol           # 每次网格开仓数量
        self.volumeList = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]    # 梯级开仓数量比例

        self.upGrids = []           # 上网格列表，专门做空
        self.dnGrids = []           # 下网格列表，专门做多

        self.avg_up_open_price = EMPTY_FLOAT        # 上网格开仓均价
        self.avg_dn_open_price = EMPTY_FLOAT        # 下网格开仓均价

        self.max_up_open_price = EMPTY_FLOAT  # 上网格开仓均价
        self.min_dn_open_price = EMPTY_FLOAT  # 下网格开仓均价

    def getVolumeRate(self, gridIndex=EMPTY_INT):
        """获取网格索引对应的开仓数量比例"""
        if gridIndex >= len(self.volumeList) or gridIndex < 0:
            return 1
        rate = self.volumeList[gridIndex]

        if rate == 0:
            return 1
        else:
            return rate

    def initGrid(self, upline=EMPTY_FLOAT, dnline=EMPTY_FLOAT):
        """初始化网格队列
        upline，上支撑线
        dnline，下阻力线
        """
        self.writeCtaLog(u'初始化网格队列，upline:{0},dnline:{1}'.format(upline, dnline))
        # 初始化上网格列表
        if len(self.upGrids) == 0:

            self.upGrids = self.load(direction= DIRECTION_SHORT)

            if len(self.upGrids) >0:
                self.writeCtaLog(u'上网格从文件加载完成')
            else:
                # 做空，开仓价为上阻力线+网格高度*i，平仓价为开仓价-止盈高度，开仓数量为缺省
                for i in range(0, self.maxLots, 1):
                    grid = CtaGrid(direction=DIRECTION_SHORT,
                                   openprice=upline+self.gridHeight*i,
                                   closeprice=upline+self.gridHeight*i-self.gridWin,
                                   volume=self.volume*self.getVolumeRate(i))
                    self.upGrids.append(grid)

                self.writeCtaLog(u'上网格{0}~{1}初始化完成'.format(upline,upline+self.gridHeight*self.maxLots))
                self.save(direction=DIRECTION_SHORT)

        # 初始化下网格列表
        if len(self.dnGrids) == 0:

            self.dnGrids = self.load(direction= DIRECTION_LONG)

            if len(self.dnGrids) >0:
                self.writeCtaLog(u'下网格从文件加载完成')
            else:
                for i in range(0, self.maxLots, 1):

                    # 做多，开仓价为下阻力线-网格高度*i，平仓价为开仓价+止盈高度，开仓数量为缺省
                    grid = CtaGrid(direction=DIRECTION_LONG,
                                   openprice=dnline - self.gridHeight * i,
                                   closeprice=dnline - self.gridHeight * i + self.gridWin,
                                   volume=self.volume*self.getVolumeRate(i))
                    self.dnGrids.append(grid)

                self.writeCtaLog(u'下网格{0}~{1}初始化完成'.format(dnline,dnline-self.gridHeight*self.maxLots))
                self.save(direction=DIRECTION_LONG)

    def writeCtaLog(self, log):
        self.strategy.writeCtaLog(log)

    def toStr(self,direction):
        """显示网格"""

        pendingCloseList = u''      # 平仓清单
        pendingOpenList = u''       # 开仓清单
        deactiveList = u''          # 待激活清单

        if direction == DIRECTION_LONG:
            for grid in self.dnGrids:
                # 待平仓
                if grid.openStatus :

                    if grid.tradedVolume == EMPTY_INT:
                        pendingCloseList = pendingCloseList + u'[{0}->{1},v:{2}];'\
                            .format(grid.openPrice, grid.closePrice, grid.volume)
                    else:
                        pendingCloseList = pendingCloseList + u'[{0}->{1},v:{2}/{3}];'\
                            .format(grid.openPrice, grid.closePrice, grid.volume, grid.tradedVolume)

                # 待开仓成交
                elif not grid.openStatus and grid.orderStatus:
                    if grid.tradedVolume == EMPTY_INT:
                        pendingOpenList = pendingOpenList + u'[{0},v:{1}];'.format(grid.openPrice, grid.volume)
                    else:
                        pendingOpenList = pendingOpenList + u'[{0},v:{1}/{2}];'\
                            .format(grid.openPrice, grid.volume, grid.tradedVolume)

                # 等待挂单
                else:
                    deactiveList = deactiveList + u'[{0}];'.format(grid.openPrice)

            return u'多:待平:{0};开:{1};待:{2}'.format(pendingCloseList,pendingOpenList,deactiveList)

        if direction == DIRECTION_SHORT:
            for grid in self.upGrids:
                # 待平仓
                if grid.openStatus:
                    if grid.tradedVolume == EMPTY_INT:
                        pendingCloseList = pendingCloseList + u'[{0}->{1},v:{2}];'\
                            .format(grid.openPrice, grid.closePrice, grid.volume)
                    else:
                        pendingCloseList = pendingCloseList + u'[{0}->{1},v:{2}/{3}];'\
                            .format(grid.openPrice, grid.closePrice, grid.volume, grid.tradedVolume)

                # 待开仓成交
                elif not grid.openStatus and grid.orderStatus:
                    if grid.tradedVolume == EMPTY_INT:
                        pendingOpenList = pendingOpenList + u'[{0},v:{1}];'.format(grid.openPrice, grid.volume)
                    else:
                        pendingOpenList = pendingOpenList + u'[{0},v:{1}/{2}];'\
                            .format(grid.openPrice, grid.volume, grid.tradedVolume)

                # 等待挂单
                else:
                    deactiveList = deactiveList + u'[{0}];'.format(grid.openPrice)

            return u'空:待平:{0};开:{1};待:{2}'.format(pendingCloseList,pendingOpenList,deactiveList)

    def getGrids(self, direction, ordered=False, opened=False, closed=False, begin=EMPTY_FLOAT, end=EMPTY_FLOAT):
        """获取未挂单的网格
        direction:做多、做空方向: 做多方向时，从dnGrids中获取;  做空方向时，从upGrids中获取
        ordered:是否已提交至服务器
        opened：是否已开仓
        closed：是否已平仓
        begin：开始价格,
        end：结束价格，
        """

        # 状态一致，价格大于最低价格
        if direction == DIRECTION_LONG:
            if begin == EMPTY_FLOAT: begin = 99999
            if end == EMPTY_FLOAT: end = - 99999
            grids = [x for x in self.dnGrids
                     if x.orderStatus == ordered
                     and x.openStatus == opened
                     and x.closeStatus == closed
                     and x.openPrice <= begin
                     and x.openPrice >= end]

            return grids

        # 状态一致，开仓价格小于最高价格
        if direction == DIRECTION_SHORT:
            if begin == EMPTY_FLOAT: begin = -99999
            if end == EMPTY_FLOAT: end = 99999
            grids = [x for x in self.upGrids
                     if x.orderStatus == ordered
                     and x.openStatus == opened
                     and x.closeStatus == closed
                     and x.openPrice >= begin
                     and x.openPrice <= end]

            return grids

    def updateOrderRef(self, direction, openPrice, orderRef):
        """更新网格的orderId"""
        if direction == DIRECTION_LONG:
            for x in self.dnGrids:
                if x.openPrice == openPrice:
                    x.orderRef = orderRef
                    x.orderStatus = True

        if direction == DIRECTION_SHORT:
            for x in self.upGrids:
                if x.openPrice == openPrice:
                    x.orderRef = orderRef
                    x.orderStatus = True

    def cancelOrderRef(self,direction, openPrice):
        """网格撤单"""
        if direction == DIRECTION_LONG:
            for x in self.dnGrids:
                if x.openPrice == openPrice and x.orderRef != EMPTY_STRING and x.orderStatus==True and x.openStatus==False:
                    x.orderRef = EMPTY_STRING
                    x.orderStatus = False
                    self.writeCtaLog(u'下网格撤单[{0}]'.format(x.openPrice))

        if direction == DIRECTION_SHORT:
            for x in self.upGrids:
                if x.openPrice == openPrice and x.orderRef != EMPTY_STRING and x.orderStatus==True and x.openStatus==False:
                    x.orderRef = EMPTY_STRING
                    x.orderStatus = False
                    self.writeCtaLog(u'上网格撤单[{0}]'.format(x.openPrice))

    def getGrid(self, direction, openPrice=EMPTY_FLOAT, closePrice=EMPTY_FLOAT, orderRef=EMPTY_STRING, t=EMPTY_STRING):
        """获取网格"""

        if direction == DIRECTION_LONG:
            for x in self.dnGrids:
                # 优先匹配价格
                if t == u'OpenPrice' and x.openPrice == openPrice:
                    return x
                elif t == u'ClosePrice' and x.closePrice == closePrice:
                    return x
                elif t == u'OrderRef' and x.orderRef == orderRef:
                    return x

        if direction == DIRECTION_SHORT:
            for x in self.upGrids:
                # 优先匹配价格
                if t == u'OpenPrice' and x.openPrice == openPrice:
                    return x
                elif t == u'ClosePrice' and x.closePrice == closePrice:
                    return x
                elif t == u'OrderRef' and x.orderRef == orderRef:
                    return x

        self.writeCtaLog(u'异常，找不到网格[{0},{1},{2},{3},{4}]'.format(direction, openPrice, closePrice, orderRef, t))
        return None

    def getLastOpenedGrid(self, direction):
        """获取最后一个开仓的网格"""
        if direction == DIRECTION_SHORT:
            opened_short_grids = self.getGrids(direction=direction, opened=True)
            if opened_short_grids is None or len(opened_short_grids) ==0 :
                return None
            if len(opened_short_grids) > 1:
                sortedGrids = sorted(opened_short_grids, key=lambda g:g.openPrice)
                opened_short_grids = sortedGrids[-1:]
            return opened_short_grids[0]

        if direction == DIRECTION_LONG:
            opened_long_grids = self.getGrids(direction=direction, opened=True)
            if opened_long_grids is None or len(opened_long_grids) ==0:
                return None
            if len(opened_long_grids) > 1:
                sortedGrids = sorted(opened_long_grids, key=lambda g: g.openPrice)
                opened_long_grids = sortedGrids[0:1]
            return opened_long_grids[0]

    def closeGrid(self, direction, closePrice, closeVolume):
        """网格交易结束"""
        if direction == DIRECTION_LONG:
            for x in self.dnGrids:
                if x.closePrice == closePrice and x.openStatus and x.volume == closeVolume:
                    self.writeCtaLog(u'下网格交易结束[{0}->{1}]，仓位:{2},移除网格'.format(x.openPrice, x.closePrice,closeVolume))
                    self.dnGrids.remove(x)
                    return

                if x.closePrice == closePrice and x.openStatus and x.volume > closeVolume:
                    self.writeCtaLog(u'下网格交易部分结束[{0}->{1}],减少仓位:{2}'.format(x.openPrice, x.closePrice,closeVolume))
                    x.volume = x.volume - closeVolume

                if x.closePrice == closePrice and x.openStatus and x.volume < closeVolume:
                    self.writeCtaLog(u'下网格交易结束[{0}->{1}],移除网格，剩余仓位:{2}'.format(x.openPrice, x.closePrice, closeVolume-x.volume))
                    closeVolume = closeVolume - x.volume
                    self.dnGrids.remove(x)

        if direction == DIRECTION_SHORT:
            for x in self.upGrids:
                if x.closePrice == closePrice and x.openStatus and x.volume == closeVolume:
                    self.writeCtaLog(u'上网格交易结束[{0}->{1}]，仓位:{2},移除网格'.format(x.openPrice, x.closePrice,closeVolume))
                    self.upGrids.remove(x)
                    return

                if x.closePrice == closePrice and x.openStatus and x.volume > closeVolume:
                   self.writeCtaLog(u'上网格交易结束[{0}->{1}]，仓位减少:{2}'.format(x.openPrice, x.closePrice,closeVolume))
                   x.volume = x.volume - closeVolume

                if x.closePrice == closePrice and x.openStatus and x.volume < closeVolume:
                    self.writeCtaLog(u'上网格交易结束[{0}->{1}]，移除网格，剩余仓位:{2}'.format(x.openPrice, x.closePrice,closeVolume-x.volume))
                    closeVolume = closeVolume - x.volume
                    self.upGrids.remove(x)

    def removeGrids(self, direction, priceline):
        """清除网格"""
        if direction == DIRECTION_LONG:
            for x in self.dnGrids[:]:
                if x.openPrice > priceline and not x.orderStatus and not x.openStatus and not x.closeStatus:
                    self.writeCtaLog(u'清除下网格[open={0}]'.format(x.openPrice))
                    self.dnGrids.remove(x)

        if direction == DIRECTION_SHORT:
            for x in self.upGrids[:]:
                if x.openPrice < priceline and not x.orderStatus and not x.openStatus and not x.closeStatus:
                    self.writeCtaLog(u'清除上网格[open={0}]'.format(x.openPrice))
                    self.upGrids.remove(x)

    def rebuildGrids(self, direction, upline=EMPTY_FLOAT, dnline=EMPTY_FLOAT, midline=EMPTY_FLOAT, upRate=1, dnRate = 1):
        """重新拉网
        清除未挂单的网格，
        在上轨/下轨位置重新挂单
        upRate , 上轨网格高度比率
        dnRate， 下轨网格高度比率
        """
        self.writeCtaLog(u'重新拉网:upline:{0},dnline:{1}'.format(upline, dnline))

        # 检查上下网格的高度比率，不能低于0.5
        if upRate < 0.5 or dnRate < 0.5:
            upRate = max(0.5, upRate)
            dnRate = max(0.5, dnRate)

        if direction == DIRECTION_LONG:
            minPriceInOrder = midline
            removePrices = []
            # 移除未挂单的下网格
            for x in self.dnGrids[:]:
                if not x.orderStatus and not x.openStatus and not x.closeStatus:
                    removePrices.append(x.openPrice)
                    self.dnGrids.remove(x)
                else:
                    self.writeCtaLog(u'保留网格[open={0}]'.format(x.openPrice))
                    if x.openPrice < minPriceInOrder :
                        minPriceInOrder = x.openPrice

            self.writeCtaLog(u'清除下网格[{0}]'.format(removePrices))

            # 需要重建的剩余网格数量
            remainLots = len(self.dnGrids)
            lots = self.maxLots - remainLots

            dnline = min(dnline, minPriceInOrder-self.gridHeight*dnRate)
            self.writeCtaLog(u'需要重建的网格数量:{0},起点:{1}'.format(lots, dnline))

            if lots > 0:
                for i in range(0, lots, 1):
                    # 做多，开仓价为下阻力线-网格高度*i，平仓价为开仓价+止盈高度，开仓数量为缺省
                    open_price = int((dnline - self.gridHeight * i * dnRate) / self.minDiff ) * self.minDiff
                    close_price = int((open_price + self.gridWin* dnRate)/self.minDiff) * self.minDiff

                    grid = CtaGrid(direction=DIRECTION_LONG,
                                   openprice=open_price,
                                   closeprice=close_price,
                                   volume=self.volume*self.getVolumeRate(remainLots + i))

                    self.dnGrids.append(grid)
                self.writeCtaLog(u'重新拉下网格:[{0}~{1}]'.format(dnline, dnline-self.gridHeight * lots))

        if direction == DIRECTION_SHORT:
            maxPriceInOrder = midline
            removePrices = []
            # 移除未挂单的上网格
            for x in self.upGrids[:]:
                if not x.orderStatus and not x.openStatus and not x.closeStatus:
                    removePrices.append(x.openPrice)
                    self.upGrids.remove(x)
                else:
                    self.writeCtaLog(u'保留网格[open={0}]'.format(x.openPrice))
                    if x.openPrice > maxPriceInOrder :
                        maxPriceInOrder = x.openPrice

            self.writeCtaLog(u'清除上网格[{0}]'.format(removePrices))

            # 需要重建的剩余网格数量
            remainLots = len(self.upGrids)
            lots = self.maxLots - remainLots
            upline = max(upline, maxPriceInOrder+self.gridHeight*upRate)
            self.writeCtaLog(u'需要重建的网格数量:{0},起点:{1}'.format(lots, upline))

            if lots > 0:
                # 做空，开仓价为上阻力线+网格高度*i，平仓价为开仓价-止盈高度，开仓数量为缺省
                for i in range(0, lots, 1):
                    open_price = int((upline + self.gridHeight * i * upRate) / self.minDiff) * self.minDiff
                    close_price = int((open_price - self.gridWin * upRate) / self.minDiff) * self.minDiff

                    grid = CtaGrid(direction=DIRECTION_SHORT,
                                   openprice=open_price,
                                   closeprice=close_price,
                                   volume=self.volume*self.getVolumeRate(remainLots + i))
                    self.upGrids.append(grid)

                self.writeCtaLog(u'重新拉上网格:[{0}~{1}]'.format(upline, upline+self.gridHeight * lots))

    def recount_avg_open_price(self):
        """计算网格的平均开仓价"""
        up_open_list = [x for x in self.upGrids if x.openStatus]

        self.max_up_open_price = -99999
        self.avg_up_open_price = -99999
        self.min_dn_open_price = 99999
        self.avg_dn_open_price = 99999

        total_price = EMPTY_FLOAT
        total_volume = EMPTY_INT
        for x in up_open_list:
            self.max_up_open_price = max(self.max_up_open_price, x.openPrice)
            total_price += x.openPrice*x.volume
            total_volume += x.volume

        if total_volume > 0:
            self.avg_up_open_price = total_price/total_volume

        total_price = EMPTY_FLOAT
        total_volume = EMPTY_INT

        dn_open_list = [x for x in self.dnGrids if x.openStatus]
        for x in dn_open_list:
            self.min_dn_open_price = min(self.min_dn_open_price,x.openPrice)
            total_price += x.openPrice*x.volume
            total_volume += x.volume

        if total_volume > 0:
            self.avg_dn_open_price = total_price/total_volume

    def save(self, direction):
        """保存网格至本地Json文件"""

        # 更新开仓均价
        self.recount_avg_open_price()
        path = os.path.abspath(os.path.dirname(__file__))

        # 保存上网格列表
        if len(self.upGrids) > 0 and direction == DIRECTION_SHORT:
            jsonFileName = os.path.join(path, u'data', u'{0}_upGrids.json'.format(self.jsonName))

            l = []
            for grid in self.upGrids:
                l.append(grid.toJson())

            with open(jsonFileName, 'w') as f:
                jsonL = json.dumps(l, indent=4)
                f.write(jsonL)

            #self.writeCtaLog(u'上网格保存文件{0}完成'.format(jsonFileName))

        # 保存上网格列表
        if len(self.dnGrids) > 0 and direction == DIRECTION_LONG:
            jsonFileName = os.path.join(path, u'data', u'{0}_dnGrids.json'.format(self.jsonName))

            l = []
            for grid in self.dnGrids:
                l.append(grid.toJson())

            with open(jsonFileName, 'w') as f:
                jsonL = json.dumps(l, indent=4)
                f.write(jsonL)

            #self.writeCtaLog(u'下网格保存文件{0}完成'.format(jsonFileName))

    def load(self, direction):
        """加载本地Json至网格"""

        path = os.path.abspath(os.path.dirname(__file__))

        if direction == DIRECTION_SHORT:
            jsonFileName = os.path.join(path, u'data', u'{0}_upGrids.json'.format(self.jsonName))
            self.writeCtaLog(u'开始加载上网格文件{0}'.format(jsonFileName))
        if direction == DIRECTION_LONG:
            jsonFileName = os.path.join(path, u'data', u'{0}_dnGrids.json'.format(self.jsonName))
            self.writeCtaLog(u'开始加载上网格文件{0}'.format(jsonFileName))

        if not os.path.isfile(jsonFileName):
            self.writeCtaLog(u'网格保存文件{0}不存在'.format(jsonFileName))
            return []

        try:
            f = file(jsonFileName)
        except IOError:
            self.writeCtaLog(u'读取网格出错，请检查')
            return []

        # 解析json文件
        l = json.load(f)
        grids = []

        if len(l) > 0:

            for i in l:
                closePrice = float(i['closePrice'])
                openPrice = float(i['openPrice'])
                stopPrice = float(i['stopPrice'])

                self.writeCtaLog(u'load Grid:open:{0},close:{1},stop:{2}'.format(openPrice, closePrice, stopPrice))

                grid = CtaGrid(direction=i['direction'], openprice=openPrice, closeprice=closePrice,
                                   stopprice=stopPrice, volume=i['volume'])
                grid.orderStatus = i['orderStatus']       # 挂单状态: True,已挂单，False，未挂单
                grid.orderRef = i['orderRef']           # OrderId
                grid.openStatus = i['openStatus']         # 开仓状态
                grid.closeStatus = i['closeStatus']         # 平仓状态

                strTime = i['openDatetime']
                if strTime == EMPTY_STRING or type(strTime)==type(None):
                    grid.openDatetime = None
                else:
                    grid.openDatetime = datetime.strptime(strTime, '%Y-%m-%d %H:%M:%S')

                try:
                    grid.tradedVolume = i['tradedVolume']   # 已交易的合约数量
                except KeyError:
                    grid.tradedVolume = EMPTY_INT
                try:
                    grid.lockGrids = i['lockGrids']
                except KeyError:
                    grid.lockGrids = []

                self.writeCtaLog(grid.toStr())

                grids.append(grid)

        else:
            self.writeCtaLog(u'解析网格出错，设置为空列表')

        f.close()
        return grids


import os

import torch

def load_model_for_evaluate(pre_model_path, model):
        map_location = torch.device('cpu')
        load_dict = torch.load(pre_model_path, map_location)
        pretrained_dict = load_dict['model_params']
        model_dict = model._networks.state_dict()

        pretrained_dict = {
            k: v
            for k, v in pretrained_dict.items() if k in model_dict
        }

        miss, unexpected = model._networks.load_state_dict(
            pretrained_dict, False)
        if miss is not None:
            print(miss)
        if unexpected is not None:
            print(unexpected)
        return model

class ModelSaver(object):
    def __init__(self, log_dir, is_parallel=False, rank_id=0):
        self.log_dir = os.path.join(log_dir, 'model')
        self.is_parallel = is_parallel
        self.rank_id = rank_id

        os.makedirs(self.log_dir, exist_ok=True)

    def _parallel_mask(func):
        def inner(self, *args, **kwargs):
            if self.rank_id == 0:
                ret = func(self, *args, **kwargs)
                return ret
            else:
                pass

        return inner

    @_parallel_mask
    def save_model(self, model, optimizers, epoch, step, is_best, name=''):
        if self.is_parallel:
            save_dict = {'model_params': model.module._networks.state_dict()}
        else:
            save_dict = {'model_params': model._networks.state_dict()}

        if is_best:
            save_path = os.path.join(self.log_dir, 'best_model{}.pth'.format(
                '' if name == '' else '-{}'.format(name)
            ))
            torch.save(save_dict, save_path)

        save_dict['epoch'] = epoch
        save_dict['step'] = step
        for group_name, (optimizer, _, _) in optimizers.items():
            save_dict[('optim_params', group_name)] = optimizer.state_dict()
        save_path = os.path.join(self.log_dir, 'last_model{}.pth'.format(
            name if isinstance(name, int) or name == 'nan' else ''))
        torch.save(save_dict, save_path)
        return is_best

    def load_model(self,
                   pre_model_path,
                   model):
        map_location = torch.device('cpu')
        load_dict = torch.load(pre_model_path, map_location)
        pretrained_dict = load_dict['model_params']
        model_dict = model._networks.state_dict()

        pretrained_dict = {
            k: v
            for k, v in pretrained_dict.items() if k in model_dict
        }

        miss, unexpected = model._networks.load_state_dict(
            pretrained_dict, False)
        if miss is not None:
            print(miss)
        if unexpected is not None:
            print(unexpected)
        return model

    def load_optim(self, pre_model_path, optimizers=None):
        map_location = torch.device('cpu')
        load_dict = torch.load(pre_model_path, map_location)

        start_epoch = load_dict['epoch'] + 1
        start_step = load_dict['step']

        for group_name, (optimizer, scheduler, st_epoch) in optimizers.items():
            # record the set rate of lr between the parameter group and optimizer
            p_lr_rates = []
            for params in optimizer.param_groups:
                p_lr_rates.append(params['lr'] / optimizer.defaults['lr'])
            optimizer.load_state_dict(load_dict[('optim_params', group_name)])
            for p_idx, params in enumerate(optimizer.param_groups):
                params['lr'] = optimizer.defaults['lr'] * p_lr_rates[p_idx]

            temp_epoch = 1
            while temp_epoch < start_epoch:
                temp_epoch += 1
                scheduler.step()
            optimizers[group_name] = (optimizer, scheduler, st_epoch)

        return optimizers, start_epoch, start_step


from typing import List
from starlette.requests import Request
from fastapi import FastAPI, File
from starlette.templating import Jinja2Templates
import uvicorn

app = FastAPI()
template = Jinja2Templates(directory='templates')

@app.get('/')
async def index(request:Request):
    return template.TemplateResponse(
        'form_for_upload.html',
        context={
            'request':request,
        }
    )

# @app.post('/files/')
# async def create_file(request:Request, file1:bytes=File(...)):
#     return {'request':request,'file_size':len(file1)}

@app.post('/files/')
async def create_many_files(file1: List[bytes] = File(...)):
    return {
        'message': [len(i) for i in file1],
    }

if __name__ == '__main__':
    uvicorn.run(app=app,host='127.0.0.1', port=8000)


"""
Algorithm

Framkvæmd:
1. Leysa báða parta í sitthvoru lagi og púsla svo saman
2. áður en byrjað er á mission 1 & 2 þá er tekið input fra user

Mission 1
---------
Finnur og skrifar út allar pósítívar tveggja stafa tölur sem eru þannig að
annað veldi af summu einstakra tölustafa er jafnt tölunni sjálfri.
---------
búa til counter
búðu til while loop sem að prufar tölur frá 10-99
    taka fyrsta tölustafinn í tölunni og seinni tölustafinn í tölunni
    plúsa fyrstu töluna og seinni töluna saman
    setja þá tölu í annað veldi og kíkja hvort hún sé sú sama og fyrsta talan sem að kom inn
    ef svo er, prenta hana út

Mission 2
---------
Finnur og skrifar út allar pósítivar tölur < 100 sem eiga sér nákvæmlega
10 deila (e. divisors)
---------
búa til counter
búa til while loop sem að prufar tölur undir hundrað
    kíkja á allar tölur sem eru minna en og jafnt og talan
    telja hversu marga divisors talan á sér
    ef að hún á sér nákvæmlega tíu skal prenta töluna

"""

num = 10
while num < 100:
    first_num = num // 10
    second_num = num % 10
    sum_num = first_num + second_num
    if sum_num ** 2 == num:
        print (num)
    num += 1
num2 = 2
while num2 < 100:
    counter = 0
    for i in range(1,num2+1):
        if num2 % i == 0:
            counter += 1
    if counter == 10:
        print (num2)
    num2 += 1


import ase.io
from ase.build import fcc100, add_adsorbate
from ase.constraints import FixAtoms
from ase.optimize import BFGS
from ase.parallel import parprint

from gpaw import GPAW, FermiDirac

from catlearn.optimize.mlneb import MLNEB

"""
Toy model for the diffusion of a Au atom on an Al(111) surface.
This example contains:
1. Optimization of the initial and final end-points of the reaction path with
GPAW
2. NEB optimization using our machine-learning surrogate model and GPAW.
"""

# 1. Structural relaxation.

# Setup calculator:
calc_args = {'mode': 'lcao',
             'h': 0.18,
             'basis': 'dzp',
             'symmetry': 'off',
             'xc': 'PBE',
             'txt': open('gpaw.txt', 'a'),
             'occupations': FermiDirac(0.03)}

# 1.1. Structures:
# 2x2-Al(001) surface with 3 layers and an
# Au atom adsorbed in a hollow site:
slab = fcc100('Al', size=(2, 2, 3))
add_adsorbate(slab, 'Au', 1.7, 'hollow')
slab.center(axis=2, vacuum=4.0)
slab.set_calculator(GPAW(**calc_args))

# Fix second and third layers:
mask = [atom.tag > 1 for atom in slab]
slab.set_constraint(FixAtoms(mask=mask))

# 1.2. Optimize initial and final end-points.
# Initial end-point:
qn = BFGS(slab, trajectory='initial.traj')
qn.run(fmax=0.01)

# Final end-point:
slab[-1].x += slab.get_cell()[0, 0] / 2
qn = BFGS(slab, trajectory='final.traj')
qn.run(fmax=0.01)

# # Define number of images:
n_images = 15

# 2.B. NEB using CatLearn
neb_catlearn = MLNEB(start='initial.traj',
                     end='final.traj',
                     ase_calc=GPAW(**calc_args),
                     n_images=n_images,
                     interpolation='idpp', restart=False)
neb_catlearn.run(fmax=0.05, trajectory='ML-NEB.traj', full_output=True)

# 3. Summary of the results #################################################
# ML-NEB:
atoms_catlearn = ase.io.read('evaluated_structures.traj', ':')
n_eval_catlearn = len(atoms_catlearn) - 2
parprint('Number of function evaluations CatLearn:', n_eval_catlearn)


# https://www.acmicpc.net/problem/1753

import sys
from heapq import heappop, heappush

def solution(V, E, K, graph):

    visited = [0]*(V+1)
    dist = ['INF']*(V+1)
    h = [(0, K)]

    while h:

        d, node = heappop(h)

        if visited[node]:
            continue
        visited[node] = 1

        dist[node] = d

        for next_node in graph[node]:
            heappush(h, (d + graph[node][next_node], next_node))

    return dist[1:]

V, E = map(int, sys.stdin.readline().split())
K = int(sys.stdin.readline())
graph = [{} for _ in range(V+1)]
for _ in range(E):
    u, v, w = map(int, sys.stdin.readline().split())
    if v in graph[u]:
        graph[u][v] = min(graph[u][v], w)
    else:
        graph[u][v] = w

print(*solution(V, E, K, graph))


import pytest
from lambda_utils.tests.unit.utils import make_aws_event

from nrlf.core.errors import NRLF_TO_SPINE_4XX_ERROR, RequestValidationError
from nrlf.core.event_parsing import fetch_body_from_event
from nrlf.core.model import APIGatewayProxyEventModel

@pytest.mark.parametrize(
    "event, expected_body",
    [
        (make_aws_event(body='{"test": "test"}'), {"test": "test"}),
        (make_aws_event(body="{}"), {}),
    ],
)
def test_parsing_body_from_event(event, expected_body):
    event_model = APIGatewayProxyEventModel(**event)
    actual_body = fetch_body_from_event(event_model)
    assert actual_body == expected_body

@pytest.mark.parametrize(
    ["event", "error_message"],
    [
        [make_aws_event(body="12345"), "Body is not expected json type"],
        [make_aws_event(body="null"), "Body is not expected json type"],
        [make_aws_event(body="true"), "Body is not expected json type"],
        [make_aws_event(body="{not json]"), "Body is not valid json"],
    ],
)
def test_parsing_body_from_event_errors(event, error_message):
    with pytest.raises(RequestValidationError) as e:
        event_model = APIGatewayProxyEventModel(**event)
        fetch_body_from_event(event_model)
    assert str(e.value) == error_message
    assert e.type in NRLF_TO_SPINE_4XX_ERROR


with open('./year-2022/day-8/tree-grid.txt') as grid_file:
    grid_lines = grid_file.readlines()

    matrix = []
    visible = 0
    score = 0

    #creates a list of lists (lines)
    for tree_line in grid_lines:
        trees = tree_line.strip()
        line = list(trees)
        lnum = []
        for n in line:
            lnum.append(int(n))
        matrix.append(lnum)

    #creates a list of lists (columns)
    columns = []
    for n in range(0, len(matrix[0])):
        col = []
        for line in matrix:
            col.append(int(line[n]))
        columns.append(col)

    #main cycle
    for l in range(1, len(matrix)-1):
        line = matrix[l]
        index = matrix.index(line)

        for tree in range(1, len(line)-1):

            #the tree
            tr = line[tree]

            #building the lists of tree in the four directions
            left = []
            right = []
            for n in range(0, tree):
                left.append(line[n])
            for n2 in range(tree+1, len(line)):
                right.append(line[n2])
            top = []
            bottom= []
            for n in range(0, index):
                top.append(columns[tree][n])
            for n in range(index+1, len(matrix)):
                bottom.append(columns[tree][n])

            t = max(top)
            b = max(bottom)
            l = max(left)
            r = max(right)

            if tr > l or tr > r or tr > t or tr > b:
                visible += 1

            #second part
            top.reverse()
            left.reverse()

            tv = 0
            bv = 0
            lv = 0
            rv = 0

            for tree in top:
                tv += 1
                if tree >= tr:
                    break
            for tree in bottom:
                bv += 1
                if tree >= tr:
                    break
            for tree in left:
                lv += 1
                if tree >= tr:
                    break
            for tree in right:
                rv += 1
                if tree >= tr:
                    break

            result = tv*bv*lv*rv
            if result > score:
                score = result
    print(visible+99+99+97+97, score)


import optuna
import kevin_toolbox.nested_dict_list as ndl

def sample_from_feasible_domain(var, trial: optuna.trial.BaseTrial, pre_name=""):
    """
        使用试验 trial 基于输入中的定义域 feasible_domain 部分进行参数采样和替换。
            遍历输入中的所有元素，找出符合 <feasible_domain> 格式要求的记录了参数定义域的元素，
            然后使用输入的试验实例 trial 结合参数定义域采样出对应的参数，最后用采样出来的参数替换掉原来的定义域。

        参数：
            inputs:             <list/dict> 当其中的元素满足 <feasible_domain> 格式要求，将进行采样与替换。
                                    <feasible_domain> 格式要求：
                                        1. 是一个 dictionary
                                        2. 包含 "p_type"  字段
                                            "p_type" 表示定义域类型，常见值包括："float" "int" "categorical" 等
                                        3. 根据不同的定义域类型，给出定义域的参数
                                            比如，p_type="categorical" 时应该包含可选值列表 "choices"
                                            p_type="float"或者"int" 时应该包含最大、最小、间隔值、坐标轴类型 "high" "low" "step" "log" 等
                                        更多参见 https://optuna.readthedocs.io/zh_CN/latest/reference/generated/optuna.trial.Trial.html#optuna.trial.Trial
                                        中的 suggest_xxx() 函数。
            trial:              <optuna.trial.BaseTrial> 试验
            pre_name:           <string> 采样出的参数在试验 trial 中注册的名称的前缀

        返回：
            var, name_ls
                var 是采样后的结果
                name_ls 是被采样的节点名称，注意并不带 pre_name 前缀

        实例：
            对于输入 inputs={
                            "thr":[
                                "interval_thr": {
                                    "p_type": "categorical",
                                    "choices": [
                                      1000,
                                      2000,
                                      5000,
                                      10000
                                    ]
                                },
                                "iou_thr": {
                                    "p_type": "float",
                                    "low": 0,
                                    "high": 1.0000001,
                                    "step": 0.05
                                },
                                "connection": {
                                    "p_type": "categorical",
                                    "choices": {
                                        "skip": lambda x:x,
                                        "and":  lambda x,y : x and y,
                                        "or":  lambda x,y : x or y,
                                    }
                                },
                            ]
                        }
            可能返回的采样结果是 res={"thr":[{"interval_thr":1000}, {"iou_thr":0.6}, {"connection":lambda x:x} ], }。
            当 pre_name="my" 时，这些参数在 trial 中注册的名称分别是 "my:thr@0:interval_thr"，"my:thr@1:iou_thr" 和 "my:thr@1:connection"。
            特别地，
                - 对于字典形式的 choices，其中保存在 trial 中的取值是其键 key 而非 value。
                - 对于list形式，但含有非支持类型的  choices，其中保存在 trial 中的取值是元素的 index。
            这些名称的含义详见 get_value()。
    """

    name_ls=[]

    def func(idx, v):
        nonlocal name_ls
        p_type = v.pop("p_type")
        kwargs = v
        choice_values = None
        if p_type == "categorical":
            # optuna 目前的类别元素仅支持 None, bool, int, float 和 str 类型
            #   对于其他类型的元素，比如 list 和 dict，需要替换成对应 index_ls 或者 key_ls
            #   然后再根据建议的 index 或者 key 到 list 和 dict 中取值
            assert "choices" in kwargs
            if isinstance(kwargs["choices"], (list, tuple,)) and \
                    not all([isinstance(i, (bool, int, float, str,)) or i is None for i in kwargs["choices"]]):
                choice_values = kwargs["choices"]
                kwargs["choices"] = list(range(len(kwargs["choices"])))
            elif isinstance(kwargs["choices"], (dict,)):
                choice_values = kwargs["choices"]
                kwargs["choices"] = list(kwargs["choices"].keys())

        v = eval(f'trial.suggest_{p_type}(name=name, **kwargs)',
                 {"trial": trial, "name": f'{pre_name}{idx}', "kwargs": kwargs})
        if choice_values is not None:
            v = choice_values[v]
        name_ls.append(idx)
        return v

    var = ndl.traverse(var=var, match_cond=lambda _, __, v: isinstance(v, (dict,)) and "p_type" in v,
                       action_mode="replace", converter=func, b_use_name_as_idx=True)

    return var, name_ls


import os

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'devproj.settings')

import django,names,random

django.setup()
from interactWBL.models import User, Academic, Course, Competency, CourseTarget, Student, Enrolment, Assignment, Submission, Reflection, PersonalCompetency, CompetencyEndorsement

def populate():
    # have existing competencies ready in a list and calculate how many there are
    competencies_list = list(Competency.objects.all())
    comps_no = len(competencies_list)

    # academic first names
    academics_names = ['Mechelle', 'Evelia', 'Sylvie', 'Stephania', 'Octavio', 'Shona', 'Spencer', 'Natisha', 'Guadalupe',
             'Lea', ]

    # course names for courses to be created
    course_names = ['Programming', 'Cyber Security Fundamentals', 'Systems and Networks', 'Enterprise Cyber Security',
                    'Database Theory and Application', 'Software Engineering', 'Software Project Managements',
                    'Internet Technology', 'Advanced Programming', 'Algorithms and Data Structures',]

    # collect existing students in a list and determine their number
    students_list = list(Student.objects.all())
    studs_no = len(students_list)
    print("there are " + str(studs_no) + " students")

    # create 10 users, then associate 10 academics with the 10 users & create 10 courses, 1 for taught by each academic

    i = 0
    for n in academics_names:
        # create a user with name from the list above
        u = User.objects.get_or_create(username=n.lower(), password='')[0]
        u.set_password('securepassword')
        u.save()
        # then associate an academic profile with that user
        a = Academic.objects.get_or_create(user=u)[0]
        u.first_name = academics_names[i]
        u.last_name = names.get_last_name()
        u.email = academics_names[i].lower() + '.'+ u.last_name.lower()+'@gla.ac.uk'
        u.save()
        # after the academic profile is fully set up, create a course taught by that academic

        c = Course.objects.get_or_create(teacher=a, year = random.randint(1,5), name=course_names[i],
                                         lecture_recordings="http://www.echo360.com",missed_lecture_procedure="The exact procedure will be announced later, but please make sure to message me if you have any pressing doubts at the moment.",
                                         ILOs="The course aims to provide students with mathematical/quantitative skills and knowledge that consititute the foundation for techniques and instruments in both microeconomic theory and intertemporal macroeconomics (such as multivariate calculus and integration, constrained optimisation, differential equations, dynamic programming methods, functional analysis), and to demonstrate various mathematical techniques are applied to economic problems.",
                                         moodle='https://moodle.org/',
                                         description="The aim of this course is to provide students with a comprehensive overview of web application development. It will provide students with the skills to design and develop distributed web applications in a disciplined manner, using a range of tools and technologies. It will also strengthen their understanding of the context and rationale of distributed systems.")[0]
        i += 1 # this is so we iterate through academic and course names at the same time

        """
                 this next sections deals with randomly assigning competency objectives to the created courses
                 We select a competency at random from the list and add about 8-9 targets to the most recent course
        """

        for j in range (1,10):
            t = CourseTarget.objects.get_or_create(course=c,competency=competencies_list[random.randint(0,comps_no-1)])[0]

        """
                this next sections deals with enrolling students in courses (according to the year of the course)
        """
    course_list = list(Course.objects.all())
    for course in course_list:
        print(course)
        print("now enrolling:")
        for s in students_list:
            if s.year == course.year:
                e = Enrolment.objects.get_or_create(course=course, student=s)[0]
                e.save()
                print(e)
            else:
                pass
    print("Generating assignments...")
    print("Generating submissions...")
    print("Generating reflections and personal competencies...")
    for course in course_list[0:6]:
        # for half of the courses determine the students enrolled
        enrollments  = list(Enrolment.objects.filter(course= course))
        students_in_course =[]
        # for each course, create an assignment
        assignment = Assignment.objects.get_or_create(name=course.name + " project", course=course,
                                                      description="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",)[0]
        # add associate 4 competencies with this assignment
        for i in range(1, 5):
            random_competency = competencies_list[random.randint(0, comps_no - 1)]
            assignment.competencies.add(random_competency)
        # from the list of enrollments, obtain the list of all students enrolled in this course
        for e in enrollments:
            students_in_course.append(e.student)

        #for each student in the course, create a weekly reflection by that student
        for student in students_in_course:
            weekly_reflection = Reflection.objects.get_or_create(student=student, course=course,type='weekly',assignment=assignment,
                                                                 content="Diam sit amet nisl suscipit adipiscing bibendum est ultricies. In pellentesque massa placerat duis ultricies lacus. Cursus mattis molestie a iaculis at erat. Libero enim sed faucibus turpis in eu mi bibendum. Purus in massa tempor nec feugiat nisl pretium fusce id. Sit amet purus gravida quis. Nisl pretium fusce id velit ut tortor. Eu consequat ac felis donec et odio pellentesque. Diam sollicitudin tempor id eu nisl nunc mi ipsum. Faucibus interdum posuere lorem ipsum. Vitae nunc sed velit dignissim sodales ut. Aenean pharetra magna ac placerat vestibulum lectus. Dictum non consectetur a erat nam at lectus urna. Nunc sed velit dignissim sodales. Eget nunc lobortis mattis aliquam faucibus purus in massa tempor. Fames ac turpis egestas integer eget aliquet nibh. Sit amet massa vitae tortor. Potenti nullam ac tortor vitae. Odio aenean sed adipiscing diam. In cursus turpis massa tincidunt dui ut ornare.")[0]
            # print info to show to the user while they are waiting for pop script to complete:
            print("created assignment: "+assignment.__str__())
            # for each weekly reflection associated with that assignment, associate some competencies with them
            for i in range(1,4):
                random_competency = competencies_list[random.randint(0,comps_no-1)]
                weekly_reflection.competencies.add(random_competency)
                # also create a PersonalCompetency object to track the student's progress with the competencies targeted by the assignment
                personal_competency = PersonalCompetency.objects.get_or_create(student=student, progress='1', competency=random_competency)[0]
                personal_competency.assignments.add(assignment)
            # for each assignment, create a submission
            submission = Submission.objects.get_or_create(student=student, assignment=assignment, course=course)[0]
            submission.file.name='codesubmission.txt'
            submission.save()
            print(submission)

    print('Printing created academics' + '\n')
    for a in Academic.objects.all():
        print(a.__str__() + '\n')

    print('Printing created courses' + '\n')
    for c in Course.objects.all():
        print(c.__str__() + '\n')

if __name__ == '__main__':
    print('Starting academic, course and course targets population script:' + '\n')
    populate()