from numpy import  array  # to create 4x4 matrix for gameboard
from square import Square # to create objects for each square on gameboard
from random import choice # for choosing a random postoin,values for inserting new value  into gameboard
import pygame

pygame.init()

class GameBoard:
    Direction={'up':(0,-2),'down':(0,2),'left':(-2,0),'right':(2,0)}
    font = pygame.font.SysFont('Comicsansms',20)
    font_h = pygame.font.SysFont('comicsansms', 25)
    highScore = 0
    """It is used to represent the gameboard
       class variable:
           Direction which is used to represnt some parameters based on direction in modify() function
       data members:
           board : stores all the square objects in 4x4 matrix format
           flag  : modification is done on board or not (True : done,False : not done)
           max   : stores the max value on board
           won   : Game Own or not
           gameOver : GameOver or not
    """
    def __init__(self,Display):
        """ Requires a Display to show the square on gameBoard
            default value
            board = with 16 square objects with 0 as value and i,j values as position
            flag  = True
            max   = 2
            won   = False
            gameOver = False
            calling insert() function
        """
        Square.Display=Display
        list=[Square((i,j)) for j in range(72,470,102) for i in range(2,400,102)]
        self.board=array(list).reshape((4,4))
        self.flag=True
        self.score = 0
        self.max=2
        self.won=False
        self.gameOver=False
        Square.Display.fill((255,255,255))
        pygame.draw.rect(Display,[0,0,255],(5,5,400,65))
        pygame.draw.rect(Square.Display,[255,255,0],(7,7,396,61))
        Score_h = GameBoard.font_h.render(' YOUR SCORE         HIGH SCORE', True, (255,0,0))
        Square.Display.blit(Score_h,(5,5))
        Score = GameBoard.font.render(str(self.score), True, (0,0,255))
        Square.Display.blit(Score,(20,40))
        Score = GameBoard.font.render(str(GameBoard.highScore), True, (0,0,255))
        Square.Display.blit(Score,(240,40))
        self.insert()

    def array(self):
        """  Generating an 4x4 matrix only with values on the gameboard to store """
        a=[self.board[i,j].value for i in range(0,4) for j in range(0,4)]+[0,self.max,self.score,GameBoard.highScore]
        return array(a).reshape((5,4))

    def restore(self,a):
        """ Regenerating the gameboard by taking values that are stored """
        GameBoard.highScore = a[4,3]
        self.score = a[4,2]
        self.max = a[4,1]
        if a.all()==None:
            self.score = 0
            self.max = 2
            return
        if self.max >= 2048:
            self.won = None
        for i in range(4):
            for j in range(4):
                self.board[i,j].value=a[i,j]

    def display(self):
        """ this is used to display the gameboard """
        if self.score !=0 :
            pygame.draw.rect(Square.Display,[255,255,0],(7,40,198,28))
            Score = GameBoard.font.render(str(self.score), True, (0,0,255))
            Square.Display.blit(Score,(20,40))
        pygame.draw.rect(Square.Display,[255,255,255],(0,80,410,410))
        for i in range(4):
            for j in range(4):
                self.board[i,j].update(self.board[i,j].value)

    def modify(self,event):
        """ This used to rotate the gameboard virtually
            so that we can use same function for all inputs with small modification on gameboard
            rules followed for player inputs:
                 Up    : No change
                 Down  : Flip the rows
                 Left  : Transpose then Flip the coloums
                 Right : Flip the rows then Transpose

               After complicaton of updating the gameboard again
                 Up    : No change
                 Down  : Flip the rows
                 Left  : Flip the coloumns then Transpose
                 Right : Transpose then Flip the coloumns
        """
        self.flag=False
        if event==pygame.K_DOWN:
            self.board[:,:]=self.board[::-1,:]
            self.update('down')
            self.board[:,:]=self.board[::-1,:]
        elif event==pygame.K_LEFT:
            self.board[:,:]=self.board.T[:,::-1]
            self.update('left')
            self.board[:,:]=self.board[:,::-1].T
        elif event==pygame.K_RIGHT:
            self.board[:,:]=self.board.T[::-1,:]
            self.update('right')
            self.board[:,:]=self.board[::-1,:].T
        elif event==pygame.K_UP:
            self.update('up')
        if self.flag:
            self.insert()

    def motion(self,direction,List):
        """ while modifying to give motion animation to the squares on board"""
        i,j = GameBoard.Direction[direction]
        X,Y = 0,0
        for m in range(0,51):
            for n in List:
                n.moveby(i,j,X,Y)
            X += i
            Y += j

    def shift(self,direction):
        """ While modifying to remove the blank spaces inbetween squares based on players input"""
        i=0
        while i<3:
            l=list()
            for j in range(4):
                if self.board[i,j].value==0:
                    l.extend(list(filter(lambda x:x.value!=0,list(self.board[i+1:,j]))))
            s = len(l)
            self.score += s
            if s==0:
                i+=1
                continue
            else:
                self.flag=True
            self.motion(direction,l)
            for j in range(4):
                if self.board[i,j].value==0:
                    for k in range(i+1,4):
                        self.board[k-1,j].update(self.board[k,j].value)
                    self.board[3,j].update()

    def update(self,direction):
        """ Update is used to initate modification of squared
            1. shifting the values will take place to remove middle spaces inbetween squares
            2. merging will takeplace next and animation is give to it by using motion function
        """
        self.shift(direction)
        i=0
        while i<3:
            l=list()
            for j in range(4):
                if self.board[i,j].value==self.board[i+1,j] and self.board[i,j].value!=0:
                    l+=list(list(self.board[i+1:,j]))
            self.motion(direction,l)
            for j in range(4):
                if self.board[i,j].value==self.board[i+1,j].value and self.board[i,j].value!=0:
                    self.flag=True
                    self.board[i,j].update(self.board[i,j].value*2)
                    self.score += self.board[i,j].value
                    for k in range(i+2,4):
                        self.board[k-1,j].update(self.board[k,j].value)
                    self.board[3,j].update()
            i+=1

    def check(self):
        """ To check whether GameOver or not by checking any two square are adjancent and same """
        for i in range(3):
            for j in range(3):
                if self.board[i,j].value==self.board[i+1,j].value or self.board[i,j].value==self.board[i,j+1].value:
                    return
            if self.board[i,3].value == self.board[i+1,3].value or self.board[3,i].value == self.board[3,i+1].value:
                return
        self.gameOver=True

    def insert(self):
        """ To insert a new value on the gameboard at random position with either 2 or 4 randomly
             it will update the score on screen also
        """
        pygame.draw.rect(Square.Display,[255,255,0],(7,40,198,28))
        Score = GameBoard.font.render(str(self.score), True, (0,0,255))
        Square.Display.blit(Score,(20,40))
        if self.score > GameBoard.highScore:
            GameBoard.highScore = self.score
            pygame.draw.rect(Square.Display,[255,255,0],(210,40,180,28))
            Score = GameBoard.font.render(str(GameBoard.highScore), True, (0,0,255))
            Square.Display.blit(Score,(240,40))
        l=list()
        for i in range(4):
            for j in range(4):
                if self.board[i,j].value==0:
                    l.append((i,j))
                elif self.max<self.board[i,j].value:
                    self.max=self.board[i,j].value
                    if self.max>=2048:
                        if self.won==None:
                            return
                        self.won=True
        if len(l)!=0 and self.flag:
            k=[2,2,2,2,2,2,2,2,4]
            self.board[choice(l)].update(choice(k))
        if len(l)==1:
            self.check()

# Below code is used to check Above class (testing Manually)
"""play=True
GameBoard=GameBoard(pygame.display.set_mode((410,410)))
while play:
    if GameBoard.gameOver:
        break
    if GameBoard.won==True:
        GameBoard.won=None
        break
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            play=False
            break
        elif event.type == pygame.KEYDOWN:
            GameBoard.modify(event.key)
pygame.quit()"""


import random
import datetime
from datetime import datetime as dt

def sequential_search(search_list, term=-1):
    """This function, sequential_search will search through a sequential list.

                    Args:
                        search_list holds a list of sequential numbers

                    Returns:
                        Returns returns the index of the number we are
                        searching for or returns none.

            """
    for index in range(len(search_list)):
        if search_list[index] == -1:
            return index
    return None

def ordered_sequential_search(search_list, term=-1):
    """This function, ordered_sequential_search will search through an ordered
        sequential list.

                    Args:
                        search_list holds a list of sequential numbers

                    Returns:
                        Returns returns the index of the number we are
                        searching for or returns none.

            """
    for index in range(len(search_list)):
        if search_list[index] == -1:
            return index
    return None

def binary_search_iterative(search_list, elem=-1):
    """This function called binary_search_iterative will search by dividing a
        list in half, checking the number and repeating the process.

                    Args:
                        search_list holds a list of sequential numbers

                    Returns:
                        Returns returns the index of the number we are
                        searching for or returns none.

            """
    left_bound = 0
    right_bound = len(search_list) - 1
    mid = (left_bound + right_bound) / 2

    while left_bound != right_bound or search_list[left_bound] == elem or search_list[right_bound] == elem:
        if elem == search_list[mid]:
            return mid
        elif elem > search_list[mid]:
            left_bound = mid + 1
        else:
            right_bound = mid
        mid = (left_bound + right_bound) / 2
    return None

def binary_search_recursive(search_list, term=-1):
    """This function called binary_search_recursive will search by dividing a
        list in half, and recalling the function until number is found.

                    Args:
                        search_list holds a list of sequential numbers

                    Returns:
                        Returns returns the index of the number we are
                        searching for or returns none.

            """
    if len(search_list) == 0:
        return None

    mid = len(search_list)/2
    if search_list[mid] == term:
        return mid
    elif search_list[mid] > term:
            return binary_search_recursive(search_list[:mid], term)
    else:
        result = binary_search_recursive(search_list[mid + 1:], term)
        if result:
            return result + mid
        else:
            return result

if __name__ == '__main__':
    lists500 = []
    lists1000 = []
    lists10000 = []
    list_of_lists = [
        lists500,
        lists1000,
        lists10000
    ]
#create 100 lists for 500, 1000, 10000
    for _ in range(100):
        lists500.append([random.randint(0, 1285398243) for _b in range(500)])

        lists1000.append([random.randint(0, 1285398243) for _b in range(1000)])

        lists10000.append([random.randint(0, 1285398243) for _b in range(10000)])

    for mega_list in list_of_lists:
        search_time = datetime.timedelta(0, 0, 0)
        for item in mega_list:
            start = dt.now()
            sequential_search(item)
            search_time += dt.now() - start

        print(
        '{}, {} from {} numbers'.format(sequential_search.__name__, search_time.total_seconds() / float(len(mega_list)), len(mega_list[0])))

    list_of_functions = [
        ordered_sequential_search,
        binary_search_iterative,
        binary_search_recursive
    ]

    for mega_list in list_of_lists:
        for item in mega_list:
            item.sort()

    for func in list_of_functions:

        for mega_list in list_of_lists:
            search_time = datetime.timedelta(0,0,0)
            for item in mega_list:
                start = dt.now()
                func(item)
                search_time += dt.now() - start

            print('{}, {} from {}'.format(func.__name__, search_time.total_seconds()/float(len(mega_list)),len(mega_list[0])))


# Please adjust the delay according to the computer time this script running on referring to the website time.is
# The post time should be about 12:00:00:300
import argparse
from application import modules
import yaml

def getPars():  # provide a entrance for custom timing time test
    myParser = argparse.ArgumentParser(description='timeSetting')
    myParser.add_argument('-hr', '--hour', type=int, default=12, help='setup hour part')
    myParser.add_argument('-m', '--min', type=int, default=0, help='setup minute part')
    myParser.add_argument('-s', '--sec', type=int, default=0, help='setup second part')
    myParser.add_argument('-d', '--delay', type=int, default=300, help='setup microsecond part')
    a = myParser.parse_args()

    t_h = a.hour
    t_m = a.min
    t_s = a.sec
    t_d = 1 - a.delay/1000
    t = [t_h, t_m, t_s, t_d]
    return t

def getConfig():
    file = open("./config/config.yaml", 'r', encoding="utf-8")
    data = yaml.load(file, Loader=yaml.FullLoader)
    file.close()
    return data

class app:
    def __init__(self, config):
        self.config = config

    def main(self):
        timing = self.config['timing']
        t = [int(timing[0]), int(timing[1]), int(timing[2]), 1-int(timing[3])/1000]
        self.config.update({'time': t})

        token = self.config['topToken']
        courtTime, court = self.config['topCourtTime'], self.config['topCourt']
        bookInfo = [courtTime, court]

        f = modules.Features(token, self.config)  # put your token here
        _, ver = f.getPriLogs()
        print(ver)
        info, info2 = f.bookCourt(bookInfo)  # put your book info here

        return info, info2


from flask import Blueprint, request, session
from flask_restful import Api, marshal_with, Resource
from flask_restful.reqparse import RequestParser

from src.config.api_utils import oper_log, check_auth
from src.dto_mapper import dictdetail_page_fields, dict_detail_fields
from src.schema import DictDetailSchema
from src.service.sys_service import DictDetailService

dictdetail_app = Blueprint('dictDetail', __name__, url_prefix='/api/dictDetail')
dictdetail_api = Api(dictdetail_app)

parser = RequestParser()
parser.add_argument('id', location='json', type=int, trim=True, required=True)
parser.add_argument('label', location='json', type=str, trim=True, required=True)
parser.add_argument('value', location='json', type=str, trim=True, required=True)
parser.add_argument('dictSort', location='json', type=int, trim=True, required=True)

@dictdetail_api.resource('', '/')
class DictDetailAPI(Resource):
    @oper_log('查询字典详情', request)
    @marshal_with(dictdetail_page_fields)
    def get(self):
        return DictDetailService.query_all(**request.args)

    @oper_log('修改字典详情', request)
    @check_auth('dict:edit', request)
    def put(self):
        parser_put = parser.copy()
        parser_put.parse_args()
        schema = DictDetailSchema()
        user = session["user"]
        params = request.get_json()
        curr_detail = schema.load(params, unknown="exclude")
        curr_detail.update_by = user["username"]
        DictDetailService.update(curr_detail=curr_detail)
        return None, 204

    @oper_log('新增字典详情', request)
    @check_auth('dict:add', request)
    def post(self):
        parser_post = parser.copy()
        parser_post.remove_argument('id')
        parser_post.parse_args()
        params = request.get_json()
        schema = DictDetailSchema()
        curr_detail = schema.load(params, unknown="exclude")
        user = session["user"]
        curr_detail.dict_id = params["dict"]["id"]
        curr_detail.dict_sort = params["dictSort"]
        curr_detail.create_by = user["username"]
        DictDetailService.create(curr_detail=curr_detail)

@dictdetail_api.resource('/<int:id_>')
class DeleteDictDetail(Resource):
    @oper_log('删除字典详情', request)
    @check_auth('dict:del', request)
    def delete(self, id_):
        DictDetailService.delete(id_=id_)

@dictdetail_api.resource('/<int:_id>')
class GetDetailById(Resource):
    @oper_log('根据ID查询岗位', request)
    @check_auth('dict:list', request)
    @marshal_with(dict_detail_fields)
    def get(self, _id):
        data = DictDetailService.find_by_id(detail_id=_id)
        return data


# feature extraction intensities along the curve
import numpy as np
import cv2
import pickle
import pandas as pd
from geomdl import BSpline
import matplotlib.pyplot as plt
import datetime
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA

def sec2hms(seconds):
    seconds = seconds % (24 * 3600)
    hours = seconds // 3600
    seconds %= 3600
    minutes = seconds // 60
    seconds %= 60

    return [np.int32(hours), np.int32(minutes), np.int32(seconds)]

####### main function ###########
if __name__== '__main__':

    filename_controlpts = 'data/controlpts_segmentations'
    filename_feat_inten = 'data/features_intensities'
    filename_pca = 'data/pca_data'
    filename_raw_features = 'data/raw_data_before_pca'

    # reading list of features
    with open(filename_feat_inten, 'rb') as fp:
        # the frames count started at 1 (first frame)
        print('reading features ...')
        [filenames_list, features_intesities_list] = pickle.load(fp)
        print ('done.')

    # print('filenames:\n', filenames_list)
    # print('feature intensities:\n ', len(features_intesities_list), len(features_intesities_list[0]), len(features_intesities_list[0][0]))
    # print(features_intesities_list[0][0])

    # training validation and test splitting
    # From the total videos, 20% for test; from the remining data, 20% for validation and 80% for training

    X_train, X_test, names_train, names_test = train_test_split(features_intesities_list, filenames_list, test_size=0.2, random_state=42)

    print(len(X_train), len(X_test), len(names_train), len(names_test))

    # train_feat, val_feat, names_tr_feat, names_val_feat = train_test_split(X_train, names_train, test_size=0.2, random_state=42)

    # print(len(train_feat), len(val_feat), len(names_tr_feat), len(names_val_feat))

    # print(len(features_intesities_list), len(features_intesities_list[0]), len(features_intesities_list[0][0]))

    frames_idx=[]
    frames_numbers = []
    dataframe_list=[]
    # training data
    # for features_video in train_feat:
    for features_video in X_train:

        df_video = pd.DataFrame(features_video)
        # resampling, making all videos with same number of frames
        # first, we choose 60s as reference from ED to ES for all videos
        time_sec = np.linspace(0,60,num=len(features_video))
        df_video.index = pd.to_datetime(time_sec, unit='s')
        # resampling to 18 frames (median of frames among the videos)
        # 18 frames in 60s, that means 3.529s between two consecutive frames (60/17)
        # we fill missing values copying the closest one in front of it (back filling)
        df_video = df_video.resample('3.529S').bfill()
        dataframe_list.append(df_video.values.tolist())

        # frames_numbers.append(len(features_video))
        # frames_idx.append(np.linspace(0,100,num=len(features_video)))

    # print('dataframe_list: ', len(dataframe_list), len(dataframe_list[7]), len(dataframe_list[7][0]))

    # initializing a list of lists (18 lists, one list for each frame from ED to ES). Each list will contain features of the same frame, for example ED, from all the videos
    feat_frames = [[] for i in range(len(dataframe_list[0]))]
    # print('feat_frames: ', feat_frames)
    # for elem in feat_frames:
    #     print(id(elem))

    # training data
    for features_video in dataframe_list:
        for id_frame, features_frame in enumerate(features_video):
            feat_frames[id_frame].append(features_frame)
            # print(len(feat_frames))
            # [print(len(elem)) for elem in feat_frames]
            # print(len(feat_frames[0][0]))
            # print('idframe: ', id_frame)

    binwidth=0.05
    min=-3.0
    max=3.0
    # PCA to each frame from the training data
    pca = PCA(n_components=25)
    # pca=PCA()
    pca_list=[]
    mean_list=[]
    std_list=[]
    print('feat_frames:',len(feat_frames))
    for cont, feat_single in enumerate(feat_frames):
        print('frame: ', cont)
        print('feat_single:', len(feat_single), len(feat_single[0]))

        pca.fit(feat_single)
        pca_feat = pca.transform(feat_single)

        mean_values = np.mean(pca_feat, axis=0)
        std_values = np.std(pca_feat, axis=0)

        pca_list.append(pca)
        mean_list.append(mean_values)
        std_list.append(std_values)

        # print('mean:', mean_values)
        # print('std:',  std_values)

        # acc = np.cumsum(pca.explained_variance_ratio_)
        # print(cont, pca.singular_values_)
        # print(cont, pca.explained_variance_ratio_)
        # print(cont, acc)
        # # print(feat_single.shape)
        # df = pd.DataFrame(pca_feat)
        # df.hist(bins=np.arange(min, max + binwidth, binwidth))
        # plt.show()

        # df = pd.DataFrame(feat_single)

        # ax = df.hist(column=['ang','x1','x2','x3','x5','x6','x7','y1','y2','y3','y4','y5','y6','y7','c0','c1'], bins=np.arange(min, max + binwidth, binwidth), alpha=0.5)
        # print(df.head)
        # list(range(11, 17))
        # df.hist(column=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24], bins=np.arange(min, max + binwidth, binwidth))
        # df.hist(column=list(range(0,12)), bins=np.arange(min, max + binwidth, binwidth))
        # df.hist(column=list(range(16+16,16+16+16)), bins=np.arange(min, max + binwidth, binwidth))

        # df.hist(column=list(range(0,49)), bins=np.arange(min, max + binwidth, binwidth))
        # plt.show()

    # with open(filename_pca, 'wb') as fp:
    #     # the frames count started at 1 (first frame)
    #     print('saving pca data ...')
    #     pickle.dump([X_train, X_test, names_train, names_test, pca_list, mean_list, std_list], fp)
    #     print ('done.')

    with open(filename_raw_features, 'wb') as fp:
        # the frames count started at 1 (first frame)
        print('saving raw data before pca ...')
        pickle.dump(feat_frames, fp)
        print ('done.')

    # print(dataframe_list[7])
    # print(frames_numbers)
    # print('mean median:', np.mean(frames_numbers), np.median(frames_numbers))
    # plt.hist(frames_numbers)
    # plt.show()

        # df_video = pd.DataFrame(features_intesities_list[7])

        # # resampling, making all videos with same number of frames
        # # arbitrary, we choose 60 s as reference from ED to ES
        # time_sec = np.linspace(0,60,num=len(features_intesities_list[7]))
        # df_video.index = pd.to_datetime(time_sec, unit='s')
    # print(df_video)
    # resampling
    # 18 frames in 60 s, that means 3.529 s between two consecutive frames (60/17)
    # print(df_video.resample('3.529S').bfill())

    # time_list=[]
    # for time_id in time_sec:
    #     time_hms = sec2hms(time_id)
    #     print('time: ', time_hms, np.sum(time_hms),pd.to_datetime(np.sum(time_hms), unit='s'))

    #     # time_formated = datetime.timedelta(seconds= time_id)
    #     # print(time_formated.hours, time_formated.minutes, time_formated.seconds)
    #     time_list.append(time_hms)
    # print('timelist: ', time_list)
    # # df_video['idx'] = np.linspace(0,10000,num=len(features_intesities_list[0]))
    # df_video.index = pd.to_datetime(time_list) # format='%H:%M:%S'
    # print(df_video)
    # print(frames_numbers)

    # print(np.mean(frames_numbers), np.median(frames_numbers))

    # plt.hist(frames_numbers, bins=20)
    # plt.show()

    # dataframe


import multires_consensus_clustering as mcc

def uncertainty_measure_cells(graph):
    """
    Calculates a probability score for all cells based on the probabilities in each node
        and the number the cell occurs with the same probability throughout the graph.

    @param graph: The graph on with the clustering is based.
    @param plot: Turns the plot on or off with True or False.

    @return: A pandas dataframe with the probabilities.
    """

    # get df of the cluster labels (contains all infos about the meta-graph)
    # cell_occurrence, cell_occurrence with the same probabilities, original probabilities
    df_clusters = mcc.graph_to_cell_labels_df(graph)

    # get the values for the cells
    cell_occurrence_node = df_clusters["number_cell_occurrence"].values
    cell_occurrence_prob = df_clusters["number_same_probability"].values
    cell_probabilities = df_clusters["probability"].values

    # divide the number a cell occurs with the same probability by the time it occurs in total
    zip_occurrence = zip(cell_occurrence_prob, cell_occurrence_node)
    occurrence = [occur[0] / occur[1] if occur[1] != 0 else 1 for occur in zip_occurrence]

    # multiple the probabilities if the occurrence is not zero
    zip_probs = zip(cell_probabilities, occurrence)
    estimator = [prob[0] * prob[1] if prob[1] != 0 else prob[0] for prob in zip_probs]

    # add new probabilities to the dataframe
    df_clusters["probability"] = estimator

    # return the new df with the newly calculated probabilities
    return df_clusters


from markdown.extensions import Extension
from markdown.treeprocessors import Treeprocessor

class BootstrapExtension(Extension):

	def extendMarkdown(self, md, md_globals):
		md.registerExtension(self)
		self.processor = BootstrapTreeprocessor()
		self.processor.md = md
		self.processor.config = self.getConfigs()
		md.treeprocessors.add('bootstrap', self.processor, '_end')

class BootstrapTreeprocessor(Treeprocessor):

	def run(self, node):
		for child in node.iter():
			if child.tag == 'img':
				child.set("class", "img-fluid")
			elif child.tag == 'table':
				child.set("class", "table table-striped")
		return node


from math import atan2, pi

def angle(x0, y0, x1, y1):
    return atan2((y1-y0),(x1-x0))

def detection_number(x, y, m):
    angles = set()
    for x1 in range(len(m)):
        for y1 in range(len(m[0])):
            if (x1, y1) != (x, y) and m[x1][y1] == 1:
                angles.add(angle(x,y,x1,y1))
    return len(angles)

def create_sets(x, y, m):
    coords_angle = {}
    for x1 in range(len(m)):
        for y1 in range(len(m[0])):
            if (x1, y1) != (x, y) and m[x1][y1] == 1:
                a = angle(x,y,x1,y1)
                if a in coords_angle:
                    coords_angle[a].append((x1,y1))
                else:
                    coords_angle[a] = [(x1,y1)]
    for a in coords_angle:
        coords_angle[a].sort(key=lambda c: abs(c[0]-x) + abs(c[1]-y))
    return coords_angle

if __name__ == '__main__':

    with open('day10.txt') as f:
        m = []
        for line in f.readlines():
            m.append([1 if c == '#' else 0 for c in line.strip()])

    # Part 1
    d = {}
    for x in range(len(m)):
        for y in range(len(m[0])):
            if m[x][y] == 1:
                d[(x,y)] = detection_number(x, y, m)
    coord = max(d, key=d.get)
    print(d[coord])

    # Part 2
    d = create_sets(coord[0], coord[1], m)
    sorted_angles = sorted(d.keys())[::-1]
    c = 1
    for a in sorted_angles:
        vaporized = d[a].pop(0)
        if c == 200:
            break
        c += 1
    print(vaporized[1]*100 + vaporized[0])


from pwn import *

sock = remote("ctf.b01lers.com",9202)
keys = [b"nwlr",b"bbmq",b"bhcd",b"arzo",b"wkky",b"hidd",b"qscd",b"xrjm",b"owfr",b"xsjy",b"bldb",b"efsa",b"rcby",b"necd",b"yggx",b"xpkl",b"orel",b"lnmp",b"apqf",b"wkho",b"pkmc",b"oqhn",b"wnku",b"ewhs",b"qmgb",b"buqc",b"ljji",b"vswm",b"dkqt",b"bxix",b"mvtr",b"rblj",b"ptns",b"nfwz",b"qfjm",b"afad",b"rrws",b"ofsb",b"cnuv",b"qhff",b"bsaq",b"xwpq",b"cace",b"hchz",b"vfrk",b"mlno",b"zjkp",b"qpxr",b"jxki",b"tzyx",b"acbh",b"hkic",b"qcoe",b"ndto",b"mfgd",b"wdwf",b"cgpx",b"iqvk",b"uytd",b"lcgd",b"ewht",b"acio",b"hord",b"tqkv",b"wcsg",b"spqo",b"qmsb",b"oagu",b"wnny",b"qxnz",b"lgdg",b"wpbt",b"rwbl",b"nsad",b"eugu",b"umoq",b"cdru",b"beto",b"kyxh",b"oach",b"wdvm",b"xxrd",b"ryxl",b"mndq",b"tukw",b"agml",b"ejuu",b"kwci",b"bxub",b"umen"]

for key in keys:
    print("send ", key)
    sock.sendlineafter(b"Guess me a string of length 4 with lowercase letters:", key)

sock.interactive()


import random
import game_framework
from pico2d import *
class Gate:
    image = None

    def __init__(self,x,y):
        self.x, self.y = x,y+60
        self.spoty=y
        self.frame = 0
        self.frame2 = 0.0
        self.realx=0
        self.clear=0
        self.quit=0
        self.clearimg2=load_image('image///death.png')
        self.clearimg=load_image('image///black.png')
        if Gate.image == None:
           Gate.image = load_image('image///gate.png')
    def update(self,frame_time):
        if(self.clear>1):
         self.quit+=1
        if(self.quit>100):
                game_framework.quit()
    def draw(self,camx):
        if (self.clear==1):
            self.clearimg.clip_draw(0,0,800,400,400,300,800,600)
            self.clearimg2.clip_draw(0,0,59,96,400,300,800,600)
        self.image.clip_draw( self.frame*32,0 , (self.frame+1)*32, 32, self.x-camx, self.y,120,120)
        self.realx=self.x-camx
    def get_bb(self):
        return self.realx - 60, self.y - 60, self.realx + 60, self.y + 60

    def draw_bb(self):
        draw_rectangle(*self.get_bb())
class Devileye :
    image = None

    def __init__(self,x,y):
        self.x, self.y = x,y
        self.spoty=y
        self.hp=40
        self.ydir=1
        self.frame = 0
        self.frame2 = 0.0
        self.realx=0

        if Devileye.image == None:
            Devileye.image = load_image('image///devileye.png')
    def update(self,frame_time):
        if(self.y>self.spoty+200):
            self.ydir=-1
        if(self.y<self.spoty-200):
            self.ydir=1
        self.frame2+=frame_time*50
        self.frame=int(self.frame2)%2
        self.y+=self.ydir
    def draw(self,camx):
        self.image.clip_draw( 0, 106*self.frame, 142, 106, self.x-camx, self.y,60,60)
        self.realx=self.x-camx
    def get_bb(self):
        return self.realx - 30, self.y - 30, self.realx + 30, self.y + 30

    def draw_bb(self):
        draw_rectangle(*self.get_bb())
class Peep :
    image = None

    def __init__(self,x,y):
        self.x, self.y = x,y
        self.hp=16
        self.xdir=1
        self.realx=0
        self.die=0
        self.spotx=x
        if Peep.image == None:
            Peep.image = load_image('image///Peep.png')
    def update(self,frame_time):
        if(self.x>self.spotx+100):
            self.xdir=-1
        if(self.x<self.spotx-100):
            self.xdir=1
        self.x+=self.xdir
        if(self.hp<0):
           self.x=0
           self.y=0
    def draw(self,camx):
        self.image.clip_draw( 0, 0, 32, 32, self.x-camx, self.y,30,30)
        self.realx=self.x-camx
    def get_bb(self):
        return self.realx - 30, self.y - 30, self.realx + 30, self.y + 30

    def draw_bb(self):
        draw_rectangle(*self.get_bb())

class Ghost :
    image = None

    def __init__(self,x,y):
        self.x, self.y = x,y
        self.hp=16
        self.xdir=1
        self.realx=0
        self.die=0
        self.spotx=x
        self.rd=0
        if Ghost.image == None:
            Ghost.image = load_image('image///ghost.png')
    def update(self,frame_time):
        self.rd+=1
        if(self.x>self.spotx+50):
            self.xdir=-1
        if(self.x<self.spotx-50):
            self.xdir=1
        self.x += self.xdir*frame_time*100 + math.cos(self.rd)
        self.y -= 10*math.sin(self.rd)
    def draw(self,camx):

        if(self.hp>8):
            self.image.clip_draw( 0, 32, 32, 64, self.x-camx, self.y,60,60)
        else:
            self.image.clip_draw( 0, 0, 32, 32, self.x-camx, self.y,60,60)
        self.realx=self.x-camx
    def get_bb(self):
        return self.realx - 25, self.y - 25, self.realx + 25, self.y + 25

    def draw_bb(self):
        draw_rectangle(*self.get_bb())


from . import context
from .exceptions import (
    MissingCommandException,
    InvalidCommandException,
    CLIIndexerException,
)
import sys
from .measure import measure_time
from .command import AbstractCommand

def parse_input() -> tuple[list[str], str, list[str]]:
    if len(sys.argv) == 1:
        raise MissingCommandException("no command specified")

    options = []
    i = 1
    for arg in sys.argv[1:]:
        if arg.startswith("--"):
            options.append(arg)
            i += 1
        else:
            break

    try:
        command = sys.argv[i]
    except IndexError:
        raise MissingCommandException("no command specified")

    args = []
    if len(sys.argv) > i:
        args.extend(sys.argv[i + 1 :])

    return options, command, args

class HelpCommand(AbstractCommand):
    name: str = "help"
    doc: str = f"""Find files, dirs or file content in specified directory.
[OPTIONS...] COMMAND ARGUMENTS...
OPTIONS:
    --no-colors     turn off colors

COMMANDS:"""

    def execute(self, args: list[str] = list()) -> None:
        print(
            "\n".join(map(lambda c: c.doc.strip(), context.Context.commands.values()))
        )

class CLIApplication:
    def __init__(self):
        self.register_command(HelpCommand())

    @staticmethod
    def register_command(command: AbstractCommand):
        context.register_command(command)

    @staticmethod
    def print_help():
        try:
            help_c = context.get_command(HelpCommand.name)
        except InvalidCommandException as e:
            print(e)
        else:
            help_c.execute()

    @measure_time(lambda res: res == 0)
    def run(self) -> int:
        try:
            options, command, args = parse_input()
        except MissingCommandException as e:
            print(str(e) + "\n")
            self.print_help()
            return 1

        try:
            context.apply_options(options)
        except CLIIndexerException as e:
            print(str(e) + "\n")
            self.print_help()
            return 1

        try:
            cmd_object = context.get_command(command)
        except InvalidCommandException as e:
            print(str(e) + "\n")
            self.print_help()
            return 1

        try:
            cmd_object.execute(args)
        except CLIIndexerException as e:
            print(str(e) + "\n")
            print(cmd_object.doc.strip())
            return 1

        return 0


import numpy as np

def standarize(data):
    means = np.mean(data, axis=0).reshape(1,-1)
    stds = np.std(data, axis=0).reshape(1,-1)
    data_s = (data-means)/stds
    return data_s, means, stds

def emotion_to_id(cats, dataset):
    if(dataset == 'enterface'):
        mapa = {'anger':0, 'disgust':1, 'fear':2, 'happiness':3, 'sadness':4, 'surprise':5}
    elif(dataset == 'iemocap'):
        mapa = {'ang': 0, 'dis':1, 'exc':2, 'fea':3, 'fru':4, 'hap':5, 'neu':6, 'sad':7, 'sur':8, 'oth':9, 'xxx':-1}
    elif(dataset == 'mosei'):
        mapa = {'ang':0, 'dis':1, 'fea':2, 'hap':3, 'sad':4, 'sur':5, 'neu':6, 'mul':-1}
    elif(dataset == 'fb'):
        mapa = {'anger':0, 'disgust':1, 'fear':2, 'happiness':3, 'sadness':4, 'surprise':5, 'other':6}
    func_vec = np.vectorize(lambda x: mapa[x])
    return func_vec(cats)

def fuse_arousal_valence_data(X_aro, X_val):
    for i in range(X_val.shape[1]):
        band = True
        for j in range(X_aro.shape[1]):
            a = X_aro[:,j]
            b = X_val[:,i]
            a = np.nan_to_num(a)
            b = np.nan_to_num(b)
            if(np.array_equal(a,b)):
                band = False
        if(band):
            X_aro = np.concatenate((X_aro, X_val[:,[i]]),axis=1)

    return X_aro

def get_angle(x,y):
    if(x == 0):
        if(y == 0):
            return 0
        elif(y > 0):
            return 90
        else:
            return 270
    elif(y == 0):
        if(x > 0):
            return 0
        else:
            return 180
    h = (x**2 + y**2)**(1/2)

    # relative angle
    rel_ang = np.arccos((x**2+h**2-y**2) / (2*x*h))

    # angle to positive x axis
    if(x > 0):
        if(y > 0):
            return rel_ang
        else:
            return 360 - rel_ang
    else:
        if(y > 0):
            return 180 - rel_ang
        else:
            return rel_ang + 180

def aro_val_to_emo(aro, val):
    mapa = {'anger':[-0.51, 0.59], 'disgust':[-0.6, 0.35], 'fear':[-0.64, 0.6], 'happiness':[0.81, 0.51], 'sadness':[-0.63, -0.27], 'surprise':[0.4, 0.67]}
    emo = 'other'
    mini = np.inf
    tol = 15
    for k,v in mapa.items():
        ang_emo = get_angle(*v)
        ang = get_angle(val, aro)

        dist = np.linalg.norm(np.array([val,aro])-np.array(v))
        if(dist < mini and ang_emo - tol < ang and ang < ang_emo + tol):
            mini = dist
            emo = k

    return emo


lower=100
upeer=1000
for num in range(lower,upeer+1):
    sum=0
    temp=num
    while (temp>0):
        digit=temp%10
        sum+=digit**3
        temp=temp/10
        if (num==sum):
            print(num)


#!/usr/bin/python
import rospy
import baxter_interface
from baxter_pykdl import baxter_kinematics
import numpy as np
import numpy.linalg as npla
from math import sqrt
import threading
import pid_controllers
import tf.transformations
import tf
from sensor_msgs.msg import PointCloud

MAX_JOINT_VEL = 1.5 # Max commanded joint velocity
MAX_NS_JOINT_VEL = 0.5 # Max nullspace joint velocity

# Arm neutral configs
NEUTRAL = {'left':
        {'left_w0': 0.0,
         'left_w1': -0.55,
         'left_w2': 0.0,
         'left_e0': 0.75,
         'left_e1': 0.0,
         'left_s0': 1.26,
         'left_s1': 0.0},
         'right':
        {'right_w0': 0.0,
         'right_w1': -0.55,
         'right_w2': 0.0,
         'right_e0': 0.75,
         'right_e1': 0.0,
         'right_s0': 1.26,
         'right_s1': 0.0}}

class EndpointVelocityController():
    """Generates joint velocity commands to produce a specified endpoint velocity for one of
    Baxter's arms.

    Args:
    limb: 'left'|'right'
    """

    def __init__(self, limb):
        self._neutral_config = NEUTRAL[limb]
        self._kin = baxter_kinematics(limb)
        self._limb = baxter_interface.Limb(limb)

    def set_endpoint_velocity(self, velocity_cmd):
        """Sends joint velocity commands to produce the instantaneous endpoint velocity specified
        by velocity_cmd

        Args:
        velocity_cmd: (6,) ndarray - the desired endpoint velocity [x', y', z', r', p' y']
        """
        # Neutral position return velocity
        # Compute nullspace velocities
        velocity_dict = {joint: self._neutral_config[joint] - self._limb.joint_angle(joint) for joint in self._limb.joint_names()}

        #Clamp the nullspace velocity command so it's within limits for each joint
        vel_scale_factor = max([abs(velocity) for velocity in velocity_dict.values()]) / MAX_NS_JOINT_VEL
        if vel_scale_factor > 1:
            velocity_dict = {joint: velocity_dict[joint] / vel_scale_factor for joint in self._limb.joint_names()}

        # Project into the nullspace
        nullspace = null(np.array(self._kin.jacobian()))[1]
        velocity_dict = project_to_nullspace(nullspace, self._limb.joint_names(), velocity_dict)

        # End effector command velocity
        # Compute the joint velocity commands
        jacobian_pinv = np.array(self._kin.jacobian_pseudo_inverse())
        joint_velocity_command = jacobian_pinv.dot(velocity_cmd)
        command_velocity_dict = {joint: joint_velocity_command[i] for i, joint in enumerate(self._limb.joint_names())}

        #Clamp the EE velocity command so it's within limits for each joint
        ee_vel_scale_factor = max([abs(velocity) for velocity in command_velocity_dict.values()]) / MAX_JOINT_VEL
        if ee_vel_scale_factor > 1:
            command_velocity_dict = {joint: command_velocity_dict[joint] / ee_vel_scale_factor for joint in self._limb.joint_names()}

        # Command the velocities
        velocity_dict = {joint:command_velocity_dict[joint] + velocity_dict[joint] for joint in self._limb.joint_names()}
        self._limb.set_joint_velocities(velocity_dict)

    def set_neutral_config(self, neutral_config_dict):
        """Sets the arm's neutral configuration to something other than the default value.

        Args:
        neutral_config_dict: dict - {'left_s1':value, ..., 'left_w2':value}
        """
        self._neutral_config = neutral_config_dict

class ContinuousEndpointPoseController():
    """A closed loop endpoint pose controller which uses joint velocity commands to move the
    specified limb's endpoint to the desired pose.

    Args:
    limb: 'left'|'right'
    """

    def __init__(self, limb):
        self._limb = baxter_interface.Limb(limb)
        self._vel_controller = EndpointVelocityController(limb)
        self._run = True

        # Choose the endpoint's current pose as the starting setpoint
        self._orientation_setpoint = np.array(self._limb.endpoint_pose()['orientation'])
        self._position_setpoint = np.array(self._limb.endpoint_pose()['position'])

        # Create the controllers for each DoF of the endpoint velocity
        self._dof_controllers = {
                'x': pid_controllers.PidController(k_p=3.0).set_desired_value(self._position_setpoint[0]),
                'y': pid_controllers.PidController(k_p=3.0).set_desired_value(self._position_setpoint[1]),
                'z': pid_controllers.PidController(k_p=3.0).set_desired_value(self._position_setpoint[2]),
                'rpy': pid_controllers.OrientationPidController(k_p=1.0).set_desired_value(self._orientation_setpoint)
        }

        # Start the velocity control loop
        self.start()

    def stop(self):
        #Stop the controller
        self._run = False

    def start(self):
        #Start the controller
        self._run = True
        threading.Thread(target=self._run_controller).start()

    def _update_endpoint_velocity(self):
        # Measures the current endpoint pose error and commands a new set of joint velocities
        CONTROL_DOFS = ['x', 'y', 'z', 'rpy']
        IGNORE_DOFS = []#'roll', 'pitch', 'yaw']
        current_ee_vel = {dof: 0.0 for dof in CONTROL_DOFS}
        current_ee_pos = {dof: self._limb.endpoint_pose()['position'][i] for i, dof, in enumerate(CONTROL_DOFS[0:3])}
        current_ee_ori = self._limb.endpoint_pose()['orientation']
        #Seems like the quaternion is actually in the correct order?
        # current_ee_ori = np.concatenate((current_ee_ori[3:4], current_ee_ori[0:3]))

        velocity_cmd = [self._dof_controllers[dof].get_control_cmd(current_ee_pos[dof], current_ee_vel[dof]) for dof in CONTROL_DOFS[0:3]]
        ori_velocity_cmd = self._dof_controllers['rpy'].get_control_cmd(current_ee_ori, 0.0)
        velocity_cmd.extend(ori_velocity_cmd)
        self._vel_controller.set_endpoint_velocity(velocity_cmd)

    def _run_controller(self):
        rate = rospy.Rate(100)
        while (not rospy.is_shutdown()) and self._run:
            self._update_endpoint_velocity()
            rate.sleep()

    def update_position_setpoint(self, setpoint):
        """Sets the endpoint position setpoint to a new value. Right now orientation is not
        supported. The controller just maintains the endpoint orientation that it measured when
        it was initialized.

        Args:
        setpoint: (3,) ndarray - the desired endpoint position [x, y, z]
        """
        self._position_setpoint = setpoint
        for i, dof in enumerate(['x', 'y', 'z']):
            self._dof_controllers[dof].set_desired_value(setpoint[i])

def null(a, rtol=1e-5):
    """ Computes the nullspace of a

    Returns:
    rank: the rank of the matrix (# of dims with singular values > rtol)
    nullspace: basis vectors for the nullspace
    """
    u, s, v = npla.svd(a)
    rank = (s > rtol*s[0]).sum()
    return rank, v[rank:].T.copy()

def project_to_nullspace(nullspace, joint_order, joint_velocities):
    """Projects a dict of joint velocities into the nullspace of a manipulator. The resulting
    joint velocity dict will not produce any endpoint motion of the arm.

    Args:
    nullspace: basis vectors for the nullspace returned from null()
    joint_order: list - the order in which joints are represented in the Jacobian
        ['left_s1', ...,'left_w2']
    joint_velocities: dict - input joint velocities to project
    """
    # Make a vector of joint velocities
    velocities = np.array([joint_velocities[joint] for joint in joint_order])

    # Compute the projection onto each nullspace vector
    proj_velocities = np.zeros_like(velocities)
    for n in range(nullspace.shape[1]):
        proj_velocities += nullspace[:,n].dot(velocities) * nullspace[:,n]

    # Convert back to a velocities dict
    return {joint: proj_velocities[i] for i, joint in enumerate(joint_order)}

class MocapPointTracker:
    """Moves both of Baxter's arms to maintain a constant position relative to a single motion
    capture marker.

    Args:
    vel_controller_left/vel_controller_right: the ContinuousEndpointPoseControllers for each arm
    """
    def __init__(self, vel_controller_left, vel_controller_right):
        self._vel_controller_left = vel_controller_left
        self._vel_controller_right = vel_controller_right
        self._tf_listener = tf.TransformListener()
        self._position_offset_left = None
        self._position_offset_right = None

    def new_frame_callback(self, message):
        """Called for each new sensor_msgs/PointCloud message received from the mocap system

        Args:
        message: the PointCloud message object
        """
        try:
            message = self._tf_listener.transformPointCloud('/base', message)
            data = point_cloud_to_array(message)
            point = data[0,:,0]
            if not np.any(np.isnan(point)):
                # Initialize the position offset
                if self._position_offset_left is None:
                    self._position_offset_left = point - np.array(self._vel_controller_left._limb.endpoint_pose()['position'])
                    self._position_offset_right = point - np.array(self._vel_controller_right._limb.endpoint_pose()['position'])
                else:
                    self._vel_controller_left.update_position_setpoint(point - self._position_offset_left)
                    self._vel_controller_right.update_position_setpoint(point - self._position_offset_right)
        except tf.LookupException:
            print("Couldn't find the mocap transformation")

def point_cloud_to_array(message):
    # Converts a sensor_msgs/PointCloud to a (num_markers, 3, 1) ndarray
    num_points = len(message.points)
    data = np.empty((num_points, 3, 1))
    for i, point in enumerate(message.points):
        data[i,:,0] = [point.x, point.y, point.z]
    return data

def main():
    rospy.init_node('baxter_velocity_control')
    vel_controller_left = ContinuousEndpointPoseController('left')
    vel_controller_right = ContinuousEndpointPoseController('right')
    tracker = MocapPointTracker(vel_controller_left, vel_controller_right)
    sub = rospy.Subscriber('/mocap_point_cloud', PointCloud, tracker.new_frame_callback)
    rospy.spin()

if __name__ == "__main__":
    main()


"""Matcher module."""
from abc import ABCMeta, abstractmethod

ESCAPE_VIM_PATTERN_TABLE = str.maketrans({
    '^': '\\^',
    '$': '\\$',
    '~': '\\~',
    '.': '\\.',
    '*': '\\*',
    '[': '\\[',
    ']': '\\]',
    '\\': '\\\\',
})

class AbstractMatcher(metaclass=ABCMeta):
    """An abstract macher class.

    Attributes:
        nvim (neovim.Nvim): A ``neovim.Nvim`` instance.
    """

    name = 'abstract'

    def __init__(self, nvim):
        """Constructor.

        Args:
            nvim (neovim.Nvim): A ``neovim.Nvim`` instance.
        """
        self.nvim = nvim
        self._match_id = None    # type: int

    def remove_highlight(self):
        """Remove current highlight."""
        if self._match_id:
            self.nvim.call('matchdelete', self._match_id)
            self._match_id = None

    def highlight(self, query, ignorecase):
        """Highlight ``query``.

        Args:
            query (str): A query string.
            ignorecase (bool): Boolean to indicate ignorecase.
        """
        self.remove_highlight()
        if not query:
            return
        pattern = self.get_highlight_pattern(query)
        self._match_id = self.nvim.call(
            'matchadd',
            'Title',
            ('\c' if ignorecase else '\C') + pattern,
            0,
        )

    @abstractmethod
    def get_highlight_pattern(self, query):
        """Get highlight pattern for ``query``.

        Args:
            query (str): A query string.
            ignorecase (bool): Boolean to indicate ignorecase.

        Returns:
            str: A pattern to highlight.
        """
        raise NotImplementedError

    @abstractmethod
    def filter(self, query, indices, candidates, ignorecase):
        """Filter candidates with query and return indices.

        Args:
            query (str): A query string.
            indices (Sequence[int]): An index list available.
            candidates (Sequence[str]): A candidate list.
            ignorecase (bool): Boolean to indicate ignorecase.

        Returns:
            Sequence[int]: A filtered candidate indices.
        """
        raise NotImplementedError

def escape_vim_patterns(text):
    """Escape patterh character used in Vim regex.

    Args:
        text (str): A text being escape.

    Returns:
        str: A escaped text.
    """
    return text.translate(ESCAPE_VIM_PATTERN_TABLE)


# Load input into a row/column list of strings
def load_row_major():
    with open("input.txt") as f:
        return [[int(tree) for tree in line.strip()] for line in f.readlines()]

# Swap rows and columns, so indexing is now [col][row]
# right becomes down (+col -> +row)
# down becomes right (+row -> +col)
def transpose_to_column_major(row_major):
    return list(zip(*row_major))

def slice_to_edge(row_major, col_major, row, col, dr, dc):
    top = 0 if dr < 0 else row+1 # slice from [0 -> row] for upward scan, [row -> end] for downward
    bottom = row if dr < 0 else len(row_major)

    left = 0 if dc < 0 else col+1 # slice from [0 -> col] for leftward scan, [col -> end] for rightward
    right = col if dc < 0 else len(col_major)

    if dc != 0: # left/right
        return [column[row] for column in col_major[left:right]]
    elif dr != 0: # up/down
        return [row[col] for row in row_major[top:bottom]]
    else:
        print("Shouldn't be here")

def max_or_empty(seq):
    if len(seq) == 0: return -1
    return max(seq)

cardinals = [(0, 1), (0, -1), (1, 0), (-1, 0)]

def visible(row_major, col_major, row, col):
    height = row_major[row][col]
    for dir in cardinals:
        if max_or_empty(slice_to_edge(row_major, col_major, row, col, *dir)) < height:
            return True
    return False

row_major = load_row_major()
col_major = transpose_to_column_major(row_major)

count = 0
for row in range(len(row_major)):
    for col in range(len(col_major)):
        if visible(row_major, col_major, row, col):
            count += 1

print(count)


# keyword arguments = arguments prefixed with the names of parameters
#                                        order of the arguments doesn’t matter
#                                        helps with readability

# basically keyword arguments are used when the order doesn't matter, in this calling names are given to the values and they are similiar to the names given in the function definition

# ---- EXAMPLE 1 ----
def hello(greeting, title, first, last):
    print(f"{greeting} {title}{first} {last}")

hello("Hello", title="Mr.", last="John", first="James")

# ---- EXAMPLE 2 ----
for number in range(1, 11):
    print(number, end=" ")

print("1", "2", "3", "4", "5", sep="-")

# ---- EXERCISE ----
def get_phone(country, area, first, last):
    return f"{country}-{area}-{first}-{last}"

phone_num = get_phone(country=1, area=123, first=456, last=7890)
print(phone_num)


import subprocess;
import json;
import urllib;
import urllib.request;
import sys;
import dbus;
from multiprocessing.pool import ThreadPool
from PyQt4 import QtGui, QtCore;

def main():
    #lyrics = getlyrics()
    app = QtGui.QApplication(sys.argv);
    q = Window();
    app.exec_();

def getlyrics():
    try:
        info = getdbusinfo();
        artist = info[0];
        track = info[1];
    except:
        print("Could not get song info.");
        return None;

    try:
        track = track.split("(")[0];
        track = track.split("[")[0];
        track = ''.join([i for i in track if (i.isalnum())]).lower();
        artist = ''.join([i for i in artist if (i.isalnum())]).lower();
        newurl = "http://www.azlyrics.com/lyrics/" + artist + "/" + track + ".html";
        lyrics = getLyricsFromPage(newurl);
    except:
        print("Could not get Lyrics for {0} by {1}.".format(track, artist));
        return None;

    return lyrics;
#def getinfo(): #depricated
#    proc = subprocess.Popen(["wmctrl -lp | grep \"$(pgrep spotify)\""], stdout=subprocess.PIPE, shell=True)
#    (out, err) = proc.communicate()
#    out = out.decode('utf-8');
#    out = out.strip();
#    out = out.split(" ");
#    out = out[8:len(out)];
#    out = " ".join(out);
#    out = out.split(" - ", 1);
#    return out;
def getdbusinfo():
    bus        = dbus.SessionBus()
    dbusobject = bus.get_object('org.mpris.MediaPlayer2.spotify','/org/mpris/MediaPlayer2')
    promanager = dbus.Interface(dbusobject, 'org.freedesktop.DBus.Properties')
    metadata   = promanager.Get('org.mpris.MediaPlayer2.Player', 'Metadata')

    artist = metadata["xesam:title"];
    track = metadata["xesam:artist"][0];
    return [track, artist]
def getHTML(url):
    request = urllib.request.Request(url, headers={'User-Agent' : "Magic Browser"})
    html = urllib.request.urlopen(request).read();
    html = html.decode("utf-8");
    return html;
def getLyricsFromPage(url):
    html = getHTML(url);
    text = html.split("", 1)[1];
    text = text.split("", 1)[0];
    return text;

class Window(QtGui.QWidget):
    lbl_lyrics = None;
    lbl_title = None;
    lbl_artist = None;

    btn_exit = None;
    btn_maximize = None;

    gradtop = None;
    gradbot = None;

    scroll = None;
    repoint = None;
    timer = None;

    lastinfo = ["", ""];

    threadresult = None;

    def __init__(self):
        super(Window, self).__init__();
        #self.resizeEvent = onResize
        self.setStyleSheet("background-color: #0A050A;");
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint);
        self.spawn();
        self.resize(1000, 700);

        self.timer = QtCore.QTimer();
        self.timer.timeout.connect(self.tick)
        self.timer.start(500);

        self.setWindowOpacity(0.8);

        #self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True);
        #self.setAttribute(QtCore.Qt.WA_TranslucentBackground);

        self.show();

    def spawn(self):
        self.lbl_lyrics = QtGui.QLabel(self);
        self.lbl_lyrics.setFont(QtGui.QFont("Helvetica", 15));
        self.lbl_lyrics.setStyleSheet("color : #DDDDDD;");
        self.lbl_lyrics.setAlignment(QtCore.Qt.AlignCenter);

        self.lbl_title = QtGui.QLabel(self);
        self.lbl_title.setFont(QtGui.QFont("Helvetica", 30));
        self.lbl_title.setStyleSheet("color : #FF6633;");
        self.lbl_title.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom);

        self.lbl_artist = QtGui.QLabel(self);
        self.lbl_artist.setFont(QtGui.QFont("Helvetica", 12));
        self.lbl_artist.setStyleSheet("color : #AAAAAA;");
        self.lbl_artist.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter);

        self.gradtop = QtGui.QLabel(self);
        self.gradtop.setStyleSheet("background: qlineargradient(x1: 0, y1: 1, x2: 0, y2: 0, stop: 0 rgba(0, 0, 0, 0%), stop: 1.0 #0A050A);");
        self.gradtop.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents);
        self.gradtop.raise_();

        self.gradbot = QtGui.QLabel(self);
        self.gradbot.setStyleSheet("background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 rgba(0, 0, 0, 0%), stop: 1.0 #0A050A);");
        self.gradbot.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents);
        self.gradbot.raise_();

        self.scroll = QtGui.QScrollArea(self);
        self.scroll.setWidget(self.lbl_lyrics)
        self.scroll.setFrameShape(QtGui.QFrame.NoFrame);
        self.scroll.horizontalScrollBar().hide();
        self.scroll.verticalScrollBar().hide();
        #self.scroll.setBackgroundRole(QtGui.QPalette);
        self.scroll.setWidgetResizable(True)

        self.btn_exit = QtGui.QPushButton("X", self);
        self.btn_exit.clicked.connect(QtCore.QCoreApplication.instance().quit);
        self.btn_maximize = QtGui.QPushButton("□", self);
        self.btn_maximize.clicked.connect(self.dynamicFullScreen);

    def dynamicFullScreen(self):
        if self.isFullScreen():
            self.showNormal()
            self.btn_maximize.setText("□");
        else:
            self.showFullScreen()
            self.btn_maximize.setText("_");

    def mousePressEvent(self, mousePressEvent):
        self.repoint = mousePressEvent.pos();

    def mouseMoveEvent(self, mouseMoveEvent):
        self.move(self.mapToGlobal(mouseMoveEvent.pos() - self.repoint));

    def resizeEvent(self, resizeEvent):
        self.scroll.setGeometry(0, 100, self.width(), self.height() - 100)
        self.lbl_title.setGeometry(50, 0, self.width() - 100, 60)
        self.lbl_artist.setGeometry(50, 60, self.width() - 100, 40)

        self.gradtop.setGeometry(0, 100, self.width(), 100);
        self.gradbot.setGeometry(0, self.height() - 100, self.width(), 100);
        self.gradtop.raise_();
        self.gradbot.raise_();

        self.btn_exit.setGeometry(self.width() - 50, 0, 50, 50)
        self.btn_maximize.setGeometry(self.width() - 100, 0, 50, 50)

    def tick(self):
        info = getdbusinfo();
        if (info[0] != self.lastinfo[0]) or (info[1] != self.lastinfo[1]):
            self.startThread();
            self.lbl_title.setText(info[1]);
            self.lbl_artist.setText(info[0].upper())
            self.lbl_lyrics.setText("Loading...");

        self.lastinfo = info;

        if self.threadresult.ready():
            lyrics = self.threadresult.get(1);
            if lyrics == "" or lyrics is None:
                lyrics = "Could not get lyrics ;_;"
            else:
                lyrics = ".\n\n\n\n\n" + lyrics + "\n\n\n\n\n.";
                lyrics = lyrics.replace("
", "").replace("
", "");
            self.lbl_lyrics.setText(lyrics);

    def startThread(self):
        pool = ThreadPool(processes=1)
        self.threadresult = pool.apply_async(getlyrics)

main();


import contextlib
import platform
from copy import deepcopy
from pathlib import Path

import numpy as np
import pkg_resources as pkg
import torch
import math
import time

from matplotlib import pyplot as plt

from torch import nn

from utils import LOGGER

try:
    import thop  # for FLOPs computation
except ImportError:
    thop = None

class TryExcept(contextlib.ContextDecorator):
    # YOLOv5 TryExcept class. Usage: @TryExcept() decorator or 'with TryExcept():' context manager
    def __init__(self, msg=''):
        self.msg = msg

    def __enter__(self):
        pass

    def __exit__(self, exc_type, value, traceback):
        if value:
            print(emojis(f"{self.msg}{': ' if self.msg else ''}{value}"))
        return True

def colorstr(*input):
    # Colors a string https://en.wikipedia.org/wiki/ANSI_escape_code, i.e.  colorstr('blue', 'hello world')
    *args, string = input if len(input) > 1 else ('blue', 'bold', input[0])  # color arguments, string
    colors = {
        'black': '\033[30m',  # basic colors
        'red': '\033[31m',
        'green': '\033[32m',
        'yellow': '\033[33m',
        'blue': '\033[34m',
        'magenta': '\033[35m',
        'cyan': '\033[36m',
        'white': '\033[37m',
        'bright_black': '\033[90m',  # bright colors
        'bright_red': '\033[91m',
        'bright_green': '\033[92m',
        'bright_yellow': '\033[93m',
        'bright_blue': '\033[94m',
        'bright_magenta': '\033[95m',
        'bright_cyan': '\033[96m',
        'bright_white': '\033[97m',
        'end': '\033[0m',  # misc
        'bold': '\033[1m',
        'underline': '\033[4m'}
    return ''.join(colors[x] for x in args) + f'{string}' + colors['end']

def check_anchor_order(m):
    # Check anchor order against stride order for YOLOv5 Detect() module m, and correct if necessary
    a = m.anchors.prod(-1).mean(-1).view(-1)  # mean anchor area per output layer
    da = a[-1] - a[0]  # delta a
    ds = m.stride[-1] - m.stride[0]  # delta s
    if da and (da.sign() != ds.sign()):  # same order
        PREFIX = colorstr('AutoAnchor: ')
        LOGGER.info(f'{PREFIX}Reversing anchor order')
        m.anchors[:] = m.anchors.flip(0)

def make_divisible(x, divisor):
    # Returns nearest x divisible by divisor
    if isinstance(divisor, torch.Tensor):
        divisor = int(divisor.max())  # to int
    return math.ceil(x / divisor) * divisor

def time_sync():
    # PyTorch-accurate time
    if torch.cuda.is_available():
        torch.cuda.synchronize()
    return time.time()

def initialize_weights(model):
    for m in model.modules():
        t = type(m)
        if t is nn.Conv2d:
            pass  # nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
        elif t is nn.BatchNorm2d:
            m.eps = 1e-3
            m.momentum = 0.03
        elif t in [nn.Hardswish, nn.LeakyReLU, nn.ReLU, nn.ReLU6, nn.SiLU]:
            m.inplace = True

def fuse_conv_and_bn(conv, bn):
    # Fuse Conv2d() and BatchNorm2d() layers https://tehnokv.com/posts/fusing-batchnorm-and-conv/
    fusedconv = nn.Conv2d(conv.in_channels,
                          conv.out_channels,
                          kernel_size=conv.kernel_size,
                          stride=conv.stride,
                          padding=conv.padding,
                          dilation=conv.dilation,
                          groups=conv.groups,
                          bias=True).requires_grad_(False).to(conv.weight.device)

    # Prepare filters
    w_conv = conv.weight.clone().view(conv.out_channels, -1)
    w_bn = torch.diag(bn.weight.div(torch.sqrt(bn.eps + bn.running_var)))
    fusedconv.weight.copy_(torch.mm(w_bn, w_conv).view(fusedconv.weight.shape))

    # Prepare spatial bias
    b_conv = torch.zeros(conv.weight.size(0), device=conv.weight.device) if conv.bias is None else conv.bias
    b_bn = bn.bias - bn.weight.mul(bn.running_mean).div(torch.sqrt(bn.running_var + bn.eps))
    fusedconv.bias.copy_(torch.mm(w_bn, b_conv.reshape(-1, 1)).reshape(-1) + b_bn)

    return fusedconv

def model_info(model, verbose=False, imgsz=640):
    # Model information. img_size may be int or list, i.e. img_size=640 or img_size=[640, 320]
    n_p = sum(x.numel() for x in model.parameters())  # number parameters
    n_g = sum(x.numel() for x in model.parameters() if x.requires_grad)  # number gradients
    if verbose:
        print(f"{'layer':>5} {'name':>40} {'gradient':>9} {'parameters':>12} {'shape':>20} {'mu':>10} {'sigma':>10}")
        for i, (name, p) in enumerate(model.named_parameters()):
            name = name.replace('module_list.', '')
            print('%5g %40s %9s %12g %20s %10.3g %10.3g' %
                  (i, name, p.requires_grad, p.numel(), list(p.shape), p.mean(), p.std()))

    try:  # FLOPs
        p = next(model.parameters())
        stride = max(int(model.stride.max()), 32) if hasattr(model, 'stride') else 32  # max stride
        im = torch.empty((1, p.shape[1], stride, stride), device=p.device)  # input image in BCHW format
        flops = thop.profile(deepcopy(model), inputs=(im,), verbose=False)[0] / 1E9 * 2  # stride GFLOPs
        imgsz = imgsz if isinstance(imgsz, list) else [imgsz, imgsz]  # expand if int/float
        fs = f', {flops * imgsz[0] / stride * imgsz[1] / stride:.1f} GFLOPs'  # 640x640 GFLOPs
    except Exception:
        fs = ''

    name = Path(model.yaml_file).stem.replace('yolov5', 'YOLOv5') if hasattr(model, 'yaml_file') else 'Model'
    LOGGER.info(f'{name} summary: {len(list(model.modules()))} layers, {n_p} parameters, {n_g} gradients{fs}')

def feature_visualization(x, module_type, stage, n=32, save_dir=Path('runs/detect/exp')):
    """
    x:              Features to be visualized
    module_type:    Module type
    stage:          Module stage within model
    n:              Maximum number of feature maps to plot
    save_dir:       Directory to save results
    """
    if 'Detect' not in module_type:
        batch, channels, height, width = x.shape  # batch, channels, height, width
        if height > 1 and width > 1:
            f = save_dir / f"stage{stage}_{module_type.split('.')[-1]}_features.png"  # filename

            blocks = torch.chunk(x[0].cpu(), channels, dim=0)  # select batch index 0, block by channels
            n = min(n, channels)  # number of plots
            fig, ax = plt.subplots(math.ceil(n / 8), 8, tight_layout=True)  # 8 rows x n/8 cols
            ax = ax.ravel()
            plt.subplots_adjust(wspace=0.05, hspace=0.05)
            for i in range(n):
                ax[i].imshow(blocks[i].squeeze())  # cmap='gray'
                ax[i].axis('off')

            LOGGER.info(f'Saving {f}... ({n}/{channels})')
            plt.savefig(f, dpi=300, bbox_inches='tight')
            plt.close()
            np.save(str(f.with_suffix('.npy')), x[0].cpu().numpy())  # npy save

def emojis(str=''):
    # Return platform-dependent emoji-safe version of string
    return str.encode().decode('ascii', 'ignore') if platform.system() == 'Windows' else str

def check_version(current='0.0.0', minimum='0.0.0', name='version ', pinned=False, hard=False, verbose=False):
    # Check version vs. required version
    current, minimum = (pkg.parse_version(x) for x in (current, minimum))
    result = (current == minimum) if pinned else (current >= minimum)  # bool
    s = f'WARNING ⚠ {name}{minimum} is required by YOLOv5, but {name}{current} is currently installed'  # string
    if hard:
        assert result, emojis(s)  # assert min requirements met
    if verbose and not result:
        LOGGER.warning(s)
    return result


import argparse
import logging
from notifications_python_client.notifications import NotificationsAPIClient

logging.basicConfig(level=logging.INFO)

def parse_arguments():
    description = "Arguments to manage stale IAM users"
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument(
        "--account-id",
        help="The name of the relevant user account ID",
        dest="account_id",
        required=True,
    )
    parser.add_argument(
        "--api-key",
        help="The API Key needed to authenticate with Gov UK Notify",
        dest="api_key",
        required=True,
    )
    parser.add_argument(
        "--days-inactive",
        help="The number of days that the relevant account has been inactive",
        dest="days_inactive",
        required=True,
    )
    parser.add_argument(
        "--deletion-threshold",
        help="The threshold at which a user should be deleted",
        dest="deletion_threshold",
        required=True,
    )
    parser.add_argument(
        "--ignore-list",
        help="Comma separated containing IAM users to ignore/exclude when filtering through stale users",
        dest="ignore_list",
        default="",
        required=False,
    )
    parser.add_argument(
        "--template-id",
        help="The ID of the template to use in order to send emails via Gov UK Notify",
        dest="template_id",
        required=True,
    )
    parser.add_argument(
        "--username",
        help="The name of the relevant IAM user",
        dest="username",
        required=True,
    )
    parser.add_argument(
        "--warning-threshold",
        help="The threshold at which a user should be warned",
        dest="warning_threshold",
        required=True,
    )
    return parser.parse_args()

def get_args(args=parse_arguments()):
    account_id = args.account_id
    api_key = args.api_key
    days_inactive = args.days_inactive
    deletion_threshold = args.deletion_threshold
    ignore_list = args.ignore_list
    template_id = args.template_id
    username = args.username
    warning_threshold = args.warning_threshold
    return (
        account_id,
        api_key,
        days_inactive,
        deletion_threshold,
        ignore_list,
        template_id,
        username,
        warning_threshold,
    )

def check_if_user_in_ignore_list(iam_username, ignore_list):
    users_to_ignore = ignore_list.split(",")
    if users_to_ignore:
        for user_to_ignore in users_to_ignore:
            if user_to_ignore == iam_username:
                user_should_be_ignored = True
                return user_should_be_ignored

def check_if_user_breaches_threshold(iam_username, number_of_inactive_days, threshold):
    if number_of_inactive_days >= threshold:
        logging.info(
            f"{iam_username} has been inactive for {number_of_inactive_days} days"
        )
        action_to_be_taken = True
    else:
        logging.info(
            f"{iam_username} has been inactive for {number_of_inactive_days}, which is not in the {threshold} threshold"
        )
        action_to_be_taken = False
    return action_to_be_taken

def send_email_via_notify(
    api_key,
    aws_account,
    email_address,
    inactive_number_of_days,
    max_number_of_days,
    template_id,
):
    notifications_client = NotificationsAPIClient(api_key)
    notifications_client.send_email_notification(
        email_address=email_address,
        template_id=template_id,
        personalisation={
            "aws_account": aws_account,
            "iam_user": email_address,
            "inactive_number_of_days": inactive_number_of_days,
            "max_number_of_days": max_number_of_days,
        },
    )

def check_iam_user_has_email_address(iam_user):
    if "@" in iam_user:
        return True
    else:
        return False


import logging
import re

ATGC = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C'}
atgc = {'A': 1, 'T': 1, 'G': 0, 'C': 0}

def is_ambiguous(a1, a2):
    """if SNP is ambiguous or not"""
    if atgc[a1] == atgc[a2]:
        return True
    return False

def match_ref(a1, a2, ref, alt):
    """Match a1, a2 with ref and alt
    None: match, 1: swap, 2: flip, 3: flip&swap, 4: exclude
    """
    if a1 == ref and a2 == alt:
        return
    elif a1 == alt and a2 == ref:
        return 1
    else:
        ambiguous = is_ambiguous(a1, a2)
        if ambiguous:
            return 4
        else:
            a1_f, a2_f = [ATGC[i] for i in [a1, a2]]
            if a1_f == ref and a2_f == alt:
                return 2
            elif a1_f == alt and a2_f == ref:
                return 3
            else:
                return 4

def get_id(a1_a2, id_element, chr_, pos_, ref_, alt_):
    # first, try to use rs
    id_ = id_element.split(':')[0]
    if id_ in a1_a2:
        return id_
    # then, try chr:pos
    id_ = "{}:{}".format(chr_, pos_)
    if id_ in a1_a2:
        return id_
    # try chr:pos:ref:alt
    id_ = "{}:{}:{}:{}".format(chr_, pos_, ref_, alt_)
    if id_ in a1_a2:
        return id_
    # try chr:pos:alt:ref
    id_ = "{}:{}:{}:{}".format(chr_, pos_, alt_, ref_)
    if id_ in a1_a2:
        return id_
    return None

def pre_imputation_check(params, reference):
    """Given a plink bim file
    0. Remove SNPS with worldwide MAF < 0.02
    1. Remove SNPs can not be matched
    2. Flip SNPs that match after flip
    3. Swap SNPs that match after swap or flip&swap
    4. Update chromosomes and positions for these SNPs
    """
    prefix = params
    fn_new = prefix
    a1_a2 = {}
    for i in open(fn_new):
        items = i.split()
        # id: (ref, alt)
        # %CHROM:%POS:%REF:%FIRST_ALT
        a1_a2[items[1]] = (items[-2], items[-1])

    # files to update bim
    chr_path = prefix + '.chr'
    pos_path = prefix + '.pos'
    force_allele_path = prefix + '.force_allele'
    flip_path = prefix + '.flip'
    freq_path = prefix + '.freq'
    with open(chr_path, 'w') as chr_file, open(pos_path, 'w') as pos_file, open(force_allele_path, 'w') as force_allele_file, open(flip_path, 'w') as flip_file, open(freq_path, 'w') as freq_file:

        af_regex = re.compile(';AF=(0.\d+)')
        # write the files to be used
        in_ref = 0
        exclude = 0
        strand_flip = 0
        swap = 0
        flip_swap = 0
        unique_ids = set()
        for i in open(reference):
            items = i.split()
            str_maf = af_regex.findall(items[7])
            maf = float(str_maf[0]) if len(str_maf) > 0 else 0.0
            chr_, pos_, ref_, alt_ = items[0], items[1], items[3], items[4]
            # first, try to use rss
            id_ = get_id(a1_a2, items[2], chr_, pos_, ref_, alt_)

            if id_ is not None:
                a1, a2 = a1_a2[id_]
                matching = match_ref(a1, a2, ref_, alt_)
                in_ref += 1
                if matching == 4:
                    exclude += 1
                else:
                    if id_ in unique_ids:
                        continue
                    if maf > 0.02:
                        freq_file.write(id_ + "\n")
                    chr_file.write("{}\t{}\n".format(id_, chr_))
                    pos_file.write("{}\t{}\n".format(id_, pos_))
                    # set alt as A1, because recode vcf will code A1 as alt later
                    force_allele_file.write("{}\t{}\n".format(id_, alt_))
                    unique_ids.add(id_)
                    if matching == 2:
                        flip_file.write(id_ + "\n")
                        strand_flip += 1
                    elif matching == 1:
                        swap += 1
                    elif matching == 3:
                        flip_file.write(id_ + "\n")
                        flip_swap += 1

    logging.info("Exclude: {} Keep: {}".format(exclude, in_ref - exclude))
    logging.info("Total flip: {}.".format(strand_flip))
    logging.info("Total swap: {}.".format(swap))
    logging.info("Total flip&swap: {}.".format(flip_swap))
    return flip_path, force_allele_path, chr_path, pos_path

if __name__ == "__main__":
    logging.basicConfig(filename=snakemake.log[0], level=logging.DEBUG, format='%(levelname)s:%(asctime)s %(message)s')

    pre_imputation_check(snakemake.input[0], snakemake.params[0])


if __name__ != '__main__':
    exit()

from Rectangle import Rectangle
from Trapezoid import Trapezoid
from Simpson import Simpson
from prettytable import PrettyTable
from integral import interval, find_best, draw_function, stop_therads
from threading import Thread

acc = '{:.7f}'.format
threads = list()
try:
    while True:
        formula = input('Введите формулу: ')  #test: (3 * (x) + 4) / (2 * (x) + 7)
        if formula == 'exit':
            exit()
        a = float(input('Введите "a": '))
        b = float(input('Введите "b": '))
        n = int(input('Введите "n": '))

        h = (b - a) / n;
        print(f'Шаг "h": {h}')

        rct = Rectangle(formula)
        trp = Trapezoid(formula)
        sim = Simpson(formula)

        Names = ['Левые прям.', 'Правые прям.', 'Средние прям.', 'Трапезоид', 'Симпсон']

        Integrals = [
            rct.integral_left,
            rct.integral_right,
            rct.integral_middle,
            trp.get_integral_value,
            sim.get_integral_value
        ]

        Runge = [
            rct.runge_left,
            rct.runge_right,
            rct.runge_middle,
            trp.runge,
            sim.runge
        ]

        Methods = {
            'Левые прям.' : rct.integral_left,
            'Правые прям.' : rct.integral_right,
            'Средние прям.' : rct.integral_middle,
            'Трапезоид' : trp.get_integral_value,
            'Симпсон' : sim.get_integral_value
        }

        Errors = {
            'Левые прям.' : rct.runge_left,
            'Правые прям.' : rct.runge_right,
            'Средние прям.' : rct.runge_middle,
            'Трапезоид' : trp.runge,
            'Симпсон' : sim.runge
        }

        tbl = PrettyTable()
        tbl.add_column('', [f'Интегральное значение с шагом {h}', f'Интегральное значение с шагом {h/2}', 'Погрешность'])
        for name, val, err in zip(Names, Integrals, Runge):
            tbl.add_column(name, (acc(val(a, b, h)), acc(val(a, b, h / 2)), acc(err(a, b, h))))
        print(tbl)

        draw_function(rct._formula, a, b)

        print('Высчитывается лучшее "n" для всех методов. Это может занять некоторое время. Ждите...')

        Best_N = {
            'Левые прям.': find_best(rct, a, b, 'l'),
            'Правые прям.': find_best(rct, a, b, 'r'),
            'Средние прям.': find_best(rct, a, b, 'm'),
            'Трапезоид': find_best(trp, a, b),
            'Симпсон': find_best(sim, a, b),
        }

        for name, n in zip(Best_N.keys(), Best_N.values()):
            print(f'{name} лучшее "n": {n}')
            print(f'\tЗначение: {acc(Methods[name](a, b, (b - a) / n))}, погрешность: {acc(Errors[name](a, b, (b - a) / n))}')

except:
    print('Неизвестная ошибка!')


# Author :   Kql_unicorn
# Date   :   2023/8/6 22:27
"""
开辟单一共享内存空间
注意：共享内存只能有一个值
"""

from multiprocessing import Process, Value
import time
import random

# 创建共享内存
money = Value('i', 5000)

# 线程函数
def man():
    for i in range(30):
        time.sleep(0.2)
        money.value += random.randint(1, 1000)

#   线程函数
def girl():
    for i in range(30):
        time.sleep(0.15)
        money.value -= random.randint(100, 800)

if __name__ == '__main__':
    p1 = Process(target=man)
    p2 = Process(target=girl)
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print("一个月余额：", money.value)


from django.contrib import messages
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm

# Create your views/pages here. Business logic is here also.

def register(request):
    # https://docs.djangoproject.com/en/4.0/topics/forms/#the-view
    if request.method == 'POST':
        # create instance and populate it with data from the request
        form = UserRegisterForm(request.POST)

        if form.is_valid():
            # to save/create a new user in DB -> form.save()
            # https://docs.djangoproject.com/en/4.0/topics/forms/modelforms/#the-save-method
            form.save()
            messages.success(
                request, f'Your account has been created! Your are now able to log in')
            return redirect('login')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', {'form': form})

# require a user to be logged in before seeing this profile view
# decorator -> adds functionality to an existing function
# in this case, adds functionality to our profile view
# where the user must be logged in to view this page

@login_required
def profile(request):
    if request.method == 'POST':
        # leaving instances so Django would know which user and profile to update
        user_update_form = UserUpdateForm(request.POST, instance=request.user)
        # request.FILES
        #  -> additional data,
        #  -> file data coming in with the request,
        #  -> uploaded image from user.
        profile_update_form = ProfileUpdateForm(
            request.POST,
            request.FILES,
            instance=request.user.profile)
        # now we have both form populated with the data form the user,
        # check if the data is valid for both forms.
        #  if both are not valid , we dont send data
        #  just like in user registration form,
        #  but now we just have 2 form,
        #  but the process is almost identical
        # both must be valid
        if user_update_form.is_valid() and profile_update_form.is_valid():
            user_update_form.save()
            profile_update_form.save()
            messages.success(
                request, f'Your account has been updated!')
            # https://youtu.be/CQ90L5jfldw?list=PL-osiE80TeTtoQCKZ03TU5fNfx2UY6U4p&t=843 redirect
            return redirect('profile')

    else:
        user_update_form = UserUpdateForm(instance=request.user)
        profile_update_form = ProfileUpdateForm(instance=request.user.profile)

    context = {
        'user_update_form': user_update_form,
        'profile_update_form': profile_update_form
    }

    return render(request, 'users/profile.html', context)