#!/usr/bin/env python3

import os
from datetime import date
import reports, emails

def main():
  home = os.path.expanduser("~")
  path = f"{home}/supplier-data/descriptions"
  files = os.listdir(path)
  paragraphs = ""

  for file in files:

    with open(f"{path}/{file}", "r") as f:
      lines = f.read().splitlines()
      while lines[-1].strip() == "":
        del lines[-1]
      del lines[-1]
      lines[0] = "name: " + lines[0]
      lines[1] = "weight: " + lines[1]
      print(lines)
      paragraph = "
".join(lines) + "

"
      paragraphs += paragraph

  today = date.today()

  reports.generate_report("/tmp/processed.pdf", f"Processed Update on {today.strftime('%B %d, %Y')}", paragraphs)

  message = emails.generate_email("automation@example.com", "student-02-96927976bbbc@example.com", "Upload Completed - Online Fruit Store", "All fruits are uploaded to our website successfully. A detailed list is attached to this email.", "/tmp/processed.pdf")

  emails.send_email(message)

if __name__ == "__main__":
  main()


import os
import json
import onnx
import onnxruntime
import numpy
import torch
import torch.nn as nn
import torch.nn.functional as F
import tvm
from config import Config
import drivers
from ModelUtils.model_utils import load_onnx_model, onnx2IRModule, build_lib, store_lib, get_lib
from tvm.contrib import graph_executor

# 模型定义
input_shape = (4, 3, 14, 14)
random_add1 = torch.rand(4, 3, 14, 14)
random_add2 = torch.rand(4, 1, 6, 6)

mydriver = drivers.GPU()
onnx_name = "easy_model"

'''
x -> conv1 ->y1
x ->add1 -> conv2 ->y2

y1+y2 -> y

y -> relu -> z1
y -> add2 -> z2

z1+z2 -> output
'''

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(
            in_channels=3, out_channels=1, kernel_size=4, stride=2)
        self.conv2 = nn.Conv2d(
            in_channels=3, out_channels=1, kernel_size=4, stride=2)
        self.linear = nn.Linear(in_features=4*1*6*6, out_features=1)

    def forward(self, x):                            # x: (4,3,14,14)        1, 11
        y1 = F.relu(self.conv1(x))                    # y1: (4,1,6,6)
        y2 = F.relu(self.conv2(x+random_add1))        # y2: (4,1,6,6)

        y = y1+y2

        output = F.relu(y)+y+random_add2
        return self.linear(torch.reshape(output, (1, 4*1*6*6)))

# def to_numpy(tensor):
#     return tensor.detach().cpu().numpy() if tensor.requires_grad else tensor.cpu().numpy()

def get_ir_module():
    onnx_path = Config.ModelSavePathName(onnx_name)
    onnx_model = load_onnx_model(onnx_path)
    x = torch.rand(*input_shape, requires_grad=True)
    shape_dict = {"input": x.shape}
    mod, _ = onnx2IRModule(onnx_model, shape_dict)
    return mod

def main():
    test_count = 10
    model = Model()
    model.eval()        # 设置为推理模型

    x = torch.rand(*input_shape, requires_grad=True)
    # 计算一次前向传播，https://blog.csdn.net/qq_44930937/article/details/109701307
    _ = model(x)

    input_name = "input"
    output_name = "output"
    onnx_path = Config.ModelSavePathName(onnx_name)
    lib_path = Config.TvmLibSavePathByName(
        onnx_name, mydriver.target, str(input_shape[0]))
    torch.onnx.export(model, x, Config.ModelSavePathName(onnx_name), export_params=True, input_names=[
        input_name], output_names=[output_name])  # "edge"使得自定义名称与tvm内部自动命名显示区分，便于理解

    # (N,3,224,224)——need to set input size for tvm model
    x = torch.rand(*input_shape, requires_grad=True)
    shape_dict = {input_name: x.shape}

    onnx_model = load_onnx_model(onnx_path)
    mod, params = onnx2IRModule(onnx_model, shape_dict)
    print(mod.get_global_vars())
    print(mod.get_global_type_vars())
    lib = build_lib(mod, params, mydriver.target, lib_path)
    print(type(lib))
    # print(lib.get_graph_json())
    # print(lib.function_metadata)

    if not os.path.exists(lib_path):
        store_lib(lib, lib_path)
    module = graph_executor.GraphModule(lib["default"](mydriver.device))
    print(type(module))

    # write check data to disk
    datas = {}
    for _ in range(test_count):
        data_input = torch.rand(*input_shape)
        # input-output map
        out = {}
        torch_out = model(data_input).tolist()[0]
        print("torch %s" % torch_out)
        out["pytorch"] = torch_out

        module.set_input(input_name, data_input.numpy())
        module.run()
        tvm_out = module.get_output(0).numpy().tolist()[0]
        print("tvm %s" % tvm_out)
        out["tvm"] = tvm_out
        datas[str(data_input.tolist())] = out

if __name__ == "__main__":
    main()

'''
compare torch & tvm

torch 0.6757051944732666
tvm 0.6757051944732666
torch 0.7329940795898438
tvm 0.7329941987991333
torch 0.8598699569702148
tvm 0.8598699569702148
torch 0.7072029113769531
tvm 0.7072029113769531
torch 0.742712140083313
tvm 0.742712140083313
torch 0.9915422201156616
tvm 0.9915421009063721
torch 0.9976719617843628
tvm 0.9976718425750732
torch 0.660358190536499
tvm 0.6603580713272095
torch 0.5278353691101074
tvm 0.527835488319397
torch 0.5978937149047852
tvm 0.5978938341140747
'''

'''
{
  "nodes": [
    {
      "op": "null",
      "name": "input",
      "inputs": []
    },
    {
      "op": "null",
      "name": "p0",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_conv2d",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "out_layout": "",
        "kernel_layout": "OIHW",
        "hash": "13d40b07e198ac6b",
        "func_name": "tvmgen_default_fused_nn_conv2d",
        "data_layout": "NCHW",
        "flatten_data": "0"
      },
      "inputs": [
        [
          0,
          0,
          0
        ],
        [
          1,
          0,
          0
        ]
      ]
    },
    {
      "op": "null",
      "name": "p1",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_bias_add",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "e11d97547da10469",
        "func_name": "tvmgen_default_fused_nn_bias_add"
      },
      "inputs": [
        [
          2,
          0,
          0
        ],
        [
          3,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_relu",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "1",
        "flatten_data": "0",
        "hash": "688034377645acbd",
        "func_name": "tvmgen_default_fused_nn_relu"
      },
      "inputs": [
        [
          4,
          0,
          0
        ]
      ]
    },
    {
      "op": "null",
      "name": "p2",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_add",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "1e4d3c7b8a161fd8",
        "func_name": "tvmgen_default_fused_add"
      },
      "inputs": [
        [
          0,
          0,
          0
        ],
        [
          6,
          0,
          0
        ]
      ]
    },
    {
      "op": "null",
      "name": "p3",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_conv2d1",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "data_layout": "NCHW",
        "kernel_layout": "OIHW",
        "hash": "13d40b07e198ac6b",
        "func_name": "tvmgen_default_fused_nn_conv2d",
        "out_layout": "",
        "flatten_data": "0"
      },
      "inputs": [
        [
          7,
          0,
          0
        ],
        [
          8,
          0,
          0
        ]
      ]
    },
    {
      "op": "null",
      "name": "p4",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_bias_add1",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "e11d97547da10469",
        "func_name": "tvmgen_default_fused_nn_bias_add"
      },
      "inputs": [
        [
          9,
          0,
          0
        ],
        [
          10,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_relu1",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "1",
        "flatten_data": "0",
        "hash": "688034377645acbd",
        "func_name": "tvmgen_default_fused_nn_relu"
      },
      "inputs": [
        [
          11,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_add_1",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "2bc969b09eab8b94",
        "func_name": "tvmgen_default_fused_add_1"
      },
      "inputs": [
        [
          5,
          0,
          0
        ],
        [
          12,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_relu2",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "1",
        "flatten_data": "0",
        "hash": "688034377645acbd",
        "func_name": "tvmgen_default_fused_nn_relu"
      },
      "inputs": [
        [
          13,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_add_11",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "2bc969b09eab8b94",
        "func_name": "tvmgen_default_fused_add_1"
      },
      "inputs": [
        [
          14,
          0,
          0
        ],
        [
          13,
          0,
          0
        ]
      ]
    },
    {
      "op": "null",
      "name": "p5",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_add_12",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "2bc969b09eab8b94",
        "func_name": "tvmgen_default_fused_add_1"
      },
      "inputs": [
        [
          15,
          0,
          0
        ],
        [
          16,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "reshape_nop",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "1",
        "flatten_data": "0",
        "hash": "268ffe95a29d9a09",
        "func_name": "__nop"
      },
      "inputs": [
        [
          17,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_batch_flatten",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "1",
        "flatten_data": "0",
        "hash": "38146c6a3882fb00",
        "func_name": "tvmgen_default_fused_nn_batch_flatten"
      },
      "inputs": [
        [
          18,
          0,
          0
        ]
      ]
    },
    {
      "op": "null",
      "name": "p6",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_nn_dense",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "3d3c2a96e0d02a43",
        "func_name": "tvmgen_default_fused_nn_dense"
      },
      "inputs": [
        [
          19,
          0,
          0
        ],
        [
          20,
          0,
          0
        ]
      ]
    },
    {
      "op": "null",
      "name": "p7",
      "inputs": []
    },
    {
      "op": "null",
      "name": "p8",
      "inputs": []
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_multiply",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "9fc35bd85efd671f",
        "func_name": "tvmgen_default_fused_multiply"
      },
      "inputs": [
        [
          22,
          0,
          0
        ],
        [
          23,
          0,
          0
        ]
      ]
    },
    {
      "op": "tvm_op",
      "name": "tvmgen_default_fused_add_2",
      "attrs": {
        "num_outputs": "1",
        "num_inputs": "2",
        "flatten_data": "0",
        "hash": "11c5f8d9fd482bd0",
        "func_name": "tvmgen_default_fused_add_2"
      },
      "inputs": [
        [
          21,
          0,
          0
        ],
        [
          24,
          0,
          0
        ]
      ]
    }
  ],
  "arg_nodes": [0, 1, 3, 6, 8, 10, 16, 20, 22, 23],
  "heads": [
    [
      25,
      0,
      0
    ]
  ],
  "attrs": {
    "dltype": [
      "list_str",
      [
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32",
        "float32"
      ]
    ],
    "shape": [
      "list_shape",
      [
        [4, 3, 14, 14],
        [1, 3, 4, 4],
        [4, 1, 6, 6],
        [1],
        [4, 1, 6, 6],
        [4, 1, 6, 6],
        [4, 3, 14, 14],
        [4, 3, 14, 14],
        [1, 3, 4, 4],
        [4, 1, 6, 6],
        [1],
        [4, 1, 6, 6],
        [4, 1, 6, 6],
        [4, 1, 6, 6],
        [4, 1, 6, 6],
        [4, 1, 6, 6],
        [4, 1, 6, 6],
        [4, 1, 6, 6],
        [1, 144],
        [1, 144],
        [1, 144],
        [1, 1],
        [],
        [1],
        [1],
        [1, 1]
      ]
    ],
    "device_index": [
      "list_int",
      [
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2,
        2
      ]
    ],
    "storage_id": [
      "list_int",
      [
        0,
        1,
        2,
        3,
        4,
        2,
        5,
        6,
        7,
        4,
        8,
        9,
        4,
        9,
        2,
        4,
        10,
        2,
        2,
        9,
        11,
        12,
        13,
        14,
        15,
        16
      ]
    ]
  },
  "node_row_ptr": [
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26
  ]
}
'''


"""
Handler class
"""
from __future__ import unicode_literals

import inspect
import six

__all__ = ['Handler']

class HandlerType(type):
    def __init__(self, name, bases, dct):
        super(HandlerType, self).__init__(name, bases, dct)

        # Collect handler functions, sorted by name
        self._handlers = [
            getattr(self, handler_name) for handler_name in sorted(dir(self))
            if handler_name.startswith('handler_')
        ]

        # Inherit missing docstrings
        if not self.__doc__:
            docbases = bases[:]
            for base in docbases:
                if issubclass(Handler, base):
                    # Either Handler or one of its bases - gone too far
                    continue
                if base.__doc__:
                    self.__doc__ = base.__doc__
                    break

@six.add_metaclass(HandlerType)
class Handler(object):
    """
    Class-based event handler
    """
    # Permanent list of all ordered handlers
    _handlers = None

    # Temporary handler queue, created for each event
    handlers = None

    # Reference to current event
    event = None

    # Reference to current container
    container = None

    def get_handlers(self):
        return self._handlers[:]

    def get_container(self, event):
        """
        Given the event, find the container so it can be made available
        """
        return event.service

    def __call__(self, event, *args, **kwargs):
        """
        Run all handlers
        """
        # Prepare handler context
        self.event = event
        self.container = self.get_container(event)

        # Load up clean queue of handlers and loop until they're all run
        self.handlers = self.get_handlers()
        while self.handlers:
            # Get next handler
            handler = self.handlers.pop(0)

            # Process
            if inspect.isgeneratorfunction(handler):
                # ++ python 3.3 has yield from
                generator = handler(self, event, *args, **kwargs)
                try:
                    next(generator)
                except StopIteration:
                    pass
                else:
                    while True:
                        try:
                            try:
                                raw = yield
                            except Exception as e:
                                generator.throw(e)
                            else:
                                generator.send(raw)
                        except StopIteration:
                            break
                # ++ end python 2.7 support
            else:
                handler(self, event, *args, **kwargs)

            # Option to terminate event
            if event.stopped:
                self.handlers = []

        # Clean up
        self.event = None
        self.container = None
        self.handlers = []


#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2020/3/11 21:47
# @Author  : LI Dongdong
# @FileName: 399. Evaluate Division.py
''''''
'''
题目分析
1.要求：Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number).
        Given some queries, return the answers. If the answer does not exist, return -1.0.

        Example:
        Given a / b = 2.0, b / c = 3.0.
        queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
        return [6.0, 0.5, -1.0, 1.0, -1.0 ].

        The input is: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector<double>.

        According to the example above:

        equations = [ ["a", "b"], ["b", "c"] ],
        values = [2.0, 3.0],
        queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].

        The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
2.理解：带权无向图的遍历 weighted undirected graph/ 并查集
3.类型：
4.确认输入输出及边界条件：
    input： equations,[[str, str]]. str is number? letters? All in possible; values, list[float, float,...].
    output: list[float]
    corner case:
        equation is None? N
        equation is only one elem? Y -> normally
        len(equation) == len(values)? Y
        value is None? N
        value is only one? Y
5.方法及方法分析：DFS, BFS
time complexity order: O(E) + O(E) * Q = (EQ + E)
space complexity order: O(E)
6.如何考
'''
'''
A. create the graph by dict and use dfs to search this graph to get result
    Method:
        1. create the graph: {a:{b:20}, b:{a:1/2, c:3.0}..} by the equation and values in dict # time O(len(equations)), space O(2 * e)
        2. traversal every pairs in queries  # t O(e * queries) space O(q + e)
            a set named visited to present if the node is visited
            use dfs(x, y of pair) to scan the elements in each pair -> get result: 1.5
                End: x ==y, return 1
                Process:
                    tag x is visited by add it to set
                    visited x's neighbors j
                        if j not visited:
                            d = dfs(j, y)
                            return d * graph[x][y]
            save the result in a ans list
        3. return the ans list
    time complexity: O(e + e * q)
    space complexity: O(e) # 不计入输出的space，map占用2e, queue占用最多e，故是e，就是边数
易错点：
    本题空间复杂度的计算
    注意dfs也是有返回值的
    格式上依照无向图的dfs写
    时间空间复杂度也是要根据变量名来写
    注意：d = dfs(elem,j),只有在d != -1时，才返回d * graph[elem][j]，否则进行i的其他neighbors
'''

'''
B. DFS
    Method:
        1. corner case
        2. create the graph, a -> b:2.0, b -> a: 1/2
        3. do dfs on each pair, i, j,of equary
            a. check i or j in the graph or i == j
            b. find the path from i to j, collect the weight, and multiply them
            c. else return the -1
        4. use ans list to save all dfs result, and return

    Time complexity: O(e + q*e)
    Space: O(e)
'''

from collections import defaultdict

class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        if not equations or equations == [[]]:  # corner case
            return []

        graph = self.createGraph(equations, values)

        res = []
        for i, j in queries:
            visited = set()
            res.append(self.dfs(i, j, graph, visited))
        return res

    def createGraph(self, equations, values):  # return 图
        g = defaultdict(dict)

        for (i, j), val in zip(equations, values):
            g[i][j] = val
            g[j][i] = 1.0 / val
        return g

    def dfs(self, i, j, graph, visited):  # return the division res
        if i not in graph or j not in graph:  # corner case
            return -1.0
        if i == j:
            return 1.0

        visited.add(i)
        for elem in graph[i]:
            if elem not in visited:
                visited.add(elem)
                d = self.dfs(elem, j, graph, visited)
                if d != -1:
                    return d * graph[i][elem]
        return -1.0

x = Solution()
print(x.calcEquation([["x1","x2"],["x2","x3"],["x3","x4"],["x4","x5"]], [3.0,4.0,5.0,6.0], [["x2","x4"]]))
'''
B Union-find method
    不理解，有点难
    方法
        1. 构造groupTag，并计算每种连接方式的值

        2. 遍历queries，求每一对的值，加入ans
'''

class Solution:
    def calcEquation(self, equations, values, queries):
        U = {}

        def find(x):
            if x != U[x][0]:
                px, pv = find(U[x][0])
                U[x] = (px, U[x][1] * pv)
            return U[x]

        for (x, y), v in zip(equations, values):
            if x not in U and y not in U:
                U[x] = (y, v)  # 把y设为共同的被除数
                U[y] = (y, 1.0)
            elif x not in U:
                U[x] = (y, v)

            elif y not in U:
                U[y] = (x, 1.0 / v)
            else:  # 如果x，y都存在
                rx, vx = find(x)
                ry, vy = find(y)
                U[rx] = (ry, v / vx * vy)

        def divide(x, y):
            rx, vx = find(x)
            ry, vy = find(y)
            if rx != ry:
                return -1
            else:
                return vx / vy

        ans = []
        for x, y in queries:
            if x in U and y in U:
                ans.append(divide(x, y))
            else:
                ans.append(-1)

        return ans

x = Solution()
x.calcEquation(equations=[["a", "b"], ["b", "c"]], values=[2.0, 3.0],
           queries=[["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"]])

'''
C.BFS
    Method:
        1. build graph
            a -> b = 2, b ->a = 1.0/2
        2. do a bfs for each query
            first check if in the map and conrer case a == b
            start to find a shortest path to b and collect the weight and multiply them
            save in res
        3. return res

    E = len(equation), Q = len(queries)
    Time complexity: O(E) + O(E) * Q = (EQ + E)
    Space:
        O(E) = O(Vertex)
易错点：改为buildMap
'''

from collections import deque, defaultdict

class Solution:
    def calcEquation(self, equations, values, queries):  # return divsion result in list
        if not equations or equations == [[]]:
            return []

        graph = self.createGraph(equations, values)

        res = []
        for x, y in queries:
            if x not in graph or y not in graph:
                res.append(-1.0)
            else:
                res.append(self.bfs(x, y, graph))
        return res

    def createGraph(self, equations, value):  # return graph in dic[dic]
        g = defaultdict(dict)
        for (i, j), val in zip(equations, value):
            g[i][j] = val
            g[j][i] = 1.0 / val
        return g

    def bfs(self, x, y, graph):  # return division result
        if x == y:  # corner case
            return 1.0

        visited = set()
        queue = deque([(x, 1.0)])
        visited.add(x)
        while queue:
            node, val = queue.popleft()
            if node == y:
                return val
            for j in graph[node]:
                if j not in visited:
                    visited.add(j)
                    queue.append([j, val * graph[node][j]])
        return -1.0

x = Solution()
print(x.calcEquation([["a","b"],["b","c"]], [2.0,3.0], [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]]))


import nltk
from bs4 import BeautifulSoup
import urllib.request
import re

def get_text_from(raw):
	return raw

def all_childs(soup):
	for x in soup.body.childGenerator():
		print (x)

def formatText(trashs, text):
	for trash in trashs:
		text.replace(trash, "")
		return text

def textFromSoup(soup):
	text = soup.body.get_text()
	return text
	#return re.findall(r'<script>(.*?)</script>', text)

raw = ""
url = "https://en.wikipedia.org/wiki/Ouro_Preto"
response = urllib.request.urlopen(url)
html = response.read().decode('utf8')
soup = BeautifulSoup(html, 'html.parser')
#print(soup.prettify())

for parag in soup("p"):
	raw += parag.get_text()

#print(raw)

tokens = nltk.word_tokenize(raw)
#print(tokens)

tagged = nltk.pos_tag(tokens)
#print(tagged)

entities = nltk.chunk.ne_chunk(tagged)
print(entities)

# textTokens = nltk.Text(tokens)
# print(textTokens[100:150])
# print(tokens)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('cov_search', '0019_auto_20150630_1923'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='program',
            name='programtype',
        ),
        migrations.AddField(
            model_name='category',
            name='programtype',
            field=models.ForeignKey(default=45, to='cov_search.ProgramType', help_text=''),
            preserve_default=False,
        ),
    ]


'''
This program displays an animation of an oscillating wave u(x,t).
'''

import numpy as np
from numpy import pi
import matplotlib.pyplot as plt
import matplotlib.animation as animation

plt.style.use('dark_background')

fig = plt.figure()
fig.set_dpi(300)
ax1 = fig.add_subplot(1, 1, 1)

# Wave speed
c = 1

# x-axis
xdomain = (-pi, pi)
x0 = np.linspace(xdomain[0], xdomain[1], 10000)

# Initial time
t0 = 0

# Time increment
dt = 0.05

# Wave to be plotted
def u(x, t):
    return 2*(np.cos(x + 3*c*t)**2 + np.cos(x - 2*c*t)**2)

a = []
for i in range(500):
    U = u(x0, t0)
    t0 += dt
    a.append(U)

k = 0
def animate(i):
    global k
    x = a[k]
    k += 1
    ax1.clear()
    plt.plot(x0, x, color='cornflowerblue')
    plt.grid(True)
    plt.ylim((-2, 2))
    plt.xlim(xdomain)

anim = animation.FuncAnimation(fig, animate, interval=17)
plt.show()


"""
버블 정렬 복습

인접한 두 수를 비교하여 크거나 작을 때 자리를 바꿔주는 알고리즘이다.
시간 복잡도는 O(N^2)을 따르고 모든 수가 정렬되어 있을 때 flag비트를 사용하면 O(N)의 시간복잡도를 갖을 수 있다.
"""
import random

def bubble_sort(data):
    for i in range(len(data)-1):
        flag=False
        for j in range(len(data)-1-i):
            if data[j]>data[j+1]:
                data[j],data[j+1]=data[j+1],data[j]
                flag=True
        if not flag:
            break

#0~99까지의 숫자중에서 50개를 선택하여 리스트로 반환
num_list=random.sample(range(100),50)

print(num_list)
bubble_sort(num_list)
print(num_list)


from brownie import (
    accounts, AToken, Contract, DefaultReserveInterestRateStrategy,
    GenericLogic, LendingPool, LendingPool2,
    LendingPoolAddressesProvider, LendingPoolConfigurator,
    LendingPoolCollateralManager, LendingRateOracle, MintableDelegationERC20, PriceOracle, ReserveLogic,
    reverts, StableDebtToken, VariableDebtToken, ValidationLogic, WETH9, ZERO_ADDRESS
)

from Crypto.Hash import keccak
import pytest

# Wei (10^18)
WEI = 1_000_000_000_000_000_000

# WadRayMath
RAY = 1000000000000000000000000000
WAD = 1000000000000000000
RAY_DIV_WAD = RAY // WAD

# PercentMath
PERCENTAGE_FACTOR = 10_000
HALF_PERCENT = 5_000

SECONDS_PER_YEAR = 60 * 60 * 24 * 365

# MAX UINT256
MAX_UINT256 = (1 << 256) - 1

# ReserveConfiguration map constants
LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16
LIQUIDATION_BONUS_START_BIT_POSITION = 32
RESERVE_DECIMALS_START_BIT_POSITION = 48
IS_ACTIVE_START_BIT_POSITION = 56
IS_FROZEN_START_BIT_POSITION = 57
BORROWING_ENABLED_START_BIT_POSITION = 58
STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59
RESERVE_FACTOR_START_BIT_POSITION = 64

# UserConfiguration map constants
BORROWING_MASK = 0x5555555555555555555555555555555555555555555555555555555555555555

# Interest rate modes used in `LendingPool`
INTEREST_RATE_MODE_NONE = 0
INTEREST_RATE_MODE_STABLE = 1
INTEREST_RATE_MODE_VARIABLE = 2

# Default values for `DefaultReserveInterestRateStrategy` constructor
OPTIMAL_UTILIZATION_RATE = 2 * RAY // 10 # 20%
BASE_VARIABLE_BORROW_RATE = 2 * RAY // 100 # 2.00%
VARIABLE_RATE_SLOPE_1 = RAY // 100 # 1.00%
VARIABLE_RATE_SLOPE_2 = 5 * RAY // 100 # 5.00%
STABLE_RATE_SLOPE_1 = 4 * RAY // 100 # 4.00%
STABLE_RATE_SLOPE_2 = 7 * RAY // 100 # 7.00%

# Lending Rate Oracle - market borrow rate
MARKET_BORROW_RATE = 30000000000000000000000000 # 3.00%

# Default Reserve Parameters
LTV = 3_000 # 30%
THRESHOLD = 5_000 # 50%
BONUS = 11_000 # 110%

#################################
# Setup and Deployment functions
#################################

# Deploy and initialize contracts required for `LendingPool`.
# Additionally, set `LendingPool` and `LendingPoolConfiguration` to the proxy contracts.
def setup_and_deploy():
    # Dependent contracts
    accounts[0].deploy(ReserveLogic)
    accounts[0].deploy(GenericLogic)
    accounts[0].deploy(ValidationLogic)

    # Deployed contracts
    provider = accounts[0].deploy(LendingPoolAddressesProvider)
    pool = accounts[0].deploy(LendingPool)
    configurator = accounts[0].deploy(LendingPoolConfigurator)
    collateral_manager = accounts[0].deploy(LendingPoolCollateralManager)
    pool_admin = accounts[1]
    emergency_admin = accounts[2]
    price_oracle = accounts[0].deploy(PriceOracle)
    lending_rate_oracle = accounts[0].deploy(LendingRateOracle)

    # Setups & Initialization
    provider.setLendingPoolImpl(pool.address)
    provider.setLendingPoolConfiguratorImpl(configurator.address)
    provider.setLendingPoolCollateralManager(collateral_manager.address)
    provider.setPoolAdmin(pool_admin)
    provider.setEmergencyAdmin(emergency_admin)
    provider.setPriceOracle(price_oracle)
    provider.setLendingRateOracle(lending_rate_oracle)

    # Proxy the required contracts
    pool_proxy = Contract.from_abi(LendingPool, provider.getLendingPool(), pool.abi)
    configurator_proxy = Contract.from_abi(LendingPoolConfigurator, provider.getLendingPoolConfigurator(), configurator.abi)

    return (provider, pool_proxy, configurator_proxy, collateral_manager,
    pool_admin, emergency_admin, price_oracle, lending_rate_oracle)

# Deploys and setup require contracts for `LendingPoolConfiguration`
def setup_and_deploy_configuration():
    # Deploy and initialize contracts
    (addresses_provider, lending_pool, configurator, collateral_manager,
    pool_admin, emergency_admin, price_oracle, lending_rate_oracle) = setup_and_deploy()

    # Deploy contracts required for a Reserve
    incentivesController = ZERO_ADDRESS
    reserveTreasuryAddress = ZERO_ADDRESS
    weth = accounts[0].deploy(WETH9)
    atoken = accounts[0].deploy(
        AToken,
        lending_pool.address,
        weth.address,
        reserveTreasuryAddress,
        'Aave interest bearing WETH',
        'aWETH',
        incentivesController
    )
    stable_debt = accounts[0].deploy(
        StableDebtToken,
        lending_pool.address,
        weth.address,
        "Aave stable debt bearing WETH",
        "stableDebtWETH",
        incentivesController,
    )
    variable_debt = accounts[0].deploy(
        VariableDebtToken,
        lending_pool.address,
        weth.address,
        "Aave variable debt bearing WETH",
        "variableDebtWETH",
        incentivesController,
    )
    strategy = deploy_default_strategy(addresses_provider.address)

    return (addresses_provider, lending_pool, configurator, collateral_manager,
        pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, atoken,
        stable_debt, variable_debt, strategy)

# Deploys and setup require contracts for `LendingPoolConfiguration`
def setup_and_deploy_configuration_with_reserve():
    (addresses_provider, lending_pool, configurator, collateral_manager,
    pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, atoken,
    stable_debt, variable_debt, strategy) = setup_and_deploy_configuration()

    # initReserve()
    (atoken_proxy, stable_proxy, variable_proxy) = setup_new_reserve(configurator, weth, lending_pool, pool_admin)

    # Set price oracle, weth and usd prices
    price_oracle.setAssetPrice(weth.address, WEI, {'from': accounts[0]})
    price_oracle.setEthUsdPrice(500)

    return (addresses_provider, lending_pool, configurator, collateral_manager,
    pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, atoken_proxy,
    stable_proxy, variable_proxy, strategy)

# Add and initialise an additional reserve, creating require tokens
def setup_new_reserve(configurator, asset, lending_pool, pool_admin):
    # Deploy contracts required for a Reserve
    incentivesController = ZERO_ADDRESS
    reserveTreasuryAddress = ZERO_ADDRESS
    atoken = accounts[0].deploy(
        AToken,
        lending_pool.address,
        asset.address,
        reserveTreasuryAddress,
        'Aave interest bearing ' + asset.symbol(),
        'a' +  asset.symbol(),
        incentivesController
    )
    stable_debt = accounts[0].deploy(
        StableDebtToken,
        lending_pool.address,
        asset.address,
        "Aave stable debt bearing " + asset.symbol(),
        "stableDebt" + asset.symbol(),
        incentivesController,
    )
    variable_debt = accounts[0].deploy(
        VariableDebtToken,
        lending_pool.address,
        asset.address,
        "Aave variable debt bearing " + asset.symbol(),
        "variableDebt" + asset.symbol(),
        incentivesController,
    )
    strategy = deploy_default_strategy(lending_pool.getAddressesProvider())

    (atoken_proxy, stable_proxy, variable_proxy) = init_reserve_and_set_proxies(configurator, atoken, stable_debt, variable_debt, asset, strategy, pool_admin)

    return (atoken_proxy, stable_proxy, variable_proxy)

# Initialises the reserve and returns the proxied token contracts
def init_reserve_and_set_proxies(configurator, atoken, stable_debt, variable_debt, asset, strategy, pool_admin):
    # initReserve()
    tx = configurator.initReserve(
        atoken.address,
        stable_debt.address,
        variable_debt.address,
        asset.decimals(),
        strategy.address,
        {'from': pool_admin},
    )

    # Update proxy addresses
    init_event = tx.events['ReserveInitialized']
    atoken_proxy_address = init_event['aToken']
    stable_proxy_address = init_event['stableDebtToken']
    variable_proxy_address = init_event['variableDebtToken']

    atoken_proxy = Contract.from_abi(AToken, atoken_proxy_address, atoken.abi)
    stable_proxy = Contract.from_abi(StableDebtToken, stable_proxy_address, stable_debt.abi)
    variable_proxy = Contract.from_abi(VariableDebtToken, variable_proxy_address, variable_debt.abi)

    return (atoken_proxy, stable_proxy, variable_proxy)

# Turn on reserve borrowing and collateral at default rates
def allow_reserve_collateral_and_borrowing(configurator, asset, pool_admin, params=None):
    configurator.enableBorrowingOnReserve(asset.address, True, {'from': pool_admin})
    if (params != None):
        (ltv, threshold, bonus) = params
        configurator.configureReserveAsCollateral(asset.address, ltv, threshold, bonus, {'from': pool_admin})
        return (ltv, threshold, bonus)
    else:
        configurator.configureReserveAsCollateral(asset.address, LTV, THRESHOLD, BONUS, {'from': pool_admin})
        return (LTV, THRESHOLD, BONUS)

# Deploys a `DefaultReserveInterestRateStrategy` with the default configuration.
def deploy_default_strategy(addresses_provider):
    return accounts[0].deploy(
        DefaultReserveInterestRateStrategy,
        addresses_provider,
        OPTIMAL_UTILIZATION_RATE,
        BASE_VARIABLE_BORROW_RATE,
        VARIABLE_RATE_SLOPE_1,
        VARIABLE_RATE_SLOPE_2,
        STABLE_RATE_SLOPE_1,
        STABLE_RATE_SLOPE_2,
    )

# Helper for testing `borrow()` functionality
# Makes a `depositer` deposit WETH
# Creates a `borrower` with a tERC20 allowance to the `LendingPool`
def setup_borrow():
    # Deploy and initialize contracts (initializes a weth reserve)
    (addresses_provider, lending_pool, configurator, collateral_manager,
    pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken,
    weth_stable_debt, weth_variable_debt, strategy) = setup_and_deploy_configuration_with_reserve()

    # Create asset and give allowance to lending pool
    depositer = accounts[4]
    deposit_amount = 10_000_000_000_000_000_000
    weth.deposit({'from': depositer, 'value': deposit_amount})
    weth.approve(lending_pool.address, deposit_amount, {'from': depositer})

    # Turn on collateral and borrowing
    (weth_ltv, weth_threhold, weth_bonus) = allow_reserve_collateral_and_borrowing(configurator, weth, pool_admin)

    # Set market lending rate
    lending_rate_oracle.setMarketBorrowRate(weth.address, MARKET_BORROW_RATE)

    # `deposit()` weth
    lending_pool.deposit(weth.address, deposit_amount, depositer, 0, {'from': depositer})

    # Add additional reserve
    terc20 = accounts[0].deploy(
        MintableDelegationERC20,
        "Test ERC20",
        "tERC20",
        18,
    )

    # Initialise reserve tERC20
    (terc20_atoken, terc20_stable_debt, terc20_variable_debt) = setup_new_reserve(configurator, terc20, lending_pool, pool_admin)

    # Turn on collateral and borrowing
    (tecr20_ltv, tecr20_threshold, tecr20_bonus) = allow_reserve_collateral_and_borrowing(configurator, terc20, pool_admin)

    # Setup price for tERC20
    price = WEI // 10 # 1 tERC20 : 0.1 ETH
    price_oracle.setAssetPrice(terc20.address, price, {'from': accounts[0]})

    # Create tERC20 tokens for `borrower` and deposit them into `LendingPool`
    borrower = accounts[5]
    terc20_deposit_amount = deposit_amount // 10
    terc20.mint(terc20_deposit_amount, {'from': borrower})
    terc20.approve(lending_pool.address, terc20_deposit_amount, {'from': borrower})
    lending_pool.deposit(terc20.address, terc20_deposit_amount, borrower, 0, {'from': borrower})

    return (addresses_provider, lending_pool, configurator, collateral_manager,
    pool_admin, emergency_admin, price_oracle, lending_rate_oracle, weth, weth_atoken,
    weth_stable_debt, weth_variable_debt, strategy, depositer, deposit_amount, borrower,
    terc20, terc20_atoken, terc20_stable_debt, terc20_variable_debt, tecr20_ltv, tecr20_threshold, tecr20_bonus,
    terc20_deposit_amount, price)

#######################
# Calculation functions
#######################

# `WadRayMath.rayMul()`
def ray_mul(a, b):
    return (a * b + RAY // 2) // RAY

# `WadRayMath.rayDiv()`
def ray_div(a, b):
    return (a * RAY + b // 2) // b

# `WadRayMath.wadMul()`
def wad_mul(a, b):
    return (a * b + WAD // 2) // WAD

# `WadRayMath.wadDiv()`
def wad_div(a, b):
    return (a * WAD + b // 2) // b

# `WadRayMath.wadToRay()`
def wad_to_ray(a):
    return a * RAY_DIV_WAD

# `PercentMath.percentMul()`
def percent_mul(a, b):
    return (a * b + HALF_PERCENT) // PERCENTAGE_FACTOR

# `PercentMath.percentMul()`
def percent_div(a, b):
    return (a * PERCENTAGE_FACTOR + b // 2) // b

# Calculates the compound interest rate according to `MathUtils.calculateCompoundedInterest()`
# Note: `exp = currentTimestamp - lastUpdateTimestamp`
def calculate_compound_interest(rate, exp):
    if exp == 0:
        return RAY

    exp_minus_one = exp - 1

    exp_minus_two = 0
    if exp > 2:
        exp_minus_two = exp - 2

    rate_per_second = rate // SECONDS_PER_YEAR

    base_power_two = ray_mul(rate_per_second, rate_per_second)
    base_power_three = ray_mul(base_power_two, rate_per_second)

    second_term = exp * exp_minus_one * base_power_two // 2
    third_term = exp * exp_minus_one * exp_minus_two * base_power_three // 6

    return RAY + rate_per_second * exp + second_term + third_term

# Calculates the linear interest rate according to `MathUtils.calculateLinearInterest()`
def calculate_linear_interest(rate, time):
    return rate * time // SECONDS_PER_YEAR + RAY

# Stable Borrow Rate SRt
# See `DefaultReserveInterestRateStrategy.calculateInterestRates()`
def calculate_stable_borrow_rate(base_rate, slope_1, slope_2, utilization_rate, optimal_utilization_rate):
    borrow_rate = base_rate
    if utilization_rate <= optimal_utilization_rate:
        # base + Ut / Uoptimal * slope1
        borrow_rate += ray_mul(slope_1, ray_div(utilization_rate, optimal_utilization_rate))
    else:
        # base + slope1 + (Ut - Uoptimal) / (1 - Uoptimal) * slope2
        borrow_rate += slope_1 + ray_mul(ray_div(utilization_rate - optimal_utilization_rate, RAY - optimal_utilization_rate), slope_2)
    return borrow_rate

# Variable Borrow Rate VRt
# See `DefaultReserveInterestRateStrategy.calculateInterestRates()`
# Note: differs from stable rate due to order of operations which gives different rounding
def calculate_variable_borrow_rate(base_rate, slope_1, slope_2, utilization_rate, optimal_utilization_rate):
    if utilization_rate <= optimal_utilization_rate:
        # base + Ut / Uoptimal * slope1
        return base_rate + ray_div(ray_mul(utilization_rate, slope_1), optimal_utilization_rate)
    else:
        # base + slope1 + (Ut - Uoptimal) / (1 - Uoptimal) * slope2
        return base_rate + slope_1 + ray_mul(slope_2, ray_div(utilization_rate - optimal_utilization_rate, RAY - optimal_utilization_rate))

# Overall Stable Borrow Rate (increasing amount)
# prev_rate: ^SRt-1
# prev_total: SDt-1 *(1 + ^SRt-1/Tyear)^Tyear  previous total supply plus interest up until the current timestamp
# curr_rate: SRt the stable rate used for the borrow (set by the previous transaction's `updateInterestRates()`)
# amount: borrow amount
# isBorrow: bool - is the amount increasing the total (borrow) or decreasing the total (repay)
# See `StableDebtToken.mint()
def calculate_overall_stable_rate(prev_rate, prev_total, curr_rate, amount, isBorrow):
    if prev_total + amount == 0:
        return RAY

    if isBorrow:
        return ray_div(
            ray_mul(prev_rate, wad_to_ray(prev_total)) + ray_mul(curr_rate, wad_to_ray(amount)),
            wad_to_ray(prev_total + amount)
        )
    else:
        return ray_div(
            ray_mul(prev_rate, wad_to_ray(prev_total)) - ray_mul(curr_rate, wad_to_ray(amount)),
            wad_to_ray(prev_total - amount)
        )

# Overall Borrow Rate ^Rt
# See `DefaultReserveInterestRateStrategy._getOverallBorrowRate()`
def calculate_overall_borrow_rate(total_stable_debt, total_variable_debt, overall_stable_rate, variable_rate):
    total_debt = total_stable_debt + total_variable_debt
    if total_debt == 0:
        return 0

    weighted_stable_rate = ray_mul(wad_to_ray(total_stable_debt), overall_stable_rate)
    weighted_variable_rate = ray_mul(wad_to_ray(total_variable_debt), variable_rate)

    return ray_div(weighted_stable_rate + weighted_variable_rate, wad_to_ray(total_debt))


import flet as ft

from ..shared.TableHeaders import *
from ..shared.LoadingRingControl import *
from ..shared.DockerContainerUtils import *

from .ContainerRowControl import *

class ContainersControl(ft.UserControl):
    def __init__(self, dockerClient):
        super().__init__()
        self.dockerClient = dockerClient
        self.containers = []
        self.selected_containers = []
        self.__create_controls_references__()

    def __create_controls_references__(self):
        self.containersWrapper = ft.Container()
        self.containersList = ft.Column()

        self.button_load_containers = ft.Container()
        self.button_start_selected = ft.Container()
        self.button_delete_selected = ft.Container()
        self.button_create_container = ft.Container()

    def __create_table_headers__(self):
        headers = [{'title': "Status", 'width': 50}]
        headers.append({"title": "Id", "width": 150}),
        headers.append({"title": "Name", "width": 200}),
        headers.append({"title": "Actions", "width": 300}),
        return TableHeaders(headers)

    def __create_start_selected_button__(self):
        self.button_start_selected.content = ft.TextButton(
            icon=ft.icons.PLAY_ARROW,
            text="Run selected containers",
            disabled=True,
            on_click=self.__start_selected_containers__,
            data=True
        )

        return self.button_start_selected

    def __create_load_button__(self):
        self.button_load_containers.content = ft.TextButton(
            icon=ft.icons.REFRESH,
            text="Load containers",
            on_click=self.__list_containers__,
            data=True
        )

        return self.button_load_containers

    def __create_delete_selected_button__(self):
        self.button_delete_selected.content = ft.TextButton(
            icon=ft.icons.DELETE,
            text="Delete selected containers",
            on_click=self.__delete_selected_containers__,
            disabled=True
        )

        return self.button_delete_selected

    def __create_add_container_button__(self):
        self.button_create_container.content = ft.TextButton(
            icon=ft.icons.ADD,
            text="Add new container",
            tooltip="Not implemented yet",
            on_click=self.__create_new_container__
        )

        return self.button_create_container

    def __list_containers__(self, listAll):
        self.containersWrapper.content = LoadingRingControl(10)
        self.update()

        containers = self.dockerClient.containers.list(all=listAll)
        if (len(containers) > 0):
            self.containers = [self.__create_table_headers__()]
            for container in containers:
                self.containers.append(
                    ContainerRowControl(container.id, self.dockerClient, self.__delete_container__, self.__select_container__)
                )

            self.containersList.controls = self.containers
            self.containersWrapper.content = self.containersList
        else:
            self.containersWrapper.content = ft.Text("There are no containers")

        self.update()

    def __start_selected_containers__(self, startAll):
        if (len(self.selected_containers) == 0):
            print("There are no containers to run")
            return

        self.containersWrapper.content = LoadingRingControl(10)
        self.update()

        for container_id in self.selected_containers:
            container = get_container_by_id(self.dockerClient, container_id)
            if (container != None and container.status != 'running'):
                container.start()

        self.containersWrapper.content = ft.Container()
        self.update()

        self.__list_containers__(startAll)

    def __delete_selected_containers__(self, args):
        # If one couldnt be delete, log and show toast
        if (len(self.selected_containers) == 0):
            print("There are no  containers to delete")
            return

        self.containersWrapper.content = LoadingRingControl(10)
        self.update()

        for container_id in self.selected_containers:
            container = get_container_by_id(self.dockerClient, container_id)
            if (container != None and container.status != 'running'):
                container.remove()

        self.selected_containers = []

        self.__list_containers__(True)

    def __create_new_container__(self, args):
        print("Not implemented yet")

    def __delete_container__(self, container):
        self.containersList.controls.remove(container)
        self.update()

    def __select_container__(self, control):
        try:
            self.selected_containers.index(control.get_container_id())
            self.selected_containers.remove(control.get_container_id())
        except ValueError:
            self.selected_containers.append(control.get_container_id())

        self.button_start_selected.content.disabled = len(self.selected_containers) == 0
        self.button_delete_selected.content.disabled = len(self.selected_containers) == 0
        self.update()

    def build(self):
        return ft.ListView(
            controls=[
                ft.Row (
                    controls=[
                        self.__create_load_button__(),
                        self.__create_start_selected_button__(),
                        self.__create_delete_selected_button__(),
                        self.__create_add_container_button__()
                    ]
                ),
                self.containersWrapper
            ]
        )


import time

import pygame

from config import *
from objects import *
from menu import Menu
from sounds import SoundManager

class Game(Menu):
    def __init__(self):
        super().__init__('Game')
        self.player = Player()
        self.enemy = Enemy()
        self.blocks = [
            # Block(i * 100, 50) for i in range(8)
        ]
        self.block_timer = time.time()
        self.ball = Ball()
        self.initialized = False
        self.game_over = False
        self.started = False

    def update(self, events):
        for e in events:
            if e.type == pygame.KEYDOWN:
                if e.key == pygame.K_RETURN or e.key == pygame.K_KP_ENTER:
                    self.started = True
                    SoundManager.play('ball')
        if not self.initialized:
            rows = len(self.blocks) // 8
            if rows < 6:
                if time.time() - self.block_timer > 0.05:
                    self.block_timer = time.time()
                    if rows <= 4:
                        self.blocks.extend([Block(i * 100, rows * 50 + 50) for i in range(8)])
                    else:
                        self.blocks.extend([Block(i * 100, rows * 50 + 50) for i in range(8)])
            else:
                self.initialized = True
                # for i in [0, 7, 14, 21, 28, 35]:
                #     self.blocks.pop(i)
                # self.blocks = self.blocks[:1]
        else:
            if len([i for i in self.blocks if i.active]) <= 0:
                self.game_over = True
        if self.started:
            self.player.update(events)
            self.enemy.update(events)
            self.enemy.use_ai(self.ball)
            self.ball.update(events)
            self.ball.collide(self.player, self.enemy, self.blocks)
        for i in self.blocks:
            i.update(events)
        if self.ball.lives <= 0:
            return False
        if self.game_over:
            return True

    def draw(self, surf: pygame.Surface):
        for i in self.blocks:
            i.draw(surf)
        self.player.draw(surf)
        self.enemy.draw(surf)
        self.ball.draw(surf)
        if not self.started:
            t = text('Press    Enter    to    Start')
            surf.blit(t, t.get_rect(center=(screen_width // 2, screen_height // 2)))
        t = text(f'Lives   {self.ball.lives}')
        surf.blit(t, (0, 0))


#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
'''
ref https://www.cnblogs.com/zingp/p/6537841.html
希尔排序是一种分组插入排序算法。
首先取一个整数d1=n/2，将元素分为d1个组，每组相邻量元素之间距离为d1，在各组内进行直接插入排序；
取第二个整数d2=d1/2，重复上述分组排序过程，直到di=1，即所有元素在同一组内进行直接插入排序。希尔排序每趟并不使某些元素有序，而是使整体数据越来越接近有序；最后一趟排序使得所有数据有序。

时间复杂度:O((1+τ)n)
不是很快，位置尴尬
'''

#coding=utf-8
import random

def sort(li):
    """希尔排序"""
    count = len(li)
    gap = count // 2
    while gap > 0:
        print("gap=", gap)
        for i in range(gap, count):
            tmp = li[i] #待排序值
            j = i - gap #排好序最大索引
            print("i=", i, "j=", j)
            while j >= 0 and tmp < li[j]:
                li[j + gap] = li[j]
                j -= gap
            li[j + gap] = tmp
        gap //= 2

if __name__ == '__main__':
    print("希尔排序")
    a = [random.randint(1,100) for i in range(11)]
    print("\nin =", a)
    sort(a)
    print("out=", a)


"""
通过接口获取腾讯股票数据，参考：https://blog.csdn.net/geofferysun/article/details/114640013。
调用例子：
param=代码，日k，开始日期，结束日期，获取多少个交易日，前复权
https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=hk00700,day,2021-07-01,2021-07-10,10,qfq
返回例子：
{
    "code":0,
    "msg":"",
    "data":{
        "hk00700":{
            "day":[
                [
                    "2021-07-02",    # 交易日
                    "598.500",    # 开盘价
                    "574.500",    # 收盘价
                    "598.500",    # 最高价
                    "572.500",    # 最低价
                    "24938624.000"    # 总手
                ],
            ],
            "prec":"3.700",
            "vcm":"",
            "version":"15"
        }
    }
}
"""
import datetime
import requests

import db

def get_data_from_api(begin_date, end_date, days_num):
    url = "https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=hk00700,day,%s,%s,%s,qfq"
    url = url % (begin_date, end_date, days_num)
    try_times = 3
    while try_times:
        try:
            r = requests.get(url, timeout=10)
        except Exception as e:
            print('Error when get data:', e)
        else:
            return r.json()
        try_times -= 1

def get_datas(begin_date, end_date, days_num):
    print(begin_date, end_date, days_num)
    results = get_data_from_api(begin_date, end_date, days_num)
    print(results)
    datas = results['data']['hk00700']['day']
    print(datas)
    for data in datas:
        db.insert_record(*data[:6])

def get_dates(begin_date, end_date):
    dates = []
    dt = datetime.datetime.strptime(begin_date, "%Y-%m-%d")
    date = begin_date[:]
    while date <= end_date:
        dates.append(date)
        dt = dt + datetime.timedelta(1)
        date = dt.strftime("%Y-%m-%d")
    return dates

def get_history_data():
    begin_date = '2004-01-01'
    end_date = '2021-09-10'
    dates = get_dates(begin_date, end_date)
    for date in dates:
        print(date)
        get_datas(date, date, 2)    # 一天一天的取

if __name__ == "__main__":
    # begin_date = '2021-01-05'
    # end_date = '2021-01-05'
    # days_num = 1
    # results = get_data_from_api(begin_date, end_date, days_num)
    # datas = results['data']['hk00700']['day']
    # for data in datas:
    #     print(data)
    # print(len(datas))
    # get_datas(begin_data, end_data, days_num)
    get_history_data()


import json, os

import boto3

import common_funcs as cf

BUCKET = os.environ['BUCKET']
BUCKET_TEMP = os.environ['BUCKET_TEMP']
MAX_MB_SIZE_ALLOWED = os.environ.get('MAX_MB_SIZE', 100)

def lambda_handler(event, context):
    if 'body' not in event:
        return {
            'statusCode': 400,
            'body': json.dumps({
                'error': "A body in the request is required."
            })
        }

    body = cf.get_body_dict_from_event(event)

    missing_parameters = cf.missing_parameters_from_file_dict(body, ['contract_number', 'filename'])
    if missing_parameters:
        return {
            'statusCode': 400,
            'body': json.dumps({
                'error': f'\'{", ".join(missing_parameters)}\' parameter(s) is/are missing.'
            })
        }

    filename_no_extension = body['filename'].split('.')[0]
    if '/' in filename_no_extension:
        return {
            'statusCode': 400,
            'body': json.dumps({
                'error': "A filename cant have '/' on it."
            })
        }

    contract_number = body['contract_number']
    root_folder_s3 = f"{contract_number}/{filename_no_extension}"

    s3_key = cf.get_new_s3_key(root_folder_s3)

    s3_client = boto3.client('s3')
    response = s3_client.generate_presigned_post(BUCKET_TEMP, s3_key,
            Conditions=[["content-length-range", 1, MAX_MB_SIZE_ALLOWED * 1048576]], # 100mb
            ExpiresIn=300)

    return {
        'statusCode': 200,
        'body': json.dumps(response)
    }


#!/usr/bin/python3
'''Function that queries the Reddit API'''

def number_of_subscribers(subreddit):
    '''Gets number of subscribers from subreddit'''
    import requests
    url = 'https://www.reddit.com/r/{}/about.json'.format(subreddit)
    h = {'User-Agent': ''}
    subreddit_info = requests.get(url, allow_redirects=False, headers=h).json()
    try:
        subscriber_count = subreddit_info['data']['subscribers']
    except AttributeError:
        return 0
    return subscriber_count


import requests
import json
from requests import (
    ConnectionError,
    HTTPError,
    TooManyRedirects,
    Timeout
)

API = r"https://www.kuaidi100.com/chaxun?com=[]&nu=[]"

if __name__ == '__main__':
    result = requests.get(API, params={"com":"zhongtong", "nu":78169856157631})
    print(result.json())


from datetime import datetime
from dateutil.relativedelta import relativedelta

class AcademicTerm():
    WINTER = 1
    SPRING = 2
    SUMMER = 3
    AUTUMN = 4

    QTR_NAMES = {WINTER: 'WIN', SPRING: 'SPR', SUMMER: 'SUM', AUTUMN: 'AUT'}

    def __init__(self, year=None, quarter=None, date=None):
        self._date = date
        if (year is not None and quarter is not None):
            self.year = year
            self.quarter = quarter
        else:
            self.current()

    def __eq__(self, __o: object) -> bool:
        if not isinstance(__o, AcademicTerm):
            return False
        return self.year == __o.year and self.quarter == __o.quarter

    def current(self):
        if self._date is None:
            self._date = datetime.now()
        year, quarter = self._term_from_datetime(self._date)
        self.year = year
        self.quarter = quarter
        return self

    def next(self):
        if self.quarter == self.AUTUMN:
            self.year = self.year + 1
            self.quarter = self.WINTER
        else:
            self.quarter = self.quarter + 1
        return self

    def previous(self):
        if self.quarter == self.WINTER:
            self.year = self.year - 1
            self.quarter = self.AUTUMN
        else:
            self.quarter = self.quarter - 1
        return self

    @property
    def name(self):
        return '{}{}'.format(self.QTR_NAMES.get(self.quarter), self.year)

    def _autumn_start_date(self, year):
        sept = datetime(year, 9, 24)
        return sept + relativedelta(weekday=2)  # last Wednesday of Sept

    def _winter_start_date(self, year):
        jan = datetime(year, 1, 2)
        # if Jan 1 is Sunday or Monday, start on Jan 3
        if jan.weekday() in [0, 1]:
            return jan.replace(day=3)
        return jan + relativedelta(weekday=0)  # first Monday after Jan 1

    def _spring_start_date(self, year):
        start = self._winter_start_date(year) + relativedelta(weeks=11, days=1)
        return start + relativedelta(weekday=0)  # second Monday after winter

    def _summer_start_date(self, year):
        start = self._spring_start_date(year) + relativedelta(weeks=11, days=1)
        return start + relativedelta(weekday=0)  # second Monday after spring

    def _term_from_datetime(self, dt: datetime):
        terms = [self._winter_start_date(dt.year),
                 self._spring_start_date(dt.year),
                 self._summer_start_date(dt.year),
                 self._autumn_start_date(dt.year)]

        quarter = 0
        while quarter < len(terms) and dt >= terms[quarter]:
            quarter += 1

        return dt.year, quarter if (quarter > 0) else self.AUTUMN


from __future__ import unicode_literals

from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _

from shuup.admin.form_part import FormPart, TemplatedFormDef
from shuup.front.utils.translation import get_shop_available_languages, set_shop_available_languages

class TranslationSettingsForm(forms.Form):
    available_languages = forms.MultipleChoiceField(
        choices=settings.LANGUAGES,
        required=False,
        label=_("Available languages in storefront"),
        help_text=_(
            "Select all the languages that should be available in storefront. "
            "Blank means that all languages should be available."
        ),
    )

class TranslationSettingsFormPart(FormPart):
    priority = 9
    name = "translation_config"
    form = TranslationSettingsForm

    def get_form_defs(self):
        if not self.object.pk:
            return
        yield TemplatedFormDef(
            name=self.name,
            form_class=self.form,
            template_name="shuup/front/admin/translation.jinja",
            required=False,
            kwargs={"initial": dict(available_languages=get_shop_available_languages(self.object))},
        )

    def form_valid(self, form):
        if self.name not in form.forms:
            return
        data = form.forms[self.name].cleaned_data
        set_shop_available_languages(self.object, data.get("available_languages", []))


from init import *
from geochart import *

def main():
    # item, date = item_and_data_in_common()
    item = 'Tomatoes'

    avg_price_visual(item)

def avg_price_visual(item_name):
    data = pd_data.filter({'item_name':item_name})
    years = list(set(data['year'].unique()))
    begin_month = list(set(data.filter({'year':years[0]})['month'].unique()))[0]
    end_month = list(set(data.filter({'year':years[-1]})['month'].unique()))[-1]
    data_r = data_range(years, begin_month, end_month)
    all_data = []
    curr_year = 0
    for date in data_r:
        if date[1] != curr_year:
            # if curr_year != 0:
                # spinner.succeed()
            # start_spinner('Retrieving data for ' + str(date[1]) + '...')
            print('Retrieving data for the year ' + str(date[1]))
            curr_year = date[1]
        all_data.append([[x[0], i_sqrt(x[1], 10)] for x in avg_price_country(item_name, date)])
    min_value, max_value = 10, 0

    for date in all_data:
        for item in date:
            if item[1] > max_value:
                max_value = item[1]
            if item[1] < min_value:
                min_value = item[1]
    labels = [str(x[0]) + ', ' + str(x[1]) for x in data_r]
    plot_geochart('average_price_of_' + item_name.lower(), all_data, {'framerate':3, 'labels':labels, 'label_prepend': 'Average price of ' + item_name.lower() + ', date: ', 'min':min_value, 'max':max_value})

def data_range(years, begin_month, end_month):
    result = []
    years_len = len(years)
    for i in range(years_len):
        if i == 0:
            for j in range(begin_month, 13):
                result.append((j, years[i]))
        elif i == years_len - 1:
            for j in range(1, end_month + 1):
                result.append((j, years[i]))
        else:
            for j in range(1, 13):
                result.append((j, years[i]))
    return result

def avg_price_country(item_name, date):
    data = pd_data.filter({'item_name':item_name, 'month':date[0],'year':date[1]})
    prices = data.get_list('price_usd')
    countries = data.get_list('country_name')
    occurrence_dic = count_occurrences(countries)
    rem_list = []
    len_countries = len(countries)
    for i in range(len_countries):
        for j in range(i+1, len_countries):
            if countries[i] == countries[j] and i not in rem_list and j not in rem_list:
                prices[i] += prices[j]
                rem_list.append(j)
    countries = rem_indeces(countries, rem_list)
    prices = rem_indeces(prices, rem_list)
    country_prices = []
    for i in range(len(countries)):
        if not np.isnan(prices[i]):
            country_prices.append([countries[i], prices[i]])
    return [[z[0], z[1] / occurrence_dic[z[0]]] for z in country_prices]

# delete all indeces from input list given in an indeces list
def rem_indeces(input, indeces):
    indeces.sort()
    for i in range(len(indeces)):
        del(input[indeces[i]-i])
    return input

def count_occurrences(items):
    result = {}
    for item in set(items):
        result[item] = items.count(item)
    return result

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
S = list("0" + input())

lanes = []
lanes.append([])
lanes.append([7])
lanes.append([4])
lanes.append([2,8])
lanes.append([1,5])
lanes.append([3,9])
lanes.append([6])
lanes.append([10])

# 指定したレーンのピンがどれか1つでも立ってたらTrueを返す
def isStand(lane):
    targetLane = lanes[lane]
    for i in range(len(targetLane)):
        if S[targetLane[i]] == '1':
            return True
    return False

# 指定したレーンのピンがすべて倒れていたらTrueを返す
def isNotStand(lane):
    targetLane = lanes[lane]
    for i in range(len(targetLane)):
        if S[targetLane[i]] == '1':
            return False
    return True

# スプリット判定する
def check(lanea, laneb):
    #print("check", lanea, laneb)
    if(isStand(lanea) and isStand(laneb)):
        #print("isStand=true")
        for i in range(laneb-lanea-1):
            targetLaneNumber = i+lanea+1
            if isNotStand(targetLaneNumber):
                #print("isNotStand=true", targetLaneNumber)
                return True
    return False

def checkAndPrint(lanea, laneb):
    if(check(lanea, laneb)):
        print("Yes")
        exit(0)

if(S[1] == '0'):
    checkAndPrint(1,7)
    checkAndPrint(1,6)
    checkAndPrint(1,5)
    checkAndPrint(1,4)
    checkAndPrint(1,3)
    checkAndPrint(2,7)
    checkAndPrint(2,6)
    checkAndPrint(2,5)
    checkAndPrint(2,4)
    checkAndPrint(3,7)
    checkAndPrint(3,6)
    checkAndPrint(3,5)
    checkAndPrint(4,7)
    checkAndPrint(4,6)
    checkAndPrint(5,7)
    print("No")
else:
    print("No")


import numpy as np
import matplotlib.pyplot as plt

#create simple gradient

x = np.linspace(0,1,100)
y = np.linspace(0,1,100)

z = np.outer(x,y)

#now, create an arbitrary rotation of this gradient

def grad(theta, x,y):
    x = np.cos(theta)*x+np.sin(theta)*y
    y = np.cos(theta)*y-np.sin(theta)*x
    zz = x*y
    zz = (zz-zz.min())
    zz = zz/zz.max()
    return zz

def rotate_g(theta):
    zz = np.outer(x*np.cos(theta)+y*np.sin(theta),y*np.cos(theta)-y*np.sin(theta))
    return zz

def rotate(theta, x_vec):
    r = np.array([[np.cos(theta), np.sin(theta)],[-np.sin(theta), np.cos(theta)]])
    y = np.matmul(r,x_vec)
    return y


import requests
from pyquery import PyQuery as pq

'''
CSS 选择器
id #
class .
节点 不用
遍历 itmes()
获取文本 text()
----------------------
查找父节点
一个parent
多个parents
查找兄弟节点
sibings

'''

# url='http://yunvs.com/list/mai_1.html'
url='https://maoyan.com/board/4?offset=0'
headers = {

    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
    }
request = requests.get(url, headers=headers)
html=request.text
doc=pq(html)

for items in doc('div .main').find('dd').items():
    print(items('i.board-index').text())
    print(items('img.board-img').attr('data-src'))
    # print(items('img:last-child').attr('data-src'))麻烦死了
    print(items('img.board-img').attr('alt'))
    print(items('p.star').text())
    print(items('p.releasetime').text())
    print(items('p.score i.integer').text()+items('p.score i.fraction').text())
#coding=utf-8
from pyquery import PyQuery as pq
from lxml import etree
# from pyquery import PyQuery as pq
# from lxml import etree
#
#
# v_source=pq(url='http://yunvs.com/list/mai_1.html')
#
#
# for data in v_source('tr'):
#     print(pq(data).text())


import pygame
from pygame import image
from direction import Direction

class Player:
    BLACK = 0, 0, 0
    RED = 255, 0, 0

    def __init__(self, window):
        self.window = window
        self.BALL_WIDTH = 55
        self.BALL_HEIGHT = 55
        self.ball_image = pygame.transform.scale(image.load(r"assets\images\snowball.png"),
                                                 (self.BALL_WIDTH, self.BALL_HEIGHT))
        self.PLAYER_SPEED = 5.5
        self.ball_image_origin = self.ball_image
        self.rect = self.ball_image.get_rect()
        self.rect.x = 355
        self.rect.y = 295
        self.collisionRect = self.rect.inflate(-15, -15)

    def drawPlayer(self):
        self.window.blit(self.ball_image, self.rect)
        # pygame.draw.rect(window, BLACK, self.rect, 2)
        # pygame.draw.rect(self.window, self.RED, self.collisionRect, 2)

    def moveBall(self, dire):
        if dire == Direction.left:
            self.rect.x -= self.PLAYER_SPEED
        elif dire == Direction.right:
            self.rect.x += self.PLAYER_SPEED
        self.collisionRect = self.rect.inflate(-15, -15)

    def inflate(self, size):
        self.BALL_WIDTH += size
        self.BALL_HEIGHT += size
        self.rect.y -= size/2
        self.rect.x += size/2
        self.ball_image = pygame.transform.scale(self.ball_image_origin, (self.BALL_WIDTH, self.BALL_HEIGHT))
        self.rect.inflate_ip(size, size)
        self.collisionRect = self.rect.inflate(-15, -15)

    def teleportBorder(self):
        borderLeft = pygame.draw.rect(self.window, self.BLACK, pygame.Rect(-59, 0, 60, 600))
        borderRight = pygame.draw.rect(self.window, self.BLACK, pygame.Rect(741, 0, 60, 600))
        if self.rect.colliderect(borderLeft):
            self.rect.x = 685
        if self.rect.colliderect(borderRight):
            self.rect.x = 5

    def isDead(self):
        return self.BALL_WIDTH == 23


import json
import requests
import argparse

parser = argparse.ArgumentParser(
    description="Upload multiple files to cgtd")
parser.add_argument('--fields', required=True,
                    help="Path to json file with fields")
parser.add_argument('--file', nargs=2, action='append',
                    metavar=('name', 'path'),
                    help="Name and path to file to submit")
args = parser.parse_args()

with open(args.fields) as f:
    fields = json.loads(f.read())

if args.file:
    print("Submitting fields and files")
    files = [("files[]", (f[0], open(f[1], "rb"))) for f in args.file]
    r = requests.post("http://localhost:5000/v0/submissions?publish=true",
                      files=files, data=fields)
else:
    print("No files, submitting only fields")
    r = requests.post("http://localhost:5000/v0/submissions?publish=true",
                      data=fields)
print(r.text)
assert(r.status_code == requests.codes.ok)


"""配置及文字信息"""

print('my_constant.py imported:', __name__)

import os
import sys

# 部落信息
clanname = '萌萌哒部落'
# 版本信息
Version = '1.2.0 beta 2015.12.4'
# 历史版本
VersionHistory ="""
1.2.0 beta 2015.12.4
大幅优化贡献显示算法，现在超快
修复了破坏百分比计算的一个BUG
1.1.1 beta 2015.9.12
增加禁赛管理
1.1.0 beta 2015.8.28
开放部分成员管理功能； 字体字号选项正经多了；直接支持50人部落战
1.0.7 beta 2015.8.10
源代码分块；动态管理；配置文件分离；增加负责恶搞的字体字号选项
1.0.6 beta 2015.8.7
分离成员设定，使得成员修改更加容易；成员选择即时显示;文件编码调整，支持50人部落战
1.0.5 beta 2015.8.6
创建了文件关联，可以双击存档文件读入；拖动复数存档到exe上可批量读入
1.0.4 beta 2015.8.1
修改了窗口大小；人员变更；对基本信息的读取；增加参战人数选项，为扩大战斗规模做准备
1.0.3 beta 2015.7.28
支持贡献读取与显示，增加一些快捷键
1.0.2 beta 2015.7.27
更换了图标，修改了外部存储文件，输入战斗信息时可响应回车，增加了百分比记录。
1.0.1 beta 2015.7.25
更新了读取战斗记录功能，并支持幻灯片播放对战信息
1.0.0 beta 2015.7.24
部落战管理软件，可以导出战斗和贡献信息
"""
# 配置信息
config = dict(wait=500,
              inf=100,
              dir=os.path.split(sys.argv[0])[0],
              title=clanname+' 部落战记录管理 ' + Version,
              icon=os.path.join(os.path.split(sys.argv[0])[0],\
                                'data', 'Clan.ico') if \
                                sys.platform.startswith('win32')\
                                else None,
              write='utf-8', read='utf-8',
              maxnum=15, maxninsuu=50,
              boxnum=15,level_box=lambda i:str(9-i if 9>i else 1) # lambda i:str(9 - i*4 // 15)
              )

# 文件选择设置
history_opt = options = {}
options['defaultextension'] = '.clh'
options['filetypes'] = [('Ceilopty History files', '.clh'),
                        ('Ceilopty files', ('.clh', '.cld')),
                        ('all files', '.*')]
options['initialfile'] = os.path.join(config['dir'], 'save', 'history.clh')
options['title'] = '选择对战历史文件'
donate_opt = options = {}
options['defaultextension'] = '.cld'
options['filetypes'] = [('Ceilopty Donation files', '.cld'),
                        ('Ceilopty files', ('.clh', '.cld')),
                        ('all files', '.*')]
options['initialfile'] = os.path.join(config['dir'], 'save', 'data.cld')
options['title'] = '选择历史贡献文件'

# 帮助主题
helptxt = """录入顺序：选择成员->输入时间等信息->确认等级->输入战斗信息
成员选择：请从1号位开始顺序选择成员
基本信息：时间格式为6或8位年月日，之间可任意非数字分割，无视空格
战斗信息：每次进攻或防守为一条指令，第1位为A(攻击)/D(防守)，第2、3位为我方位序与敌方位序
第4位为星数，如三星则就此结束，否则继续输入百分比的1-2位整数，之后按确定或者回车。
所有战斗均输入完毕请再输入一条"End"
我方敌方位序永远分别为1位：
15人及以下部落战请以16进制数表示，
15人以上部落战输入方式较为特殊， 用0-9a-zA-Z表示0-61, 大小写敏感
更多问题请咨询Ceilopty
其他字母大小写不敏感
"""

# 快捷键
shortcuts ="""
全局
Esc:退出程序或返回

主界面
Ctrl/Alt+O:文件读取对战历史/贡献
Ctrl+H/D:打开战斗选择/贡献菜单
Ctrl+Alt+退格:界面初始化
Ctrl+Alt+R:重启程序
F1/F5/F12:帮助/刷新/另存为

战斗输入
Enter/Ctrl+Z:添加/撤销
如需更多快捷键，请联系CEILOPTY
"""


"""
- Semaphore vs Mutex
    - 둘 다 모두 병렬 프로그래밍 환경에서 상호배제를 위해 사용된다
    - Semaphore는 리소스에 대한 제한된 수의 동시 엑세스를 허용
    - Mutex는 단일 스레드만 리소스 엑세스를 허용
"""

import logging
from concurrent.futures import ThreadPoolExecutor
import time

class FakeDataStore:
    def __init__(self) -> None:
        # thread들이 공유하는 변수 (data영역에 있음)
        self.value = 0

    def update(self, n):
        logging.info(f"Thread {n} start update!")

        local_copy = self.value
        local_copy += 1
        time.sleep(0.1)  # 일부러 문제를 발생시키기 위해
        self.value = local_copy

        logging.info(f"Thread {n} end update!")

if __name__ == '__main__':
    format = "%(asctime)s: %(message)s"
    logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")

    store = FakeDataStore()

    logging.info(f"Test update. Starting valid is {store.value}")

    with ThreadPoolExecutor(max_workers=2) as executor:
        for n in ['first', 'second', 'third']:
            executor.submit(store.update, n)

    logging.info(f"Testing update. Ending value is {store.value}")

"""
- 문제없이 진행된다면 결과 최종 결과값은 3이 나와야 한다.
    - 3개의 thread가 공유하는 self.value에 1을 더하기 때문이다.
- 하지만 실제로 돌려보면 1 또는 2가 나온다.
- 어떤 thread가 self.value = local_copy를 하기전에 (update전에)
  다른 thread가 local_copy = self.value를 실행해버리기 때문이다.
"""

"""결과
22:48:58: Test update. Starting valid is 0
22:48:58: Thread first start update!
22:48:58: Thread second start update!
22:48:59: Thread first end update!
22:48:59: Thread third start update!
22:48:59: Thread second end update!
22:48:59: Thread third end update!
22:48:59: Testing update. Ending value is 2
"""


from cProfile import run
from ctypes.wintypes import RGB
from symtable import Symbol
from attr import evolve
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
import numpy as np
import sympy as sym

def RGB(r, g ,b):
    """ Function to normalize RGB """
    return (float(r)/255, float(g)/255, float(b)/255)

darkred= RGB(92,26,18)

def inv_stereo(x_coord, y_coord ):
    """ stereographic projection from plane to sphere"""
    const = x_coord ** 2 + y_coord ** 2 + 1 #denominator
    if const !=0:
        result =  1 / const * np.array([2* x_coord, 2 * y_coord, x_coord ** 2 + y_coord ** 2 - 1 ])
    else:
        result = None
        print("Error denominator is zero")
    return result

def stereo(x_sphere, y_sphere, z_sphere):
    """stereographic projection from sphere to plane"""
    if z_sphere != 1:
        result = 1 /(z_sphere - 1) * np.array([x_sphere, y_sphere])
    else:
        result = None
        print("Error denominator is zero")
    return result

def circ(r, pos):
    """creating a circle with radius r and pos as position of center"""
    theta = np.linspace(0, 2 * np.pi, 1000)
    x_circl = pos[0] + r * np.cos(theta)
    y_circl = pos[1] + r * np.sin(theta)
    return x_circl, y_circl, [0]*1000

def sphere(r, pos):
    """ Function to get the points of a sphere"""
    u, v = np.mgrid[0:2*np.pi:50j, 0:np.pi:50j]
    x_sph = pos[0] + np.cos(u)*np.sin(v)
    y_sph = pos[1] + np.sin(u)*np.sin(v)
    z_sph = pos[2] + np.cos(v)
    return x_sph, y_sph, z_sph

def eval_stereo_list(x_coords, y_coords):
    """ Function to apply a inverse stereographic projection to a set of points """
    n = len(x_coords)
    lstx = []
    lsty = []
    lstz = []
    for i in range(n):
        [xs, ys, zs] =  inv_stereo(x_coords[i], y_coords[i] )
        lstx.append(xs)
        lsty.append(ys)
        lstz.append(zs)
    return lstx, lsty, lstz

def plot_circ(r, pos):
    """ Function to plot a circle in 3D """
    x_coords, y_coords, z_coords = circ(r, pos)
    ax.plot(x_coords, y_coords, z_coords)

def vecCom(vec):
    return complex(vec[0], vec[1])

def comVec(com):
    return [np.real(com), np.imag(com)]

def T1(Z, A1, A2, A3):
    """Mobius transformation  send A1->0, A2->1, A3->inf """
    z = vecCom(Z)
    a1 = vecCom(A1)
    a2 = vecCom(A2)
    a3 = vecCom(A3)
    return comVec((z*(a1-a3)+a2*(a3-a1))/(z*(a1-a2)+a3*(a2-a1)))

def invT2(Z, B1, B2, B3):
    """Inverse Mobius transformation  send 0->B1, 1->B2, inf->B3"""
    z = vecCom(Z)
    b1 = vecCom(B1)
    b2 = vecCom(B2)
    b3 = vecCom(B3)
    return comVec((b3*(b1-b2)*z+b2*(b3-b1))/(z*(b1-b2)+b3*(b1-b2)))

def mob_transf_T1(x_coords, y_coords):
    """ Function to apply a Mobius transformation define by six points to a set of points """
    n = len(x_coords)
    lstx = []
    lsty = []

    for i in range(n):
        [xs, ys] = T1([x_coords[i], y_coords[i]], A1, A2, A3 )
        lstx.append(xs)
        lsty.append(ys)
    lstz = [0]*n
    return lstx, lsty, lstz

def mob_transf_invT2(x_coords, y_coords):
    """ Function to apply a Mobius transformation define by six points to a set of points """
    n = len(x_coords)
    lstx = []
    lsty = []

    for i in range(n):
        [xs, ys] = invT2([x_coords[i], y_coords[i]], B1, B2, B3 )
        lstx.append(xs)
        lsty.append(ys)
    lstz = [0]*n
    return lstx, lsty, lstz

def mob_transf_Comp(x_coords, y_coords):
    """ Function to apply a Mobius transformation define by six points to a set of points """
    t1x, t1y, _ = mob_transf_T1(x_coords, y_coords)
    lstx, lsty, lstz = mob_transf_invT2(t1x, t1y)

    return lstx, lsty, lstz

def mob_transf_Comp_ster(x_coords, y_coords):
    """ Function to apply a Mobius transformation define by six points to a set of points """
    t1x, t1y, _ = mob_transf_T1(x_coords, y_coords)
    lstx, lsty, lstz = mob_transf_invT2(t1x, t1y)
    return lstx, lsty, lstz

def line(dir):
    """ Function to define a line """
    l = np.linspace(-200, 200, 1000)
    return dir[0]*l, dir[1]*l, [0]*1000

def plot_line(dir):
    """ Function to plot a line """
    xs, ys, zs = line(dir)
    ax.plot(xs, ys, zs)

def plot_stereo(x_coords, y_coords, plot_label='', cl=RGB(18, 47, 92) ):
    """ Function to plot the inverse stereographic projection of a set of points """
    # Function to plot the inverse stereographic projection of points in the plane
    x_coords, y_coords, z_coords = eval_stereo_list(x_coords, y_coords )
    # Plot the transformed points
    ax.plot(x_coords, y_coords, z_coords, label=plot_label, color=cl)

def plot_stere_circ(r, pos, label):
    """ Function to plot the inverse stereographic projection of a cirlce """
    # Get the points of the circle
    xs, ys, _ = circ(r, pos)
    # Plot the inverse stereographic projection of the circle
    plot_stereo(xs, ys, label)

def plot_stere_line(dir, label):
    """ Function to plot the inverse stereographic projection of a line """
    # Get the points of the line
    xs, ys, _ = line(dir)
    # Plot the inverse stereographic projection of the line
    plot_stereo(xs, ys, label)

def plot_sphere(r, pos):
    """ Function to plot a sphere of radius r and position pos """
    # Points of the sphere
    x_sph, y_sph, z_sph = sphere(r, pos)
    # Plot the sphere
    ax.plot_surface(x_sph, y_sph, z_sph, alpha=0.3, color='white')

def Lat_circ(n, r_i, r_f):
    """Function to create a list of circles that correspond to latitude constanc circles"""
    # Range of radius
    radius = np.linspace(r_i, r_f, n)
    # List to store the circles
    circles = []
    for r in radius:
        # Add circles of the given range of radius
        circles.append(circ(r, [0,0]))
    return circles

def Long_circ(n):
    """Function to define create a list of lines that correspond to constant longitude circles"""
    # Define a range of angles
    angles = np.linspace(0, 2*np.pi, n)
    # List of lines
    lines = []
    for theta in angles:
        # Add lines
        lines.append(line([np.cos(theta), np.sin(theta)]))
    return lines

def plot_3d(xs,ys,zs, lbl='', cl='blue'):
    ax.plot(xs, ys, zs, label= lbl, color= cl)

def plot_2d(xs,ys, lbl='',  cl='blue'):
    ax2d.plot(xs, ys, label= lbl, color= cl)

def eval_plots(ls_geo_objs, cl1='black', cl2='red'):
    """ Function that plot a list of geometric objects """
    for geo_obj in ls_geo_objs:
        xls = geo_obj[0]
        yls = geo_obj[1]
        zls = geo_obj[2]
        x_ster, y_ster, z_ster = eval_stereo_list(xls, yls)
        plot_3d(xs=x_ster, ys=y_ster, zs=z_ster, cl=cl1 )
        plot_2d(xs=xls, ys=yls, cl=cl2 )

def eval_transS(ls_geo_objs, color="red"):
    """ Function that take a list of geometric objects define on R^2
    apply a mobius transformation and plot the inverse stereographic projection of them"""
    for geo_obj in ls_geo_objs:
        xs = geo_obj[0]
        ys = geo_obj[1]
        xt, yt, zt = mob_transf_Comp(xs, ys)
        plot_stereo(x_coords=xt, y_coords=yt, cl=color)

def eval_transPlane(ls_geo_objs, cl="red"):
    """ Function that take a list of geometric objects define on R^2
    apply a mobius transformation and plot the inverse stereographic projection of them"""
    for geo_obj in ls_geo_objs:
        xs = geo_obj[0]
        ys = geo_obj[1]
        n = len(xs)
        xt, yt, _ = mob_transf_Comp(xs, ys)
        ax.plot(xt, yt, [0]*n, color=cl)

def lag_to_bluchke(x,y):
    x_l = 2 * x / (1 + x * x)
    y_l = (1-  x * x) / (1 + x * x)
    z_l = 2 * y / (1 + x * x)
    return [x_l, y_l, z_l]

def bluchke_to_euc(n1,n2,h):
    x_e = np.linspace(-100, 100, 100)
    y_e = (-n2 * x_e - h) / n1
    return [x_e, y_e]

def func(t):
    return [t^2 + t, t^4 + t + 2]

def curve(x, y):
    n1 = 2 * x / (1 + x * x)
    n2 = (1-  x * x) / (1 + x * x)
    h = 2 * y / (1 + x * x)
    dx = sym.diff(x, t)
    dy = sym.diff(y, t)
    n1p = (2 - 2 * x ** 2) * dx / (1 + x ** 2) ** 2
    n2p = (-4 * x) * dx / (1 + x ** 2) ** 2
    hp = (2* y * dy * (1 + x ** 2) - 2 * x * dx * 2 * y) / (1 + x ** 2) ** 2
    cx = (hp - h * n2p) / (n1 * n2p - n1p)
    cy = (hp - h * n1p) / (n2 * n1p - n2p)
    return cx, cy

def curve_ofset(x, y, d):
    n1 = 2 * x / (1 + x * x)
    n2 = (1-  x * x) / (1 + x * x)
    h = 2 * (y+(d/2)*(1+x**2)) / (1 + x * x)
    dx = sym.diff(x, t)
    dy = sym.diff(y, t)
    n1p = sym.diff(n1, t)
    n2p = sym.diff(n2, t)
    hp = sym.diff(h, t)
    cx = (hp - h * n2p) / (n1 * n2p - n1p)
    cy = (hp - h * n1p) / (n2 * n1p - n2p)
    return cx, cy

def center_c(p1, p2, p3):
    """
    Returns the center and radius of the circle passing the given 3 points.
    In case the 3 points form a line, returns (None, infinity).
    """
    temp = p2[0] * p2[0] + p2[1] * p2[1]
    bc = (p1[0] * p1[0] + p1[1] * p1[1] - temp) / 2
    cd = (temp - p3[0] * p3[0] - p3[1] * p3[1]) / 2
    det = (p1[0] - p2[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p2[1])

    if abs(det) > 1.0e-6:
       return None

    # Center of circle
    cx = (bc*(p2[1] - p3[1]) - cd*(p1[1] - p2[1])) / det
    cy = ((p1[0] - p2[0]) * cd - (p2[0] - p3[0]) * bc) / det

    return cx, cy

def evalue(lst):
    eval = []
    for i in range(1, len(lst) - 1):

        center = center_c(lst[i-1], lst[i], lst[i+1])
        if center != None:
            eval.append(center)

    return eval

def eval_func_ls(func, ti, tf, n, *args):
    ls_t = np.linspace(ti, tf, n)
    pts = []
    for t0 in ls_t:
        pt = list(map(lambda point:  point.subs(t, t0),  func(*args) ))
        pts.append(pt)
    return pts

A1 = [1,2]
A2 = [2,3]
A3 = [4,5]
B1 = [6,7]
B2 = [7,8]
B3 = [9,10]

def vecCom(vec):
    return complex(vec[0], vec[1])

def comVec(com):
    return [np.real(com), np.imag(com)]

fig2 = plt.figure(figsize=plt.figaspect(1.))
ax2d = fig2.add_subplot()
# ax = fig.add_subplot(projection='3d')
# # Plots
# # plot_sphere(1,[0,0,0])
# # plot_circ(1,[1,1])
# # plot_line([1,1])
# # plot_stere_circ(1, [1,1], "Stero Circle")
# # plot_stere_line([1,1], "Stero Line")
# lat_circles = Lat_circ(10, 0.5, 10)

# t1_lat_circles = list(map(lambda geo: mob_transf_T1(geo[0], geo[1]), lat_circles ))
# t2_lat_circles = list(map(lambda geo: mob_transf_invT2(geo[0], geo[1]), t1_lat_circles ))

# long_circles = Long_circ(10)
# t1_long_circles = list(map(lambda geo: mob_transf_T1(geo[0], geo[1]), long_circles ))
# t2_long_circles = list(map(lambda geo: mob_transf_invT2(geo[0], geo[1]), t1_long_circles ))

# eval_plots(long_circles,cl1='blue', cl2='blue' )
# eval_plots(lat_circles,cl1='purple', cl2='purple' )
# eval_plots(t2_lat_circles, cl1='black', cl2='black')
# eval_plots(t2_long_circles, cl1='green', cl2='green')
# #eval_plots(lat_circles,cl1='red', cl2='red' )
# #eval_plots(t1_lat_circles, cl1='purple', cl2='purple')
# #eval_plots(t2_lat_circles, cl1='green', cl2='green')
# plot_sphere(1,[0,0,0])

# ax2d.axes.set_xlim(left=-2, right=2)
# ax2d.axes.set_ylim(bottom=-2, top=2)
# ax.axes.set_xlim3d(left=-1.5, right=1.5)
# ax.axes.set_ylim3d(bottom=-1.5, top=1.5)
# ax.axes.set_zlim3d(bottom=-1.5, top=1.5)
# ax.set_box_aspect((1, 1, 1))

# custom_lines1 = [Line2D([0], [0], color='red', lw=4),
#                 Line2D([0], [0], color='purple', lw=4),
#                 Line2D([0], [0], color='green', lw=4)]

# custom_lines2 = [Line2D([0], [0], color='blue', lw=4),
#                 Line2D([0], [0], color='black', lw=4),
#                 Line2D([0], [0], color='red', lw=4)
#                 ]

# custom_lines3 = [Line2D([0], [0], color='blue', lw=4),
#                 Line2D([0], [0], color='purple', lw=4),
#                 Line2D([0], [0], color='black', lw=4),
#                 Line2D([0], [0], color='green', lw=4)
#                 ]

# ax2d.legend(custom_lines3,["Longituted C","Latituted C", "Transf Long", "Transf Lat"], loc="upper right")
# ax.legend(custom_lines3,["Longituted C","Latituted C", "Transf Long", "Transf Lat"], loc="upper right")

# pts = []

# for t in range(10):
#     x, y = func(t)
#     x_lst, y_lst =  bluchke_to_euc(lag_to_bluchke(x,y)[0], lag_to_bluchke(x,y)[1], lag_to_bluchke(x,y)[2])
#     ax2d.plot(x_lst, y_lst)
# ax2d.set_xlim(-10,10)
# ax2d.set_ylim(-10,10)
# plt.show()
a, b, t = sym.symbols('a b t')

# Rational curve in IC2
x = (t ** 2 + t**4)/(t**3+2*t+t**2)
y = (t**3+2*t+t**2)/(t ** 2 + t**4)

# List of offsets
ls_offsets = [-1,-2,-5,1,2,3]
# Initial t0
ini_t  = 0.1
# Fintal tf
final_t = 12
# Number of points between t0 and tf
n = 50

pts = np.array(eval_func_ls(curve, ini_t, final_t, n, x, y))
pts_off = np.array(list(map( lambda d: np.array(eval_func_ls(curve_ofset, ini_t, final_t, n, x, y, d)), ls_offsets )))
#pts_off =  np.array(eval_func_ls(curve_ofset, 0.1, 12, 50, x, y, 2))
pts_evo = np.array(evalue(pts))

ax2d.plot(pts[:,0],pts[:,1])
for i in range(len(pts_off)):

    ax2d.plot(pts_off[i][:,0],pts_off[i][:,1])

ax2d.plot(pts_evo[:,0],pts_evo[:,1])
ax2d.set_xlim(-5,5)
ax2d.set_ylim(-5,5)
plt.show()


from django.db import models
from django.urls import reverse, reverse_lazy
from django.utils.translation import gettext_lazy as _
from django.core.validators import MinValueValidator, MaxValueValidator
from django.contrib.auth.models import User

class Software(models.Model):
    class Categories(models.TextChoices):
        GRAPHICAL   = 'G', _('Графическое')
        CONSOLE     = 'C', _('Консольное')
        LIBRARY     = 'L', _('Библиотека')
        APPLICATION = 'A', _('Приложение')

    owner         = models.ForeignKey(User, on_delete=models.CASCADE)
    category      = models.CharField(max_length=1, blank=False, choices=Categories.choices, default='A')
    title         = models.CharField(max_length=100, blank=False)
    version       = models.CharField(max_length=100, blank=False, default='Unknown')
    build_options = models.TextField(blank=True)

    def get_absolute_url(self):
        return reverse('software', kwargs={'software_id': self.pk})

    # class Meta:
    #     constraints = [
    #         models.UniqueConstraint(fields=['category', 'title', 'version', 'build_options'], name='unique_row_software')
    #     ]


from skimage.measure import label
import numpy as np
import sys

def TruncatedNormal(loc, scale, size, min_v, max_v):
    vec = np.random.normal(loc=loc, scale=scale, size=size)
    def f(val):
        if min_v > val:
            return True
        elif val > max_v:
            return True
        else:
            return False
    res = np.array(map(f, vec))
    if True in res:
        n_size = res.sum()
        vec[res] = TruncatedNormal(loc, scale, n_size, min_v, max_v)
    return vec

#col = TruncatedNormal(loc=127, scale=100, size=3, min_v=1, max_v=255)
#print(col)
def AddNoise(GT, mu, std, std_2, min_v, max_v):
    GT_lbl = label(GT)
    x, y = GT.shape
    GT_noise = np.zeros(shape=(x, y, 3))

    for i in range(1, GT_lbl.max() + 1):

        col = TruncatedNormal(loc=mu, scale=std, size=3, min_v=min_v, max_v=max_v)

        print('type col:', type(col))

        #GT_noise[GT_lbl == i] = col.astype(int)
        nrow = GT_lbl[GT_lbl == i].shape[0]

        print('nrow:', nrow)

        RANDOM = np.zeros(shape=(nrow, 3))

        print(f'random shape: {RANDOM.shape}')

        for j in range(3):
            RANDOM[:, j] = TruncatedNormal(loc=col[j], scale=std_2, size=nrow, min_v=min_v, max_v=max_v)

        GT_noise[GT_lbl == i] = RANDOM
        #sys.exit(0)

    return GT_noise.astype('uint8')

def AddNoiseFiber(fiber):
    lbl = fiber.copy()
    # lbl = lbl.reshape(256,256)
    col = TruncatedNormal(loc=127, scale=100, size=3, min_v=1, max_v=255)
    nrow = lbl[lbl==255].shape[0]
    RANDOM = np.zeros(shape=(nrow, 3))
    for j in range(3):
        RANDOM[:, j] = TruncatedNormal(loc=col[j], scale=10, size=nrow, min_v=1, max_v=255)
    return RANDOM

def Noise(img, std):
    fl = img.flatten()
    vec = np.random.normal(loc=0, scale=std, size=len(fl))
    def g(val):
        if 0 > val:
            return -val
        else:
            return val
    #noise = np.array(map(g, vec))
    noise = list(map(g, vec))
    #noise = np.fromiter(noise, dtype=np.float64)
    noise = np.array(noise)
    #print(noise.shape)
    #print("*****", fl.shape, "***", vec.shape)
    res = fl + noise
    #res = fl + vec
    res = res.reshape(img.shape)
    res[res > 255.] = 255.
    return res.astype('uint8')