from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score
from sklearn.metrics import accuracy_score
from sklearn.metrics import log_loss

import pandas as pd

import lightgbm as lgb
from datetime import datetime
import os

phase1 = '/home/malware/trace1_test/dex.txt'
phase2 = '/home/OpenCode/malware/phase2/trace1_test/dex.txt'
def line2data(line):
    return line.strip().split(';')

def readFile(filename):
    dataList = []
    shaList = []
    inf = open(filename)
    keys = line2data(inf.readline())
    for line in inf.readlines():
        vals = line2data(line)
        newData = {}
        for i in range(len(keys)):
            newData[keys[i]] = vals[i]
        dataList.append(newData)
        shaList.append(newData['sha1'])
    return dataList,shaList

def processDex(dataList):
    train = []
    for data in dataList:
        newData = {}
        permList = data['permission_list'].split(',')
        # newData['perms']  = len(permList)
        for key in data:
            if key not in ['sha1','permission_list','opcode_count']:
                newData[key] = int(data[key])
        train.append(newData)
    return train

def binLabel(typeList):
    result = []
    for data in typeList:
        result.append(int(data['safe_type']))
    return result

def multiLabel(typeList):
    result = []
    for data in typeList:
        result.append(int(data['family_id']))
    return result

def readDataFromDir(dirname,multi=False):
    dexFile = os.path.join(dirname,'dex.txt')
    typeFile = os.path.join(dirname,'safetype.txt')
    v = DictVectorizer()

    dataList,nameList = readFile(dexFile)
    trainList = processDex(dataList)
    x = v.fit_transform(trainList)

    typeList,_ = readFile(typeFile)
    if multi:
        y = multiLabel(typeList)
    else:
        y = binLabel(typeList)
    return x,y,nameList,trainList

def formatLabel(y_pred,multi=False):
    if multi:
        newLabel = []
        classLen = len(y_pred[0])
        for i in range(len(y_pred)):
            label = 0
            for j in range(classLen):
                if y_pred[i][j]>0.5:
                    label = j
            newLabel.append(label)
        y_pred = newLabel
    else:
        for i in range(len(y_pred)):
            if y_pred[i]>=.5:       # setting threshold to .5
                y_pred[i]=1
            else:
                y_pred[i]=0
    return y_pred

def checkModel(y_test,y_pred,multi=False):

    y_pred = formatLabel(y_pred)

    #calculating accuracy
    accuracy_lgbm = accuracy_score(y_pred,y_test)
    print(accuracy_lgbm)

    if not multi:
        auc_lgbm =  roc_auc_score(y_test,y_pred)
        print(auc_lgbm)

def checkMultiLabel():
    x,y,shaList,_ = readDataFromDir('/home/malware/trace1_train1',multi=True)

    x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=.1)
    train_data=lgb.Dataset(x_train,label=y_train)

    param = {'num_leaves':150, 'objective':'multiclass','max_depth':7,'learning_rate':.05,'max_bin':200,'num_class':6}
    param['metric'] = ['auc']

    #Here we have set max_depth in xgb and LightGBM to 7 to have a fair comparison between the two.

    #training our model using light gbm
    num_round=50
    start=datetime.now()
    lgbm=lgb.train(param,train_data,num_round)
    stop=datetime.now()

    #Execution time of the model
    execution_time_lgbm = stop-start
    print('train time:',execution_time_lgbm)

    #predicting on test set
    y_pred=lgbm.predict(x_test)
    checkModel(y_test,y_pred,multi=True)
    x1,y1,_,_ = readDataFromDir('/home/malware/trace1_train2')
    checkModel(y1,lgbm.predict(x1))

def makeModel(x_train,y_train,multi=False):
    train_data=lgb.Dataset(x_train,label=y_train)

    if multi:
        param = {'num_leaves':50, 'objective':'multiclass','max_depth':7,'learning_rate':.05,'max_bin':200,'num_class':6}
        param['metric'] = ['auc']
    else:
        param = {'num_leaves':50, 'objective':'binary','max_depth':7,'learning_rate':.05,'max_bin':200}
        param['metric'] = ['auc']

    num_round=1000
    lgbm=lgb.train(param,train_data,num_round)
    lgbm.save_model('model.txt', num_iteration=lgbm.best_iteration)

    return lgbm

def predictData(filename,multi=False,append=False):
    v = DictVectorizer()
    x1,y1,_,trainX1 = readDataFromDir('/home/malware/trace1_train1',multi=multi)
    x2,y2,_,trainX2 = readDataFromDir('/home/malware/trace1_train2',multi=multi)
    x3,y3,_,trainX3 = readResultLabel(multi)
    trainX = trainX1+trainX2
    if append:
        trainX = trainX+trainX3
    x =  v.fit_transform(trainX)

    if append:
        y = y1+y2+y3
    else:
        y = y1 + y2
    print(len(trainX),len(y))
    model = makeModel(x,y,multi=multi)
    dataList, nameList = readFile(filename)
    trainList = processDex(dataList)
    x_test = v.fit_transform(trainList)
    y_pred = model.predict(x_test)
    if multi:
        outf = open('data/trace1_lgbm_output.txt', 'w+')
        outf.write('sha1,0,1,2,3,4,5\n')
        for i in range(len(nameList)):
            result = y_pred[i]
            outf.write(
                '%s,%f,%f,%f,%f,%f,%f\n' % (nameList[i], result[0], result[1], result[2], result[3], result[4], result[5]))
    return nameList,formatLabel(y_pred,multi=multi)

def solutionPhase1():
    nameList,y1 = predictData(phase2)
    _,y2 = predictData(phase2,multi=True)
    with open('/home/malware/phase1_trace1.csv','w+') as outf:
        for i in range(len(nameList)):
            outf.write(nameList[i]+','+str(int(y1[i]))+','+str(y2[i])+'\n')

def solutionPhase2():
    nameList,y1 = predictData(phase2,multi=False,append=False)
    _,y2 = predictData(phase2,multi=True,append=False)
    with open('/home/malware/trace1_test/trace1.csv','w+') as outf:
        for i in range(len(nameList)):
            outf.write(nameList[i]+','+str(int(y1[i]))+','+str(y2[i])+'\n')

def readResultLabel(multi):
    df2 = pd.read_csv('/home/malware/phase1_trace1.csv',header=None)
    df2.columns = ['sha1','safe_type','family_id']

    v = DictVectorizer()
    dataList, nameList = readFile(phase1)
    trainList = processDex(dataList)
    x = v.fit_transform(trainList)

    if multi:
        y = list(df2.family_id)
    else:
        y = list(df2.safe_type)
    return x, y, nameList, trainList

if __name__=='__main__':
    # solutionPhase1()
    solutionPhase2()


# -*- coding: UTF-8 -*-
import numpy as np

class DPC(object):

  def __init__(self, dist_array):
    """
    :param dist_array: pre-calculated pairwise distance array
    """
    super(DPC, self).__init__()
    assert len(dist_array.shape) == 2
    assert dist_array.shape[0] == dist_array.shape[1]
    self.dist_array = dist_array.astype(float)
    self.max_dist = dist_array.max()
    self.min_dist = dist_array.min()
    self.n = dist_array.shape[0]

    self.rho = None
    self.delta = None
    self.father = None
    self.label = None

  def cal_decision_map(self):
    # step 1: cal cut distance
    max_dist, min_dist = self.max_dist, self.min_dist
    cut_dist = (max_dist + min_dist) / 2
    delta_dist = max_dist - min_dist
    while True:
      p = (self.dist_array < cut_dist).sum() / float(self.n ** 2)
      # criteria according to paper
      if 0.01 <= p <= 0.02:
        break
      # bin search
      if p < 0.01:
        min_dist = cut_dist
      else:
        max_dist = cut_dist
      cut_dist = (max_dist + min_dist) / 2
      # handle extreme cases
      if max_dist - min_dist < 1e-5 * delta_dist:
        break
    self.cut_dist = cut_dist

    # step 2: cal rho
    self.rho = (self.dist_array < self.cut_dist).sum(axis=1)

    # step 3: cal delta & father
    rho_idx = np.argsort(-self.rho)
    father = list(range(len(self.rho)))
    delta = np.ones(len(self.rho)) * (self.max_dist + 1)
    for i in range(1, self.n):
      for j in range(0, i):
        ori_i, ori_j = rho_idx[i], rho_idx[j]
        if self.dist_array[ori_i, ori_j] < delta[ori_i]:
          delta[ori_i] = self.dist_array[ori_i, ori_j]
          father[ori_i] = ori_j
    self.delta = delta
    self.father = father

    print('delta-rho map calculated')

  def do_cluster(self, n_center):
    assert n_center < self.n
    self.label = [x for x in self.father]

    # select center according to gamma
    gamma = self.rho * self.delta
    gamma_idx = np.argsort(-gamma)[:n_center]
    for center in gamma_idx:
      self.label[center] = center

    # union find class center for each point
    for i in range(self.n):
      if self.label[i] == i:
        continue
      passed_by = []
      label_i = i
      while label_i != self.label[label_i]:
        passed_by.append(label_i)
        label_i = self.label[label_i]
      for j in passed_by:
        self.label[j] = label_i

    print('clustering done')


from collections import deque
class Solution:
  def left(self,arr,n):
    # search for the nearest smaller height on left side ..
    result = [-1]*n
    stack = deque()
    stack.append(0)
    for i in range(1,n):
      currH = arr[i]
      if stack and arr[stack[-1]]<currH:
        result[i] = stack[-1]
      else:
        while stack and arr[stack[-1]]>=currH:
          stack.pop()
        if stack:
          result[i] = stack[-1]
      stack.append(i)
    return result

  def right(self,arr,n):
    # search for the nearest smaller on the right side..to get width..
    stack = deque()
    stack.append(n-1)
    result=[n]*n
    for i in range(n-2,-1,-1):
      currH = arr[i]
      if stack and arr[stack[-1]]<currH:
        result[i] = stack[-1]
      else:
        while stack and arr[stack[-1]]>=currH:
          stack.pop()

        if stack:
          result[i] = stack[-1]
      stack.append(i)
    return result

  def getMaxArea(self,arr,n):
    left = self.left(arr,n)
    right = self.right(arr,n)
    maxArea = 0
    for i in range(n):
      currArea = ((right[i]-left[i])-1)*(arr[i])
      maxArea = max(maxArea,currArea)
    return maxArea

  def maximalRectangle(self,matrix):
    n = len(matrix)
    m = len(matrix[0])
    maxArea = 0
    height=[0]*m
    for i in range(n):

      for j in range(m):
        if matrix[i][j] == "0":
          height[j] = 0
        else:
          height[j]+= int(matrix[i][j])
      maxArea = max(maxArea, self.getMaxArea(height,m))
    return maxArea

arr = [[0,1],[1,0]]
n = len(arr)
m = len(arr[0])
res = Solution().maximalRectangle(arr)
print(res)


import logging
import os
import random
import re
from collections import defaultdict
from statistics import mean

import torch
import torchvision.transforms.functional as TF
from torch.utils.data import RandomSampler, SequentialSampler
from torchvision.utils import draw_bounding_boxes

from dataset.utils import WordVocab, ProgramVocab
from utils import join, mkdir, underscores, camel_case, num2word
from utils import to_cpu_detach, nonzero

class Dataset(torch.utils.data.Dataset):
    DATASET_REGISTRY = {}
    image_size = (224, 224)
    split2spec = {"train": 0, "val": 1, "test": 2}
    period_map = {"train": 1, "val": 1, "test": 1}
    concept_maps_ = {}
    max_question_length = 50

    @property
    def is_builder(self):
        return 'Builder' in self.__class__.__name__

    @property
    def is_support(self):
        return 'Support' in self.__class__.__name__

    @property
    def is_debias(self):
        return 'Debias' in self.__class__.__name__

    @staticmethod
    def get_name(name):
        return underscores(name[:-len("Dataset")])

    def get_augmented_name(self, name):
        name = underscores(name[:-len("Dataset")])
        if self.shot_k > 1: name = name.replace('few', num2word(self.shot_k))
        return name

    @property
    def base_dataset(self):
        return underscores(self.__class__.__name__).split('_')[0]

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        name = Dataset.get_name(cls.__name__)
        cls.DATASET_REGISTRY[name] = cls
        cls.name = name

    def __str__(self):
        return f"{self.name}_{self.split}"

    @property
    def kinds(self):
        return torch.arange(len(self.kinds_))

    @property
    def tag(self):
        if self.split in ["train", "val"]:
            return self.split
        else:
            return f"{self}"

    @property
    def sampler(self):
        if self.split in ["train", "val"]:
            sampler = RandomSampler(self)
        else:
            sampler = SequentialSampler(self)
        return sampler

    def get_batch_sampler(self, batch_size):
        return None

    def select_split(self, split_spec):
        if self.split == "all":
            return list(range(len(split_spec)))
        else:
            return nonzero(split_spec == self.split2spec[self.split])

    @property
    def principal_metric(self):
        return "accuracy"

    def __init__(self, cfg, args):
        self.root = cfg.ROOT
        self.has_mask = cfg.HAS_MASK
        self.shot_k = cfg.SHOT_K
        self.query_k = cfg.QUERY_K
        self.dropout_rate = cfg.DROPOUT_RATE
        self.use_text = cfg.USE_TEXT
        self.opts = cfg.OPTS

        self.args = args
        self.split = cfg.SPLIT
        self.split_ratio = cfg.SPLIT_RATIO
        self.indices_split = []
        self.split_specs = torch.LongTensor([])
        self.kinds_ = []
        self.concepts_ = []
        self.concepts = []
        self.concept2kinds = torch.LongTensor([])
        self.named_entries_ = []
        self.names = []
        self.synonyms = {}
        self.entry2kinds = torch.LongTensor([])
        self.entry2idx_ = {}

        self.image_split_specs = torch.LongTensor([])
        self.concept_split_specs = torch.LongTensor([])
        self.itself2samekinds = {}

        self.transform = self.transform_fn(self.image_size)
        self.word_vocab = None
        self.program_vocab = None
        self.split_seed = cfg.SPLIT_SEED
        self.iteration = 0
        self.mode = "default"

    @property
    def augmented_root(self):
        root_head, root_tail = os.path.split(self.root)
        assert os.access(root_head, os.W_OK)
        return mkdir(join(root_head, '.augmented', root_tail, str(self.split_seed)))

    @property
    def is_alt(self):
        return 'alt' in self.opts

    @property
    def is_shallow(self):
        return 'shallow' in self.opts

    def log_info(self):
        logger = logging.getLogger("falcon_logger")
        logger.warning(f"{self} dataset uses {len(self.indices_split)} out of "
                       f"{len(self.split_specs)} samples.")
        logger.info(f"{self} has {len(self.kinds)} kinds.")
        logger.info(f"{self} has a word vocabulary size of {len(self.word_vocab)}.")
        if self.program_vocab is not None:
            logger.info(f"{self} has a program vocabulary size of {len(self.program_vocab)}.")

    @property
    def info(self):
        return {"concept_entries": len(self.named_entries_), "kind_entries": len(self.kinds_),
            "split": self.split, 'use_text': self.use_text}

    @property
    def empty_image(self):
        return torch.zeros((6 if self.has_mask else 3, *self.image_size))

    @property
    def transform_fn(self):
        raise NotImplementedError

    def get_stacked_scenes(self, image_index):
        raise NotImplementedError

    def get_image(self, image_index):
        raise NotImplementedError

    def get_mask(self, image_index):
        raise NotImplementedError

    def get_annotated_image(self, image_index, mask_index=None):
        masks, image = self.transform(self.get_mask(image_index), self.get_image(image_index))
        if mask_index is not None:
            masks = masks[mask_index:mask_index + 1]
        y_sum = masks.sum(-2).bool()
        y_min_value, y_min = y_sum.max(-1)
        y_max = y_sum.shape[-1] - 1 - y_sum.flip(-1).max(-1).indices
        x_sum = masks.sum(-1).bool()
        x_min_value, x_min = x_sum.max(-1)
        x_max = x_sum.shape[-1] - 1 - x_sum.flip(-1).max(-1).indices
        bboxes = torch.stack([y_min, x_min, y_max, x_max], -1)
        bboxes = bboxes[y_min_value & x_min_value]
        annotated_image = draw_bounding_boxes((image * 255).to(torch.uint8), bboxes, width=1) / 255
        return TF.resize(annotated_image, self.image_size)

    def __len__(self):
        return len(self.indices_split)

    def init_evaluate(self, mode):
        if mode is None: mode = self.mode
        return defaultdict(list, mode=mode)

    def batch_evaluate(self, inputs, outputs, evaluated):
        inputs = to_cpu_detach(inputs)
        outputs = to_cpu_detach(outputs)
        handler = getattr(self, f"batch_{evaluated['mode']}_handler", self.batch_default_handler)
        for k, v in handler(inputs, outputs).items():
            evaluated[k].extend(v)

    def evaluate_metric(self, evaluated):
        handler = getattr(self, f"metric_{evaluated['mode']}_handler", self.metric_default_handler)
        metrics = handler(evaluated)
        if self.principal_metric in metrics: metrics['principal'] = metrics[self.principal_metric]
        return  metrics

    def save(self, output_dir, evaluated, checkpointer, metrics):
        output_dir = mkdir(join(output_dir, "inference", str(self)))
        handler = getattr(self, f"save_{evaluated['mode']}_handler", self.save_default_handler)
        handler(output_dir, evaluated, checkpointer, metrics)

    def batch_default_handler(self, inputs, outputs):
        return {}

    def metric_default_handler(self, evaluated):
        return {}

    def save_default_handler(self, output_dir, evaluated, iteration, metrics):
        pass

    def callback(self, iteration):
        pass

    def _build_word_tokens(self):
        raise NotImplementedError

    def _build_word_vocab(self):
        word_tokens = self._build_word_tokens()
        vocab = WordVocab()
        vocab.words.update(word_tokens)
        vocab.freeze()
        return vocab

    def _build_program_tokens(self):
        raise NotImplementedError

    def _build_program_vocab(self):
        program_tokens = self._build_program_tokens()
        vocab = ProgramVocab()
        vocab.words.update(program_tokens)
        vocab.freeze()
        return vocab

    @staticmethod
    def answer2text(target):
        assert target is not None
        if isinstance(target, bool):
            return "Yes" if target else "No"
        else:
            return str(target)

    def answer2category(self, target):
        if self.use_text:
            return "token"
        elif isinstance(target, str):
            return "choice"
        elif isinstance(target, bool):
            return "boolean"
        else:
            return "count"

    @staticmethod
    def answer2target(answer):
        return torch.tensor(answer).float()

    @staticmethod
    def clevr2nscl(clevr_program):
        nscl_program = list()
        mapping = dict()

        for block_id, block in enumerate(clevr_program):
            op = block['type'] if 'type' in block else block['function']
            current = None
            if op == 'scene':
                current = dict(op='scene')
            elif op.startswith('filter'):
                concept = block['value_inputs'][0]
                last = nscl_program[mapping[block['inputs'][0]]]
                if last['op'] == 'filter':
                    last['concept'].append(concept)
                else:
                    current = dict(op='filter', concept=[concept])
            elif op.startswith('relate'):
                concept = block['value_inputs'][0]
                current = dict(op='relate', relational_concept=[concept])
            elif op.startswith('same'):
                current = dict(op='relate_attribute_equal', attribute=(op.split('_')[1]))
            elif op in ('intersect', 'union'):
                current = dict(op=op)
            elif op == 'unique':
                pass  # We will ignore the unique operations.
            else:
                if op.startswith('query'):
                    if block_id == len(clevr_program) - 1:
                        current = dict(op='query', attribute=(op.split('_')[1]))
                elif op.startswith('equal') and op != 'equal_integer':
                    current = dict(op='query_attribute_equal', attribute=(op.split('_')[1]))
                elif op == 'exist':
                    current = dict(op='exist')
                elif op == 'count':
                    if block_id == len(clevr_program) - 1:
                        current = dict(op='count')
                elif op == 'equal_integer':
                    current = dict(op='count_equal')
                elif op == 'less_than':
                    current = dict(op='count_less')
                elif op == 'greater_than':
                    current = dict(op='count_greater')
                else:
                    raise ValueError('Unknown CLEVR operation: {}.'.format(op))

            if current is None:
                assert len(block['inputs']) == 1
                mapping[block_id] = mapping[block['inputs'][0]]
            else:
                current['inputs'] = list(map(mapping.get, block['inputs']))
                nscl_program.append(current)
                mapping[block_id] = len(nscl_program) - 1

        return nscl_program

    def nscl2program(self, nscl_program):
        programs = []
        for np in nscl_program:
            op = np["op"]
            if op == "filter":
                p = programs[np["inputs"][0]]
                for c in np['concept']:
                    p = ('Filter', p, [self.entry2idx_[c]])
            elif op == "query":
                p = ('Query', ('Unique', programs[np["inputs"][0]]),
                [[self.entry2idx_[_] for _ in self.concept_maps_[np["attribute"]]]])
            else:
                p = [camel_case(op)]
                for i in np['inputs']:
                    if 'relational_concept' in np or 'attribute' in np:
                        p.append(('Unique', programs[i]))
                    else:
                        p.append((programs[i]))
                if 'relational_concept' in np:
                    p.append([self.entry2idx_[np['relational_concept'][0]]])
                if 'attribute' in np:
                    p.append([self.entry2idx_[np['attribute']]])
                p = tuple(p)
            programs.append(p)
        return programs[-1]

    def metaconcept_text(self, supports, relations, concept_index):
        raise NotImplementedError

    def encode_text(self, question):
        encoded = self.word_vocab(question)
        length = len(encoded)
        assert length < self.max_question_length
        encoded.extend([self.word_vocab.pad] * (self.max_question_length - length))
        return encoded, length

    def encode_unknown(self, text, concept_id):
        for word in self.synonyms.get(self.names[concept_id], [self.names[concept_id]]):
            text = re.subn(f"(?<!\w){word}s?(\\b)", "unk\\1", text)[0]
        encoded = self.word_vocab(text)
        length = len(encoded)
        assert length < self.max_question_length
        encoded.extend([self.word_vocab.pad] * (self.max_question_length - length))
        return encoded, length

class BuilderDataset(Dataset):
    MAC_ROOT = "/data/vision/billf/scratch/jerrymei/BoxEmbedding/vendor/mac-network-original"
    texts = ["statement"]
    num_inputs = {}
    num_value_inputs = {}
    max_program_length = 50
    max_samekinds = 8
    metaconcepts_ = ['hypernym', 'hyponym', 'samekind']

    @property
    def info(self):
        return {**super(BuilderDataset, self).info, 'word_entries': len(self.word_vocab),
            'program_entries': len(self.program_vocab), 'start_id': self.program_vocab.start,
            'end_id': self.program_vocab.end, 'max_length': self.max_program_length}

    @property
    def principal_metric(self):
        return 'accuracy'

    def __init__(self, cfg, args):
        super().__init__(cfg, args)
        self.questions = []
        self.program_vocab = None
        self.mode = "build" if self.split != 'all' else 'inference'

    def _build_program_tokens(self):
        raise NotImplementedError

    def encode_program(self, program):
        encoded = [[self.program_vocab.start, self.program_vocab.start]]

        def _build_subtree(node):
            t = node['type']
            arg = self.program_vocab.unk if self.num_value_inputs[t] == 0 else self.program_vocab[
                node['value_inputs'][0]]
            entry = [self.program_vocab[t], arg]

            encoded.append(entry)
            for i in node['inputs']:
                _build_subtree(program[i])

        _build_subtree(program[-1])
        encoded.append([self.program_vocab.end, self.program_vocab.end])
        length = len(encoded)

        encoded.extend([[self.program_vocab.pad, self.program_vocab.pad]] * (self.max_program_length - length))
        assert length < self.max_program_length
        return encoded, length

    def encode_metaconcept(self, program):
        encoded = [[self.program_vocab.start, self.program_vocab.start]]
        for p in program:
            encoded.append([self.program_vocab[p['type']], self.program_vocab[p['value_inputs'][0]]])
        encoded.append([self.program_vocab.end, self.program_vocab.end])
        length = len(encoded)

        assert length < self.max_program_length
        encoded.extend([[self.program_vocab.pad, self.program_vocab.pad]] * (self.max_program_length - length))
        return encoded, length

    def decode_program(self, predicted):
        def canonical(operation):
            return operation.replace('_material', '').replace('_size', '').replace('_color', '').replace(
                '_shape', '')

        es = nonzero(predicted[..., 0] == self.program_vocab.end)
        end_index = es[0] if len(es) > 0 else predicted.shape[0]
        program_encoded = predicted[1:end_index].tolist()
        family = tuple(canonical(self.program_vocab.index2word[t]) for t, a in program_encoded)
        program = []

        def expand_node():
            if len(program_encoded) == 0:
                program.append({'type': 'scene', 'value_inputs': [], 'inputs': []})
                return len(program) - 1
            t, a = [self.program_vocab.index2word[_] for _ in program_encoded.pop(0)]
            value_inputs = [a] if a in self.named_entries_ else [] if self.num_value_inputs[t] == 0 else [
                random.choice(self.named_entries_)]
            p = {'type': t, 'value_inputs': value_inputs}
            ii = [expand_node() for _ in range(self.num_inputs[t])]
            p['inputs'] = ii
            program.append(p)
            return len(program) - 1

        expand_node()
        return program, family

    def decode_metaconcept(self, predicted):
        end_index = nonzero(predicted[..., 0] == self.program_vocab.end)[0]
        program_encoded = predicted[1:end_index].tolist()
        family = tuple(self.program_vocab.index2word[t] for t, a in program_encoded)
        program = [
            {'type': self.program_vocab.index2word[t], 'value_inputs': [self.program_vocab.index2word[a]],
                'inputs': []} for t, a in program_encoded if a not in self.program_vocab.special_tokens]
        return program, family

    def encode(self, text, program, name):
        encoded, length = self.encode_text(text)
        target, _ = self.encode_program(program) if name != 'metaconcept' else self.encode_metaconcept(program)
        return {f'{name}_encoded': encoded, f'{name}_length': length, f'{name}_target': target, f'{name}': text,
            f"{name}_program": program}

    def batch_build_handler(self, inputs, outputs):
        accuracies = {}
        for t in ["statement", "metaconcept", "question"]:
            # noinspection PyTypeChecker
            accuracies[f"{t}_accuracy"] = torch.all(
                torch.all(inputs[f"{t}_target"] == outputs[f"{t}_predicted"], -1), -1).tolist()
        return accuracies

    def metric_build_handler(self, evaluated):
        metrics = {}
        for k, v in evaluated.items():
            if k != "mode":
                metrics[k] = torch.tensor(v).float().mean().item()
        metrics['accuracy'] = mean(metrics.values())
        return metrics

    def exist_question_program(self, candidate):
        return [{'type': 'scene', 'inputs': [], 'value_inputs': []},
            {'type': 'filter', 'inputs': [0], 'value_inputs': [self.named_entries_[candidate]]},
            {'type': 'exist', 'inputs': [1], 'value_inputs': []}]

    def exist_statement_program(self, candidate):
        return [{'type': 'scene', 'inputs': [], 'value_inputs': []}]

    def __getitem__(self, index):
        question_index = self.indices_split[index]
        question = {k: torch.tensor(v) if re.search('encoded|target', k) else v for k, v in
            self.questions[question_index].items()}
        return {**question, 'question_index': question_index, 'index': index, 'info': self.info}

    def filter_question_program(self, candidate, filters):
        return [{'type': 'scene', 'inputs': [], 'value_inputs': []},
            *({'type': 'filter', 'inputs': [i], 'value_inputs': [self.named_entries_[f]]} for i, f in
                enumerate(filters)),
            {'type': 'filter', 'inputs': [len(filters)], 'value_inputs': [self.named_entries_[candidate]]},
            {'type': 'exist', 'inputs': [len(filters) + 1], 'value_inputs': []}]

    def filter_statement_program(self, candidate, filters):
        return [{'type': 'scene', 'inputs': [], 'value_inputs': []},
            *({'type': 'filter', 'inputs': [i], 'value_inputs': [self.named_entries_[f]]} for i, f in
                enumerate(filters))]


import numpy as np
#
from nn import NN

#
#
# def test_calc_next_state_expected_value():
#     output = calc_state_prime_value([1, 2, 3, 4])
#     # if output != 4 * (1 - epsilon) + 1 * epsilon/3 + 2 * epsilon/3 + 3 * epsilon/3:
#     #     raise ValueError("expected next state value is wrong")
#
#
def run_tests():
    test_feed_forward()
    test_calc_output_grad()

def test_feed_forward():
    config = {
        "learning rate": .0001,
        "debug": False,
        "layer node count": [2, 2, 2],
        "first moment decay rate": .9,
        "second moment decay rate": .999,
        "experience replay size": 8,
        "replay batches": 4,
        "model size": 50000,
        "report frequency": 10,
        "number episodes": 300000000,
        "initial temp": 1,
        "adam epsilon": 10 ** -8
    }
    num_inputs = config["layer node count"][0]
    num_hidden = config["layer node count"][1]
    num_output = config["layer node count"][2]
    config["weights"] = [np.ones((num_inputs, num_hidden)), np.ones((num_hidden, num_output)) * 2]
    config["bias"] = [np.ones((num_hidden)), np.ones((num_output)) * 2]

    nn = NN(config)

    state = np.ones(num_inputs) * 1
    state2 = np.ones(num_inputs) * 2
    state3 = np.ones(num_inputs) * 3
    states = np.row_stack((state, state2, state3))
    zs, activations = nn.feed_forward(states)
    for i in range(3):
        if not np.allclose(activations[-2][i], num_inputs * (i + 1) + 1):
            raise ValueError("hidden outputs are off")
    for j in range(3):
        if not np.allclose(activations[-1][j], ((num_inputs * (j + 1) + 1) * num_hidden * 2) + 2):
            raise ValueError("hidden outputs are off")

    # Test RELU

    state = np.ones(num_inputs) * -2
    states = state.reshape((1, 2))
    zs, activations = nn.feed_forward(states)
    if not np.allclose(activations[-2][:], 0):
        raise ValueError("hidden outputs are off")

    if not np.allclose(activations[-1][:], 2):  # only bias..
        raise ValueError("hidden outputs are off")

def test_calc_output_grad():
    config = {
        "learning rate": .0001,
        "debug": False,
        "layer node count": [2, 2, 2],
        "first moment decay rate": .9,
        "second moment decay rate": .999,
        "experience replay size": 8,
        "replay batches": 4,
        "model size": 50000,
        "report frequency": 10,
        "number episodes": 300000000,
        "initial temp": 1,
        "adam epsilon": 10 ** -8
    }

    num_inputs = config["layer node count"][0]
    num_hidden = config["layer node count"][1]
    num_output = config["layer node count"][2]
    config["weights"] = [np.ones((num_inputs, num_hidden)), np.ones((num_hidden, num_output))]
    config["bias"] = [np.ones((num_hidden)), np.ones((num_output))]
    states = []
    action_indices = []
    targets = []
    finals = []
    for i in range(2):
        state = np.array([i, i])
        action_index = i
        target = i
        states.append(state)
        action_indices.append(action_index)
        targets.append(target)
        finals.append(i == 1)

    nn = NN(config)
    bg, wg = nn.calc_gradients(states, action_indices, states, np.ones(2), finals, 1, 1)
    test_weight_g = [np.array([[3., 3.],
                                          [3., 3.]]), np.array([[-.5, 9.],
                                                                [-.5, 9.]])]
    test_bias_g = [np.array([[2.5, 2.5]]), np.array([[-.5, 3.]])]

    for i in range(2):
        if not np.allclose(wg[i], test_weight_g[i]):
            raise ValueError("Error in calc weight grad")

        if not np.allclose(bg[i], test_bias_g[i]):
            raise ValueError("Error in calc weight grad")
#     error1 = nn.last_output[0] - 0
#     output_weights_gradient = nn.last_hidden_output * error1
#     output_bias_gradient = error1
#     result = error1, output_bias_gradient, output_weights_gradient
#     error, out_bias_gradient, out_weights_gradient = result
#     if not np.allclose(2, out_weights_gradient):
#         raise ValueError("out weight gradient is off")
#
#     if not np.allclose(2, out_bias_gradient):
#         raise ValueError("out bias gradient is off")
#
#
# def test_calc_hidden_grad():
#     test_num_input = 1
#     test_num_hidden = 2
#     test_num_output = 1
#
#     test_hidden_weights = np.ones((test_num_output, test_num_hidden))
#     test_out_weights = np.ones((test_num_hidden, test_num_output))
#     test_hidden_bias = np.zeros(test_num_hidden)
#     test_out_bias = np.zeros(test_num_output)
#     nn = NN(test_num_input, test_num_hidden, test_num_output, test_hidden_weights, test_hidden_bias, test_out_weights, test_out_bias)
#     nn.feed_forward([1])
#     hidden_error, hidden_weights_gradient, hidden_bias_gradient = nn.calc_hidden_nodes_gradient(2,0)
#     if not np.allclose(2, hidden_weights_gradient):
#         raise ValueError("hidden weight gradient is off")
#
#     if not np.allclose(2, hidden_bias_gradient):
#         raise ValueError("hidden bias gradient is off")


class Solution(object):
    def removeElement(nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        lastpos = len(nums)-1
        pos = 0
        valcount = 0
        while (pos <=  lastpos):
            if(nums[pos] == val):
                valcount += 1
                nums[pos] = nums[lastpos]
                lastpos -= 1
            else:
                pos += 1
        if(valcount > 0):
            del nums[-valcount:]
        print(nums)
        print(valcount)

    nums = [2,1,9,13,27,1,7,9,6]
    val = 9
    removeElement(nums,val)


#coding=utf-8
import jieba,re,os,io
from gensim.models import word2vec
import logging
#jieba.load_userdict("data\\userdict.txt")

# logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO,filename='test_01.log')
#测试原数据
filename = 'test_01.txt'
pre,ext = os.path.splitext(filename)   #输入文件分开前缀，后缀   pre=test_01   ext=.txt
corpus = pre + '_seg' + ext    #训练语料为按行分词后的文本文件    corpus=test_01_seg.txt
fin = io.open(filename,encoding='utf8').read().strip(' ').strip('\n').replace('\n\n','\n')   #strip()取出首位空格，和换行符，用\n替换\n\n
stopwords = set(io.open('stop_list.txt',encoding='utf8').read().strip('\n').split('\n'))   #读入停用词

# 第二：分词，将训练文本中的词做处理，不能包含停用词中的词，以及长度少于等于1的词，去标点，
#去掉停用词中的词，去掉长度小于等于1的词
text = ' '.join([x for x in jieba.lcut(fin) if x not in stopwords and len(x)>1 and x != '\n'])
print(text)
#去标点，将【】里面的标点全部替换为‘，’
# results = re.sub('[（）：:？“”《》，。！·、\d ]+',' ',text)
#按行分词后存为训练语料
io.open(corpus,'w+',encoding='utf8').write(text)

#3.训练模型
# 加载语料,LineSentence用于处理分行分词语料
sentences = word2vec.LineSentence(corpus)
#用来处理按文本分词语料
#sentences1 = word2vec.Text8Corpus(corpus)
# print('=--=-=-=-=-=',sentences)
# 训练skip-gram模型; 第一个参数是训练预料，min_count是小于该数的单词会被踢出，默认值为5，
# size是神经网络的隐藏层单元数，在保存的model.txt中会显示size维的向量值。默认是100。默认window=5
#训练模型就这一句话  去掉出现频率小于2的词
model = word2vec.Word2Vec(sentences, size=12,window=25,min_count=2,workers=5,sg=1,hs=1)

# 4保存模型，以便重用
# model.save("test_01.model")
# 将模型保存成文本，model.wv.save_word2vec_format()来进行模型的保存的话，会生成一个模型文件。里边存放着模型中所有词的词向量。这个文件中有多少行模型中就有多少个词向量。
# model.wv.save_word2vec_format('test_01.model.txt','test_01.vocab.txt',binary=False)
#5词向量验证
#加载训练好的模型
model = word2vec.Word2Vec.load("test_01.model")  #加载训练好的语料模型
#计算两个句子间的相似度
list1 = ['孙悟空']
list2 = ['唐僧', '西天', '取经']
print(model.most_similar(list1))

# 计算两个词的相似度/相关程度
# role1 = ['大圣','悟空','齐天大圣','师兄','老孙','行者','孙行者','孙悟空']
# role2 = ['天蓬','猪悟能','老猪','八戒','猪八戒','呆子']
# role1 = ['天地','万物','一元']
# role2 = ['天地','百岁']
# pairs = [(x,y) for x in role1 for y in role2]
# print(pairs)  #[('天地', '天地'), ('天地', '百岁'), ('万物', '天地'), ('万物', '百岁'), ('一元', '天地'), ('一元', '百岁')]
#
# #pairs = [('观音','猪悟能'),('观音','天蓬'),('观音','八戒'),('呆子','八戒'),('天蓬','嫦娥'),('天蓬','大圣'),('天蓬','卷帘'),('八戒','姐姐')]
# for pair in pairs:
#     print("> [%s]和[%s]的相似度为：" % (pair[0],pair[1]), model.similarity(pair[0], pair[1]))   # 预测相似性
#
# # 计算某个词的相关词列表
# figures = ['如来','西天','观音','老君','师父','老孙','八戒','沙和尚','南天门','王母','天王']
# for figure in figures:
#     print("> 和[%s]最相关的词有：\n" % figure, '\n'.join([x[0].ljust(4,'　')+str(x[1]) for x in model.most_similar(figure, topn=10)


from model_railway_signals import *
import power_switches

# The default colours for the schematic
off_colour = "grey75" # sections that are switched off
local_colour = "orange"
branch_colour="yellow"
up_colour="red"
down_colour="green"

# The default values for the global lists of drawing objects
# These are the drawing objects we need to track as we need to
# change the colours based on point and power section settings.
lh_auto_sec1 = [0]
lh_auto_sec2 = [0]
lh_auto_sec3 = [0]
rh_auto_sec1 = [0]
rh_auto_sec2 = [0]
rh_auto_sec3 = [0]
platform1 = [0]
platform2 = [0]
platform3  = [0]
through_loop = [0]
goods_loop  = [0]
rh_headshunt = [0]
lh_headshunt = [0]
goods_yard = [0]
point10 = [0]
point12 = [0]
point13 = [0]
point14 = [0]
point15 = [0]
point16 = [0]
point17 = [0]
siding1 = [0]
siding2 = [0]
siding3 = [0]
siding4 = [0]
siding5 = [0]
siding6 = [0]
siding7 = [0]
siding8 = [0]
mpd = [0]
point20 = [0]
point21 = [0]
point22 = [0]
point23 = [0]
mpd1 = [0]
mpd2 = [0]
mpd3 = [0]
mpd4 = [0]
mpd5 = [0]
mpd6 = [0]

#------------------------------------------------------------------------------------
# Externally called Function to create the schematic diagram (including the points)
# This function calls the points package to create points as required.
# All the other lines are drawn via tkinter
#------------------------------------------------------------------------------------

def create_track_schematic (canvas, point_callback, fpl_enabled:bool=True):

    # Global baseline colour definition (everything else inherits from these)
    global up_colour, down_colour, branch_colour, local_colour, off_colour

    # Global drawing objects for the main station schematic
    global platform1, platform2, platform3, through_loop, goods_loop
    global lh_headshunt, lh_auto_sec1, lh_auto_sec2, lh_auto_sec3
    global rh_headshunt, rh_auto_sec1, rh_auto_sec2, rh_auto_sec3

    # Global drawing objects for the Goods Yard Schematic
    global goods_yard, point10, point12, point13, point14, point15, point16, point17
    global siding1, siding2, siding3, siding4, siding5, siding6, siding7, siding8

    # Global drawing objects for the MPD Schematic
    global mpd, point20, point21, point22, point23, mpd1, mpd2, mpd3, mpd4, mpd5, mpd6

    #------------------------------------------------------------------------------------
    # Draw the Goods Yard
    #------------------------------------------------------------------------------------

    # Goods yard LH headshunt
    lines1 = [canvas.create_line(450,240,450,260,fill=off_colour,width=3)] # End stop
    lines2 = [canvas.create_line(450,250,575,250,fill=off_colour,width=3)]  # up to point 5
    lines3 = create_point (canvas,5,point_type.RH,600,250,off_colour,also_switch=105,
                point_callback=point_callback)
    lines4 = [canvas.create_line(625,250,875,250,fill=off_colour,width=3)]  # from point 5 to point 18
    lines5 = [canvas.create_line(600,275,700,375,fill=off_colour,width=3)]  # from point 5 to point 105
    lines6 = create_point (canvas,18,point_type.LH,900,250,off_colour,
                point_callback=point_callback)

    # Goods yard RH headshunt
    lines7 = create_point (canvas,110,point_type.RH,1225,400,off_colour,auto=True,
                orientation=180, point_callback=point_callback)
    lines8 = [canvas.create_line(1250,400,1500,400,fill=off_colour,width=3)] # point 101 Headshunt
    lines9 = [canvas.create_line(1500,390,1500,410,fill=off_colour,width=3)] # End stop

    goods_yard = lines1 + lines2 + lines3 + lines4 + lines5 + lines6 + lines7 + lines8 + lines9

    # Draw the sidings - all are switchable depending on the point settings
    siding1 = [canvas.create_line(900,225,1075,50,fill=off_colour,width=3), # point 18 siding
               canvas.create_line(1068,43,1082,57,fill=off_colour,width=3)] # End stop

    lines1 = [canvas.create_line(925,250,975,250,fill=off_colour,width=3)] # point 18 to point 14
    lines2 = create_point (canvas,14,point_type.LH,1000,250,off_colour,
                point_callback=point_callback)
    point14 = lines1 + lines2

    lines1 = [canvas.create_line(1025,250,1100,250,fill=off_colour,width=3)] # point 14 to point 13
    lines2 = create_point (canvas,13,point_type.RH,1125,250,off_colour,
                point_callback=point_callback)
    point13 = lines1 + lines2

    # Top ladder of sidings

    lines1 = [canvas.create_line(1000,225,1025,200,fill=off_colour,width=3)] # point 14 to point 15
    lines2 = create_point (canvas,15,point_type.LH,1050,200,off_colour,
                point_callback=point_callback)
    point15 = lines1 + lines2

    lines1 = [canvas.create_line(1050,175,1075,150,fill=off_colour,width=3)] # point 15 to point 16
    lines2 = create_point (canvas,16,point_type.LH,1100,150,off_colour,
                point_callback=point_callback)
    point16 = lines1 + lines2

    lines1 = [canvas.create_line(1100,125,1125,100,fill=off_colour,width=3)] # point 16 to point 17
    lines2 =create_point (canvas,17,point_type.LH,1150,100,off_colour,
                point_callback=point_callback)
    point17 = lines1 + lines2

    lines1 = [canvas.create_line(1150,75,1175,50,fill=off_colour,width=3)] # point 17 to top siding
    lines2 = [canvas.create_line(1175,50,1500,50,fill=off_colour,width=3)] # top siding
    lines3 = [canvas.create_line(1500,40,1500,60,fill=off_colour,width=3)] # End stop
    siding2 = lines1 + lines2 + lines3

    siding3 = [canvas.create_line(1175,100,1500,100,fill=off_colour,width=3),
               canvas.create_line(1500,90,1500,110,fill=off_colour,width=3)] # End stop

    siding4 = [canvas.create_line(1125,150,1500,150,fill=off_colour,width=3), # point 16 siding
               canvas.create_line(1500,140,1500,160,fill=off_colour,width=3)] # End stop

    siding5 = [canvas.create_line(1075,200,1500,200,fill=off_colour,width=3), # point 15 siding
               canvas.create_line(1500,190,1500,210,fill=off_colour,width=3)] # End stop

    # Bottom ladder of sidings

    siding6 =  [canvas.create_line(1150,250,1500,250,fill=off_colour,width=3), # point 13 siding
                canvas.create_line(1500,240,1500,260,fill=off_colour,width=3)] # End stop

    lines1 = [canvas.create_line(1125,275,1150,300,fill=off_colour,width=3)] # point 13 to point 12
    lines2 = create_point (canvas,12,point_type.RH,1175,300,off_colour,
                point_callback=point_callback)
    point12 = lines1 + lines2

    lines1 = [canvas.create_line(1175,325,1200,350,fill=off_colour,width=3)] # point 12 to point 11
    lines2 = create_point (canvas,10,point_type.RH,1225,350,off_colour, also_switch=110,
                point_callback=point_callback)
    point10 = lines1 + lines2

    siding7 = [canvas.create_line(1200,300,1500,300,fill=off_colour,width=3), # point 12 siding
               canvas.create_line(1500,290,1500,310,fill=off_colour,width=3)] # End stop

    siding8 = [canvas.create_line(1250,350,1500,350,fill=off_colour,width=3), # point 10 siding
               canvas.create_line(1500,340,1500,360,fill=off_colour,width=3)] # End stop

    #------------------------------------------------------------------------------------
    # Draw the Motive Power Depot
    #------------------------------------------------------------------------------------

    lines1 = [canvas.create_line(500,400,625,400,fill=off_colour,width=3)]  # point 19 to point 4
    lines2 = create_point(canvas,19,point_type.RH,475,400,off_colour,
                        orientation=180, point_callback=point_callback)
    mpd = lines1 + lines2  # The Main MPD Section

    mpd1 = [canvas.create_line(475,375,325,225,fill=off_colour,width=3), # point 19 siding
              canvas.create_line(318,232,332,218,fill=off_colour,width=3)] # End stop

    lines1 = [canvas.create_line(425,400,450,400,fill=off_colour,width=3)]  # point 20 to point 19
    lines2 = create_point(canvas,20,point_type.RH,400,400,off_colour,
                        orientation=180, point_callback=point_callback)
    point20 = lines1 + lines2

    lines1 = create_point(canvas,21,point_type.RH,275,400,off_colour,
                        orientation=180, point_callback=point_callback)
    lines2 = [canvas.create_line(300,400,375,400,fill=off_colour,width=3)] # point 21 to point 20
    point21 = lines1 + lines2

    mpd6 = [canvas.create_line(100,400,250,400,fill=off_colour,width=3), # point 21 siding 1
            canvas.create_line(100,390,100,410,fill=off_colour,width=3)] # End stop

    mpd5 = [canvas.create_line(275,375,250,350,fill=off_colour,width=3),
            canvas.create_line(100,350,250,350,fill=off_colour,width=3), # point 21 siding 2
            canvas.create_line(100,340,100,360,fill=off_colour,width=3)] # End stop

    lines1 = create_point(canvas,22,point_type.RH,300,300,off_colour,
                        orientation=180, point_callback=point_callback)
    lines2 = [canvas.create_line(400,375,325,300,fill=off_colour,width=3)]
    point22 = lines1 + lines2

    mpd2 = [canvas.create_line(300,275,200,175,fill=off_colour,width=3), # point 22 siding
              canvas.create_line(193,182,207,168,fill=off_colour,width=3)] # End stop
    canvas.create_oval (200,175,250,225, width=3, outline=off_colour)

    lines1 = create_point(canvas,23,point_type.RH,225,300,off_colour,
                        orientation=180, point_callback=point_callback)
    lines2 = [canvas.create_line(250,300,275,300,fill=off_colour,width=3)]
    point23 = lines1 + lines2

    mpd4 = [canvas.create_line(100,300,200,300,fill=off_colour,width=3), # point 23 siding 1
            canvas.create_line(100,290,100,310,fill=off_colour,width=3)] # End stop

    mpd3 = [canvas.create_line(225,275,200,250,fill=off_colour,width=3),
            canvas.create_line(100,250,200,250,fill=off_colour,width=3), # point 23 siding 2
            canvas.create_line(100,240,100,260,fill=off_colour,width=3)] # End stop

    #------------------------------------------------------------------------------------
    # Draw the Goods loop and associated auto sections
    #------------------------------------------------------------------------------------

    # LH auto section #3 (on goods loop)
    lines1 = create_point(canvas,4,point_type.LH,650,400,off_colour,fpl=fpl_enabled, also_switch=104,
                        orientation=180, point_callback=point_callback)
    # Point return comprises: [straight blade, switched blade, straight route ,switched route]
    lh_auto_sec3 = lines1

    # Goods loop (switchable between rh and lh auto sections)
    lines1 = create_point (canvas,105,point_type.RH,700,400,off_colour, auto=True, orientation=180)
    lines2 = [canvas.create_line(725,400,1150,400,fill=off_colour,width=3)]  # point 105 to point 6
    # Point return comprises: [straight blade, switched blade, straight route ,switched route]
    goods_loop = lines1 + lines2

    # RH auto section #3 (on goods loop)
    lines1 = create_point (canvas,6,point_type.RH,1175,400,off_colour,fpl=fpl_enabled,also_switch=106,
                point_callback=point_callback)
    # Point return comprises: [straight blade, switched blade, straight route ,switched route]
    rh_auto_sec3 = lines1

    #------------------------------------------------------------------------------------
    # Draw the BRANCH Line
    #------------------------------------------------------------------------------------

    # lh Branch line route (objects that are never going to change colour)
    canvas.create_line(0,500,175,500,fill=branch_colour,width=3) # End of canvas to  signal 1

    # Right Hand headshunt
    lines1 = [canvas.create_line(175,500,525,500,fill=off_colour,width=3)] # signal 1 to point 102
    lh_headshunt = lines1

    # draw lh auto section #2(on branch-line)
    lines1 = create_point (canvas,102,point_type.LH,550,500,off_colour,auto=True,orientation=180)
    lines2 = [canvas.create_line(575,500,625,450,fill=off_colour,width=3)] # Point 102 to Point 104
    lines3 = create_point (canvas,104,point_type.LH,650,450,off_colour,auto=True)
    # Point return comprises: [straight blade, switched blade, straight route ,switched route]
    lh_auto_sec2 = lines1 + lines2 + lines3

    # Branch platform (switchable between rh and lh auto sections)
    lines1 = [canvas.create_line(675,450,1150,450,fill=off_colour,width=3)]  # point 104 to point 106
    platform3 = lines1

    # draw rh auto section #2(on branch-line)
    lines1 = create_point (canvas,106,point_type.RH,1175,450,off_colour,auto=True,orientation=180)
    lines2 = [canvas.create_line(1200,450,1250,500,fill=off_colour,width=3)] # Point 102 to Point 104
    lines3 = create_point (canvas,108,point_type.RH,1275,500,off_colour,auto=True)
    # Point return comprises: [straight blade, switched blade, straight route ,switched route]
    rh_auto_sec2 = lines1 + lines2 + lines3

    # Right Hand headshunt
    lines1 = [canvas.create_line(1300,500,1700,500,fill=off_colour,width=3)] # point 108 to signal 9
    rh_headshunt = lines1

    # Branch line route (objects that are never going to change colour)
    canvas.create_line(1700,500,1900,500,fill=branch_colour,width=3) # signal 9 to end of canvas

    #------------------------------------------------------------------------------------
    # Draw the UP Line
    #------------------------------------------------------------------------------------

    # lh Up line route (objects that are never going to change colour)
    canvas.create_line(0,550,425,550,fill=up_colour,width=3) # end of canvas to point 101
    canvas.create_line(575,550,650,550,fill=up_colour,width=3) # point 2 to start of platform

    # draw lh auto section #1(on down-line)
    lines1 = create_point (canvas,101,point_type.LH,450,550,up_colour,auto=True,orientation=180)
    lines2 = [canvas.create_line(475,550,525,550,fill=up_colour,width=3)] # point 101 to point 2
    lines3 = create_point (canvas,2,point_type.LH,550,550,up_colour,fpl=fpl_enabled,also_switch=102,
                point_callback=point_callback)
    # Point return comprises: [straight blade, switched blade, straight route ,switched route]
    lh_auto_sec1 = lines1 + lines2 + lines3

    # Up line platform (switchable on/off)
    lines1 = [canvas.create_line(650,550,1150,550,fill=off_colour,width=3)]  # point 103 to point 7
    platform2 = lines1

    # draw rh auto section #1(on down-line)
    lines1 = create_point (canvas,8,point_type.RH,1275,550,up_colour,fpl=fpl_enabled,also_switch=108,
                orientation=180,point_callback=point_callback)
    lines2 = [canvas.create_line(1300,550,1350,550,fill=up_colour,width=3)] # point 8 to point 109
    lines3 = create_point (canvas,109,point_type.RH,1375,550,up_colour,auto=True)
    # Point return comprises: [straight blade, switched blade, straight route ,switched route]
    rh_auto_sec1 = lines1 + lines2 + lines3

    # rh Up line route (objects that are never going to change colour)
    canvas.create_line(1150,550,1250,550,fill=up_colour,width=3) # end of platform to point 8
    canvas.create_line(1400,550,1900,550,fill=up_colour,width=3) # point 109 to end of canvas

    #------------------------------------------------------------------------------------
    # Draw the DOWN Line (including the platform loop)
    #------------------------------------------------------------------------------------

    # lh Down line route (objects that are never going to change colour)
    canvas.create_line(0,600,425,600,fill=down_colour,width=3)  # end of canvas to point 1
    create_point(canvas,1,point_type.LH,450,600,down_colour,fpl=fpl_enabled,also_switch=101,
            point_callback=point_callback)

    canvas.create_line(475,600,600,600,fill=down_colour,width=3) # point 1 to point 103
    create_point(canvas,103,point_type.RH,625,600,down_colour,auto=True)
    canvas.create_line(575,640,575,660,fill=down_colour,width=3) # End stop
    canvas.create_line(575,650,600,650,fill=down_colour,width=3) # End stop to point 3

    create_point(canvas,3,point_type.RH,625,650,down_colour,fpl=fpl_enabled,also_switch=103,
                orientation=180, point_callback=point_callback)

    # Down through loop (switchable on/off)
    lines1 = [canvas.create_line(650,600,1150,600,fill=off_colour,width=3)]  # point 103 to point 7
    through_loop = lines1

    # Platform loop (switchable on/off)
    lines1 = [canvas.create_line(650,650,1150,650,fill=off_colour,width=3)] # point 3 to end of loop
    platform1 = lines1

    # rh Down line route (objects that are never going to change colour)
    canvas.create_line(1150,650,1175,625,fill=down_colour,width=3) # end of loop to point 7
    create_point(canvas,7,point_type.LH,1175,600,down_colour,fpl=fpl_enabled,orientation=180,
                point_callback=point_callback)
    canvas.create_line(1200,600,1350,600,fill=down_colour,width=3) # point 7 to point 9
    create_point(canvas,9,point_type.RH,1375,600,down_colour,fpl=fpl_enabled, also_switch=109,
                orientation=180,point_callback=point_callback)
    canvas.create_line(1400,600,1900,600,fill=down_colour,width=3) # point 9 to end of canvas

    return()

#----------------------------------------------------------------------
# Externally called function to create the signals for the schematic
#----------------------------------------------------------------------

def create_layout_signals(canvas, sig_callback):

    create_colour_light_signal (canvas,1,100,500,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,2,475,500,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            lhfeather45= True, position_light=True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,3,400,550,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            lhfeather45 = True, lhfeather90 = True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,4,1050,550,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,5,750,400,orientation=180,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            lhfeather45= True, position_light=True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,6,750,450, orientation=180,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            lhfeather45= True, position_light=True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,7,1050,400,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            rhfeather45= True, position_light=True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,8,1050,450,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            rhfeather45= True, position_light=True,
            refresh_immediately = False)

    create_colour_light_signal(canvas,9,1730,500,orientation=180,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,10,1400,500, orientation=180,
            signal_subtype = signal_sub_type.three_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            rhfeather45= True, position_light=True,
            refresh_immediately = False)

    create_colour_light_signal(canvas,11,1500,600, orientation=180,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            lhfeather45=True, rhfeather45=True, rhfeather90=True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,12,750,600, orientation=180,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,13,750,650, orientation=180,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback, sig_passed_button = True,
            refresh_immediately = False)

    create_ground_position_signal(canvas,14,550,250, shunt_ahead=True,
            sig_callback=sig_callback)

    create_ground_position_signal(canvas,15,575,400,
            sig_callback=sig_callback)

    create_ground_position_signal(canvas,16,1300,400,orientation=180,
            shunt_ahead=True, sig_callback=sig_callback,)

    create_colour_light_signal (canvas,20,1850,600, orientation=180,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback,sig_passed_button=True,fully_automatic=True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,21,100,600, orientation=180,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback,fully_automatic=True)

    create_colour_light_signal (canvas,22,50,550,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback,sig_passed_button=True,fully_automatic=True,
            refresh_immediately = False)

    create_colour_light_signal (canvas,23,1800,550,
            signal_subtype = signal_sub_type.four_aspect,
            sig_callback=sig_callback,fully_automatic=True)

    return()

#----------------------------------------------------------------------
# Externally called function to colour the track sections according to the
# track power section switches and the point settings (to reflect what
# sections are powered andwhere they are powered from (up, down, branch,
# or local). Called when either a section switch or point has been changed
#----------------------------------------------------------------------

def update_track_schematic(canvas):

    # Global baseline colour definition (everything else inherits from these)
    global up_colour, down_colour, branch_colour, local_colour, off_colour

    # Global drawing objects for the main station schematic
    global platform1, platform2, platform3, through_loop, goods_loop
    global lh_headshunt, lh_auto_sec1, lh_auto_sec2, lh_auto_sec3
    global rh_headshunt, rh_auto_sec1, rh_auto_sec2, rh_auto_sec3

    # Global drawing objects for the Goods Yard Schematic
    global goods_yard, point10, point12, point13, point14, point15, point16, point17
    global siding1, siding2, siding3, siding4, siding5, siding6, siding7, siding8

    # Global drawing objects for the MPD Schematic
    global mpd, point20, point21, point22, point23, mpd1, mpd2, mpd3, mpd4, mpd5, mpd6

    #-----------------------------------------------------------------------------------------------
    # Do the headshunts, mpd and goods yard first (as other sections can "inherit" from them)
    #-----------------------------------------------------------------------------------------------

    # lh Headshunt
    if power_switches.switch_active(6,1): lh_headshunt_colour = branch_colour
    elif power_switches.switch_active(6,2): lh_headshunt_colour = local_colour
    else: lh_headshunt_colour = off_colour
    for i in lh_headshunt: canvas.itemconfig (i, fill=lh_headshunt_colour)

    # rh Headshunt
    if power_switches.switch_active(7,1): rh_headshunt_colour = branch_colour
    elif power_switches.switch_active(7,2): rh_headshunt_colour = local_colour
    else: rh_headshunt_colour = off_colour
    for i in rh_headshunt: canvas.itemconfig (i, fill=rh_headshunt_colour)

    # goods yard and headshunt
    if power_switches.switch_active(8,1): goods_yard_colour = local_colour
    else: goods_yard_colour = off_colour
    for i in goods_yard: canvas.itemconfig (i, fill=goods_yard_colour)

    # Motive Power Depot
    if power_switches.switch_active(9,1): mpd_colour = local_colour
    else: mpd_colour = off_colour
    for i in mpd: canvas.itemconfig (i, fill=mpd_colour)

    #-----------------------------------------------------------------------------------------------
    # Work through the auto sections in the appropriate sequence of inheritence
    # (i.e. some auto sections will inherit from other auto sections)
    #-----------------------------------------------------------------------------------------------

    if point_switched(1): lh_auto_sec1_colour = down_colour
    else: lh_auto_sec1_colour = up_colour
    for i in lh_auto_sec1: canvas.itemconfig (i, fill=lh_auto_sec1_colour)

    if point_switched(2): lh_auto_sec2_colour = lh_auto_sec1_colour
    else: lh_auto_sec2_colour = lh_headshunt_colour
    for i in lh_auto_sec2:canvas.itemconfig(i, fill=lh_auto_sec2_colour)

    if point_switched(4): lh_auto_sec3_colour = lh_auto_sec2_colour
    else: lh_auto_sec3_colour = mpd_colour
    # We colour this in later with the goods loop

    if point_switched(9): rh_auto_sec1_colour = down_colour
    else: rh_auto_sec1_colour = up_colour
    for i in rh_auto_sec1: canvas.itemconfig (i,fill=rh_auto_sec1_colour)

    if point_switched(8): rh_auto_sec2_colour = rh_auto_sec1_colour
    else: rh_auto_sec2_colour = rh_headshunt_colour
    for i in rh_auto_sec2: canvas.itemconfig (i, fill=rh_auto_sec2_colour)

    if point_switched(6): rh_auto_sec3_colour = rh_auto_sec2_colour
    else: rh_auto_sec3_colour = goods_yard_colour
    # We colour this in later with the goods loop

    #-----------------------------------------------------------------------------------------------
    # Switch the remaining platform and loop sections (that may depend on the auto sections)
    #-----------------------------------------------------------------------------------------------

    if power_switches.switch_active(1,1) and point_switched(5):
        goods_loop_colour = goods_yard_colour
        lh_auto_sec3_colour = off_colour
        rh_auto_sec3_colour = goods_loop_colour
    elif power_switches.switch_active(1,1) and not point_switched(5):
        goods_loop_colour = lh_auto_sec3_colour
        rh_auto_sec3_colour = goods_loop_colour
    elif power_switches.switch_active(1,2):
        goods_loop_colour = rh_auto_sec3_colour
        lh_auto_sec3_colour = goods_loop_colour
    else:
        goods_loop_colour = off_colour
        rh_auto_sec3_colour = off_colour
        lh_auto_sec3_colour = off_colour

    for i in goods_loop: canvas.itemconfig (i, fill=goods_loop_colour)
    for i in rh_auto_sec3: canvas.itemconfig (i, fill=rh_auto_sec3_colour)
    for i in lh_auto_sec3: canvas.itemconfig (i, fill=lh_auto_sec3_colour)

    if power_switches.switch_active(2,1):
        for i in platform3: canvas.itemconfig(i,fill = lh_auto_sec2_colour)
    elif power_switches.switch_active(2,2):
        for i in platform3: canvas.itemconfig(i,fill = rh_auto_sec2_colour)
    else:
        for i in platform3: canvas.itemconfig(i,fill = off_colour)

    if power_switches.switch_active(3,1):
        for i in platform2: canvas.itemconfig (i, fill = up_colour)
    else:
        for i in platform2: canvas.itemconfig (i, fill = off_colour)

    if power_switches.switch_active(4,1):
        for i in through_loop: canvas.itemconfig (i, fill = down_colour)
    else:
        for i in through_loop: canvas.itemconfig (i, fill = off_colour)

    if power_switches.switch_active(5,1):
        for i in platform1: canvas.itemconfig (i, fill = down_colour)
    else:
        for i in platform1: canvas.itemconfig (i, fill = off_colour)

    #-----------------------------------------------------------------------------------------------
    # Change the colours of the the goods yard sections according to the point settings
    # (Track power is switched by the point settings - fed from the LH Headshunt
    #-----------------------------------------------------------------------------------------------

    # The easiest thing to do is to switch off everything and then only switch on what we need
    all_sidings = (point10 + point12 + point13 + point14 + point15 + point16 + point17 +
            siding1 + siding2 + siding3 + siding4 + siding5 + siding6 + siding7 + siding8)
    for i in all_sidings: canvas.itemconfig (i, fill = off_colour)

    if point_switched(18):
        for i in siding1: canvas.itemconfig (i, fill = goods_yard_colour)
    else :
        for i in point14: canvas.itemconfig (i, fill = goods_yard_colour)
        if point_switched(14):
            for i in point15: canvas.itemconfig (i, fill = goods_yard_colour)
            if point_switched(15):
                for i in point16: canvas.itemconfig (i, fill = goods_yard_colour)
                if point_switched(16):
                    for i in point17: canvas.itemconfig (i, fill = goods_yard_colour)

                    if point_switched(17):
                        for i in siding2: canvas.itemconfig (i, fill = goods_yard_colour)
                    else:
                        for i in siding3: canvas.itemconfig (i, fill = goods_yard_colour)
                else: #point16 not switched
                    for i in siding4: canvas.itemconfig (i, fill = goods_yard_colour)
            else: #point15 not switched
                for i in siding5: canvas.itemconfig (i, fill = goods_yard_colour)
        else: #point14 not switched
            for i in point13: canvas.itemconfig (i, fill = goods_yard_colour)
            if point_switched(13):
                for i in point12: canvas.itemconfig (i, fill = goods_yard_colour)
                if point_switched(12):
                    for i in point10: canvas.itemconfig (i, fill = goods_yard_colour)
                    if not point_switched(10):
                        for i in siding8: canvas.itemconfig (i, fill = goods_yard_colour)
                else: #point12  not switched
                    for i in siding7: canvas.itemconfig (i, fill = goods_yard_colour)
            else: #point13 not switched
                for i in siding6: canvas.itemconfig (i, fill = goods_yard_colour)

    #-----------------------------------------------------------------------------------------------
    # Change the colours of the the MPD sections according to the point settings
    # (Track power is switched by the point settings - if MPD section switch is active)
    #-----------------------------------------------------------------------------------------------

    # The easiest thing to do is to switch off everything and then only switch on what we need
    all_sidings = point20 + point21 + point22 + point23 + mpd1 + mpd2 + mpd3 +mpd4 + mpd5 + mpd6
    for i in all_sidings: canvas.itemconfig (i, fill = off_colour)

    if point_switched(19):
        for i in mpd1: canvas.itemconfig (i, fill = mpd_colour)
    else:
        for i in point20: canvas.itemconfig (i, fill = mpd_colour)

        if point_switched(20):
            for i in point22: canvas.itemconfig (i, fill = mpd_colour)

            if point_switched(22):
                for i in mpd2: canvas.itemconfig (i, fill = mpd_colour)

            else: # point 22 not switched
                for i in point23: canvas.itemconfig (i, fill = mpd_colour)
                if point_switched(23):
                    for i in mpd3: canvas.itemconfig (i, fill = mpd_colour)
                else: # point 23 not switched
                    for i in mpd4: canvas.itemconfig (i, fill = mpd_colour)

        else: # point 20 not switched
            for i in point21: canvas.itemconfig (i, fill = mpd_colour)
            if point_switched(21):
                for i in mpd5: canvas.itemconfig (i, fill = mpd_colour)
            else: # point 21 not switched
                for i in mpd6: canvas.itemconfig (i, fill = mpd_colour)

    return()


from tkinter import *
from BetTypes import *
from functools import reduce

#Create a bet calculator class
class BetCalculator:

    def __init__(self, master):

        self.master = master
        master.title("Bet Calculator")

        #----------Top Frame
        self.topframe = Frame(master)

        Label(self.topframe,justify=LEFT, text = "Stake").grid(row=0, column = 0, sticky=W)

        self.stakeinput = StringVar()
        Entry(self.topframe, width=10, textvariable = self.stakeinput, justify=LEFT).grid(row=0, column=1)

        Label(self.topframe, text = "Each-Way").grid(row=0, column = 2)

        self.ewinput = IntVar()
        r1 = Radiobutton(self.topframe, text="Yes", variable=self.ewinput, value=True).grid(row=0,column=3)
        r2 = Radiobutton(self.topframe, text="No",variable=self.ewinput, value=False).grid(row=0,column=4)

        Label(self.topframe, text="Bet Type").grid(row=1,column=0)

        self.bettype = StringVar()
        choices = ["Single/Accum", "Lucky 15 Type", "Yankee Type"]
        self.bettype.set("Pick an option")

        OptionMenu(self.topframe, self.bettype, *choices).grid(row=1,column=1)

        Label(self.topframe, text="No. of Selections").grid(row=1, column=2)

        self.selections = StringVar()
        self.selections.set('4')
        selectchoices = [str(i) for i in range(1,9)]

        def ChangeMidFrames(event):
            for widget in self.midframe.winfo_children():
                widget.destroy()
            for i in range(1,int(event)+1):
                showMidframes(rows=i)

        OptionMenu(self.topframe,  self.selections, *selectchoices, command=ChangeMidFrames).grid(row=1, column=3)

        def storewin(event):
            wins = {"Win":True,"Place":False}
            self.listOfWins.append(wins[event])

        #----------Middle Frame
        self.midframe = Frame(master)

        def showMidframes(rows=1):

            Label(self.midframe, text="Odds").grid(row=rows, column = 0)

            self.odds = StringVar()
            Entry(self.midframe, width=5, textvariable = self.odds, justify = RIGHT).grid(row=rows, column=1)

            Label(self.midframe, text="E/W Terms").grid(row=rows, column = 2)

            self.ewterms = StringVar()
            Entry(self.midframe, width=5, textvariable = self.ewterms, justify=RIGHT).grid(row=rows, column=3)

            Label(self.midframe, text="Win?").grid(row=rows, column=4)

            self.win = StringVar()
            self.win.set("Win")
            winplace = ["Win", "Place"]
            OptionMenu(self.midframe, self.win, *winplace, command=storewin).grid(row=rows, column=5)

        for i in range(1,int(self.selections.get())+1):
            showMidframes(rows=i)

        #----------Bottom Frame
        self.bottomframe = Frame(master)

        Label(self.bottomframe, text = "Total Stake").grid(row=1, column=0)
        Label(self.bottomframe, text = "Payout").grid(row=1, column=2)

        self.totalstakes = StringVar()
        lblTotalStakes = Label(self.bottomframe, width=10, textvariable=self.totalstakes).grid(row=1, column=1)

        self.payout = StringVar()
        lblPayout = Label(self.bottomframe,width=10, textvariable=self.payout).grid(row=1, column=3)

        btComputeStakes = Button(self.bottomframe, text = "Compute Payout", command=self.computePayout).grid(row=0, column = 0,columnspan=2)

        self.topframe.pack(side=TOP)
        self.midframe.pack()
        self.bottomframe.pack(side=BOTTOM)

        master.grid_rowconfigure(0, weight=1)
        master.grid_columnconfigure(0, weight=1)

        self.listOfOdds = []
        self.listOfEWTerms = []
        self.listOfWins = [True]

    def computePayout(self):

        i=0
        for widget in self.midframe.winfo_children():
            if widget.winfo_class() == 'Entry' and i%2==0:
                self.listOfOdds.append(widget.get())
                i+=1
            elif widget.winfo_class() == 'Entry' and i%2==1:
                self.listOfEWTerms.append(widget.get())
                i+=1

        self.listOfOdds = [reduce(lambda x,y:x/y, list(map(float,item.split('/')))) for item in self.listOfOdds]
        self.listOfEWTerms = [reduce(lambda x,y:x/y, list(map(float,item.split('/')))) for item in self.listOfEWTerms]

        if self.bettype.get()=="Single/Accum":
            bet = Accum(stakes = float(self.stakeinput.get()), odds=self.listOfOdds, ew=self.ewinput.get(), ewterms=self.listOfEWTerms, winner=self.listOfWins)

        elif self.bettype.get()=="Lucky 15 Type":
            bet = LuckyFifteen(stakes = float(self.stakeinput.get()), odds=self.listOfOdds, ew=self.ewinput.get(), ewterms=self.listOfEWTerms ,winner=self.listOfWins)

        elif self.bettype.get()=="Yankee Type":
            bet = Yankee(stakes = float(self.stakeinput.get()), odds=self.listOfOdds, ew=self.ewinput.get(), ewterms=self.listOfEWTerms,winner=self.listOfWins)

        self.totalstakes.set(bet.totalstakes())
        self.payout.set(round(bet.payout(),2))

#Execution
if __name__=='__main__':

    #Step 6: Create the main window of an application
    root = Tk()

    #Step 6: Tell our calculator class to use this window
    my_gui = BetCalculator(root)

    #Step 6: Executable loop on the application, waits for user input
    root.mainloop()


from http import HTTPStatus

import pytest
from crud.crud_questions_services import question_service
from httpx import AsyncClient
from schemas.questions_services import CreateQuestionService

@pytest.mark.anyio
async def test_get_all(client: AsyncClient, get_question_service: CreateQuestionService):
    obj = await question_service.create(get_question_service)
    response = await client.get("/api/v1/questions-services/")
    assert response.status_code == int(HTTPStatus.OK)
    assert obj.id in [album["id"] for album in response.json()]

@pytest.mark.anyio
async def test_get_one(client: AsyncClient, get_question_service: CreateQuestionService):
    obj = await question_service.create(get_question_service)
    response = await client.get(f"/api/v1/questions-services/{obj.id}/")
    assert response.status_code == int(HTTPStatus.OK)
    assert response.json()["id"] == obj.id


import re
import json
import shutil
from pathlib import Path

def copy_resource(src, dst, error_msg):
    dst.mkdir(parents=True, exist_ok=True)
    if src.exists():
        shutil.copytree(src, dst, dirs_exist_ok=True)
    else:
        print(error_msg)

def check_file(file_path, missing_on_mac_os=None):
    """Check existence of a file."""
    if not file_path.is_file():
        print(f"{file_path} does not exist")
        if missing_on_mac_os is not None:
            if file_path.stem in missing_on_mac_os:
                return
        exit(1)

def get_missing_on_mac_os():
    with open("../CMakeLists.txt", "r", encoding="utf-8") as fi:
        root_cmake_text = fi.read()

    mt = re.findall(r"if\(NOT APPLE\)(.*?)endif\(\)",
                    root_cmake_text,
                    flags=re.MULTILINE | re.DOTALL)
    return re.findall(r"add_subdirectory\((.+?)\)", mt[0])

def create_archive_from_github_actions_artifact():
    with open("manual.json", "r", encoding="utf-8") as fi:
        manual_dict = json.load(fi)

    pack_dir = Path("pack")
    pack_dir.mkdir(exist_ok=True)

    # For manual packaging.
    for zip_file in Path().glob("*.zip"):
        shutil.unpack_archive(zip_file, pack_dir, format="zip")

    # For GitHub Actions.
    for artifact_dir in Path().glob("vst_*"):
        if not artifact_dir.is_dir():
            continue
        shutil.copytree(artifact_dir, pack_dir, dirs_exist_ok=True)

    for dsym in pack_dir.glob("*.dSYM"):
        shutil.rmtree(dsym)

    missing_on_mac_os = get_missing_on_mac_os()

    for vst3_dir in pack_dir.glob("*.vst3"):
        plugin_name = vst3_dir.stem

        manual_name = (plugin_name
                       if not plugin_name in manual_dict else manual_dict[plugin_name])

        # # Do not make package if a plugin doesn't have manual.
        # if not Path(f"../docs/manual/{manual_name}").exists():
        #     print(f"Skipping {plugin_name}: manual not found")
        #     continue

        copy_resource(
            Path(f"../docs/manual/{manual_name}"),
            vst3_dir / Path("Contents/Resources/Documentation"),
            f"{plugin_name} manual was not found",
        )
        copy_resource(
            Path("../License"),
            vst3_dir / Path("Contents/Resources/License"),
            "License directory was not found",
        )

        # Ensuring that no binary is missing.
        check_file(vst3_dir / Path(f"Contents/x86_64-win/{plugin_name}.vst3"))
        check_file(vst3_dir / Path(f"Contents/x86_64-linux/{plugin_name}.so"))
        check_file(vst3_dir / Path(f"Contents/MacOS/{plugin_name}"), missing_on_mac_os)

        packed_path_str = shutil.make_archive(
            str(vst3_dir.parent / Path(f"{plugin_name}")),
            "zip",
            pack_dir,
            vst3_dir.name,
        )
        packed_path = Path(packed_path_str)

def add_version_to_archive_name():
    re_major_version = re.compile(r"^#define MAJOR_VERSION_INT ([0-9]+)",
                                  flags=re.MULTILINE | re.DOTALL)
    re_minor_version = re.compile(r"^#define SUB_VERSION_INT ([0-9]+)",
                                  flags=re.MULTILINE | re.DOTALL)
    re_patch_version = re.compile(r"^#define RELEASE_NUMBER_INT ([0-9]+)",
                                  flags=re.MULTILINE | re.DOTALL)

    current = list(Path("pack").glob("*.zip"))

    for path in current:
        version_hpp = Path("../") / Path(path.stem) / Path("source/version.hpp")
        if not version_hpp.exists():
            print(f"{version_hpp} was not found")
            continue

        with open(version_hpp, "r", encoding="utf-8") as fi:
            text = fi.read()

        major = re_major_version.search(text).groups()[0]
        minor = re_minor_version.search(text).groups()[0]
        patch = re_patch_version.search(text).groups()[0]

        new_path = path.parent / Path(f"{path.stem}_{major}.{minor}.{patch}.zip")
        if new_path.exists():
            print(f"Error: {new_path} already exists.")
            exit()
        path.rename(new_path)

if __name__ == "__main__":
    create_archive_from_github_actions_artifact()
    add_version_to_archive_name()


# 导入 List 类型标注
from typing import List

class Solution:
    def countFairPairs(self, nums: List[int], lower: int, upper: int) -> int:
        # 定义 countLess 函数
        def countLess(val: int) -> int:
            # 初始化 res 和 j
            res, j = 0, len(nums) - 1
            # 使用 for 循环遍历数组
            for i in range(len(nums)):
                # 使用 while 循环减小 j 的值，使得 nums[i] + nums[j] 不超过 val
                while i < j and nums[i] + nums[j] > val:
                    j -= 1
                # 计算符合条件的对的数量，并累加到 res
                res += max(0, j-i)
            # 返回 res
            return res

        # 对 nums 进行排序
        nums.sort()
        # 计算并返回符合条件的对的数量
        return countLess(upper) - countLess(lower - 1)

        """
给定一个大小为 n 的 0 索引整数数组 nums 和两个整数 lower 和 upper，返回公平对的数量。

一对 (i, j) 是公平（fair）的，如果：
    1. 0 <= i < j < n，并且
    2. 下限 <= nums[i] + nums[j] <= 上限

解题思路：
这题要求在给定的整数阵列 nums 中找出所有 "公平的" 数对 (i, j)，其中 nums[i] + nums[j] 要在 [lower, upper] 的范围内。

这个问题可以透过排序和双指针方法来解决。首先，对 nums 阵列进行排序。然后，定义一个函数 countLess(val) 来计算所有数对 (i, j) 的和小于等于 val 的数量。

最后，我们计算 countLess(upper) - countLess(lower - 1)，这样就能得到所有和在 [lower, upper] 范围内的数对的数量。

时间复杂度: 排序的时间复杂度是 O(n log n)，countLess 函数中的两个循环的时间复杂度为 O(n)。所以总的时间复杂度是 O(n log n + n) = O(n log n)。
空间复杂度: 我们只用了常数的额外空间，所以空间复杂度是 O(1)。
        """


from selenium import webdriver
import pandas as pd
import random
import time

df = pd.read_csv('SalaryTravel.csv')

def get_professors():
    return df[df.Title.str.contains('PROFESSOR')]

df = get_professors()

browser = webdriver.Chrome()

class MultipleDirectoryMatchesException(Exception):
    pass

class NoDirectoryMatchesException(Exception):
    pass

def submit_form(first_name, last_name):
    first_name_textbox = browser.find_element_by_id('edit-firstname')
    first_name_textbox.send_keys(first_name)

    last_name_textbox = browser.find_element_by_id('edit-lastname')
    last_name_textbox.send_keys(last_name)

    captcha_answer = (browser.find_element_by_name('captcha-answer')
        .get_attribute('value'))
    captcha_textbox = browser.find_element_by_id('edit-captcha-test')
    captcha_textbox.send_keys(captcha_answer)

    captcha_textbox.submit()

def click_detail_link():
    a_tags = browser.find_elements_by_tag_name('a')
    a_tags = [a for a in a_tags if a.get_attribute('href')]
    detail_links = [a for a in a_tags if '/directory/detail' in a.get_attribute('href')]
    if len(detail_links) > 1:
        raise MultipleDirectoryMatchesException()
    elif not detail_links:
        raise NoDirectoryMatchesException()

    detail_link = detail_links[0]
    detail_link.click()

def get_details():
    details = browser.find_elements_by_css_selector('#block-system-main div p')
    detail_text = [d.text for d in details]
    department_raw = detail_text[1]
    title_raw = detail_text[2]

    department = department_raw.split(':')[1].strip()
    title = title_raw.split(':')[1].strip()

    return department, title

def get_first_last_name(name):

    def get_name_parts(name):
        return name.split(',') if ',' in name else (None, None)

    def get_first_name(name):
        last, first = get_name_parts(name)
        return first

    def get_last_name(name):
        last, first = get_name_parts(name)
        return last

    first_name = get_first_name(name)
    last_name = get_last_name(name)

    return first_name, last_name

def crawl():
    details = []

    browser.get('https://www.directory.gatech.edu/')

    for row in df.itertuples():
        first_name, last_name = get_first_last_name(row.Name)
        submit_form(first_name, last_name)

        multiple_matches = False
        try:
            click_detail_link()
            department, title = get_details()
        except MultipleDirectoryMatchesException:
            department, title = None, None
            multiple_matches = True
        except NoDirectoryMatchesException:
            department, title = None, None
        except:
            department, title = None, None
        details.append({
            'Name': row.Name,
            'Department': department,
            'Title': title,
            'MultipleMatches': multiple_matches
        })

        time.sleep(random.randrange(3, 10))

    browser.close()

    return details

if __name__ == '__main__':
    details = crawl()
    details = pd.DataFrame(details)
    details.to_csv('Details.csv', index=False)


from flask import Flask, request, jsonify
from flask_mysqldb import MySQL
from os import urandom
from yaml import load, FullLoader
import json

app = Flask(__name__)
mysql = MySQL(app)

# MySQL Configuration
db_keeps = load(open('db.yaml'), Loader=FullLoader)
app.config['MYSQL_HOST'] = db_keeps['mysql_host']
app.config['MYSQL_USER'] = db_keeps['mysql_user']
app.config['MYSQL_PASSWORD'] = db_keeps['mysql_password']
app.config['MYSQL_DB'] = db_keeps['mysql_db']
app.config['SECRET_KEY'] = urandom(24)

@app.after_request
def add_headers(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization, data')
    return response

@app.route('/add-data/<provider>')
def index(provider):
    f = open(f'sites/{provider}.json')
    data = json.load(f)
    cur = mysql.connection.cursor()
    for listing in data:
        infochips = listing['infoChips'].split(',')
        title = listing['title']
        description = listing['description']
        rent = listing['rent']
        imgCount = listing['imgCount']
        imgs = listing['imgs']
        furnishing = listing['furnishing']
        postedBy = listing['postedBy']
        infoChips = ", ".join(infochips)
        date = listing['date']
        area = listing['area']
        updatedOn = listing['updatedOn']
        bhk = listing['bhk']
        source = listing['source']
        contactType = listing['contactType']
        contact = listing['contact']

        cur.execute("INSERT INTO listings (title, description, rent, contactType, contact, imgCount, urlList, furnishing, postedBy, infoChips, date, area, updatedOn, bhk, source) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (title, description, rent, contactType, contact, imgCount, imgs, furnishing, postedBy, infoChips, date, area, updatedOn, bhk, source))
        cur.connection.commit()
    cur.close()
    return "Added to database"

@app.route('/api/v1.7/available')
def db():
    cur = mysql.connection.cursor()
    q = cur.execute("SELECT * FROM listings;")
    if q > 0:
        allApartments = []
        listings = cur.fetchall()
        for _list in listings:
            infoChipsList = _list[14].split(', ')
            imgUrlsList = _list[2].split(',')
            allApartments.append({
                "id": _list[0],
                "title": _list[1],
                "description": _list[15],
                "imgUrl": imgUrlsList,
                "furnishing": _list[3],
                "area": _list[4],
                "bhk": _list[5],
                "imgCount": _list[6],
                "postedBy": _list[7],
                "rent": _list[8],
                "contactType": _list[9],
                "contact": _list[10],
                "source": _list[11],
                "date": _list[12],
                "updatedOn": _list[13],
                "infoChips": infoChipsList
            })
    return jsonify(allApartments)

@app.route('/api/filters')
def filters():
    if len(request.args) == 4:
        bhk = request.args.get('bhk')
        furnishings = request.args.get('furnishing').split(',')
        area = request.args.get('area')

        if furnishings[0] != '':
            furnishing = "'" + "', '".join(furnishings) + "'"
        else:
            furnishing = "'semifurnished','furnished','unfurnished'"

        priceQuery = request.args.get('price').split("to")
        if len(priceQuery) == 2:
            priceTo = priceQuery[1]
        else:
            priceTo = '100'

        if bhk != '':
            queryBhk = f"(bhk IN ({bhk}))"
        else:
            queryBhk = f"(bhk IN (1, 2, 3))"
        queryFurnishing = f"(furnishing IN ({furnishing}))"
        queryPrice = f"(rent <= {priceTo}000)"
        finalQuery = f"SELECT * FROM listings WHERE {queryBhk} AND {queryFurnishing} AND {queryPrice} AND area='{area}';"
        print('\n' + finalQuery + '\n')
        flats = []
        cur = mysql.connection.cursor()
        q = cur.execute(finalQuery)
        if q > 0:
            listings = cur.fetchall()
            for _list in listings:
                infoChipsList = _list[14].split(',')
                imgUrlsList = _list[2].split(',')
                flats.append({
                    "id": _list[0],
                    "title": _list[1],
                    "description": _list[15],
                    "imgUrl": imgUrlsList,
                    "furnishing": _list[3],
                    "area": _list[4],
                    "bhk": _list[5],
                    "imgCount": _list[6],
                    "postedBy": _list[7],
                    "rent": _list[8],
                    "contactType": _list[9],
                    "contact": _list[10],
                    "source": _list[11],
                    "date": _list[12],
                    "updatedOn": _list[13],
                    "infoChips": infoChipsList
                })
        return jsonify(flats)
    else:
        return "Invalid request"

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


#python
#!/usr/bin/python3
# Filename:

from excel_deal import  excel_deal
from zentao_api import zentao_api
from structs import ProductStorie
from structs import TaskStruct
import sys
class AppPersonInfo(object):
    def __init__(self) -> None:
        self.assigned_pre_=""
        self.assigned_list_=["A","B","C","D","E"]
        pass
    def IsAppAuth(self,name):
        for x in self.assigned_list_:
            if x==name:
                return True
        return False
    def GetRightAssigne(self,name):
        msg = str(name)
        if msg!="None":
            self.assigned_pre_=msg
        return self.assigned_pre_
    def GetEstimate(self,estimate):
        estimat = str(estimate).replace("h","")
        return float(estimat)

if __name__ == "__main__":
    person=AppPersonInfo()
#禅道信息
    zentao_ = zentao_api("http://zentao_url:8080",
    "test",
    "pwd")
    zentao_.SetExecutionsId(550)
    zentao_.SetProductId(71)
    ProName = "装置"
#EXCEL信息
    pro = ProductStorie()
    taskStruct = TaskStruct()
    exlce_ = excel_deal("月度需求计划-5月")

    for x in range(1,exlce_.GetExcelRowsNum()):
        bResult,pro,taskStruct = exlce_.GetNextRow()
        if bResult and pro.product==ProName :
            taskStruct.assignedTo = person.GetRightAssigne(taskStruct.assignedTo)
            if person.IsAppAuth(taskStruct.assignedTo):
                taskStruct.estimate = person.GetEstimate(taskStruct.estimate)
                print("满足需求 x=%d pro.title = %s;taskStruct:name %s ;assignedTo:%s GetEstimate:%f"
                   % (x,pro.title,taskStruct.name,taskStruct.assignedTo,taskStruct.estimate))
                id = zentao_.CreateStories(pro)
                taskStruct.story =  id
                zentao_.CreateTask(taskStruct)


"""
Ce fichier sera appelé avec des paramètres par le serveur unified remote
"""

import argparse
import json

parser = argparse.ArgumentParser()
parser.add_argument('-r','--red', type=int, help='tell server to change the red color')
parser.add_argument('-g','--green', type=int, help='tell server to change the green color')
parser.add_argument('-b','--blue', type=int,default=10, help='tell server to change the blue color')
parser.add_argument('-p','--power', type=bool, help='tell server to turn the lights on (1) or off (0)')
args = parser.parse_args()

f = open('/home/guillaume/git_folder/Light_server/comm_file','w')
liste=[]
for arg in args.__dict__ :
  if args.__dict__[arg]!=None:
      liste.append([arg,args.__dict__[arg]])
f.write(json.dumps(liste))
f.close


#!/usr/bin/python3
"""
Module prints pascal triangle given (n)
"""

def pascal_triangle(n):
    """
    prints pascal's triangle

    Args:
        n: number
    """
    if n < 1:
        return []

    triangle = [[1]]
    while len(triangle) < n:
        prev_row = triangle[-1]
        new_row = [1]
        for i in range(1, len(prev_row)):
            new_row.append(prev_row[i - 1] + prev_row[i])
        new_row.append(1)
        triangle.append(new_row)

    return triangle


from fastapi import APIRouter, FastAPI
from users.views import router as users
from auth.views import router as auth
from database import create_database

app = FastAPI()
router = APIRouter()

@app.on_event("startup")
def on_starup():
    create_database()

@router.get('/')
def index():
    return {'status':'ok'}

router.include_router(users, prefix='/users', tags=['Users'])
router.include_router(auth, prefix='/auth', tags=['Authentication'])
app.include_router(router)


"""
The class contains a neural net for predicting 13824 led
brightness values from an 30 bin fft vector input.
"""
import os
import keras
from keras.models import Sequential
from keras.utils import plot_model
from keras.utils.vis_utils import model_to_dot
from keras.layers import Dense, LSTM, Dropout, Activation
from keras.optimizers import SGD
from keras.models import model_from_json
from keras.models import load_model
from keras import backend as kerasBackend
import numpy as np

# os.environ['CUDA_VISIBLE_DEVICES'] = '-1' #force Tensorflow to use the
# computed
LOAD_MODEL = True
SAVE_MODEL = False

MODEL_FILE_PATH = './data/dictionary_model.h5'
MODEL_TRAININGS_DATA_FILE_PATH = './data/trainingsset_dodeca.csv'
MODEL_SAVE_FILE_PATH = './data/dictionary_model.h5'

INPUT_DIM = 512
BATCH_SIZE = 32
EPOCHS = 30
INITIAL_EPOCHS = 100

HIDDEN1_DIM = 512
HIDDEN2_DIM = 64
OUTPUT_DIM = 8

model = Sequential()

def load_model_from_file():
    """
    Load model from file
    """
    global model
    model = load_model(MODEL_FILE_PATH)
    model._make_predict_function()
    print('Loaded saved model from file')

def train_model():
    """
    loading the trainingsdata from a textfile. Convert the
    trainingpoints in the right dimension: One line in the text file is
    one trainingpoint with 30 FFT values and 13824 LED values, separated by tabulators
    """
    global model
    # import fft and led input data
    file_name = MODEL_TRAININGS_DATA_FILE_PATH
    file = open(file_name)
    print('Loading Trainingsdata from File:', file_name, '  ...')
    values = np.loadtxt(file_name, dtype='float32')
    print('Trainingsdata points: ', values.shape[0], "\n")
    print('Trainingsdata shape: ', values.shape, "\n")

    # split into input and outputs
    training_input, training_output = values[:,
                                             :-OUTPUT_DIM], values[:, INPUT_DIM:]
    print(
        'training_input shape: ',
        training_input.shape,
        'training_output shape: ',
        training_output.shape)
    my_init = keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)
    model.add(
        Dense(
            HIDDEN1_DIM,
            activation='sigmoid',
            input_dim=INPUT_DIM,
            kernel_initializer=my_init,
            bias_initializer=my_init))
    model.add(
        Dense(
            HIDDEN2_DIM,
            activation='sigmoid',
            input_dim=HIDDEN1_DIM,
            kernel_initializer=my_init,
            bias_initializer=my_init))
    model.add(
        Dense(
            OUTPUT_DIM,
            activation='sigmoid',
            kernel_initializer=my_init,
            bias_initializer=my_init))
    sgd = SGD(lr=0.2, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(
        loss='binary_crossentropy',
        optimizer=sgd,
        metrics=['accuracy'])
    model.fit(
        training_input,
        training_output,
        epochs=INITIAL_EPOCHS,
        batch_size=32,
        shuffle=True)
    model._make_predict_function()
    model.summary()
    print('Loaded new model')

def new_model_handler(unused_addr, args):
    """
    this function should reinitialize the model, to start the training from scratch again.
    ToDo: make it work. Probably the crash is caused because of the multi-threading?
    """
    global model
    kerasBackend.clear_session()
    my_init = keras.initializers.RandomNormal(mean=0.0, stddev=0.05, seed=None)

    model.add(
        Dense(
            6144,
            activation='sigmoid',
            input_dim=30,
            kernel_initializer=my_init,
            bias_initializer=my_init))
    model.add(
        Dense(
            OUTPUT_DIM,
            activation='sigmoid',
            kernel_initializer=my_init,
            bias_initializer=my_init))
    sgd = SGD(lr=0.5, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(
        loss='binary_crossentropy',
        optimizer=sgd,
        metrics=['accuracy'])
    model.fit(
        training_input,
        training_output,
        epochs=1,
        batch_size=32,
        shuffle=True)
    model._make_predict_function()
    print('Loaded new model')

def train_handler(unused_addr, args):
    """
    neural network trainer
    """
    global model
    model.fit(
        training_input,
        training_output,
        epochs=EPOCHS,
        batch_size=BATCH_SIZE,
        shuffle=True)
    model._make_predict_function()
    print('training finished...')
    print('')

def frame_count_handler(unused_addr, args):
    """
    a function to synchronize for recording the output of the neural network
    """
    #print('received frameCoount: ', args)
    global frame_count
    frame_count = args

def run():
    """
    Executes model loading/training/saving
    """
    global model
    if LOAD_MODEL:
        load_model_from_file()
    else:
        train_model()
    if SAVE_MODEL:
        model.save(MODEL_SAVE_FILE_PATH)
        print('Saved new model to path: ', MODEL_SAVE_FILE_PATH)
        model.summary()

if __name__ == "__main__":
    run()


from flask import Flask, request, render_template
import os
import pickle
import zipfile

with zipfile.ZipFile('svc_model.zip', 'r') as zip_ref:
    zip_ref.extractall('.')

loaded_model = pickle.load(open("svc_model.sav", "rb"))

app = Flask(__name__)

@app.route('/', methods=["GET", "POST"])
def home():
    message = "Welcome to my flask based web application ... !!!"
    return render_template("home.html", message=message)

@app.route('/getPrediction', methods=["GET", "POST"])
def getPrediction():
    incoming_text = request.form["review_text"]
    print(incoming_text)
    res = make_prediction_linReg(incoming_text)
    print(res)
    return res

def make_prediction_linReg(text):
    res = loaded_model.predict([text])
    result = ""
    if res == 0:
        result = "Negative Review"
    elif res == 1:
        result = "Neutral Review"
    elif res == 2:
        result = "Positive Review"
    else:
        result = "UNKNOWN"
    return result

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


#!/usr/bin/python
# -*- coding: utf-8 -*-
# Author: yeshengwei
# E-mail: shw.ye@qq.com

try:
    num = int(input("请输入一个整数："))
    result = 8 / num
    print(result)

except ValueError:
    print("请输入正确的整数！")

# 捕获所有未知错误：
except Exception as result:
    print(f"未知错误：{result}")

12面向对象Ⅱ/06-异常捕获/03-捕获未知错误.py

03-捕获未知错误.py