import bmxobs as bmx
import matplotlib.pyplot as plt
import numpy as np
import statistics as stats

def bin_data(bmx_obj, channel, bin_fact, axis = "Time"):
    data = np.transpose(bmx_obj[int(channel)])
    data_shape = np.shape(data)

    if axis == "Time":
        ubin_len = float(data_shape[1])

    if axis == "Frequency":
        ubin_len = float(data_shape[0])

    if axis != "Time" and axis != "Frequency":
        print("ERROR: The allowed options for 'axis' are 'Time' and 'Frequency'")
        quit()

    bin_len = ubin_len/float(bin_fact)

    rem = (ubin_len-1.0)%(bin_len-1.0)
    n = (ubin_len-1.0-rem)/(bin_len-1.0)
    bin_len = int(((ubin_len-1.0)/n)+1)

    new_dat_list = np.zeros(bin_len)

    if axis == "Time":
        data_out = np.zeros(shape = (data_shape[0], bin_len))
        for row_index in np.arange(data_shape[0]):
            for element in np.arange(bin_len):
                if element == 0:
                    new_dat_list[element] = stats.mean(data[row_index, 0:int((n+1)/2)])

                if element == bin_len-1:
                    new_dat_list[element] = stats.mean(data[row_index, int(n*element - (n-1)/2):int(n*element + 1)])

                if element != 0 and element != bin_len-1:
                    new_dat_list[element] = stats.mean(data[row_index, int(n*element-(n-1)/2):int(n*element+(n+1)/2)])

            data_out[row_index, :] = new_dat_list

    if axis == "Frequency":
        data_out = np.zeros(shape = (bin_len, data_shape[1]))
        for col_index in np.arange(data_shape[1]):
            for element in np.arange(bin_len):
                if element == 0:
                    new_dat_list[element] = stats.mean(data[0:int((n+1)/2),col_index])

                if element == bin_len-1:
                    new_dat_list[element] = stats.mean(data[int(n*element - (n-1)/2):int(n*element + 1),col_index])

                if element != 0 and element != bin_len-1:
                    new_dat_list[element] = stats.mean(data[int(n*element-(n-1)/2):int(n*element+(n+1)/2),col_index])

            data_out[:, col_index] = new_dat_list

    return data_out

data = bmx.BMXObs("/home/chandrahas/Desktop/BMX/pas/210903_0000", channels="111")
data_out = bin_data(data,"111",40,"Frequency")
print(np.shape(data_out))

################### PLOT ##########################
extent = [0,1,data.freq[1][0],data.freq[1][-1]]
im = plt.imshow(data_out, cmap = "Blues", extent = extent, aspect = 'auto', interpolation = None)
plt.colorbar()
plt.show()


import cv2 as cv
import numpy as np

camera_res = (640, 480)
post_crop = (19, 44, 617, 394)

img_shape = (post_crop[2] - post_crop[0], post_crop[3] - post_crop[1])

def order_points(pts):
    '''
    From: https://stackoverflow.com/questions/62295185/warping-a-license-plate-image-to-be-frontal-parallel
    '''
    # Step 1: Find centre of object
    center = np.mean(pts)

    # Step 2: Move coordinate system to centre of object
    shifted = pts - center

    # Step #3: Find angles subtended from centroid to each corner point
    theta = np.arctan2(shifted[:, 0], shifted[:, 1])

    # Step #4: Return vertices ordered by theta
    ind = np.argsort(theta)
    return pts[ind]

def view(img, text=''):
    cv.imshow(text, img)
    cv.waitKey()
    # exit()

def unwrap(img : cv.Mat):
    '''
    highly influenced by: https://stackoverflow.com/questions/62295185/warping-a-license-plate-image-to-be-frontal-parallel
    '''
    assert img.ndim == 2, img.ndim

    # print(img.shape)

    _, thresh = cv.threshold(img, 150, 255, cv.THRESH_BINARY)
    img_blur = cv.GaussianBlur(thresh, (5, 5), 1)
    # view(img_blur)

    dst = cv.Canny(img_blur, 50, 200, None, 3)

    # view(dst)
    contours, hierarchy = cv.findContours(dst, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
    # print("Number of Contours found = " + str(len(contours)))

    maxArea = 0
    biggest = np.array([])
    index = None
    for i, cnt in enumerate(contours):  # Change - also provide index
        area = cv.contourArea(cnt)
        if area > 500:
            peri = cv.arcLength(cnt, True)
            approx = cv.approxPolyDP(cnt,0.02*peri, True)
            if area > maxArea and len(approx) == 4:
                biggest = approx
                maxArea = area
                index = i  # Also save index to contour
    warped = None  # Stores the warped license plate image
    height = img.shape[0]
    width = height * 74 // 27
    # cv.drawContours(background, contours, index, (255,255,255), 3)
    # view(background)
    if index is not None: # Draw the biggest contour on the image
        # cv.drawContours(background, contours, index, (255, 255, 255), 3)

        src = np.squeeze(biggest).astype(np.float32) # Source points

        # Destination points
        dst = np.float32([[0, 0], [0, height - 1], [width - 1, 0], [width - 1, height - 1]])

        # Order the points correctly
        biggest = order_points(src)
        dst = order_points(dst)
        # print(biggest)
        # print(dst)

        # Get the perspective transform
        M = cv.getPerspectiveTransform(src, dst)

        # Warp the image
        img_shape = (width, height)
        # print(img_shape)
        warped = cv.warpPerspective(img, M, img_shape, flags=cv.INTER_LINEAR)

    margins = 5
    # view(warped)
    return warped[margins: height - margins, margins : width - margins]

def segment(img):
    _, thresh = cv.threshold(img, 100, 255, cv.THRESH_BINARY)
    dst = cv.Canny(thresh, 140, 150, None, 3)

    # view(dst)
    contours, hierarchy = cv.findContours(dst, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
    # print("Number of Contours found = " + str(len(contours)))
    # view(img)
    cnts = np.concatenate(contours)
    x, y, w, h = cv.boundingRect(cnts)
    img_cropped = thresh[y:y+h, x:x+w]

    # view(img_cropped)
    return [img_cropped[:, i * w//4 : (i+1) * w//4 + 1] for i in range(0, 4)]

def classify_number(img):
    padding = 20
    img = img[padding:img.shape[0] - padding, padding:img.shape[1] - padding]
    edges = cv.Canny(img, 50, 150)
    contours, hierarchy = cv.findContours(edges, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
    # print("Number of Contours found = " + str(len(contours)))

    angles = []
    for cnt in contours:
        rect = cv.minAreaRect(cnt)
        if rect[1][1] * rect[1][0] < 500:
            continue
        angle = rect[-1] + (0 if rect[1][1] > rect[1][0] else 90)
        # print(angle)
        angles.append(angle)

    #     cv.drawContours(blank,[box],0,(0,255,255),2)
    # view(blank)
    print(len(angles))
    # view(img)
    if len(angles) != 4:
        mapping = {6 : 2, 2 : 3, 5 : 5}
        return mapping[len(angles)]

    # find horizontal lines
    h_line = np.count_nonzero(np.abs(np.abs(np.array(angles)) - 90) < 20)
    mapping = [6, 4, 1]
    return mapping[h_line]

def task5(img, rotate180 = False):
    if rotate180:
        img = cv.rotate(img, cv.ROTATE_180)
    unwrapped = unwrap(img)
    view(unwrapped)

    chars = segment(unwrapped)
    assert len(chars) == 4
    ret = [classify_number(chars[i]) for i in range(len(chars))]
    if rotate180:
        print(f'task 5 output: {ret[::-1]}')
    else:
        print(f'task 5 output: {ret}')
    return ret

if __name__ == '__main__':
    # img_path = r'/Users/yefan/Downloads/task5-obj/0022.png'
    # img_path = r'src/perception/task5_test_data/0009.png'
    # img_path = r'/Users/yefan/Downloads/task5-obj/0027.png'
    # img_path = r'/Users/yefan/Downloads/task5-obj/0015.png'
    # img_path = r'/Users/yefan/Downloads/task5-obj/0004.png'
    img_path = r'/Users/yefan/Downloads/qwer.jpg'
    # img_path = r'/Users/yefan/Downloads/test.jpg'
    img_obj = cv.imread(img_path, cv.IMREAD_GRAYSCALE)
    # assert img_obj != None
    # view(img_obj)
    try:
        task5(img_obj, rotate180=False)
    except:
        task5(img_obj, rotate180=True)
    # if False:
    #     view(chars[3])
    #     print(classify_number(chars[3]))
    # else:
    #     for i in range(0,4):
    #         # view(chars[i])
    #         print(classify_number(chars[i]))


#!/usr/bin/python
#-*- coding: utf-8 -*-
"""NLP Homework #3: Twenty Newsgroups Classification

This is a skeleton file for NLP homework.
Please complete your task with respect to the given guideline.
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy import rand
from sklearn import (datasets, feature_extraction, linear_model, metrics,svm)
from sklearn.naive_bayes import ComplementNB
from sklearn.neural_network import MLPClassifier
def train(dataset, target):
    '''
    Train my model with the given training dataset

    Parameters
    ----------
    dataset: list or numpy.array
        The given training dataset

    target: list or numpy.array
        The given training target (true labels)

    Returns
    -------
    object or tuple of objects
        My trained model such as a feature extractor and classifier

    Notes
    -----
    * My name: 김예빈
    * My student ID: 19101198
    * My accuracy (max. 1): 0.699
    * Brief description
      - ml 수업 때 배운 다양한 Classifier를 적용해보았습니다.
      - 약 10개 정도를 검사했고 그 결과 중 0.5 이상의 정확도를 가지는 것들을 선택하였습니다.
      - 추려진 결과 각각에 대해 vectorizer를 TfidfVectorizer로 변경하여 정확도를 높이고자 했고 그 중 가장 높은 정확도를 내는 값을 선택하였습니다.
      - 결과적으로 변경된 부분은 다음과 같습니다.
      - classifier = svm.LinearSVC()
      - vectorizer = feature_extraction.text.TfidfVectorizer()
    * Discussion
      - 과제를 진행하면서 가능하면 0.7 이상의 정확도를 내고자 노력했으나 다양한 방법을 시도해도 0.699까지가 한계였습니다.
      - 아쉬운 마음이 드는데 어떻게 하면 0.7 이상의 정확도를 가질 수 있는지가 너무 궁금합니다.
      - classifier를 ComplementNB()로 변경하여 0.712 획득.
    * Collaborators: 혼자 진행하였습니다.
    * References
      - ml 강의자료와 vectorization_bow 강의자료를 참고했습니다.
      - 그동안 colab에서 실행하여 시스템에서 .py 파일을 돌리기 위해 아래 웹사이트를 참고하여 시스템 환경설정을 실행하였습니다.
        - https://blog.naver.com/PostView.naver?blogId=racoonpapa&logNo=222435398541&redirect=Dlog&widgetTypeCall=true&directAccess=false
      - 사이킷런 웹사이트에서 20 newgroups dataset을 활용하는 부분을 참고했습니다.
        - https://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html
      - classifier의 정확도를 높이기 위해 사이킷런 웹사이트에서 LinearSVC 를 참고했습니다.
        https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVC.html

    '''

    # PLEASE WRITE YOUR CODE HERE
    # (The following lines are my example, you can remove them.)
    vectorizer = feature_extraction.text.TfidfVectorizer(stop_words='english', ngram_range=(1,3), max_df=1.0, min_df=1, sublinear_tf=True, analyzer='word')
    vector = vectorizer.fit_transform(dataset)
    # classifier = svm.LinearSVC(multi_class='crammer_singer', random_state=0, tol=0.001, C=1.0, fit_intercept=True, intercept_scaling=1.0, class_weight=None, verbose=0)
    classifier = ComplementNB(alpha=0.4)
    classifier.fit(vector, target)
    return (vectorizer, classifier)

def predict(model, dataset):
    '''
    Predict lables of the given test dataset

    Parameters
    ----------
    model: object or tuple of objects
        My trained model such as a feature extractor and classifier

    dataset: list or numpy.array
        The given test dataset

    Returns
    -------
    list or numpy.array
        Predicted labels
    '''

    # PLEASE MODIFY THE FOLLOW IF NECESSARY
    vectorizer, classifier = model
    vector = vectorizer.transform(dataset)
    pred = classifier.predict(vector)
    return pred

if __name__ == '__main__':
    # Load a dataset (Note: For the first time, it spent long time to download the datasets.)
    remove = ('headers', 'footers', 'quotes')
    news20_train = datasets.fetch_20newsgroups(subset='train', remove=remove)
    news20_test  = datasets.fetch_20newsgroups(subset='test',  remove=remove)

    # Train a model and evaluate it
    model = train(news20_train.data, news20_train.target)
    pred = predict(model, news20_test.data)
    accuracy = metrics.balanced_accuracy_score(news20_test.target, pred)

    # Print the results
    print('### My results')
    print(f'* My accuracy: {accuracy:.3}')


import typing

import pytest

from synchronicity import Interface, Synchronizer, combined_types
from synchronicity.type_stubs import StubEmitter

class ImplType:
    attr: str

synchronizer = Synchronizer()

BlockingType = synchronizer.create_blocking(ImplType, "BlockingType", __name__)
AsyncType = synchronizer.create_async(ImplType, "AsyncType", __name__)

def test_wrapped_class_keeps_class_annotations():
    assert BlockingType.__annotations__ == ImplType.__annotations__
    assert AsyncType.__annotations__ == AsyncType.__annotations__

@pytest.mark.parametrize(
    "t,interface,expected",
    [
        (
            typing.AsyncGenerator[int, str],
            Interface.BLOCKING,
            typing.Generator[int, str, None],
        ),
        (
            typing.AsyncContextManager[ImplType],
            Interface.BLOCKING,
            combined_types.AsyncAndBlockingContextManager[BlockingType],
        ),
        (
            typing.AsyncContextManager[ImplType],
            Interface.ASYNC,
            typing.AsyncContextManager[AsyncType],
        ),
        (
            typing.Awaitable[typing.Awaitable[str]],
            Interface.ASYNC,
            typing.Awaitable[typing.Awaitable[str]],
        ),
        (typing.Awaitable[typing.Awaitable[str]], Interface.BLOCKING, str),
        (typing.Coroutine[None, None, str], Interface.BLOCKING, str),
        (typing.AsyncIterable[str], Interface.BLOCKING, typing.Iterable[str]),
        (typing.AsyncIterator[str], Interface.BLOCKING, typing.Iterator[str]),
        (
            typing.Optional[ImplType],
            Interface.BLOCKING,
            typing.Union[BlockingType, None],
        ),
        (typing.Optional[ImplType], Interface.ASYNC, typing.Union[AsyncType, None]),
    ],
)
def test_annotation_mapping(t, interface, expected):
    stub_emitter = StubEmitter(__name__)
    assert stub_emitter._translate_annotation(t, synchronizer, interface, __name__) == expected


# =============================================================================
# Libs
# =============================================================================

from torch.utils.data import Dataset
import torch.nn.functional as F
from collections import Counter
import os
import torch.optim as optim
import torch.nn as nn
import numpy as np
import random
import torch
import math
import re
import pandas as pd
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# =============================================================================
# Dataset
# =============================================================================
class SVDataset(Dataset):
    #Init dataset
    def __init__(self, datapath, vocab, seq_len):
        dataset = self
        dataset.data_df = pd.read_table(datapath)
        dataset.texts = dataset.data_df["sentence"]
        dataset.sentences = [s.split() for s in dataset.texts]
        dataset.verbs = dataset.data_df["verb"]

        #get the verb_positon
        dataset.verb_pos = dataset.data_df["verb_index"]
        # Define the mapping
        mapping = {'VBP': 1, 'VBZ': 0}

        # Convert labels to numbers using the mapping
        dataset.sv_targets = dataset.data_df["verb_pos"].map(mapping).tolist()

        dataset.vocab = ['[PAD]', '[CLS]', '[SEP]', '[MASK]', '[UNK]'] + vocab
        dataset.vocab = {e:i for i, e in enumerate(dataset.vocab)}
        dataset.rvocab = {v:k for k,v in dataset.vocab.items()}
        dataset.seq_len = seq_len

        #special tags
        dataset.PAD = dataset.vocab['[PAD]'] #replacement tag for tokens to ignore  - 0
        dataset.UNK = dataset.vocab['[UNK]'] #replacement tag for unknown words 4
        dataset.MASK = dataset.vocab['[MASK]'] #replacement tag for the masked word prediction task - 3
        dataset.CLS= dataset.vocab['[CLS]'] #Classification token -1
        dataset.SEP = dataset.vocab['[SEP]' ] # EOS token -2

    #fetch data
    def __getitem__(self, index):
        dataset = self
        sentence  = dataset.sentences[index]
        target = dataset.sv_targets[index]
        text = dataset.texts[index]
        verb = dataset.verbs[index]
        sentence = dataset.sentences[index]

        #get verb position
        verb_position = dataset.verb_pos[index] # in the dataset pos starts from 1

        #tokenize the sentence
        sent_tokenized = dataset.tokenize(sentence)
        sent_tokenized = [dataset.CLS] + sent_tokenized + [dataset.SEP]

        #replace verb with UNK
        sent_tokenized[verb_position] = dataset.UNK

        #ensure that the sequence is of length seq_len
        sv_input = sent_tokenized[:dataset.seq_len]
        #print(sv_input)

        #apply padding
        padding = [dataset.PAD for _ in range(dataset.seq_len - len(sv_input))]
        sv_input.extend(padding)

        return {'input': torch.Tensor(sv_input).long(),
                'sv_target': torch.Tensor([target]).long()}

    #return length
    def __len__(self):
        return len(self.sentences)

    def tokenize(self, tokens):
        """
        Tokenize the sentence.
        param tokens: list of words in a sentence
        return token ids of the words as list
        """
        dataset = self
        token_idx = [0] * len(tokens)
        for i, token in enumerate(tokens):
            if token in dataset.vocab:
                token_idx[i]=dataset.vocab[token]
            else:
                token_idx[i]=dataset.UNK
        return token_idx


import collections

########################################################

def eulerian_cycle(graph, root=None):
    unexplored_edges = set()
    unexplored_nodes = set()

    if len(graph) is 0:
        return list()

    for k in graph:
        for elem in graph[k]:
            unexplored_edges.add((k, elem))

    def random_walk(origin):
        path = list()
        path.append(origin)
        curr = origin
        next_node = None

        while len(graph[curr]) is not 0:
            next_node = graph[curr].pop()
            if len(graph[curr]) is not 0:
                unexplored_nodes.add(curr)
            unexplored_edges.remove((curr, next_node))
            path.append(next_node)
            curr = next_node

        return path

    # Gets a random key if needed
    if root is None:
        (first_node, values) = graph.popitem()
        graph[first_node] = values
    else:
        first_node = root

    result = random_walk(first_node)

    while len(unexplored_edges) > 0:
        new_origin = unexplored_nodes.pop()
        cycle = random_walk(new_origin)
        index = result.index(new_origin)
        result = result[:index] + cycle + result[index + 1:]

    return result

def eulerian_path(graph):
    in_degrees = collections.defaultdict(int)
    out_degrees = collections.defaultdict(int)
    root = None

    for node in graph:
        for out in graph[node]:
            in_degrees[out] += 1

    for node in graph:
        out_degrees[node] = len(graph[node])

    nodes = set(out_degrees.keys()).union(set(in_degrees.keys()))

    for node in nodes:
        if in_degrees[node] < out_degrees[node]:
            root = node

    return eulerian_cycle(graph, root)

###############################################################

def format_path(path):
    return '->'.join(map(str, path))

def format_kmers_path(path):
    res = path[0]
    for elem in path[1:]:
        res += elem[-1:]
    return res

def format_kdmers_path(path, k, d):
    begin = path[0][0]
    end = path[0][1]
    for elem in path[1:]:
        begin += elem[0][-1:]
        end += elem[1][-1:]

    return begin + end[-(k+d):]

#################################################################

def parse_input_graph(fname):
    workfile = open(fname, 'r')
    lines = workfile.readlines()
    lines = map(lambda x: x.strip(), lines)

    graph = collections.defaultdict(set)
    for line in lines:
        pair = line.split(' -> ')
        for elem in pair[1].split(','):
            graph[int(pair[0])].add(int(elem))

    return graph

def parse_input_kmers_with_k(fname):
    workfile = open(fname, 'r')
    _ = int(workfile.readline().strip())
    kmers = workfile.readlines()
    return map(lambda x: x.strip(), kmers)

def parse_input_kmers(fname):
    workfile = open(fname, 'r')
    kmers = workfile.readlines()
    return map(lambda x: x.strip(), kmers)

def parse_input_kdmers(fname):
    workfile = open(fname, 'r')
    [k, gap] = map(int, workfile.readline().strip().split(' '))
    lines = workfile.readlines()
    kmers = list(map(lambda x: x.strip().split('|'), lines))
    return (k, gap, kmers)

##############################################################

def de_bruijn_graph(kmers):
    graph = collections.defaultdict(set)

    for kmer in kmers:
        graph[kmer[:-1]].add(kmer[1:])

    return graph

def kd_de_bruijn_graph(kmers):
    graph = collections.defaultdict(set)

    for kmer in kmers:
        graph[(kmer[0][:-1], kmer[1][:-1])].add((kmer[0][1:], kmer[1][1:]))

    return graph

##############################################################

def generate_kmers(k):
    result = set(['0', '1'])
    for _ in range(1, k):
        tmp = set()
        for elem in result:
            tmp.add(elem + '0')
            tmp.add(elem + '1')
        result = tmp
    return result

#############################################################

def main():
    (k, gap, kmers) = parse_input_kdmers('input.txt')
    graph = kd_de_bruijn_graph(kmers)
    print(graph)
    path = eulerian_path(graph)
    print(format_kdmers_path(path, k, gap))

if __name__ == '__main__':
    main()


from django.test import TestCase

class TestIndex(TestCase):
    """
    Test to see if the main index page is working.
    """
    def test_get_index(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'home/index.html')


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2017-04-19 21:08:28
# Project: maoyan

from pyspider.libs.base_handler import *
import json
import os
import time
import MySQLdb
import re
import time
import datetime

class Handler(BaseHandler):
    crawl_config = {
        'itag': 'v223',
    }

    def __init__(self):
        self.headers = {
            'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Encoding':'gzip, deflate, sdch, br',
            'Accept-Language':'zh-CN,zh;q=0.8',
            'cache-control':'max-age=0',
            'Cookie':'_lxsdk=15b427e86df0-013da14baa8ae5-24414032-100200-15b427e86e0c8; __utma=17099173.1793184252.1492609870.1492609870.1492609870.1; __utmz=17099173.1492609870.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _lx_utm=; __mta=41653021.1491469240404.1496486523638.1496486534862.164; _lxsdk_s=02f55d53e9ed2594387964d3afb1%7C%7C76; lt=GZGYNzTTEA9xQ3yubJoT_m8yKC4AAAAAKAQAAMziXZo3J0DdZBE5D55vl-By0BTPBumYmHDoCSCW-8y123cXiC4qYTUfzXY0sZk8FA; lt.sig=PiC6DPxLrYQkAfLOVSAOQZwcyEk',
            # 'Host':'xueqiu.com',
            'Referer':'https://passport.meituan.com/account/unitivelogin?service=maoyan&continue=https%3A%2F%2Fmaoyan.com%2Fpassport%2Flogin%3Fredirect%3D%252Ffilms%253FshowType%253D1%2526offset%253D3000',
            'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/58.0.3029.110 Chrome/58.0.3029.110 Safari/537.36',
            'X-Requested-With':'XMLHttpRequest',
        }

    @every(minutes=24 * 60)
    def on_start(self):
        self.crawl('https://maoyan.com/films?showType=1&offset=0', fetch_type='js', callback=self.index_page)

    @config(age=10 * 24 * 60 * 60)
    def index_page(self, response):
        for each in response.doc('.movie-list dd').items():
            string = '暂无评分'
            tip = each.children('.channel-detail-orange').text()
            if tip != '暂无评分':
                rating1 = each.children('.channel-detail-orange .integer').text()
                rating2 = each.children('.channel-detail-orange .fraction').text()
                string = rating1+rating2
            url = each.children('.movie-item a').attr('href')
            self.crawl(url, fetch_type='js', callback=self.detail_page, save={'rating':string})
        url = response.url
        offset = url.split('offset=')
        index = 0
        if len(offset) > 1:
            index = int(offset[1]) / 30 + 1
        if index < 15:
            nextpage = response.doc('.list-pager :last-child a').attr('href')
            self.crawl(nextpage, fetch_type='js', callback=self.index_page)

    @config(priority=2)
    def detail_page(self, response):
        db = MySQLdb.connect('localhost', 'root', 'hu13580503105', 'film_db', charset='utf8')
        cursor = db.cursor()
        info = {}
        info['chinese_name'] = response.doc('.movie-brief-container h3').text()
        info['english_name'] = response.doc('.movie-brief-container div').text()
        info['url'] = response.doc('.avater-shadow img').attr('src')
        info['rating'] = response.save['rating']

        for index, item in enumerate(response.doc('.movie-brief-container ul li').items()):
            string = item.text()
            if index is 0:
                tmp = string.split(',')
                info['type'] = tmp[0]
            if index is 1:
                tmp = string.split('/')
                info['country'] = tmp[0].strip(' ').strip('\n')
                if len(tmp) > 1:
                    info['length'] = tmp[1].strip(' ')
                else:
                    info['length'] = None
            if index is 2:
                searchObj = re.search(r'\d+-\d+-\d+', string)
                if searchObj:
                    date = searchObj.group()
                    info['release_date'] = date
                    string = string.strip(date)
                else:
                    info['release_date'] = None
                searchObj = re.search(r'\d+(-\d+)*', string)
                if searchObj:
                    string = string.strip(searchObj.group())
                info['show_place'] = string
        for index, item in enumerate(response.doc('.module').items()):
            if index is 0:
                info['introduction'] = item.children('.mod-content span').text()  #剧情
            if index is 1:
                for i, group in enumerate(item.children('.mod-content .celebrity-container .celebrity-group').items()):
                    if i is 0:
                        director = []
                        persontype = group.children('.celebrity-type').text()
                        if persontype == '导演':
                            for li in group.children('ul li').items():
                                item = {}
                                name = li.children('.info a').text()
                                item['name'] = name
                                url = li.children('a img').attr('data-src')
                                if url == None:
                                    url = li.children('a img').attr('src')
                                item['url'] = url
                                director.append(item)
                            info['director'] = director  #导演
                        else:
                            actor = []
                            for li in group.children('ul li').items():
                                item = {}
                                name = li.children('.info a').text()
                                item['name'] = name
                                url = li.children('a img').attr('data-src')
                                if url == None:
                                    url = li.children('a img').attr('src')
                                item['url'] = url
                                actor.append(item)
                            info['actor'] = actor #演员
                    if i is 1:
                        actor = []
                        for li in group.children('ul li').items():
                            item = {}
                            name = li.children('.info a').text()
                            item['name'] = name
                            url = li.children('a img').attr('data-src')
                            if url == None:
                                url = li.children('a img').attr('src')
                            item['url'] = url
                            actor.append(item)
                        info['actor'] = actor #演员
        album = []
        for item in response.doc('.tab-img img').items():
            album.append(item.attr('data-src'))
        print(len(album))
        if len(album) > 0:
            info['album'] = album

        cursor.execute('SELECT id FROM movie WHERE chinese_name="%s"' % info['chinese_name'])
        rowcount = cursor.rowcount
        if rowcount is 0:
            cursor.execute('SELECT * FROM movie')
            filmid = cursor.rowcount
            date = None
            if info['release_date'] != None:
                tmp = info['release_date'].split('-')
                date = datetime.date(int(tmp[0]), int(tmp[1]), int(tmp[2]))
                date.strftime('%Y-%m-%d')

            part1 = []
            part2 = []
            part3 = []
            part1.append('INSERT INTO movie (id, chinese_name')
            part2.append('VALUES ("%d", "%s"')
            part3.append(filmid)
            part3.append(info['chinese_name'])

            if info['english_name'] != '':
                part1.append(', english_name')
                part2.append(', "%s"')
                part3.append(info['english_name'])

            part1.append(', url, type')
            part2.append(', "%s", "%s"')
            part3.append(info['url'])
            part3.append(info['type'])

            if info['length'] != None:
                part1.append(', length')
                part2.append(', "%s"')
                part3.append(info['length'])

            if date != None:
                part1.append(', release_date')
                part2.append(', "%s"')
                part3.append(date)

            part1.append(', introduction, rating, country')
            part2.append(', "%s", "%s", "%s"')
            part3.append(info['introduction'])
            part3.append(info['rating'])
            part3.append(info['country'])

            if info['show_place'] != None:
                part1.append(', show_place')
                part2.append(', "%s"')
                part3.append(info['show_place'])

            part1.append(') ')
            part2.append(')')

            part1_string = ''.join(part1)
            part2_string = ''.join(part2)
            part3_tuple = tuple(part3)

            string = part1_string + part2_string
            sql = string % part3_tuple

            try:
                cursor.execute(sql)
                db.commit()
            except:
                db.rollback()

            if 'director' in info:
                for i in range(len(info['director'])):
                    item = (info['director'])[i]
                    cursor.execute('SELECT id FROM person WHERE name="%s" AND type="导演"' % (item['name']))
                    rowcount = cursor.rowcount
                    directorid = -1
                    if rowcount != 0:
                        directorid = (cursor.fetchone())[0]
                    else:
                        cursor.execute('SELECT id FROM person')
                        directorid = cursor.rowcount
                        sql = 'INSERT INTO person(id, name, url, type) VALUES ("%d", "%s", "%s", "导演")' % (directorid, item['name'], item['url'])
                        try:
                            cursor.execute(sql)
                            db.commit()
                        except:
                            db.rollback()
                    sql = 'INSERT INTO movie_person(mid, pid) VALUES ("%d", "%d")' % (filmid, directorid)
                    try:
                        cursor.execute(sql)
                        db.commit()
                    except:
                        db.rollback()

            if 'actor' in info:
                for i in range(len(info['actor'])):
                    item = (info['actor'])[i]
                    cursor.execute('SELECT id FROM person WHERE name="%s" AND type="演员"' % (item['name']))
                    rowcount = cursor.rowcount
                    actorid = -1
                    if rowcount != 0:
                        actorid = (cursor.fetchone())[0]
                    else:
                        cursor.execute('SELECT id FROM person')
                        actorid = cursor.rowcount
                        sql = 'INSERT INTO person(id, name, url, type) VALUES ("%d", "%s", "%s", "演员")' % (actorid, item['name'], item['url'])
                        try:
                            cursor.execute(sql)
                            db.commit()
                        except:
                            db.rollback()
                    sql = 'INSERT INTO movie_person(mid, pid) VALUES ("%d", "%d")' % (filmid, actorid)
                    try:
                        cursor.execute(sql)
                        db.commit()
                    except:
                        db.rollback()

            if 'album' in info:
                for i in range(len(info['album'])):
                    item = (info['album'])[i]
                    print(item)
                    sql = 'INSERT INTO movie_picture(url, mid) VALUES ("%s", "%d")' % (item, filmid)
                    try:
                        cursor.execute(sql)
                        db.commit()
                    except:
                        db.rollback()

        db.close()


from dataclasses import dataclass, field
from enum import Enum
from typing import List, Optional

class BitmapFormat(Enum):
    PNG = "PNG"
    JPG = "JPG"

@dataclass(slots=True, kw_only=True)
class Component:
    originating_system: Optional[str] = field(
        default=None,
        metadata={
            "name": "OriginatingSystem",
            "type": "Element",
        }
    )
    authoring_tool_id: Optional[str] = field(
        default=None,
        metadata={
            "name": "AuthoringToolId",
            "type": "Element",
        }
    )
    ifc_guid: Optional[str] = field(
        default=None,
        metadata={
            "name": "IfcGuid",
            "type": "Attribute",
            "length": 22,
            "pattern": r"[0-9,A-Z,a-z,_$]*",
        }
    )

@dataclass(slots=True, kw_only=True)
class Direction:
    x: float = field(
        metadata={
            "name": "X",
            "type": "Element",
            "required": True,
        }
    )
    y: float = field(
        metadata={
            "name": "Y",
            "type": "Element",
            "required": True,
        }
    )
    z: float = field(
        metadata={
            "name": "Z",
            "type": "Element",
            "required": True,
        }
    )

@dataclass(slots=True, kw_only=True)
class Point:
    x: float = field(
        metadata={
            "name": "X",
            "type": "Element",
            "required": True,
        }
    )
    y: float = field(
        metadata={
            "name": "Y",
            "type": "Element",
            "required": True,
        }
    )
    z: float = field(
        metadata={
            "name": "Z",
            "type": "Element",
            "required": True,
        }
    )

@dataclass(slots=True, kw_only=True)
class ViewSetupHints:
    spaces_visible: Optional[bool] = field(
        default=None,
        metadata={
            "name": "SpacesVisible",
            "type": "Attribute",
        }
    )
    space_boundaries_visible: Optional[bool] = field(
        default=None,
        metadata={
            "name": "SpaceBoundariesVisible",
            "type": "Attribute",
        }
    )
    openings_visible: Optional[bool] = field(
        default=None,
        metadata={
            "name": "OpeningsVisible",
            "type": "Attribute",
        }
    )

@dataclass(slots=True, kw_only=True)
class ClippingPlane:
    location: Point = field(
        metadata={
            "name": "Location",
            "type": "Element",
            "required": True,
        }
    )
    direction: Direction = field(
        metadata={
            "name": "Direction",
            "type": "Element",
            "required": True,
        }
    )

@dataclass(slots=True, kw_only=True)
class ComponentColoringColor:
    class Meta:
        global_type = False

    component: List[Component] = field(
        default_factory=list,
        metadata={
            "name": "Component",
            "type": "Element",
            "min_occurs": 1,
        }
    )
    color: Optional[str] = field(
        default=None,
        metadata={
            "name": "Color",
            "type": "Attribute",
            "pattern": r"[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?",
        }
    )

@dataclass(slots=True, kw_only=True)
class ComponentSelection:
    component: List[Component] = field(
        default_factory=list,
        metadata={
            "name": "Component",
            "type": "Element",
            "min_occurs": 1,
        }
    )

@dataclass(slots=True, kw_only=True)
class ComponentVisibilityExceptions:
    class Meta:
        global_type = False

    component: List[Component] = field(
        default_factory=list,
        metadata={
            "name": "Component",
            "type": "Element",
            "min_occurs": 1,
        }
    )

@dataclass(slots=True, kw_only=True)
class Line:
    start_point: Point = field(
        metadata={
            "name": "StartPoint",
            "type": "Element",
            "required": True,
        }
    )
    end_point: Point = field(
        metadata={
            "name": "EndPoint",
            "type": "Element",
            "required": True,
        }
    )

@dataclass(slots=True, kw_only=True)
class OrthogonalCamera:
    """
    Attributes
        camera_view_point:
        camera_direction:
        camera_up_vector:
        view_to_world_scale: view's visible size in meters
    """
    camera_view_point: Point = field(
        metadata={
            "name": "CameraViewPoint",
            "type": "Element",
            "required": True,
        }
    )
    camera_direction: Direction = field(
        metadata={
            "name": "CameraDirection",
            "type": "Element",
            "required": True,
        }
    )
    camera_up_vector: Direction = field(
        metadata={
            "name": "CameraUpVector",
            "type": "Element",
            "required": True,
        }
    )
    view_to_world_scale: float = field(
        metadata={
            "name": "ViewToWorldScale",
            "type": "Element",
            "required": True,
        }
    )

@dataclass(slots=True, kw_only=True)
class PerspectiveCamera:
    """
    Attributes
        camera_view_point:
        camera_direction:
        camera_up_vector:
        field_of_view: It is currently limited to a value between 45 and
            60 degrees. This limitation will be dropped in the next
            release and viewers should be expect values outside this
            range in current implementations.
    """
    camera_view_point: Point = field(
        metadata={
            "name": "CameraViewPoint",
            "type": "Element",
            "required": True,
        }
    )
    camera_direction: Direction = field(
        metadata={
            "name": "CameraDirection",
            "type": "Element",
            "required": True,
        }
    )
    camera_up_vector: Direction = field(
        metadata={
            "name": "CameraUpVector",
            "type": "Element",
            "required": True,
        }
    )
    field_of_view: float = field(
        metadata={
            "name": "FieldOfView",
            "type": "Element",
            "required": True,
            "min_inclusive": 1.0,
            "max_inclusive": 170.0,
        }
    )

@dataclass(slots=True, kw_only=True)
class VisualizationInfoBitmap:
    class Meta:
        global_type = False

    bitmap: BitmapFormat = field(
        metadata={
            "name": "Bitmap",
            "type": "Element",
            "required": True,
        }
    )
    reference: str = field(
        metadata={
            "name": "Reference",
            "type": "Element",
            "required": True,
        }
    )
    location: Point = field(
        metadata={
            "name": "Location",
            "type": "Element",
            "required": True,
        }
    )
    normal: Direction = field(
        metadata={
            "name": "Normal",
            "type": "Element",
            "required": True,
        }
    )
    up: Direction = field(
        metadata={
            "name": "Up",
            "type": "Element",
            "required": True,
        }
    )
    height: float = field(
        metadata={
            "name": "Height",
            "type": "Element",
            "required": True,
        }
    )

@dataclass(slots=True, kw_only=True)
class ComponentColoring:
    color: List[ComponentColoringColor] = field(
        default_factory=list,
        metadata={
            "name": "Color",
            "type": "Element",
            "min_occurs": 1,
        }
    )

@dataclass(slots=True, kw_only=True)
class ComponentVisibility:
    exceptions: Optional[ComponentVisibilityExceptions] = field(
        default=None,
        metadata={
            "name": "Exceptions",
            "type": "Element",
        }
    )
    default_visibility: Optional[bool] = field(
        default=None,
        metadata={
            "name": "DefaultVisibility",
            "type": "Attribute",
        }
    )

@dataclass(slots=True, kw_only=True)
class VisualizationInfoClippingPlanes:
    class Meta:
        global_type = False

    clipping_plane: List[ClippingPlane] = field(
        default_factory=list,
        metadata={
            "name": "ClippingPlane",
            "type": "Element",
        }
    )

@dataclass(slots=True, kw_only=True)
class VisualizationInfoLines:
    class Meta:
        global_type = False

    line: List[Line] = field(
        default_factory=list,
        metadata={
            "name": "Line",
            "type": "Element",
            "min_occurs": 1,
        }
    )

@dataclass(slots=True, kw_only=True)
class Components:
    view_setup_hints: Optional[ViewSetupHints] = field(
        default=None,
        metadata={
            "name": "ViewSetupHints",
            "type": "Element",
        }
    )
    selection: Optional[ComponentSelection] = field(
        default=None,
        metadata={
            "name": "Selection",
            "type": "Element",
        }
    )
    visibility: ComponentVisibility = field(
        metadata={
            "name": "Visibility",
            "type": "Element",
            "required": True,
        }
    )
    coloring: Optional[ComponentColoring] = field(
        default=None,
        metadata={
            "name": "Coloring",
            "type": "Element",
        }
    )

@dataclass(slots=True, kw_only=True)
class VisualizationInfo:
    """
    VisualizationInfo documentation.
    """
    components: Optional[Components] = field(
        default=None,
        metadata={
            "name": "Components",
            "type": "Element",
        }
    )
    orthogonal_camera: Optional[OrthogonalCamera] = field(
        default=None,
        metadata={
            "name": "OrthogonalCamera",
            "type": "Element",
        }
    )
    perspective_camera: Optional[PerspectiveCamera] = field(
        default=None,
        metadata={
            "name": "PerspectiveCamera",
            "type": "Element",
        }
    )
    lines: Optional[VisualizationInfoLines] = field(
        default=None,
        metadata={
            "name": "Lines",
            "type": "Element",
        }
    )
    clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
        default=None,
        metadata={
            "name": "ClippingPlanes",
            "type": "Element",
        }
    )
    bitmap: List[VisualizationInfoBitmap] = field(
        default_factory=list,
        metadata={
            "name": "Bitmap",
            "type": "Element",
        }
    )
    guid: str = field(
        metadata={
            "name": "Guid",
            "type": "Attribute",
            "required": True,
            "pattern": r"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}",
        }
    )


import os
import re
from typing import Callable, Iterable

from lifecycle.config import Config
from lifecycle.monitor.base import JobMonitor
from lifecycle.monitor.health import check_until_job_is_operational, quick_check_job_condition
from lifecycle.monitor.metric_parser import read_last_call_timestamp_metric, scrape_metrics
from racetrack_client.log.exception import short_exception_details
from racetrack_client.utils.shell import shell_output
from racetrack_client.utils.time import datetime_to_timestamp, now
from racetrack_commons.deploy.resource import job_resource_name
from racetrack_commons.entities.dto import JobDto, JobStatus
from racetrack_client.log.logs import get_logger

from plugin_config import InfrastructureConfig

logger = get_logger(__name__)

class DockerDaemonMonitor(JobMonitor):
    """Discoverer listing job workloads deployed on a remote docker instance"""
    def __init__(self, infrastructure_target: str, infra_config: InfrastructureConfig) -> None:
        super().__init__()
        self.infra_config = infra_config
        self.infrastructure_target = infrastructure_target

    def list_jobs(self, config: Config) -> Iterable[JobDto]:
        # Heredoc to not mix quotes inside
        # Ports section needs to be last, because there were differences in outputs on developer systems:
        # One system had: 0.0.0.0:7020->7000/tcp
        # The other: 0.0.0.0:7000->7000/tcp, :::7000->7000/tcp
        cmd = f'DOCKER_HOST={self.infra_config.docker_host} ' + """
        docker ps -a --filter "name=^/job-" --format '{{.Names}} {{ .Label "job-name" }} {{ .Label "job-version" }} {{.Ports}}'
        """.strip()
        regex = r'(?P<resource_name>job-.+) (?P<job_name>.+) (?P<job_version>.+) 0\.0\.0\.0:(?P<job_port>\d+)->7000\/tcp'
        output = shell_output(cmd)

        assert self.infra_config.hostname, 'hostname of a docker daemon must be set'

        for line in output.splitlines():
            match = re.match(regex, line.strip())
            if match:
                resource_name = match.group('resource_name')
                job_name = match.group('job_name')
                job_version = match.group('job_version')
                job_port = match.group('job_port')

                internal_name = f'{self.infra_config.hostname}:{job_port}'

                job = JobDto(
                    name=job_name,
                    version=job_version,
                    status=JobStatus.RUNNING.value,
                    create_time=datetime_to_timestamp(now()),
                    update_time=datetime_to_timestamp(now()),
                    manifest=None,
                    internal_name=internal_name,
                    error=None,
                    infrastructure_target=self.infrastructure_target,
                )
                try:
                    job_url = f'http://{job.internal_name}'
                    quick_check_job_condition(job_url)
                    job_metrics = scrape_metrics(f'{job_url}/metrics')
                    job.last_call_time = read_last_call_timestamp_metric(job_metrics)
                except Exception as e:
                    error_details = short_exception_details(e)
                    job.error = error_details
                    job.status = JobStatus.ERROR.value
                    logger.warning(f'Job {job} is in bad condition: {error_details}')
                yield job

    def check_job_condition(self,
                               job: JobDto,
                               deployment_timestamp: int = 0,
                               on_job_alive: Callable = None,
                               logs_on_error: bool = True,
                               ):
        try:
            check_until_job_is_operational(f'http://{job.internal_name}', deployment_timestamp, on_job_alive)
        except Exception as e:
            if logs_on_error:
                logs = self.read_recent_logs(job)
                raise RuntimeError(f'{e}\nJob logs:\n{logs}')
            else:
                raise RuntimeError(str(e))

    def read_recent_logs(self, job: JobDto, tail: int = 20) -> str:
        container_name = job_resource_name(job.name, job.version)
        return shell_output(f'DOCKER_HOST={self.infra_config.docker_host} docker logs "{container_name}" --tail {tail}')


#!/usr/bin/python3

import pyglet
from Pendulum import PendulumPhysics
from Environment import Environment
from Policy import ValueIteration
import numpy as np
from utils import StatesEncoder, reward_function, get_all_states
from StateTransitionModel import StateTransitionModel
from tqdm import tqdm
import sys
import pickle

np.set_printoptions(threshold=sys.maxsize)

pendulum_physics = PendulumPhysics()

stm = StateTransitionModel(pendulum_physics,dt = 1/60)

action_space = np.linspace(-500000, 500000, 3)
states_max = np.array([1920,0.3,500,3])
states_min = np.array([0,-0.3,-500,-3])
divisions = 21
states_encoder = StatesEncoder(states_min = states_min, states_max = states_max, divisions=divisions)

policy = ValueIteration(actions=action_space,states_encoder=states_encoder,state_transition_model=stm,reward_function=reward_function,discount_factor = 0.99)

all_states = get_all_states(states_min, states_max, divisions*np.ones(4).astype(int))

ITERATION = 10
try:
    policy.value_function = pickle.load(open(f"data/value_function-{divisions}.p","rb"))
except:
    pass

value_function = None

for iteration in range(1,ITERATION+1):
    print("Iteration:",iteration)
    policy.multiple_update_value_function(all_states)
    new_value_function = np.array(list(policy.value_function.values()))
    if value_function is not None:
        if np.all((new_value_function - value_function) < 1e-3):
            break
    value_function = new_value_function
    print(value_function)
    print(value_function.size)
    print(all_states.shape)
    print(np.sum(value_function != 0)/value_function.size)

pickle.dump(policy.value_function,open(f"data/value_function-{divisions}.p","wb"))
print("Training Completed")


from flask import Flask, jsonify, request
from flask_cors import CORS
from webhook import post_message_to_discord

app = Flask(__name__)
CORS(app)

@app.route("/api/home", methods=['GET'])
def return_home():
    return jsonify({

        'message': "Matthew King"

    })

@app.route("/api/submit-data", methods=['POST'])
def return_submit():
    # Check if the request contains JSON data
    if not request.is_json:
        return jsonify({"error": "Invalid JSON data in the request"}), 400

    data = request.get_json()

    # Check if the required fields are present in the JSON data
    email = data.get('email')
    subject = data.get('subject')
    message = data.get('message')

    if email is None or subject is None or message is None:
        return jsonify({"error": "Missing required fields in the JSON data"}), 400

    print("Received data:")
    print(f"Email: {email}")
    print(f"Subject: {subject}")
    print(f"Message: {message}")

    message_content = f"Email: {email}, Subject: {subject}, Message: {message}"
    post_message_to_discord(message_content)

    # You can return a JSON response to acknowledge the successful receipt
    return jsonify({"message": "Data received successfully"}), 200

if __name__ == "__main__":
    app.run(debug=True, port=8080)


from binance.client import Client
from binance import exceptions
import time

apiKey = ""
apiSecret = ""

makerFee = .09
takerFee = .09

class Market:
    def __init__(self):
        self.client = Client(api_key=apiKey, api_secret=apiSecret, tld='us')

    def buy_coin_possible(self, symbol, percentOfEquity):
        # Get equity amount of our USD, BTC, ETH
        accountValue = float(self.client.get_asset_balance("USD")["free"])
        accountValue += float(self.client.get_asset_balance("BTC")["free"]) * float(self.client.get_symbol_ticker(symbol="BTCUSD")["price"])
        accountValue += float(self.client.get_asset_balance("ETH")["free"]) * float(self.client.get_symbol_ticker(symbol="ETHUSD")["price"])

        # calculate how much of the symbol that is
        moneyToSpend = percentOfEquity * accountValue / 100.0
        symbolQuantity = moneyToSpend / float(self.client.get_symbol_ticker(symbol=symbol)["price"])

        # get recent trades to see current volatility
        recentTrades = self.client.get_recent_trades(symbol=symbol)
        lastTrade = {}
        totalSum = 0
        weightedSum = 0
        for trade in recentTrades:
            if lastTrade == {} or int(trade["time"]) > int(lastTrade["time"]):
                lastTrade = trade
            totalSum += float(trade["qty"])
            weightedSum += float(trade["price"]) * float(trade["qty"])
        weightedAvg = weightedSum / totalSum

        # calculate the price we should strive for with current volatility
        symbolQtyAdjustedBefore = symbolQuantity * (1.0 - takerFee)
        symbolQtyAdjustedAfter = symbolQtyAdjustedBefore * (1.0 - takerFee)
        endProfitPrice = 0
        if weightedAvg > float(lastTrade["price"]):
            endProfitPrice = weightedAvg + (weightedAvg - float(lastTrade["price"])) * .5
        else:
            endProfitPrice = float(lastTrade["price"]) + abs(weightedAvg - float(lastTrade["price"])) * .5

        # calculate stop loss at 3 : 1 risk ratio using expected profit
        expectedProfit = (endProfitPrice * symbolQtyAdjustedAfter) - (float(lastTrade["price"]) * symbolQtyAdjustedAfter)
        if expectedProfit <= 0:
            return
        stopLossPrice = float(lastTrade["price"]) - expectedProfit * (1/3)
        # possibleLoss = (stopLossPrice * symbolQtyAdjusted) - (float(lastTrade["price"]) * symbolQtyAdjusted) # for reference

        # set the limit buy so we get it at the price we want hopefully
        order = None
        try:
            order = self.client.order_limit_buy(
                symbol=symbol,
                quantity="{:0.0{}f}".format(symbolQuantity, 3),
                price="{:0.0{}f}".format(float(lastTrade["price"]) + float(lastTrade["price"]) * .001, 2),
            )
        except exceptions.BinanceAPIException as e:
            print(e)
            return

        # wait 3 seconds.  usually small orders will go through immediately but if this scales it wouldn't
        time.sleep(5)

        # see if it went through at our price, otherwise cancel it
        if order is not None:
            for openOrder in self.client.get_open_orders():
                if order["orderId"] == openOrder["orderId"]:
                    self.client.cancel_order(symbol=symbol, orderId=order["orderId"])
                    return

        try:
            # set our end/expected price for this trade
            self.client.order_limit_sell(
                symbol=symbol,
                quantity="{:0.0{}f}".format(symbolQtyAdjustedBefore, 3),
                price="{:0.0{}f}".format(endProfitPrice, 2)
            )

            self.client.create_order(
                symbol=symbol,
                side=Client.SIDE_SELL,
                type=Client.ORDER_TYPE_STOP_LOSS_LIMIT,
                quantity="{:0.0{}f}".format(symbolQtyAdjustedBefore, 3),
                price="{:0.0{}f}".format(stopLossPrice, 2),
                stopPrice="{:0.0{}f}".format(stopLossPrice + .01, 2),
                timeInForce=Client.TIME_IN_FORCE_GTC
            )
        except exceptions.BinanceAPIException as e:
            print(e)
            return

    def get_symbol_price(self, symbol):
        recentTrades = self.client.get_recent_trades(symbol=symbol)
        lastTrade = {}

        for trade in recentTrades:
            if lastTrade == {} or int(trade["time"]) > int(lastTrade["time"]):
                lastTrade = trade

        return float(lastTrade["price"])

    def get_account_value(self):
        valueInUSD = 0.0
        usdBalance = self.client.get_asset_balance("USD")
        valueInUSD = valueInUSD + float(usdBalance["free"]) + float(usdBalance["locked"])
        time.sleep(.1)

        ethBalance = self.client.get_asset_balance("ETH")
        ethPrice = self.get_symbol_price("ETHUSD")
        valueInUSD = valueInUSD + float(ethBalance["free"]) * ethPrice + float(ethBalance["locked"]) * ethPrice
        time.sleep(.1)

        btcBalance = self.client.get_asset_balance("BTC")
        btcPrice = self.get_symbol_price("BTCUSD")
        valueInUSD = valueInUSD + float(btcBalance["free"]) * btcPrice + float(btcBalance["locked"]) * btcPrice
        time.sleep(.1)

        return valueInUSD


import blenderbim.tool as tool
import ifcopenshell
import sys

import os
from sys import platform

file = tool.Ifc.get()
if not file:
    print("No ifc file")
    sys.exit()

annotations = file.by_type('IfcAnnotation')
count = 0

for annotation in annotations:
    if annotation.ObjectType == 'DRAWING':
        psets = ifcopenshell.util.element.get_psets(annotation)
        pset = psets['EPset_Drawing']
        pset_ifc = file.by_id(pset['id'])
        wrong_sep = ""
        if platform == 'linux' or platform == 'linux2' or platform == 'darwin':
            wrong_sep = "\\"
        if platform == 'win32':
            wrong_sep = "/"
        ifcopenshell.api.run("pset.edit_pset", file, pset = pset_ifc, properties = {
            'Stylesheet' : pset['Stylesheet'].replace(wrong_sep, os.path.sep),
            'Markers' : pset['Markers'].replace(wrong_sep, os.path.sep),
            'Symbols' : pset['Symbols'].replace(wrong_sep, os.path.sep),
            'Patterns' : pset['Patterns'].replace(wrong_sep, os.path.sep),
        })
        count+=1

print(f"DONE! Checked {count} drawings")


import datetime
import shutil
import os
import os.path
import urllib.request

PYTHON="python-3.9.10"
PYTHON_URL="https://www.python.org/ftp/python/3.9.10/python-3.9.10-embed-amd64.zip"

BUILD_DIR = os.path.join("..", "release", "build")
PYPI_DIR = os.path.join("..", "release", "PYPI")
PROJECTNAME = "PyWavTool"
RELEASE_FILE = os.path.join("..", "release", PROJECTNAME + "-" + datetime.datetime.strftime(datetime.datetime.now(), "%Y%m%d"))
EXE_DIR = os.path.join("..", "PyWavToolExe", "bin", "Release", "net6.0-windows")
EXE_DIR_EXTENSIONS = [".exe",".dll",".runtimeconfig.json"]
SOURCE_FILES = ['__init__.py',
                'PyWavTool.py',
                'dat.py',
                'whd.py',
                'length_string.py']
README=os.path.join("..","README.md")
LICENSE=os.path.join("..","LICENSE")

os.makedirs(BUILD_DIR, exist_ok=True)
os.makedirs(os.path.join(BUILD_DIR, "src"), exist_ok=True)
os.makedirs(os.path.join(PYPI_DIR, "src", "PyWavTool"), exist_ok=True)
os.makedirs(os.path.join(PYPI_DIR, "tests"), exist_ok=True)

exe_dir_files = os.listdir(EXE_DIR)
for file in exe_dir_files:
    for extensions in EXE_DIR_EXTENSIONS:
        if file.endswith(extensions):
            shutil.copy(os.path.join(EXE_DIR, file),os.path.join(BUILD_DIR, file))
            break

for file in os.listdir():
    if file in SOURCE_FILES:
        shutil.copy(file, os.path.join(BUILD_DIR, "src", file))
        shutil.copy(file, os.path.join(PYPI_DIR, "src", "PyWavTool", file))

if not os.path.isdir(os.path.join(BUILD_DIR,PYTHON)):
    urllib.request.urlretrieve(PYTHON_URL, os.path.join(BUILD_DIR,PYTHON+".zip"))
    shutil.unpack_archive(os.path.join(BUILD_DIR,PYTHON+".zip"),os.path.join(BUILD_DIR,PYTHON))
    os.remove(os.path.join(BUILD_DIR,PYTHON+".zip"))

if os.path.exists(LICENSE):
    shutil.copy(LICENSE, os.path.join(BUILD_DIR, "license.txt"))
    shutil.copy(LICENSE, os.path.join(PYPI_DIR, "LICENSE"))
if os.path.exists(README):
    shutil.copy(README, os.path.join(BUILD_DIR, "readme.txt"))
    shutil.copy(README, os.path.join(PYPI_DIR, "README.md"))

shutil.make_archive(RELEASE_FILE, format="zip", root_dir=BUILD_DIR)


import requests
from bs4 import BeautifulSoup
from flask import Flask, render_template, request, redirect, url_for
import time
import random

app = Flask(__name__, template_folder=r"C:\Users\adamk\gitpractice\practice\wiki")

def wiki_article(article):
    # get wikipage of a specific article
    url = 'https://en.wikipedia.org/wiki/' + article
    webpage_response = requests.get(url)
    webpage = webpage_response.content
    soup = BeautifulSoup(webpage, "html.parser")
    return soup, url

def get_first_img_src(soup):
    # get first SIGNIFICANT image with width bigger than 50
    for n in range(5):
        img = soup.find_all("img")[n]
        img_width = img.get('width')
        if int(img_width) > 50:
            img_src = img.get('src')
            return img_src
    # no big img found, return first
    img_src = soup.img.get('src')
    return img_src

def get_categories(soup):
    # get soup categories
    try:
        categories_data = soup.select('.mw-normal-catlinks > ul')[0]
    except IndexError:
        return ["No tags available"]
    categories = (categories_data.get_text('|')).split('|')
    return categories

def related_to_categories(subject, categories):
    subject = subject.lower()
    for category in categories:
        if subject in category.lower():
            return True
    return False

def get_head(soup):
    # get heading
    return soup.select("#firstHeading")[0].string

def get_paragraph_text(soup):
    # get first SIGNIFICANT paragraph (longer than 20)
    n = 0
    p = soup.select('.mw-parser-output > p')[n]
    p_text = p.get_text()
    while len(p_text) < 20:
        n += 1
        p = soup.select('.mw-parser-output > p')[n]
        p_text = p.get_text()
    return p_text

def rand_article():
    rand_url = "https://en.wikipedia.org/wiki/Special:Random"
    webpage_response = requests.get(rand_url)
    webpage = webpage_response.content
    soup = BeautifulSoup(webpage, "html.parser")
    return soup

def rand_article_by_category(subject):
    rand_url = "https://en.wikipedia.org/wiki/Special:RandomInCategory/" + subject.replace(" ", "_")
    print("rand url: ", rand_url)
    webpage_response = requests.get(rand_url)
    webpage = webpage_response.content
    soup = BeautifulSoup(webpage, "html.parser")
    return soup

def generate_url_by_head(head):
    url = 'https://en.wikipedia.org/wiki/' + head.replace(" ", "_")
    return url

def get_sub_pages(soup):
    pages = soup.select(".mw-category-group > ul > li > a")
    return pages

def rand_inner_page(soup):
    pages = get_sub_pages(soup)
    try:
        ran_page = random.choice(pages)
    except IndexError:
        raise NameError("Category has no subpages")
    page_url = ran_page['href']
    article = "https://en.wikipedia.org" + page_url
    return wiki_article(article)

def is_category(head):
    if head == "Random page in category":
        raise NameError('No such category')
    elif "Category:" in head:
        return True
    return False

@app.route("/", methods=["POST", "GET"])
def random_page():
    subject = request.form.get("subject")
    t0 = time.perf_counter()
    if subject is None:
        return render_template("index.html")
    else:
        soup = rand_article_by_category(subject)
        head = get_head(soup)
        print("First head: " ,head)
        if is_category(head):
            #entered a sub category
            soup, wiki_url = rand_inner_page(soup)
            print("wiki url: ", wiki_url)
        else:
            wiki_url = generate_url_by_head(head)
            print("else wikiurl: ", wiki_url)

        categories = get_categories(soup)
        img_src = get_first_img_src(soup)
        text = get_paragraph_text(soup)
        t1 = time.perf_counter()
        elapsed_time = round(t1-t0, 2)
        return render_template("index.html", head=head, img_src=img_src,
                               categories=categories, text=text,
                               wiki_url=wiki_url, elapsed_time=elapsed_time)

@app.route("/<string:article>", methods=["POST", "GET"])
def index(article):
    soup, wiki_url = wiki_article(article)
    head = get_head(soup)
    img_src = get_first_img_src(soup)
    text = get_paragraph_text(soup)
    categories = get_categories(soup)
    return render_template("index.html", head=head, img_src=img_src,
                           categories=categories, text=text, wiki_url=wiki_url)

if __name__ == "__main__":
    app.debug = True
    app.run()

'''
webpage_response = requests.get("https://en.wikipedia.org/wiki/Category:Economic_history")
webpage = webpage_response.content
soup = BeautifulSoup(webpage, "html.parser")
#print(get_head(soup))
#print(get_paragraph_text(soup))
#print(get_categories(soup))

def get_sub_categories(soup):
    sub_categories = soup.select(".CategoryTreeItem > a")
    return sub_categories

def page_or_sub_category(soup):
    pages = get_sub_pages(soup)
    sub_categories = get_sub_categories(soup)
    if random.randint(0,1) == 0:
        #50% precent chance
        chosen_articles = pages
    else:
        chosen_sub_category = random.choice(sub_categories)
        sub_category_url = "https://en.wikipedia.org" + chosen_sub_category.['href']
        webpage_response = requests.get(sub_category_url)
        webpage = webpage_response.content
        sub_soup = BeautifulSoup(webpage, "html.parser")
        chosen_articles = get_sub_pages(sub_soup)
'''


import collections
import datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
from sklearn.decomposition import PCA
from sklearn.cluster import MeanShift, DBSCAN, KMeans

percetanges = ['1day%', 'GC%', 'TT%', 'sprint%', 'climber%']
n_comp = 3

# PCA on points per specialty
def pca_analysis_on_points(save=False):
    riders_info = classify_points()
    riders_points = riders_info[percetanges]

    pca = PCA(n_components=n_comp)
    pca.fit(riders_points)
    print('Variance ratio', pca.explained_variance_ratio_) # first 3 accounts for 93%

    # Corelation matrix
    corr = riders_points.corr()
    fig = px.imshow(corr, color_continuous_scale='RdBu')
    fig.update_layout(title_text="Correlation matrix")
    fig.show()
    if save:
        fig.write_image('reports/figures/corr_matrix.png')
        # fig.write_html("reports/figures/riders_points_corr.html")

    # Eigenvector bar plot
    eigenvectors = np.abs(pca.components_)
    print(eigenvectors)
    ind = np.arange(len(percetanges))
    width = 0.25
    for i in range(n_comp):
        print(i)
        plt.bar(ind+i*width, eigenvectors[i], width, label=f'ev{i}')

    plt.xticks(ind+width/2, percetanges)
    plt.legend()
    plt.xlabel('Point percentage')
    plt.ylabel('Eigenvector components')
    plt.tight_layout()
    if save:
        plt.savefig('reports/figures/riders_points_pca_eigenvectors.png')
    plt.show()

    # 3D clustering
    principalComponents = pca.fit_transform(riders_points)
    riders_points_pca = pd.DataFrame(data=principalComponents, columns=['pca1', 'pca2', 'pca3'])

    # clustering = MeanShift().fit(riders_points_pca)
    # clustering = DBSCAN().fit(riders_points_pca)
    clustering = KMeans(n_clusters=3).fit(riders_points_pca)
    clustering_freq = collections.Counter(clustering.labels_)
    print('Clustering freq:', clustering_freq)

    riders_points_pca_labelled = pd.concat((riders_points_pca, pd.DataFrame(clustering.labels_, columns=['cluster'])), axis=1)

    fig = px.scatter_3d(riders_points_pca_labelled, x='pca1', y='pca2', z='pca3', color='cluster')
    fig.update_layout(title_text="3D PCA plot of riders points (variance ratio: 93% for the first 3)")
    fig.show()
    if save:
        fig.write_html("reports/figures/riders_PCA.html")

# Age, Weight, Height
def pca_analysis_on_figure(save=False):
    riders_info = pd.read_csv('data/processed/riders_info_cleaned.csv')
    this_year = datetime.date.today().year

    # Find age
    riders_info['DOB'] = pd.to_datetime(riders_info['DOB'])
    riders_info['age'] = this_year - riders_info['DOB'].dt.year
    riders_info = riders_info[['age', 'weight', 'height']]

    clustering = KMeans(n_clusters=3).fit(riders_info)
    clustering_freq = collections.Counter(clustering.labels_)
    print('Clustering freq:', clustering_freq)

    riders_info_labelled = pd.concat((riders_info, pd.DataFrame(clustering.labels_, columns=['cluster'])), axis=1)

    # 3d plot
    fig = px.scatter_3d(riders_info_labelled, x='height', y='weight', z='age', color='cluster')
    fig.update_layout(title_text="Age, weight and height of riders")
    fig.show()
    if save:
        fig.write_html("reports/figures/riders_awh.html")

# Points per specialty
def classify_points(plot=False):
    riders_info = pd.read_csv('data/processed/riders_info_cleaned.csv')
    riders_info['total'] = riders_info['one day races'] + riders_info['GC'] + riders_info['TT'] + riders_info['sprint'] + riders_info['climber']

    min_total = 50 # flexible
    riders_info = riders_info[riders_info['total'] > min_total]

    riders_info['1day%'] = riders_info['one day races'] / riders_info['total']
    riders_info['GC%'] = riders_info['GC'] / riders_info['total']
    riders_info['TT%'] = riders_info['TT'] / riders_info['total']
    riders_info['sprint%'] = riders_info['sprint'] / riders_info['total']
    riders_info['climber%'] = riders_info['climber'] / riders_info['total']

    # sort by total points
    riders_info = riders_info.sort_values(by='total', ascending=False)

    # hist of total point
    if plot:
        print(riders_info.head()[['name', 'total', '1day%', 'GC%', 'TT%', 'sprint%', 'climber%']])
        riders_info.hist(column='total', bins=1000)
        plt.show()

    return riders_info

if __name__ == "__main__":
    pca_analysis_on_points(save=True)
    # pca_analysis_on_figure()


from functools import reduce
import operator as op
def nCr(n,r):
    numerator=reduce(op.mul,range(n,n-r,-1))
    denominator=reduce(op.mul,range(1,r+1))
    return numerator//denominator

p=1.09/(1+1.09)
q=1/(1+1.09)
ans=0
for i in range(3,7):
    ans+=nCr(6,i)*pow(p,i)*pow(q,6-i)
print(round(ans,3))

10 Days of Statistics/Binomial Distribution I/Solution.py


import csv
import networkx as nx
import matplotlib.pyplot as plt

class Graph:
    def __init__(self):
        self.G = nx.Graph()

    def createGraph(self, data):
        for item in data:
            self.G.add_edge(item[0], item[1], weight=item[3])

    def getGraphInfo(self):
        return nx.number_of_nodes(self.G), nx.number_of_edges(self.G)

    def __getCliques(self):
        return sorted(list(nx.enumerate_all_cliques(self.G)), key=len)

    def drawGraph(self):
        # Drawing the Graph using matplotlib
        nx.draw_networkx(self.G, node_color=['red'], with_labels=True)
        plt.show()

    def numberOfCliques(self):
        nq = nx.graph_number_of_cliques(self.G)  # Number of cliques in graph
        bq = nx.graph_clique_number(self.G)  # Max clique size of Graph
        return nq, bq

    def numberOfCliquesByK(self, k):
        # get all the cliques with k factor
        cliques = [x for x in self.__getCliques() if len(x) == k]
        return cliques

with open('DataSets/book1.csv', 'r') as dataset:  # Open the file
    nodereader = csv.reader(dataset)  # Read the csv
    # Retrieve the data (using Python list comprhension and list slicing to remove the header row, see footnote 3)
    rows = [n for n in nodereader][1:]

if __name__ == "__main__":
    community = Graph()
    community.createGraph(rows)
    print('Number of Nodes: {}\nNumber of Edges: {}\n***'.format(
        community.getGraphInfo()[0], community.getGraphInfo()[1]))
    print('Number of Cliques: {}\nMax Size Clique: {}\n***'.format(
        community.numberOfCliques()[0], community.numberOfCliques()[1]))
    # define the value of k, can be modified
    k = 3
    cliquesByK = community.numberOfCliquesByK(k)
    print('Number of cliques with k = {} ===> {}\n***'.format(k, len(cliquesByK)))

    # for the max size clique in graph
    k = community.numberOfCliques()[1]
    cliquesByK = community.numberOfCliquesByK(k)
    print('Number of cliques with k = {} ===> {}\n***'.format(k, len(cliquesByK)))
    print(cliquesByK)


from fastapi import FastAPI
import requests

# To run on server - uvicorn main:app --reload

app = FastAPI()

classes={
'A':{

'network_bits':7,

'host_bits':24

},

'B':{

'network_bits':14,

'host_bits':16

},

'C':{

'network_bits':21,

'host_bits':8

},

'D':{

'network_bits':'N/A',

'host_bits':'N/A'

},

'E':{

'network_bits':'N/A',

'host_bits':'N/A'

},

}

######################

@app.get("/ipcalc")
async def ipcalc():
    output = {}
    newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}

    response = requests.post('https://httpbin.org/post',
                             data={"address": "136.206.18.7"},
                             headers=newHeaders)

    response_Json = response.json()
    ip = response_Json['data'][8:]

    # Check the class of the ip address by calling the convert_to_bin method.
    # By converting to binary, you can check the first bits of the ip address to find out the class
    if convert_to_bin(ip)[0][0:1] == "0":
        output["Class"] = "A"
    elif convert_to_bin(ip)[0][0:2] == "10":
        output["Class"] = "B"
    elif convert_to_bin(ip)[0][0:2] == "11":
        output["Class"] = "C"
    elif convert_to_bin(ip)[0][0:3] == "111":
        output["Class"] = "D"
    else:
        output["Class"] = "E"

    # Check what class the ip address is
    # Can find the number of networks by doing 2 to the power of network bits
    # The network bits are found in the classes dictionary
    if output["Class"] == "A":
        output["num_networks"] = 2 ** classes["A"]["network_bits"]
    elif output["Class"] == "B":
        output["num_networks"] = 2 ** classes["B"]["network_bits"]
    elif output["Class"] == "C":
        output["num_networks"] = 2 ** classes["C"]["network_bits"]
    else:
        output["num_networks"] = "N/A"

    # Check what class the ip address is
    # Can find the number of hosts by doing 2 to the power of hosts bits
    # The host bits are found in the classes dictionary
    if output["Class"] == "A":
        output["num_hosts"] = 2 ** classes["A"]["host_bits"]
    elif output["Class"] == "B":
        output["num_hosts"] = 2 ** classes["B"]["host_bits"]
    elif output["Class"] == "C":
        output["num_hosts"] = 2 ** classes["C"]["host_bits"]
    # For class D and E, no answer for number of hosts and number of networks
    else:
        output["num_hosts"] = "N/A"

    # First, check the class of the ip address
    # Can then get the first and last address after finding out the class
    if output["Class"] == "A":
        output["first_address"] = "0.0.0.0"
        output["last_address"] = "127.255.255.255"
    elif output["Class"] == "B":
        output["first_address"] = "128.0.0.0"
        output["last_address"] = "191.255.255.255"
    elif output["Class"] == "C":
        output["first_address"] = "192.0.0.0 "
        output["last_address"] = "223.255.255.255"
    elif output["Class"] == "D":
        output["first_address"] = "224.0.0.0"
        output["last_address"] = "239.255.255.255"
    elif output["Class"] == "E":
        output["first_address"] = "240.0.0.0"
        output["last_address"] = "255.255.255.255"

    return output

######################

@app.get("/subnet")
async def subnet():
    output={}
    newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
    response = requests.post('https://httpbin.org/post',
                             data={
                                 "address": "192.168.10.0",
                                 "mask": "255.255.255.192"
                             },
                             headers=newHeaders)

    response_Json = response.json()
    address = response_Json['data'][8:20]
    m=response_Json['data'][26:]

    ip=convert_to_bin(address)
    mask=convert_to_bin(m)

    cidr_num = cidr_not(mask)
    output["address_cidr"] = address + "/" + str(cidr_num)

    host_bits=mask[-1]

    # Iterate through last byte in subnet mask to count up zero and one bits
    one_bits=0
    zero_bits=0
    for i in host_bits:
        if i == "1":
            one_bits+=1
        elif i == "0":
            zero_bits+=1

    #2 to the power of the number of one bits is equal to the number of subnets
    output["num_subnets"] = 2**one_bits
    #2 to the power of the number of zero bits minus 2 (network address and broadcast address) is equal to the addressable hosts
    output["addressable_hosts_per_subnet"] = (2 ** zero_bits) - 2

    # Split string IP address into list
    # Split subnet mask into list
    # 256 - the last byte in the subnet mask
    # Make last byte in IP address '0' - this will be the first valid subnet
    # Make last byte of IP addresses equal to last byte + (256 - last byte in the subnet mask)
    # Change the last byte to a string
    # Add this string to the string version of the IP address
    # Appened this new IP to the list of Valid Subnets
    validSubnets = []
    i = -1
    ip = address.split(".")
    blocksList = m.split(".")
    blocks = 256 - int(blocksList[i])
    ip[i] = '0'
    newIP = '.'.join(ip)
    validSubnets.append(newIP)
    ip[i] = 0
    for block in range(output["num_subnets"] - 1):
        ip[i] += blocks
        ip[i] = str(ip[i])
        newIP = '.'.join(ip)
        ip[i] = int(ip[i])
        validSubnets.append(newIP)

    output["valid_subnets"] = validSubnets
    output["broadcast_addresses"] = get_broadcasts(validSubnets)
    output["first_addresses"] = get_firstAddress(validSubnets)
    output["last_addresses"] = get_lastAddress(validSubnets)

    return output

######################

@app.get("/supernet")
async def supernet():
    output={}

    newHeaders = {'Content-type': 'application/json', 'Accept': 'text/plain'}
    response = requests.post('https://httpbin.org/post',
                             data={"addresses":["205.100.0.0","205.100.1.0","205.100.2.0","205.100.3.0"]},
                             headers=newHeaders)
    addresses=[]

    response_Json = response.json()
    input = response_Json['data'].split('&')
    for ip in input:
        #Append just the string IP to addresses without the 'address' key
        addresses.append(ip[10:])

    # Convert each IP to binary list
    # Use .join() to join the list of bytes into a string
    first = ''.join(convert_to_bin(addresses[0]))
    second = ''.join(convert_to_bin(addresses[1]))
    third = ''.join(convert_to_bin(addresses[2]))
    fourth = ''.join(convert_to_bin(addresses[3]))

    # Iterate through each binary IP address from input
    # This allows you to find the common prefix of the binary addresses to find network mask
    # While each bit is equivalent, increment count by 1
    count=0
    i=0
    while first[i] == second[i] == third[i] == fourth[i]:
        count+=1
        i+=1

    cidr="{}/{}".format(addresses[0], count)
    output["address"] = cidr

    mask = "1" * count + first[count:]
    maskList = []
    for i in range(4):
        maskList.append(mask[:8])
        mask = mask[8:]

    output["mask"] = convert_to_decimal(maskList)

    return output

def get_broadcasts(subnets):
    """
        Calculates a list of braodcast addresses for each subnet
        :param subnets: An array containing 4 ip addresses
        each represented as a string. The ip addresses are the valid subnets
        eg. ["192.168.10.0","192.168.10.64","192.168.10.128","192.168.10.192"]
        :return broadcasts: An array containing 4 ip addresses
        each represented as a string. The ip addresses are the broadcast addresses
        eg. ["192.168.10.63","192.168.10.127","192.168.10.191","192.168.10.255"]
    """
        # For each ip string in the list, split each byte of the ip into a list
        # Add this list of bytes to a new list 'tmp'
        # Pop off the last element of the list of bytes and call it last
        # Add 63 to the int version of the string byte and call it last_n
        # Append the string version of last_n to the list of bytes
        # Create new list called broadcasts and append each list of bytes to it
        # Call '.'.join() to make the list of bytes a string again

    tmp = []
    for ip in subnets:
        ip = ip.split(".")
        tmp.append(ip)
        last = ip.pop()
        last_n = int(last) + 63
        ip.append(str(last_n))

    broadcasts = []
    for item in tmp:
        broadcasts.append('.'.join(item))

    return broadcasts

def get_firstAddress(subnets):
    """
        Calculates a list of ip addresses as strings that represent the network addresses of a subnet
        :param subnets: An array containing 4 ip addresses
        each represented as a string. The ip addresses are the valid subnets
        eg. ["192.168.10.0","192.168.10.64","192.168.10.128","192.168.10.192"]
        :return: An array containing 4 ip addresses
        each represented as a string. The ip addresses are the network addresses (first addresses of the subnet)
    """
    # For each ip string in the list, split each byte of the ip into a list
    # Add this list of bytes to a new list 'tmp'
    # Pop off the last element of the list of bytes and call it last
    # Add 1 to the int version of the string byte and call it last_n
    # Append the string version of last_n to the list of bytes
    # Create new list called first_addr and append each list of bytes to it
    # Call '.'.join() to make the list of bytes a string again

    tmp = []
    for ip in subnets:
        ip = ip.split(".")
        tmp.append(ip)
        last = ip.pop()
        last_n = int(last) + 1
        ip.append(str(last_n))

    first_addr = []
    for item in tmp:
        first_addr.append('.'.join(item))

    return first_addr

def get_lastAddress(subnets):
    """
        Calculates a list of ip addresses as strings that represent the last addresses of a subnet
        :param subnets: An array containing 4 ip addresses
        each represented as a string. The ip addresses are the valid subnets
        eg. ["192.168.10.0","192.168.10.64","192.168.10.128","192.168.10.192"]
        :return: An array containing 4 ip addresses
        each represented as a string. The ip addresses are the last addresses of the subnet
    """
    # For each ip string in the list, split each byte of the ip into a list
    # Add this list of bytes to a new list 'tmp'
    # Pop off the last element of the list of bytes and call it last
    # Add 62 to the integer version of the string byte and call it last_n
    # Append the string version of last_n to the list of bytes
    # Create new list called last_addr and append each list of bytes to it
    # Call '.'.join() to make the list of bytes a string again

    tmp = []
    for ip in subnets:
        ip = ip.split(".")
        tmp.append(ip)
        last = ip.pop()
        last_n = int(last) + 62
        ip.append(str(last_n))

    last_addr = []
    for item in tmp:
        last_addr.append('.'.join(item))

    return last_addr

def cidr_not(mask):
    """
    Take in an array of four strings representing the bytes of a subnet mask
    Calculates the CIDR number
    :param mask: An array containing the subnet mask of an IP address in binary
    :return cidr: The CIDR number for the IP address in the subnet endpoint
    """
    # Iterate through each of the 4 strings representing the bytes of subnet mask
    # If the bit is a 1, increment the CIDR number
    # The look will check every bit in the subnet mask and then return the CIDR number
    # Used for the subnet endpoint

    cidr=0
    for byte in mask:
        for bit in byte:
            if bit == "1":
                cidr+=1

    return cidr

def convert_to_bin(ip):
    """
    	Converts an ip address in decimal dot notation
    	represented as a string into a list of
    	four binary strings
    	each representing one byte of the address
    	:param ip: The ip address as a string in decimal dot notation
    	e.g. "132.206.19.7"
    	:return: An array of four binary strings each representing one byte
    	of ip e.g.
    	['10000100', '11001110', '00010011', '00000111']
    """
    # Split IP into an array
    # For each number in it convert to an integer
    # Format the integer as binary
    # Return an array

    return [format(int(x), '08b') for x in ip.split('.')]

def convert_to_decimal(ip_addr_list):
	"""
	Take in an array of four strings represting the bytes of an ip address
	and convert it back into decimal dot notation
	:param ip_addr_list: An array of four binary strings each
	representing one byte of ip_addr e.g. ['10000100', '11001110',
	'00010011', '00000111']
	:return: The ip address as a string in decimal dot notation e.g.
	'132.206.19.7'
	"""
	# for each string in the list
	# use str(int(x,2)) to convert it into a decimal number
	# and then turn that number into a string e.g. '10000100' -> '132'
	# put all converted numbers into a list ["132","206","19","7"]
	# call ".".join on the list to merge them into a string separated by "."
	return ".".join([str(int(x,2)) for x in ip_addr_list])


from web3 import Web3
import os

# Networks setup
web3_local_rinkeby = Web3(Web3.HTTPProvider('http://127.0.0.1:8888'))
web3_arbitrum_rinkeby = Web3(Web3.HTTPProvider('https://rinkeby.arbitrum.io/rpc'))

# Arbitrum TheLootBox contract setup
addr_lootbox_arbitrum = os.environ.get("TEST_NET_ARBITRUM_LOOTBOX")
addr_lootbox_arbitrum_abi = os.environ.get("TEST_NET_ARBITRUM_LOOTBOX_ABI")
addr_lootbox_factory_rinkeby = os.environ.get("LOOTBOX_FACTORY_CONTRACT_RINKEBY")
addr_lootbox_factory_rinkeby_abi = os.environ.get("TEST_NET_RINKEBY_LOOTBOX_FACTORY_ABI")
lootbox_contract_arbitrum = web3_arbitrum_rinkeby.eth.contract(address=addr_lootbox_arbitrum,
                                                               abi=addr_lootbox_arbitrum_abi)
lootbox_contract_rinkeby = web3_local_rinkeby.eth.contract(address=addr_lootbox_factory_rinkeby,
                                                           abi=addr_lootbox_factory_rinkeby_abi)

# TheLootBox bundle contract setup
addr_lootbox_bundle_arbitrum = os.environ.get("TEST_NET_ARBITRUM_LOOTBOX_BUNDLE_CONTRACT")
addr_lootbox_arbitrum_abi_v2 = os.environ.get("TEST_NET_ARBITRUM_LOOTBOX_ABI_V2")
lootbox_contract_arbitrum_bundle = web3_arbitrum_rinkeby.eth.contract(address=addr_lootbox_bundle_arbitrum,
                                                                      abi=addr_lootbox_arbitrum_abi_v2)

# DAI contract setup
dai_abi = os.environ.get("DAI_ABI")
addr_dai = os.environ.get("DAI_ADDR")
dai_contract_rinkeby = web3_local_rinkeby.eth.contract(address=addr_dai, abi=dai_abi)

# Dev setup
dev = os.environ.get("DEV")
key = os.environ.get('ARBITRUM_PRIVATE_KEY')
gas_price = web3_arbitrum_rinkeby.eth.gasPrice


'''
Example: s1: 'horse'
         s2: 'ros'

Case1: Inserting a Character

Now if we have to match the strings by insertions, what would we do?:

We would have placed an ‘s’ at index 5 of S1.
Suppose i now point to s at index 5 of S1 and j points are already pointing to s at index j of S2.
Now, we hit the condition, where characters do match. (as mentioned in case 1).
Therefore, we will decrement i and j by 1. They will now point to index 4 and 1 respectively.

Now, the number of operations we did were only 1 (inserting s at index 5) but do we need to really insert the ‘s’ at index 5 and modify the string? The answer is simply NO. As we see that inserting a character (here ‘s’ at index 5), we will eventually get to the third step. So we can just return 1+ f(i,j-1) as i remains there only after insertion and j decrements by 1. We can say that we have hypothetically inserted character s.

Case 2: Deleting a character

Consider the same example,

We can simply delete the character at index 4 and check from the next index.

Now, j remains at its original index and we decrement i by 1. We perform 1 operation, therefore we will recursively call 1+f(i-1,j).

Case3: Replacing a character

Consider the same example,

If we replace the character ‘e’ at index 4 of S1 with ‘s’, we have matched both the characters ourselves. We again hit the case of character matching, therefore we decrement both i and j by 1. As the number of operations performed is 1, we will return 1+f(i-1,j-1).

To summarise, these are the three choices we have in case characters don’t match:

return 1+f(i-1,j) // Insertion of character.
return 1+f(i,j-1) // Deletion of character.
return 1+f(i-1,j-1) // Replacement of character.
'''

#Recursion
#Time Complexity: O(2^(m+n))
#Space Complexity: O(m+n)
class Solution1:
    def minDistance(self, word1: str, word2: str) -> int:
        def solve(i,j):
            if i==0:
                return j
            if j==0:
                return i
            if word1[i-1]==word2[j-1]:
                return solve(i-1,j-1)
            else:
                return 1 + min(solve(i,j-1),solve(i-1,j),solve(i-1,j-1))
        m,n=len(word1),len(word2)
        return solve(m,n)

#Memoization (Top-Down)
#Time Complexity: O(m*n)
#Space Complexity: O(m+n) + O(m*n)
class Solution2:
    def minDistance(self, word1: str, word2: str) -> int:
        def solve(i,j):
            if i==0:
                return j
            if j==0:
                return i
            if dp[i][j]!=-1:
                return dp[i][j]
            if word1[i-1]==word2[j-1]:
                dp[i][j]=solve(i-1,j-1)
                return dp[i][j]
            else:
                dp[i][j]=1 + min(solve(i,j-1),solve(i-1,j),solve(i-1,j-1))
                return dp[i][j]
        m,n=len(word1),len(word2)
        dp=[[-1 for j in range(n+1)] for i in range(m+1)]
        return solve(m,n)

class Solution3:
    def minDistance(self, word1: str, word2: str) -> int:
        m,n = len(word1),len(word2)
        dp = [[0 for j in range(n+1)] for i in range(m+1)]
        for i in range(m+1):
            dp[i][0] = i
        for j in range(n+1):
            dp[0][j] = j
        for i in range(1,m+1):
            for j in range(1,n+1):
                if word1[i-1] == word2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = 1 + min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1])
        return dp[m][n]

#Space Optimization
#Time Complexity: O(m*n)
#Space Complexity: O(n)
class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        m,n = len(word1),len(word2)
        prev=[0]*(n+1)
        curr=[0]*(n+1)
        for j in range(n+1):
            prev[j]=j
        for i in range(1,m+1):
            curr[0]=i
            for j in range(1,n+1):
                if word1[i-1] == word2[j-1]:
                    curr[j] = prev[j-1]
                else:
                    curr[j] = 1 + min(prev[j-1], prev[j], curr[j-1])
            prev=curr[:]
        return prev[n]

# https://zhuanlan.zhihu.com/p/553078167
# 动态规划三部曲  1)dp数组含义  2)初始值  3)状态转移方程
# dp[i][j]定义为 word1前i个字符转换到word2前j个字符所需的最少操作数
#   | '' | r | o | s
# ''| 0  | 1 | 2 | 3
# h | 1  |
# o | 2  |
# r | 3  |
# s | 4  |
# e | 5  |
# dp[0][j]的含义: 从''转换为'',r,ro,ros所需的最少操作数
# dp[i][0]的含义: 从'',h,ho,hor,hors,horse转换为''所需的最少操作数
# dp[i][j] = dp[i-1][j-1] if word1[i-1]==word2[j-1] else min(dp[i-1][j-1]+1,dp[i-1][j]+1,dp[i][j-1]+1)
def editDistance(word1, word2):
    m,n = len(word1),len(word2)
    dp = [[0]*(n+1) for _ in range(m+1)]
    for i in range(m+1):
        for j in range(n+1):
            if i==0 or j==0:
                dp[i][j] = i if j==0 else j
            else:
                dp[i][j] = dp[i-1][j-1] if word1[i-1]==word2[j-1] else min(dp[i-1][j-1]+1,dp[i-1][j]+1,dp[i][j-1]+1)
    return dp[m][n]

from functools import lru_cache
def edit_distance(word1, word2):
    m, n = len(word1), len(word2)

    @lru_cache(None)
    def dp(i,j):
        if i>=m: return n-j
        if j>=n: return m-i
        if word1[i] == word2[j]: return dp(i+1, j+1)
        return min(dp(i,j+1), dp(i+1,j), dp(i+1,j+1)) + 1

    return dp(0,0)


import os
import random as rnd

from PIL import Image, ImageFilter, ImageStat
import numpy as np
from pandas import array
from engine import distorsion_generator
import cv2
def getbackgroundImage(foreground, backgroundList):

    backgroundFile = rnd.choice(backgroundList)
    background = Image.open(backgroundFile)
    if foreground.mode != background.mode:
        foreground = foreground.convert(background.mode)
    fwidth,fheight = foreground.size
    bwidth,bheight = background.size
    if bwidth>fwidth and bheight>fheight:
        top = rnd.randint(0,bheight-fheight)
        left = rnd.randint(0,bwidth-fwidth)
        background = background.crop((left, top, left+fwidth, top+fheight))
    else:
        background = background.resize(foreground.size)
    return background

class FakeformularDataGenerator(object):
    @classmethod
    def generate_from_tuple(cls, t):
        """
            Same as generate, but takes all parameters as one tuple
        """

        cls.generate(*t)

    @classmethod
    def generate(
        cls, foreImage, backgroundList,
        skewing_angle,
        random_skew, blur,random_blur, distorsion_type,
        distorsion_orientation, margins,
        image_mode="RGB",
    ):
        image = None

        margin_top, margin_left, margin_bottom, margin_right = margins
        horizontal_margin = margin_left + margin_right
        vertical_margin = margin_top + margin_bottom

        ##########################S
        # get foreground image #
        ##########################
        image = cv2.imread(foreImage)
        mask = 255-image
        mask = np.where(mask>175,255,0)
        mask = Image.fromarray(mask.astype(np.uint8))
        image = Image.fromarray(image)

        random_angle = rnd.randint(0 - skewing_angle, skewing_angle)

        rotated_img = image.rotate(
            skewing_angle if not random_skew else random_angle, expand=1
        )
        rotated_mask = mask.rotate(
            skewing_angle if not random_skew else random_angle, expand=1
        )

        #############################
        # Apply distorsion to image #
        #############################
        if distorsion_type == 0:
            distorted_img = rotated_img  # Mind = blown
            distorted_mask = rotated_mask
        elif distorsion_type == 1:
            distorted_img, distorted_mask = distorsion_generator.sin(
                rotated_img,
                rotated_mask,
                vertical=(distorsion_orientation == 0 or distorsion_orientation == 2),
                horizontal=(distorsion_orientation == 1 or distorsion_orientation == 2),
            )
        elif distorsion_type == 2:
            distorted_img, distorted_mask = distorsion_generator.cos(
                rotated_img,
                rotated_mask,
                vertical=(distorsion_orientation == 0 or distorsion_orientation == 2),
                horizontal=(distorsion_orientation == 1 or distorsion_orientation == 2),
            )
        else:
            distorted_img, distorted_mask = distorsion_generator.random(
                rotated_img,
                rotated_mask,
                vertical=(distorsion_orientation == 0 or distorsion_orientation == 2),
                horizontal=(distorsion_orientation == 1 or distorsion_orientation == 2),
            )

        #############################
        # Generate background image #
        #############################

        background_img =getbackgroundImage(
                distorted_img, backgroundList
            )

        #############################
        # Place text with alignment #
        #############################

        new_text_width, _ = distorted_img.size

        background_img.paste(distorted_img, (margin_left, margin_top), distorted_mask.convert("L"))
        #background_img.paste(image, (margin_left, margin_top), mask.convert("L"))

        #######################
        # Apply gaussian blur #
        #######################

        gaussian_filter = ImageFilter.GaussianBlur(
            radius=blur if not random_blur else rnd.randint(0, blur)
        )
        final_image = background_img.filter(gaussian_filter)

        ############################################
        # Change image mode (RGB, grayscale, etc.) #
        ############################################

        final_image = final_image.convert(image_mode)

        return final_image


from django.contrib import admin
from .models import *

# Register your models here.
class ProductAdmin(admin.ModelAdmin):
    list_display = ('name', 'category', 'priceh', 'pricef')
    list_filter = ('category',)
    search_fields = ('name', 'category')

class ItemAdmin(admin.ModelAdmin):
    list_display = ('product', 'quantityh', 'quantityf', 'order')
    list_filter = ('order',)

class ItemInline(admin.TabularInline):
    model = Item
    extra = 0

class OrderAdmin(admin.ModelAdmin):
    list_display = ('username', 'phone', 'type', 'amount', 'timestamp')
    list_filter = ('username', 'phone', 'type', 'timestamp')
    search_fields = ('username', 'phone', 'type', 'address', 'amount', 'timestamp')
    inlines = [ItemInline]
    readonly_fields = ('timestamp',)

admin.site.register(Category)
admin.site.register(Product, ProductAdmin)
admin.site.register(Item, ItemAdmin)
admin.site.register(Order, OrderAdmin)