#!/usr/bin/python

import torch
from torch import nn
from torch.utils.data import DataLoader
from torch.optim import lr_scheduler
import torch.nn.functional as F

from custom_loss import TripletMarginWithDistanceLossCustom
import time
import copy
from tqdm import tqdm
import pandas as pd

from utils import *

from dataloader_replica import ReplicaDataset
from model_replica import ReplicaNet

from glob import glob
import pickle

import argparse
from datetime import datetime

now = datetime.now()
now = now.strftime("%d-%m-%Y_%H:%M:%S")
print(now)

def main(data_dir, batch_size, num_epochs, model_name, device, resolution, num_c, retrain, continue_train, effort, predict):
    if device == 'cuda':
        device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") # cuda requires batch size of 4
    else:
        device='cpu'

    model = ReplicaNet(model_name, device)

    noww = '01-06-2022_18:09:19' #'25-05-2022_23:44:19' #'19-05-2022_10:33:39' #'30-05-2022_17:15:00'

    print(continue_train)
    if continue_train:
        if data_dir + "models/model_weights_" + noww + model_name in glob(data_dir + "models/*"):
            print("loaded from previously stored weights")
            model.load_state_dict(torch.load(data_dir + "models/model_weights_" + noww + model_name))

    with open(data_dir + 'uid2path.pkl', 'rb') as outfile:
        uid2path = pickle.load(outfile)

    triplet_loss = TripletMarginWithDistanceLossCustom(
        distance_function=lambda x, y: 1.0 - F.cosine_similarity(x, y), margin=0.01,
        beta=0.1, reduction="sum", swap=True, intra=True
    )

    optimizer = torch.optim.Adam(
        model.parameters(), lr=1e-6, weight_decay=1e-4
    )

    scheduler = lr_scheduler.StepLR(
        optimizer, step_size=1000, gamma=0.01
    )

    if predict:
        data = pd.read_csv(data_dir + "data_all.csv").drop(columns=['level_0'])
        data = data[~data['path'].str.contains('9C')]
        train_test = data[data["set"].notnull()].reset_index()

        embeddings = [[uid, catch_error(path_, model, device, resolution)] for uid, path_ in tqdm(zip(data['uid'].unique(), data['path'].unique()))]
        embeddings = np.array(embeddings, dtype=np.ndarray)
        np.save(data_dir + 'embeddings/' + model_name + '_epoch_none' + now + '.npy', embeddings)

        return get_scores(embeddings, train_test, data)

    else:
        embeddings = np.load(
            data_dir + "embeddings/" + model_name + "_epoch_none" + noww + ".npy",
            allow_pickle=True,
        )

    if retrain:
        datasets = {x: ReplicaDataset(data_dir + 'dataset/retrain_'+str(effort)+'_'  + x + '.csv', data_dir, x, resolution) for x in ['train', 'val']}

        data = pd.read_csv(data_dir + "data_retrain_"+str(effort)+".csv").drop(columns=['level_0'])
        data['path'] = data['uid'].apply(lambda x: uid2path[x])

        print(data.head())
        train_test = data[data["set"].notnull()].reset_index()

        model = train_replica_f(
            model, datasets, data, train_test, triplet_loss, optimizer, scheduler, embeddings, uid2path,
            batch_size=batch_size, num_epochs=num_epochs, num_c=num_c, resolution=resolution, device=device,
            retrain=retrain, model_name=model_name,  data_dir=data_dir
        )

        torch.save(model.state_dict(), data_dir + "models/model_weights_retrain_" + now + model_name + str(effort))

    else:
        data = pd.read_csv(data_dir + "data_sample.csv")
        train_test = data[data["set"].notnull()].reset_index()

        make_training_set_orig(embeddings, train_test, data, data_dir, uid2path, epoch=10, n=num_c)
        print(pd.read_csv(data_dir + "dataset/abc_train_" + str(10) + ".csv")['C'].nunique())

        datasets = {x: ReplicaDataset(data_dir + 'dataset/abc_'+ x +'_10.csv', data_dir, x, resolution) for x in ['train', 'val']}

        model = train_replica_f(
            model, datasets, data, train_test, triplet_loss, optimizer, scheduler, embeddings, uid2path,
            batch_size=batch_size, num_epochs=num_epochs, num_c=num_c, resolution=resolution, device=device,
            retrain=retrain, model_name=model_name,  data_dir=data_dir
        )
        torch.save(model.state_dict(), data_dir + "models/model_weights_" + now + model_name)

def train_replica_f(
    model, datasets, data, train_test, triplet_loss, optimizer, scheduler, embeddings, uid2path,
    batch_size=4, num_epochs=5, num_c=5, resolution=320, device='cuda',
    retrain=False, model_name='resnext-101',  data_dir='/scratch/students/schaerf'
):

    dataset_sizes = {x: len(datasets[x]) for x in ["train", "val"]}

    train_dataloaders = {
        x: DataLoader(datasets[x], batch_size=batch_size, shuffle=True)
        for x in ["train", "val"]
    }

    since = time.time()
    best_model_wts = copy.deepcopy(model.state_dict())

    best_loss = 100
    losses = []
    scores = []

    for param in model.modules():
        if isinstance(param, nn.BatchNorm2d):
            param.requires_grad = False

    scores.append(get_scores(embeddings, train_test, data))

    for epoch in range(num_epochs):

        print("Epoch {}/{}".format(epoch, num_epochs - 1))
        print("-" * 10)

        # Each epoch has a training and validation phase
        for phase in ["train", "val"]:  # , 'val'

            if phase == 'train':
                model.train()  # Set model to training mode
            else:
                model.eval()   # Set model to evaluate mode

            running_loss = 0.0

            # Iterate over data.
            for a, b, c in tqdm(train_dataloaders[phase]):
                a = a.squeeze(1).to(device)
                b = b.squeeze(1).to(device)
                c = c.squeeze(1).to(device)

                # zero the parameter gradients
                optimizer.zero_grad()

                # forward
                # track history if only in train
                with torch.set_grad_enabled(phase == "train"):

                    # Forward pass
                    A, B, C = model(a, b, c)
                    # Compute and print loss
                    loss = triplet_loss(A, B, C)

                    # backward + optimize only if in training phase
                    if phase == "train":
                        loss.backward()
                        optimizer.step()

                # statistics
                running_loss += loss.item() * a.size(0)

            if phase == "train":
                scheduler.step()

            epoch_loss = running_loss * batch_size / dataset_sizes[phase]
            losses.append(epoch_loss)

            print("{} Loss: {:.4f}".format(phase, epoch_loss))

            if phase == "val":
                embeddings = [[uid, catch_error(path_, model, device, resolution),]
                    for uid, path_ in tqdm(zip(data["uid"].unique(), data["path"].unique()))
                ]
                embeddings = np.array(embeddings, dtype=np.ndarray)
                np.save(
                    data_dir + "embeddings/" + model_name + "_epoch_"
                    + str(epoch) + now + ".npy", embeddings,
                )
                print(embeddings.shape)
                old_score = scores[-1][-1]
                scores.append(get_scores(embeddings, train_test, data))

            # deep copy the model
            if phase == "val" and (epoch_loss < best_loss or scores[-1][-1] > old_score) and not retrain:  # needs to be changed to val
                print("Model updating! Best loss so far")
                best_loss = epoch_loss
                best_model_wts = copy.deepcopy(model.state_dict())

                make_training_set_orig(
                    embeddings, train_test, data, data_dir, uid2path, epoch=epoch, n=num_c
                )
                datasets["train"].__reload__(
                    data_dir + "dataset/abc_train_" + str(epoch) + ".csv"
                )
                datasets["val"].__reload__(
                    data_dir + "dataset/abc_val_" + str(epoch) + ".csv"
                )
                train_dataloaders = {
                    x: DataLoader(datasets[x], batch_size=batch_size, shuffle=True)
                    for x in ["train", "val"]
                }

    time_elapsed = time.time() - since
    print(
        "Training complete in {:.0f}m {:.0f}s".format(
            time_elapsed // 60, time_elapsed % 60
        )
    )
    print("Best val loss: {:4f}".format(best_loss))

    # load best model weights
    model.load_state_dict(best_model_wts)

    pd.DataFrame(
        scores,
        columns=[
            "mean_position", "mean_min_position",
            "mean_median_position", "map", "recall_400",
            "recall_200", "recall_100", "recall_50", "recall_20",
        ],
    ).to_csv(data_dir + "scores/scores_" + str(now) + ".csv")

    return model

def catch_error(path, model, device, resolution):
    try:
        return get_embedding(preprocess_image_test(path, resolution=resolution), model, device=device)
    except Exception as e:
        print(e)
        return np.zeros(2048)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Model specifics')
    parser.add_argument('--data_dir', dest='data_dir', type=str, help='Directory where data is stored', default='/scratch/students/schaerf/')
    parser.add_argument('--batch_size', dest='batch_size', type=int, help='Batch size', default=4)
    parser.add_argument('--num_epochs', dest='num_epochs', type=int, help='Number of epochs', default=5)
    parser.add_argument('--num_c', dest='num_c', type=int, help='Number of c', default=10)
    parser.add_argument('--resolution', dest='resolution', type=int, help='Image resolution', default=320)
    parser.add_argument('--device', dest='device', type=str, help='Device to use for computation', default='cuda')
    parser.add_argument('--model_name', dest='model_name', type=str, help='Name of pretrained model to use', default='resnext-101')
    parser.add_argument('--retrain', dest='retrain', type=bool, default=False)
    parser.add_argument('--continue_train', dest='continue_train', type=bool, default=False)
    parser.add_argument('--effort', dest='effort', type=int, default=1)
    parser.add_argument('--predict', dest='predict', type=bool, default=False)

    args = parser.parse_args()
    main(data_dir=args.data_dir, batch_size=args.batch_size, num_epochs=args.num_epochs,
         model_name=args.model_name, device=args.device, resolution=args.resolution,
         num_c=args.num_c, retrain=args.retrain, continue_train=args.continue_train,
         effort=args.effort, predict=args.predict)

#'24-05-2022_22:50:41'#'24-05-2022_10:05:12'#'23-05-2022_17:14:25' #'19-05-2022_10:33:39'
#'13-05-2022_14:35:30' #'30-04-2022_14:32:33' #'29-04-2022_23:38:51' #'29-04-2022_17:29:42'
#'14-04-2022_08:27:32' #"06-04-2022_09:33:39"  #'04-04-2022_19:55:56' '14-04-2022_23:25:29'


import re
from .cmudict import CMUDict

_letter_to_arpabet = {
    'A': 'EY1',
    'B': 'B IY1',
    'C': 'S IY1',
    'D': 'D IY1',
    'E': 'IY1',
    'F': 'EH1 F',
    'G': 'JH IY1',
    'H': 'EY1 CH',
    'I': 'AY1',
    'J': 'JH EY1',
    'K': 'K EY1',
    'L': 'EH1 L',
    'M': 'EH1 M',
    'N': 'EH1 N',
    'O': 'OW1',
    'P': 'P IY1',
    'Q': 'K Y UW1',
    'R': 'AA1 R',
    'S': 'EH1 S',
    'T': 'T IY1',
    'U': 'Y UW1',
    'V': 'V IY1',
    'X': 'EH1 K S',
    'Y': 'W AY1',
    'W': 'D AH1 B AH0 L Y UW0',
    'Z': 'Z IY1',
    's': 'Z'
}

# must ignore roman numerals
_acronym_re = re.compile(r'([A-Z][A-Z]+)s?|([A-Z]\.([A-Z]\.)+s?)')
cmudict = CMUDict('data/cmudict_dictionary', keep_ambiguous=False)

def _expand_acronyms(m, add_spaces=True):
    acronym = m.group(0)

    # remove dots if they exist
    acronym = re.sub('\.', '', acronym)

    acronym = "".join(acronym.split())
    arpabet = cmudict.lookup(acronym)

    if arpabet is None:
        acronym = list(acronym)
        arpabet = ["{" + _letter_to_arpabet[letter] + "}" for letter in acronym]
        # temporary fix
        if arpabet[-1] == '{Z}' and len(arpabet) > 1:
            arpabet[-2] = arpabet[-2][:-1] + ' ' + arpabet[-1][1:]
            del arpabet[-1]

        arpabet = ' '.join(arpabet)
    else:
        arpabet = "{" + arpabet[0] + "}"

    return arpabet

def normalize_acronyms(text):
    text = re.sub(_acronym_re, _expand_acronyms, text)
    return text


from plane_sprites import *
import pygame

class PlaneGame(object):
    def __init__(self):
        pygame.init()
        # 1.创建游戏窗口
        self.screen = pygame.display.set_mode(SCREEN_RECT.size)
        # 2.创建时钟
        self.clock = pygame.time.Clock()
        # 3.调用私有方法，精灵和精灵族的创建
        self.__create_sprites()
        print("init")
        # 4.设置定时器事件 创建敌机 1s
        #pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
        pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
        pygame.time.set_timer(HERO_FIRE_EVENT, 500)

    def __create_sprites(self):
        bq1 = Background()
        bq2 = Background(is_alt=True)
        self.back_group = pygame.sprite.Group(bq1, bq2)
        # 创建敌机精灵组
        self.enemy_group = pygame.sprite.Group()
        # 创建英雄的精灵族
        self.hero = Hero()
        self.hero_group = pygame.sprite.Group(self.hero)

    def start_game(self):
        print("start...")
        while True:
            # 1.设置刷新帧
            self.clock.tick(FRAME_PER_SEC)
            # 2.事件监听
            self.__event_handler()
            # 3.碰撞检测
            self.__check_collide()
            # 4.更新/绘制精灵族
            self.__update_sprites()
            # 5.更新显示
            pygame.display.update()

    def __event_handler(self):
        for event in pygame.event.get():
            # 判断退出
            if event.type == pygame.QUIT:
                PlaneGame.__game_over()
            elif event.type == CREATE_ENEMY_EVENT:
                # print("敌机出场...")
                # 创建敌机精灵
                enemy = Enemy()
                # enemy.speedx = random.randint(0, 3)
                # 将敌机精灵加入到精灵族
                self.enemy_group.add(enemy)
            elif event.type == HERO_FIRE_EVENT:
                self.hero.fire()
        # 使用键盘提供的方法提取键盘按键
        keys_pressed = pygame.key.get_pressed()
        if keys_pressed[pygame.K_RIGHT]:
            self.hero.speedx = 5
        elif keys_pressed[pygame.K_LEFT]:
            self.hero.speedx = -5
        else:
            self.hero.speedx = 0

        if keys_pressed[pygame.K_DOWN]:
            self.hero.speedy = 5
        elif keys_pressed[pygame.K_UP]:
            self.hero.speedy = -5
        else:
            self.hero.speedy = 0

    def __check_collide(self):
        # 1.子弹摧毁敌机
        pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
        # 2.敌机摧毁英雄
        enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
        # 判断列表是否有内容
        if len(enemies) > 0:
            self.hero.kill()
            PlaneGame.__game_over()

    def __update_sprites(self):
        self.back_group.update()
        self.back_group.draw(self.screen)
        self.enemy_group.update()
        self.enemy_group.draw(self.screen)
        self.hero_group.draw(self.screen)
        self.hero_group.update()
        self.hero.bullets.update()
        self.hero.bullets.draw(self.screen)

    @staticmethod
    def __game_over():
        print("游戏结束")
        pygame.quit()
        exit()

if __name__ == '__main__':
    game = PlaneGame()
    game.start_game()


import gym
import itertools as it
import typing

from vel.api import LinearBackboneModel, ModelFactory, BackboneModel
from vel.modules.input.identity import IdentityFactory
from vel.rl.api import Rollout, RlModel, Evaluator
from vel.rl.modules.action_head import ActionHead
from vel.rl.modules.value_head import ValueHead
from vel.rl.models.stochastic_policy_model import StochasticPolicyEvaluator

class StochasticPolicyModelSeparate(RlModel):
    """
    Policy gradient model class with an actor and critic heads that don't share a backbone
    """

    def __init__(self, input_block: BackboneModel,
                 policy_backbone: LinearBackboneModel, value_backbone: LinearBackboneModel,
                 action_space: gym.Space):
        super().__init__()

        self.input_block = input_block
        self.policy_backbone = policy_backbone
        self.value_backbone = value_backbone

        self.action_head = ActionHead(
            action_space=action_space,
            input_dim=self.policy_backbone.output_dim
        )

        self.value_head = ValueHead(input_dim=self.value_backbone.output_dim)

    def reset_weights(self):
        """ Initialize properly model weights """
        self.input_block.reset_weights()

        self.policy_backbone.reset_weights()
        self.value_backbone.reset_weights()

        self.action_head.reset_weights()
        self.value_head.reset_weights()

    def forward(self, observations):
        """ Calculate model outputs """
        input_data = self.input_block(observations)

        policy_base_output = self.policy_backbone(input_data)
        value_base_output = self.value_backbone(input_data)

        action_output = self.action_head(policy_base_output)
        value_output = self.value_head(value_base_output)

        return action_output, value_output

    def step(self, observation, argmax_sampling=False):
        """ Select actions based on model's output """
        policy_params, values = self(observation)
        actions = self.action_head.sample(policy_params, argmax_sampling=argmax_sampling)

        # log likelihood of selected action
        logprobs = self.action_head.logprob(actions, policy_params)

        return {
            'actions': actions,
            'values': values,
            'action:logprobs': logprobs
        }

    def policy_parameters(self):
        """ Parameters of policy """
        return it.chain(self.policy_backbone.parameters(), self.action_head.parameters())

    def logprob(self, action_sample, policy_params):
        """ Calculate - log(prob) of selected actions """
        return self.action_head.logprob(action_sample, policy_params)

    def value(self, observations):
        """ Calculate only value head for given state """
        input_data = self.input_block(observations)
        base_output = self.value_backbone(input_data)
        value_output = self.value_head(base_output)
        return value_output

    def policy(self, observations):
        """ Calculate only action head for given state """
        input_data = self.input_block(observations)
        policy_base_output = self.policy_backbone(input_data)
        policy_params = self.action_head(policy_base_output)
        return policy_params

    def evaluate(self, rollout: Rollout) -> Evaluator:
        """ Evaluate model on a rollout """
        return StochasticPolicyEvaluator(self, rollout)

    def entropy(self, policy_params):
        """ Entropy of a probability distribution """
        return self.action_head.entropy(policy_params)

    def kl_divergence(self, pd_q, pd_p):
        """ Calculate KL-divergence between two probability distributions """
        return self.action_head.kl_divergence(pd_q, pd_p)

class StochasticPolicyModelSeparateFactory(ModelFactory):
    """ Factory class for policy gradient models """
    def __init__(self, input_block: ModelFactory, policy_backbone: ModelFactory, value_backbone: ModelFactory):
        self.input_block = input_block
        self.policy_backbone = policy_backbone
        self.value_backbone = value_backbone

    def instantiate(self, **extra_args):
        """ Instantiate the model """
        input_block = self.input_block.instantiate()
        policy_backbone = self.policy_backbone.instantiate(**extra_args)
        value_backbone = self.value_backbone.instantiate(**extra_args)

        return StochasticPolicyModelSeparate(input_block, policy_backbone, value_backbone, extra_args['action_space'])

def create(policy_backbone: ModelFactory, value_backbone: ModelFactory,
           input_block: typing.Optional[ModelFactory] = None):
    """ Vel factory function """
    if input_block is None:
        input_block = IdentityFactory()

    return StochasticPolicyModelSeparateFactory(
        input_block=input_block,
        policy_backbone=policy_backbone,
        value_backbone=value_backbone
    )


from art import logo
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',]

print(logo)
restart=""
def ceasar(direction,text,shift):
  if direction[0]=='e':
    if shift>26:
      shift=shift%26    #If the person entors a shift number greater than 26, we will modify it to be such thst to which we can calculate
    cipher_text=""
    for letter in text:
      if letter in alphabet:
        if (shift+alphabet.index(letter))>=26:  #If the letter need to go back to the beginning because it exceeds its limit
            cipher_text+=alphabet[shift-(26-alphabet.index(letter))]
        else:
            cipher_text+=alphabet[alphabet.index(letter)+shift]
      else:
        cipher_text+=letter
    print(f"The encoded text is {cipher_text}")

  elif direction[0]=='d':
     if shift>26:
       shift=shift%26  #If the person entors a shift number greater than 26, we will modify it to be such thst to which we can calculate
     plain_text=""
     for letter in text:
       if letter in alphabet:
         if (alphabet.index(letter)-shift)<0: #If the letter goes below "a" then we execute as a circular loop and start from the end
           plain_text+=alphabet[26-(shift-alphabet.index(letter))]
         else:
           plain_text+=alphabet[alphabet.index(letter)-shift]
       else:
         plain_text+=letter
     print(f"The decoded text is {plain_text}")
  else:
    print("Wrong choice my friend, \nWrong Choice.")
end=False
while not end:
  direction = input("Type 'encode' to encrypt, type 'decode' to decrypt:\n").lower()
  text = input("Type your message:\n").lower()
  shift = int(input("Type the shift number:\n"))
  ceasar(direction,text,shift)
  restart=input("Do you want to run again? :").lower()
  if restart[0]!='y':
    end=True
    print("GoodBye.")


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

import datetime

from django.db.backends.mysql.schema import DatabaseSchemaEditor as BaseDatabaseSchemaEditor

class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
    sql_alter_column_no_default = ""
    sql_alter_column_no_default_bak = "ALTER COLUMN %(column)s DROP DEFAULT"
    sql_alter_column_default_null = "ALTER COLUMN %(column)s SET DEFAULT NULL"
    sql_rename_column = "ALTER TABLE %(table)s CHANGE %(old_column)s %(new_column)s %(type)s %(default)s"

    def column_sql(self, model, field, include_default=False):
        '''
        修改 设置字段允许为NULL时，增加DEFAULT NULL
        修改 include_default为FALSE时，有设置DEFAULT的值列设置DEFAULT，方法的不设置
        '''
        # Get the column's type and use that as the basis of the SQL
        db_params = field.db_parameters(connection=self.connection)
        sql = db_params['type']
        params = []
        # Check for fields that aren't actually columns (e.g. M2M)
        if sql is None:
            return None, None
        # Work out nullability
        null = field.null

        ############# modify 20170420 ###################
        # If we were told to include a default value, do so
        if not self.skip_default(field):
            include_default = self._has_default(field) \
                if not include_default else include_default

            if include_default:
                default_value = self.effective_default(field)
                if default_value is not None:
                    if self.connection.features.requires_literal_defaults:
                        # Some databases can't take defaults as a parameter (oracle)
                        # If this is the case, the individual schema backend should
                        # implement prepare_default
                        sql += " DEFAULT %s" % self.prepare_default(default_value)
                    else:
                        sql += " DEFAULT %s"
                        params += [default_value]
                else:
                    if field.null:
                        # 没有DEFAULT，可允许为空，需要设置DEFAULT NULL
                        sql += ' DEFAULT NULL'
        ############# modify end ###################

        # Oracle treats the empty string ('') as null, so coerce the null
        # option whenever '' is a possible value.
        if (field.empty_strings_allowed and not field.primary_key and
                self.connection.features.interprets_empty_strings_as_nulls):
            null = True
        if null and not self.connection.features.implied_column_null:
            sql += " NULL"
        elif not null:
            sql += " NOT NULL"
        # Primary key/unique outputs
        if field.primary_key:
            sql += " PRIMARY KEY"
        elif field.unique:
            sql += " UNIQUE"
        # Optionally add the tablespace if it's an implicitly indexed column
        tablespace = field.db_tablespace or model._meta.db_tablespace
        if tablespace and self.connection.features.supports_tablespaces and field.unique:
            sql += " %s" % self.connection.ops.tablespace_sql(tablespace, inline=True)
        # Return the sql
        return sql, params

    def add_field(self, model, field):
        '''
        修改 当DEFAULT为方法生成的时，要删除DEFAULT，其它情况保留DEFAULT
        '''
        super(DatabaseSchemaEditor, self).add_field(model, field)

        # 删除不需要保留的default
        result = self._del_auto_default(model, field)
        if field.null and result:
            # 删除默认值，又允许空，那要设置default null
            self._set_default_null(model, field)

    def _alter_field(self, model, old_field, new_field, old_type, new_type,
                     old_db_params, new_db_params, strict=False):
        '''
        调用父类方法前，当新字段没有default而旧的有时，先删除
        调完后，删除不需要保留的default
        '''
        old_has_default = self._has_default(old_field)
        new_has_default = self._has_default(new_field)

        if old_has_default and not new_has_default:
            # 新的字段没有default,删除
            self._del_default(model, old_field)

        super(DatabaseSchemaEditor, self)._alter_field(model, old_field,
            new_field, old_type, new_type, old_db_params, new_db_params, strict)

        # 删除不需要保留的default
        result = self._del_auto_default(model, new_field)
        if new_field.null and (result or self.effective_default(new_field) is None):
            # 没设置default或有设置但被删了，但可为空,设置default null
            self._set_default_null(model, new_field)

    def _rename_field_sql(self, table, old_field, new_field, new_type):
        ''' 列重命令操作语句'''

        default_value = ''
        if not self.skip_default(new_field):
            default = self.effective_default(new_field)
            if default is not None:
                default_value = 'DEFAULT {0}'.format(default)
            else:
                if new_field.null:
                    # 没有DEFAULT，可允许为空，需要设置DEFAULT NULL
                    default_value = ' DEFAULT NULL'

        return self.sql_rename_column % {
            "table": self.quote_name(table),
            "old_column": self.quote_name(old_field.column),
            "new_column": self.quote_name(new_field.column),
            "type": new_type,
            "default": default_value
        }

    def _has_default(self, field):
        '''
        字段是否有设置default
        '''
        if self.skip_default(field):
            return False

        if field.null:
            # 允许为空，不管有没有设置DEFAULT都会有
            return True

        if field.has_default():
            default = field.default
            if default is not None and not callable(default):
                return True
        if field.blank and field.empty_strings_allowed:
            return True

        return False

    def _del_auto_default(self, model, field):
        '''
        删除自动生成的DEFAULT，如方法、auto_now、auto_now_add
        '''
        if self.skip_default(field):
            return False

        default = None
        if field.has_default():
            default = field.default

        if getattr(field, 'auto_now', False) or \
            getattr(field, 'auto_now_add', False) or \
            (default is not None and callable(default)):
            # 删除DEFAULT
            self._del_default(model, field)
            return True

        return False

    def _del_default(self, model, field):
        '''
        删除DEFAULT
        '''
        sql = self.sql_alter_column % {
            "table": self.quote_name(model._meta.db_table),
            "changes": self.sql_alter_column_no_default_bak % {
                "column": self.quote_name(field.column)
                }
            }

        self.execute(sql)

    def _set_default_null(self, model, field):
        '''
        设置DEFAULT NULL
        '''
        sql = self.sql_alter_column % {
            "table": self.quote_name(model._meta.db_table),
            "changes": self.sql_alter_column_default_null % {
                "column": self.quote_name(field.column)
                }
            }

        self.execute(sql)


import json
import sys
import numpy as np
from scipy.signal import find_peaks
from scipy.ndimage import grey_erosion, grey_dilation

def detect_eeg_peaks(signal):
    # Define a function for opening operation
    def opening_operation(signal, distance):
        erosion_result = grey_erosion(signal, size=distance)
        dilation_result = grey_dilation(erosion_result, size=distance)
        return dilation_result

    # Define a function for closing operation
    def closing_operation(signal, distance):
        dilation_result = grey_dilation(signal, size=distance)
        erosion_result = grey_erosion(dilation_result, size=distance)
        return erosion_result

    # Define a function for average OC/CO operation
    def average_occo(signal, distance):
        opening_result = opening_operation(signal, distance)
        closing_result = closing_operation(signal, distance)
        occo_result = (opening_result + closing_result) / 2
        return occo_result

    # Define a function to apply the filter
    def apply_filter(signal, distance):
        occo_result = average_occo(signal, distance)
        filtered_signal = signal - occo_result
        return filtered_signal

    # Define a function to calculate the threshold
    def calculate_threshold(filtered_signal):
        extrema_amplitudes = np.abs(filtered_signal[find_peaks(filtered_signal)[0]])
        threshold = 8 * np.median(extrema_amplitudes)
        return threshold

    # Apply the filter to the original EEG signal
    filtered_signal = apply_filter(signal, distance=len(signal)//10)  # Adjust the distance as needed

    # Calculate the threshold
    threshold = calculate_threshold(filtered_signal)

    # Count the peaks above the threshold with width and prominence criteria
    detected_peaks_indices, _ = find_peaks(filtered_signal, height=threshold, width=40, prominence=237)

    detected_peaks_count = len(detected_peaks_indices)

    result = {
        "peaks_count": detected_peaks_count,
        # "peaks_array": detected_peaks_indices.tolist(),
    }

    return result

if __name__ == "__main__":
    try:
        input_data = json.loads(sys.stdin.read())

        # Check for required fields
        if "signal" not in input_data:
            raise ValueError("Missing required fields in input data")

        signal = input_data["signal"]

        result = detect_eeg_peaks(signal)

        print(json.dumps(result))
    except Exception as e:
        print(json.dumps({"error": str(e)}))


# coding: utf-8
import re
from datetime import datetime
from sqlalchemy.exc import IntegrityError
from builder.exceptions import InvalidRoleName, RoleAlreadyExist, RoleNotFound
from builder.models import Model, db

class Role(Model):
    id = db.Column(db.Integer, primary_key=True)
    __tablename__ = 'role'

    name = db.Column(db.String(80), unique=True, nullable=False)
    description = db.Column(db.String(255))
    active = db.Column(db.Boolean(), default=True)
    created_at = db.Column(db.DateTime, index=True, default=datetime.now())

    @property
    def is_active(self):
        """Return current status of role"""
        return self.active

    @classmethod
    def create(cls, name, description=None):
        """Create new role"""
        if not cls.verify_role_name(name):
            raise InvalidRoleName

        try:
            role = Role()
            role.name = name
            role.description = description
            role.save()
            db.session.commit()
            return role
        except IntegrityError:
            raise RoleAlreadyExist

    def edit(self, name=None, description=None):
        """Edit existent role"""
        try:
            if name:
                if not self.verify_role_name(name):
                    raise InvalidRoleName
                self.name = name
            if description:
                self.description = description
            self.save()
            db.session.commit()
        except IntegrityError:
            raise RoleAlreadyExist
        return self

    @classmethod
    def search_role(cls, name, exactly=False):
        """Search role by name, exactly or not"""
        if exactly:
            role = cls.query.filter(Role.name == name).first()
        else:
            role = cls.query.filter(Role.name.contains(name)).all()
        if not role:
            raise RoleNotFound
        return role

    @staticmethod
    def verify_role_name(role_name):
        """Check length and if the username does not contains invalid chars"""
        if len(role_name) >= 3 and re.search(r'^[a-zA-Z0-9_.-]+$', role_name):
            return True


from time import time
from texttable import Texttable

def test(matrix):
    times = [len(matrix.get_matrix()[0])]
    start = time()
    result = matrix.naive_search()
    stop = time()
    times.append(stop - start)
    times.append(float(len(result)))
    start = time()
    result = matrix.rabin_karp()
    stop = time()
    times.append(stop - start)
    times.append(float(len(result)))
    return times

class Table:
    def __init__(self, path):
        file = open(path)
        self.matrix = [k.strip() for k in file]
        file.close()

    def get_matrix(self):
        return self.matrix

    def print_table(self):
        print(self.matrix)

    def naive_search(self, pattern='ABC'):
        result = []
        for x in range(len(self.matrix) - len(pattern)):
            for y in range(len(self.matrix[x])):
                if self.matrix[x][y] == pattern[0]:
                    if self.matrix[x][y:y + len(pattern)] == pattern:
                        if pattern == "".join(self.matrix[k][y] for k in range(x, x + len(pattern))):
                            result.append((x, y))
        return result

    def rabin_karp(self, pattern='ABC', d=16, q=13):
        matrixlen = len(self.matrix)
        patternlen = len(pattern)
        h = (d ** (patternlen - 1)) % q
        result = set()
        for x in range(matrixlen - 2):
            p = 0
            t = 0
            for i in range(patternlen):
                p = (d * p + ord(pattern[i])) % q
                t = (d * t + ord(self.matrix[x][i])) % q
            for y in range(matrixlen - patternlen + 1):
                if p == t:
                    if self.matrix[x][y:y + patternlen] == pattern:
                        if pattern == "".join(self.matrix[k][y] for k in range(x, x + patternlen)):
                            result.add((x, y))
                if y < matrixlen - patternlen:
                    t = ((t - h * ord(self.matrix[x][y])) * d + ord(self.matrix[x][y + patternlen])) % q
        return result

p1, p2, p3, p4, p5, p8 = "patterns/1000_pattern.txt", "patterns/2000_pattern.txt", \
                         "patterns/3000_pattern.txt", "patterns/4000_pattern.txt", \
                         "patterns/5000_pattern.txt", "patterns/8000_pattern.txt"
matrix1, matrix2, matrix3, matrix4, matrix5, matrix8 = Table(p1), Table(p2), Table(p3), Table(p4), Table(p5), Table(p8)
times = []

times.append(test(matrix1))
times.append(test(matrix2))
times.append(test(matrix3))
times.append(test(matrix4))
times.append(test(matrix5))
times.append(test(matrix8))

table = Texttable()
table.add_rows([["size", "naive_time", "naive_result", "rabin_karp_time", "rabin_karp_result"],
                [times[0][0], times[0][1], times[0][2], times[0][3], times[0][4]],
                [times[1][0], times[1][1], times[1][2], times[1][3], times[1][4]],
                [times[2][0], times[2][1], times[2][2], times[2][3], times[2][4]],
                [times[3][0], times[3][1], times[3][2], times[3][3], times[3][4]],
                [times[4][0], times[4][1], times[4][2], times[4][3], times[4][4]],
                [times[5][0], times[5][1], times[5][2], times[5][3], times[5][4]]])

f = open('times.txt', 'w')
f.write(table.draw())
f.close()


import os

from cs50 import SQL
from flask import Flask, flash, jsonify, redirect, render_template, request, session
from flask_session import Session
from tempfile import mkdtemp
from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError
from werkzeug.security import check_password_hash, generate_password_hash

from helpers import apology, login_required, lookup, usd

# Configure application
app = Flask(__name__)

# Ensure templates are auto-reloaded
app.config["TEMPLATES_AUTO_RELOAD"] = True

# Ensure responses aren't cached
@app.after_request
def after_request(response):
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Expires"] = 0
    response.headers["Pragma"] = "no-cache"
    return response

# Custom filter
app.jinja_env.filters["usd"] = usd

# Configure session to use filesystem (instead of signed cookies)
app.config["SESSION_FILE_DIR"] = mkdtemp()
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

# Configure CS50 Library to use SQLite database
db = SQL("sqlite:///finance.db")

# Make sure API key is set
if not os.environ.get("API_KEY"):
    raise RuntimeError("API_KEY not set")

@app.route("/")
@login_required
def index():
    """Show portfolio of stocks"""
    user_id = session["user_id"]
    benefit = 0
    purchases = db.execute("SELECT symbol, AVG(price) as price, SUM(quantity) as quantity, SUM(total) as total FROM purchases WHERE user_id = :id GROUP BY symbol",
                          id = user_id)
    for purchase in purchases:
        stock = lookup(purchase["symbol"])
        purchase["current_price"] = stock["price"]
        purchase["current_price_usd"] = usd(stock["price"])
        purchase["plus"] = (stock["price"] - purchase["price"]) / purchase["price"]
        purchase["profit"] = (purchase["total"] * purchase["plus"]) + purchase["total"]
        purchase["profit_usd"] = usd(purchase["profit"])
        benefit += purchase["profit"]

    user = db.execute("SELECT cash FROM users WHERE id = :id",
                          id = user_id)
    cash = user[0]["cash"]

    return render_template("index.html", purchases=purchases, cash_usd=usd(cash + benefit), benefit=benefit)

@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
    """Buy shares of stock"""
    if request.method == "POST":
        # Ensure symbol was submitted
        if not request.form.get("symbol"):
            return apology("must provide a symbol", 403)

        symbol = request.form.get("symbol")
        stock = lookup(symbol)

        if stock == None:
            return apology("Stock could not be found")

        # Ensure symbol was submitted
        if not request.form.get("shares"):
            return apology("must provide a positive integer", 403)

        user_id = session["user_id"]
        user = db.execute("SELECT cash FROM users WHERE id = :id",
                          id = user_id)

        shares = request.form.get("shares")
        total = stock["price"] * float(shares)

        new_cash = float(user[0]["cash"]) - total

        if (new_cash < 0):
            return apology("sorry! you don't have enough cash", 403)
        else:
            db.execute("INSERT INTO purchases (user_id, symbol, price, total, quantity) VALUES (:user_id, :symbol, :price, :total, :quantity)",
                        user_id = user_id, symbol = symbol, price = stock["price"], total = total, quantity = shares)
            db.execute("UPDATE users SET cash=:new_cash WHERE id = :user_id",
                        new_cash = new_cash, user_id = user_id)
            return redirect("/")
    else:
        return render_template("buy.html")

@app.route("/history")
@login_required
def history():
    """Show history of transactions"""
    purchases = db.execute("SELECT symbol, price, quantity, bought_at FROM purchases WHERE user_id = :user_id ORDER BY bought_at ASC", user_id=session["user_id"])

    return render_template("history.html", purchases=purchases)

@app.route("/login", methods=["GET", "POST"])
def login():
    """Log user in"""

    # Forget any user_id
    session.clear()

    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure username was submitted
        if not request.form.get("username"):
            return apology("must provide username", 403)

        # Ensure password was submitted
        elif not request.form.get("password"):
            return apology("must provide password", 403)

        # Query database for username
        rows = db.execute("SELECT * FROM users WHERE username = :username",
                          username=request.form.get("username"))

        # Ensure username exists and password is correct
        if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
            return apology("invalid username and/or password", 403)

        # Remember which user has logged in
        session["user_id"] = rows[0]["id"]

        # Redirect user to home page
        return redirect("/")

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("login.html")

@app.route("/logout")
def logout():
    """Log user out"""

    # Forget any user_id
    session.clear()

    # Redirect user to login form
    return redirect("/")

@app.route("/quote", methods=["GET", "POST"])
@login_required
def quote():
    if request.method == "POST":
        # Ensure symbol was submitted
        if not request.form.get("symbol"):
            return apology("must provide a symbol", 403)

        stock = lookup(request.form.get("symbol"))

        if stock == None:
            return apology("Stock could not be found")

        return render_template("quoted.html", stock=stock)

    else:
        return render_template("quote.html")

@app.route("/register", methods=["GET", "POST"])
def register():
    """Register user"""
    # User reached route via POST (as by submitting a form via POST)
    if request.method == "POST":

        # Ensure username was submitted
        if not request.form.get("username"):
            return apology("must provide username", 403)

        # Ensure password was submitted
        elif not request.form.get("password"):
            return apology("must provide password", 403)

        # Query database for username
        rows = db.execute("SELECT * FROM users WHERE username = :username",
                          username=request.form.get("username"))
        # Ensure username doesn't exist
        if len(rows) > 0:
            return apology("username already exists! choose another please", 403)

        # Query database for username
        db.execute("INSERT INTO users (username, hash) VALUES (:username, :hash)",
                          username=request.form.get("username"), hash=generate_password_hash(request.form.get("password")))

        # Redirect user to login
        return redirect("/login")

    # User reached route via GET
    else:
        return render_template("register.html")

@app.route("/sell", methods=["GET", "POST"])
@login_required
def sell():
    """Sell shares of stock"""
    user_id = session["user_id"]
    stocks = db.execute("SELECT symbol, SUM(quantity) as total_quantity FROM purchases WHERE user_id = :id GROUP BY symbol",
                          id = user_id)

    if request.method == "POST":
        symbol = request.form.get("symbol")
        quote = lookup(symbol)
        # Ensure symbol was submitted
        if not symbol:
            return apology("must provide a symbol", 403)

        if len(stocks) == 0:
            return apology("Stock could not be found")

        if quote == None:
            return apology("invalid symbol", 403)

        try:
            shares = int(request.form.get("shares"))
        except:
            return apology("shares must be a positive integer", 403)

        # Check if number of shares requested was 0
        if shares <= 0:
            return apology("can't sell less than or 0 shares", 403)

        # Check if we have enough shares
        stock = db.execute("SELECT SUM(quantity) as total_quantity FROM purchases WHERE user_id = :user_id AND symbol = :symbol GROUP BY symbol",
                           user_id=user_id, symbol=request.form.get("symbol"))

        print(stock)
        if stock[0]["total_quantity"] <= 0 or stock[0]["total_quantity"] < shares:
            return apology("you can't sell less than 0 or more than you own", 403)

        # Query database for user cash
        user = db.execute("SELECT cash FROM users WHERE id = :user_id", user_id=user_id)

        # How much $$$ the user still has in her account
        cash_remaining = user[0]["cash"]
        price_per_share = quote["price"]

        # Calculate the price of requested shares
        total_price = price_per_share * shares

        # Book keeping (TODO: should be wrapped with a transaction)
        db.execute("UPDATE users SET cash = cash + :price WHERE id = :user_id", price=total_price, user_id=user_id)
        db.execute("INSERT INTO purchases (user_id, symbol, price, quantity, total) VALUES(:user_id, :symbol, :price, :quantity, :total)",
                   user_id=user_id,
                   symbol=request.form.get("symbol"),
                   price=price_per_share,
                   quantity=-shares,
                   total = -total_price)

        return redirect("/")
    else:
        return render_template("sell.html", stocks=stocks)

def errorhandler(e):
    """Handle error"""
    if not isinstance(e, HTTPException):
        e = InternalServerError()
    return apology(e.name, e.code)

# Listen for errors
for code in default_exceptions:
    app.errorhandler(code)(errorhandler)


import os
import cv2
import json
import bezier
import numpy as np

def four00Points(points):
    new_points = []
    for i in range(len(points) - 1):
        pi, pj = i, i + 1
        new_points.append(points[pi])
        center = ((points[pi][0] + points[pj][0]) / 2, (points[pi][1] + points[pj][1]) / 2)
        new_points.append(center)
    new_points.append(points[-1])
    return new_points

def approximate_curved_polygon(_contour, point_num=200):
    """
    使用贝塞尔曲线进行拟合,得到平滑的闭合多边形轮廓
    :param _contour: 构成多边形轮廓的点集. Array:(N, 2)
    :param point_num: 每次拟合的点的数量,越大则越平滑. Int
    :return: 返回平滑后的轮廓点
    """
    to_return_contour = []
    _contour = np.reshape(_contour, (-1, 2))
    # 复制起始点到最后,保证生成闭合的曲线
    # _contour = np.vstack((_contour, _contour[0, :].reshape((-1, 2))))
    for start_index in range(0, _contour.shape[0], point_num):
        # 多取一个点,防止曲线中间出现断点
        end_index = start_index + point_num + 1
        end_index = end_index if end_index < _contour.shape[0] else _contour.shape[0]
        nodes = np.transpose(_contour[start_index:end_index, :])
        # 拟合贝塞尔曲线
        curve = bezier.Curve(nodes, degree=nodes.shape[1] - 1)
        curve = curve.evaluate_multi(np.linspace(0.0, 1.0, point_num * 5))
        to_return_contour.append(np.transpose(curve))
    to_return_contour = np.array(to_return_contour).reshape((-1, 2))
    return to_return_contour

def select_seven_points(ori_points):
    points = ori_points
    while len(points) < 40:
        points = four00Points(points)
    points = np.array(points)
    res_point = approximate_curved_polygon(points)
    num = (len(res_point)) // 6
    mod = len(res_point) % 6
    new_points = []
    i = 0
    count = 0
    while i < len(res_point):
        new_points.append(res_point[i])
        if count == mod:
            i += num
        else:
            i += num + 1
            count += 1
    new_points.append(ori_points[-1])
    new_points = np.array(new_points)
    return new_points

def feed_data(image_dict, data):
    image_name, number, content, new_points, top_line, end_line = data
    if number in image_dict[image_name]:
        if top_line:
            image_dict[image_name][number].update({"content": content, "top_line": new_points})
        else:
            image_dict[image_name][number].update({"end_line": new_points})
    else:
        if top_line:
            image_dict[image_name].update({number:{"content": content, "top_line": new_points}})
        else:
            image_dict[image_name].update({number:{"end_line": new_points}})
    return image_dict

def write_label_with_PgNet(fp, label_dict):
    write_line = ""
    for image_name in label_dict.keys():
        try:
            write_line = image_name + "\t"
            label_str = ""
            for num in label_dict[image_name].keys():
                content = label_dict[image_name][num]["content"]
                top_line = label_dict[image_name][num]["top_line"].tolist()
                end_line = label_dict[image_name][num]["end_line"].tolist()
                points = top_line + end_line
                write_str = "{" + '"{}": "{}", "{}": {}'.format("transcription", content, "points", points) + "}"
                if len(label_str) < 1:
                    label_str = write_str
                else:
                    label_str = label_str + ',' + write_str
            write_line = write_line + "[" + label_str + "]" + "\n"
        except Exception as e:
            print(e)
    fp.write(write_line)

def data_preproces(root_dir):
    '''
    root_dir: 目录下存放标注的文件
    '''
    fw = open("{}_label.txt".format(root_dir), "w")
    for sub_dir_root in os.listdir(root_dir):
        print(sub_dir_root)
        image_dir = os.path.join(root_dir, sub_dir_root)
        if not os.path.isdir(image_dir):
            continue
        json_file = '{}.json'.format(image_dir)
        with open(json_file) as fr:
            label_dict = json.load(fr)
        img_metadata = label_dict['_via_img_metadata']
        for key in img_metadata.keys():
            image_dict = {}
            sub_dir = img_metadata[key]
            image_name = sub_dir['filename']
            image_dict[image_name] = {}
            image = cv2.imread(os.path.join(image_dir, image_name))
            if image is None:
                continue
            regions = sub_dir["regions"]
            if len(regions) < 1:
                continue
            for sub_regions in regions:
                try:
                    shape_attributes = sub_regions["shape_attributes"]
                    all_points_x = shape_attributes["all_points_x"]
                    all_points_y = shape_attributes["all_points_y"]
                    points = np.vstack((all_points_x, all_points_y))
                    points = np.transpose(points)
                    cv2.polylines(image, [points], False, (255, 0, 0), 5, 1)
                    new_points = select_seven_points(points)        # 平均选7个点
                    region_attributes = sub_regions["region_attributes"]
                    number = region_attributes["number"]
                    top_line, end_line = False, False
                    if "top_line" in region_attributes["line"].keys():
                        content = region_attributes["content"]      # 选取文本信息
                        top_line = True
                    if "end_line" in region_attributes["line"].keys():
                        end_line = True
                        content = ""
                    if "\n" in content:
                        print(image_name)
                        print("###################")
                        exit()
                    image_dict  = feed_data(image_dict, [image_name, number, content, new_points, top_line, end_line])
                except Exception as e:
                    print(image_name)
                    print(e, "@@@@@@@@@@@@@@@@@@@@@@@@")
            write_label_with_PgNet(fw, image_dict)
    fw.close()

def main():
    data_preproces()

if __name__ == '__main__':
    main()


from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from django.contrib.auth import authenticate, login, get_user_model
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.contrib import messages
from math import floor

from .forms import SetPassForm, UserRegistrationForm
from .models import *

def main(request):
    tests = Test.objects.all()
    return render(request, 'app/main.html', {'tests': tests})

@login_required(login_url='app:login')
def test_view(request, id):
    test = get_object_or_404(Test, id=id)
    username = request.user.username
    user = get_user_model().objects.filter(username=username).first()
    prof = get_prof(user)
    que_id = prof.que_id
    questions = QuestionList.objects.filter(test=test)
    end = len(questions)

    if request.method == 'POST':
        r = updtae_result(request, que_id[id], questions, prof, id)
        if r != -1:
            que_id[id] += 1
            prof.que_id = que_id
            prof.save()
            if que_id[id] >= end:
                return redirect(str(id) + '/result')
            return redirect('/test/' + str(id))

    now = que_id[id]
    question = questions[now].question
    answers = Answer.objects.filter(question=question)

    return render(request, 'app/question.html', {"question": question, "test": test, "que_id":que_id,
                                                 "answers": answers, "now": now+1, "end": end})

def updtae_result(request, id, questions, prof, test_id):
    answers = Answer.objects.filter(question=questions[id].question)
    res, null = True, True
    for answer in answers:
        if request.POST.get(str(answer.id)):
            null = False
            if not answer.is_right:
                res = False
    if null:
        return -1
    if res:
        corr = prof.count_corr
        corr[test_id] += 1
        prof.count_corr = corr
        prof.save()
    return 0

@login_required(login_url='app:login')
def result_view(request, id):
    test = get_object_or_404(Test, id=id)
    username = request.user.username
    user = get_user_model().objects.filter(username=username).first()
    prof = get_prof(user)
    questions = QuestionList.objects.filter(test=test)
    end = len(questions)
    que_id = prof.que_id

    if que_id[id] < end:
        return redirect('/')

    corr = prof.count_corr[id]
    prof.count_corr[id] = 0
    prof.que_id[id] = 0
    prof.count_test += 1
    prof.count_ok += corr
    prof.count_total += end
    prof.save()

    return render(request, 'app/result.html', {"test": test, "corr": corr, "total": end, "prec": get_prec(corr, end)})

@login_required(login_url='app:login')
def password_change(request):
    user = request.user
    if request.method == 'POST':
        form = SetPassForm(user, request.POST)
        if form.is_valid():
            form.save()
            return redirect('app:login')

    form = SetPassForm(user)
    return render(request, 'registration/password_change.html', {'form': form})

def register(request):
    if request.user.is_authenticated:
        return redirect("/")

    if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            Profile.objects.create(user=user)
            return redirect('/')
    else:
        form = UserRegistrationForm()

    return render(request, 'registration/reg.html', {"form": form})

@login_required(login_url='app:login')
def profile(request):
    username = request.user.username
    user = get_user_model().objects.filter(username=username).first()
    prof = get_prof(user)
    return render(request, 'registration/profile.html', {"prof": prof, "user": user, "prec": get_prec(prof.count_ok, prof.count_total)})

def get_prec(a, b):
    if b == 0:
        return "-"
    return floor((a / b) * 100)

def get_prof(user):
    try:
    	prof = get_object_or_404(Profile, user=user)
    except:
    	Profile.objects.create(user=user)
    	prof = get_object_or_404(Profile, user=user)
    return prof


## Transfer Learning - Scaling Up ##
'''
NOTE:
We've seen the power of transfer learning feature extraction and fine-tuning, now
it's time to scale up to all of the classes in Food101 (101 total classes). The
goal is to beat the original Food101 paper with the 10% of training (leveraging the
power of deep learning). The baseline to beat is 50.76% accuracy across 101 classes.
https://data.vision.ee.ethz.ch/cvl/datasets_extra/food-101/static/bossard_eccv14_food-101.pdf
'''

import os
import numpy as np
import pandas as pd
import tensorflow as tf
import my_functions as myfunc
import prepare_data as prep
import matplotlib.pyplot as plt
import matplotlib.image as mimg

print(f'\ntensorflow: {tf.__version__}')

OG_PATH = '../data/food-101/images'
PATH_10_PERCENT = '../data/food_101_10_percent_all_classes'
CUSTOM_PATH = '../data/custom_food_data'

IMAGE_SIZE = (224, 224)
TARGET_SIZE = IMAGE_SIZE + (3,)
BATCH_SIZE = 32
INITIAL_EPOCHS = 5

TENSORBOARD_PATH = './tmp/transfer_learning/scaling_up/tensorboard'
CHECKPOINT_PATH = './tmp/transfer_learning/scaling_up/checkpoints'
SAVE_MODEL_PATH = './tmp/saved_models'

## Preparing the data
food_class_names = list(prep.get_labels(OG_PATH, filename='train.json'))

prep.prepare(OG_PATH, PATH_10_PERCENT,
             datasets=['train', 'test'],
             labels=food_class_names,
             train_data_size=.1)

# Visualize the samples from 10% training dataset
file_dirs_10_percent = os.listdir(PATH_10_PERCENT + '/train')
filenames = []
for fdir in file_dirs_10_percent:
    for filename in os.listdir(f'{PATH_10_PERCENT}/train/{fdir}'):
        filenames.append(f'{fdir}/{filename}')
myfunc.plot_sample_images(filenames,
                          label_size=15,
                          dir_path=PATH_10_PERCENT + '/train',
                          read_from_dir=True)

## Importing the datasets
from tensorflow.keras.preprocessing import image_dataset_from_directory

# 10% training set
training_set_10_percent = image_dataset_from_directory(PATH_10_PERCENT + '/train',
                                                       image_size=IMAGE_SIZE,
                                                       batch_size=32,
                                                       label_mode='categorical')

# test set
test_set = image_dataset_from_directory(PATH_10_PERCENT + '/test',
                                        image_size=IMAGE_SIZE,
                                        batch_size=BATCH_SIZE,
                                        label_mode='categorical',
                                        shuffle=False)

## Prepare data augmentation layer to add to the base model
from tensorflow.keras import Sequential
from tensorflow.keras.layers.experimental import preprocessing

# Creating the data augmentation layer
data_augmentation = Sequential(name='data_augmentation', layers=[
    preprocessing.RandomFlip('horizontal'),
    preprocessing.RandomZoom(.2),
    preprocessing.RandomWidth(.2),
    preprocessing.RandomHeight(.2),
    preprocessing.RandomRotation(.2),
    # preprocessing.Rescale(1./225)
    ])

# Visualize the sample augmented data
images, labels = list(training_set_10_percent.take(1))[0]
augmented_images = data_augmentation(images, training=True)
myfunc.plot_augmented_data(augmented_data=augmented_images/255.,
                           original_data=images/255.,
                           with_keras_layers=True)

## Build and train transfer learning model with 10% of 101 food classes
from tensorflow.keras import Model
from tensorflow.keras.applications import EfficientNetB0
from tensorflow.keras.layers import Input, GlobalAveragePooling2D, Dense
from tensorflow.keras.activations import softmax
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.losses import CategoricalCrossentropy

# Setup the base model and freeze its layers (this will extract features)
base_model = EfficientNetB0(include_top=False)
base_model.trainable = False

# Setup model architecture with trainbale top layers
inputs = Input(shape=TARGET_SIZE, name='input_layer')
x = data_augmentation(inputs) # augment images (only happens during training phase)
x = base_model(x, training=False) # Put the base model in inference mode so the weights which needed will stay frozen
x = GlobalAveragePooling2D(name='global_average_pooling_layer')(x)
outputs = Dense(units=len(food_class_names), activation=softmax, name='output_layer')(x)
model = Model(inputs, outputs, name='food_101_classification_model')

# Compile the model
model.compile(optimizer=Adam(learning_rate=.001),
              loss=CategoricalCrossentropy(),
              metrics=['accuracy'])

# Model Summary
print('\nModel Summary:')
model.summary()

# Fit the model into the training set
print(f'\nFitting {model.name}')
model_tensorboard_callback = myfunc.create_tensorboard_callback(dir_name=TENSORBOARD_PATH,
                                                                experiment_name='model')
model_checkpoint_callback = myfunc.create_model_checkpoint_callback(dir_name=CHECKPOINT_PATH,
                                                                    experiment_name='model')
model_history = model.fit(training_set_10_percent,
                          epochs=INITIAL_EPOCHS,
                          steps_per_epoch=len(training_set_10_percent),
                          validation_data=test_set,
                          validation_steps=len(training_set_10_percent),
                           callbacks=[model_tensorboard_callback, model_checkpoint_callback])

# Evaluate the model
print(f'Evaluating {model.name}')
model.evaluate(test_set)
myfunc.plot_model_history(model_history)

'''
NOTE:
If the val-accuracy plot is lower that then the training_accuracy, there is probability
that model is overfitting. Ideally, the two curves should be very similar to each
other. We can try to improve the model performance with fine-tuning.
'''

## Fine-tuning
from tensorflow.keras.models import load_model

# Check if the layers inside the model are trainable
for layer in model.layers:
    print(layer.name, layer.trainable)

# Setting the last 5 layers of the base_model to be trainable
model.layers[2].trainable = True
for layer in model.layers[2].layers[:-10]:
    layer.trainable = False

print(f'\nTotal layers inside the base_model: {len(model.layers[2].layers)}')
print('\nTrainable layers inside the base_model:')
for layer_idx, layer in enumerate(model.layers[2].layers):
    if layer.trainable == True:
        print((layer_idx + 1), layer.name, layer.trainable)

# Recompile the model (we have to recompile the model everytime me make some changes)
model.compile(optimizer=Adam(learning_rate=.0001), # Learning rate lowered by 10x
              loss=CategoricalCrossentropy(),
              metrics=['accuracy'])

# Refit our fine-tuned model
print(f'\nFitting fine-tuned {model.name}')
fine_tune_epochs = INITIAL_EPOCHS + 5
fine_tuning_tensorboard_callback = myfunc.create_tensorboard_callback(dir_name=TENSORBOARD_PATH,
                                                                      experiment_name='fine_tuning_model')
fine_tuning_checkpoint_callback = myfunc.create_model_checkpoint_callback(dir_name=CHECKPOINT_PATH,
                                                                          experiment_name='fine_tuning_model')
fine_tuning_history = model.fit(training_set_10_percent,
                                epochs=fine_tune_epochs,
                                steps_per_epoch=len(training_set_10_percent),
                                validation_data=test_set,
                                validation_steps=len(training_set_10_percent),
                                initial_epoch=model_history.epoch[-1],
                                callbacks=[fine_tuning_tensorboard_callback,
                                            fine_tuning_checkpoint_callback])

# Evaluate the fine-tuned model
print(f'\nEvaluating fine-tuned {model.name}')
fine_tuning_evaluation = model.evaluate(test_set)
myfunc.plot_model_history(fine_tuning_history)
myfunc.plot_2_model_histories(fine_tuning_history, model_history,
                              model_1_name=('fine-tuned ' + model.name))

# Save and load our saved model
model.save(SAVE_MODEL_PATH + model.name)
loaded_model = load_model(SAVE_MODEL_PATH + model.name)

# Evaluate the loaded model
print('\nEvaluating loaded model')
loaded_model_evaluation = loaded_model.evaluate(test_set)
myfunc.compare_two_model_results(fine_tuning_evaluation, loaded_model_evaluation)

## Making predictions
print(f'\nMaking predicting with {model.name}')
pred_probs = model.predict(test_set, verbose=1)

print(f'Number of prediction probabities for sample 0: {len(pred_probs[0])}')
print(f'What prediction probability sample 0 looks like: \n{pred_probs[0]}')
print(f'The class with the highest predicted probability by the model for sample 0: {pred_probs[0].argmax()} \
      ({food_class_names[pred_probs[0].argmax()]})')

# Get the pred classes of each label
pred_classes = pred_probs.argmax(axis=1)

## Compare the model's predictions with the original test dataset labels
from sklearn.metrics import accuracy_score

y_labels = []
for _, labels in test_set.unbatch():
    y_labels.append(labels.numpy().argmax())
print(len(y_labels), len(pred_classes))

pred_accuracy = accuracy_score(y_labels, pred_classes)
print("\nPrediction accuracy: ", pred_accuracy)

## Making confusion matrix plot
myfunc.plot_confusion_matrix(y_labels, pred_classes, food_class_names,
                             title=f'{model.name} Confusion Matrix',
                             figsize=(150, 150),
                             title_size=120,
                             label_size=80,
                             savefig=True,
                             save_path='./tmp/')

## Classification report
'''
NOTE:
Scikit-learn has a helpful function for aquiring many different classification
metrics per class (e.g. precision, recall and F1) called classification report,
let's try it out.
'''

from sklearn.metrics import classification_report
print(f'Classification report: \n{classification_report(y_labels, pred_classes)}')

# Plot the f1-score from classification report
model_report_dict = classification_report(y_labels, pred_classes, output_dict=True)
classification_f1_dict = {}
for k, v in model_report_dict.items():
    if k == 'accuracy':
        break
    else:
        classification_f1_dict[food_class_names[int(k)]] = v['f1-score']

f1_df = pd.DataFrame({'class_names': classification_f1_dict.keys(),
                      'f1_scores': classification_f1_dict.values()}).sort_values('f1_scores', ascending=False)
myfunc.plot_f1_scores(f1_df, title=f'F1-Score of {model.name}')

## Visualizing predictions on test images
'''
NOTE:
To visualize our model's predictions on our own images, we'll need a function
to load and preprocess the images. Specially, it will need to:
*   Read in a target image file path using tf.io.read_file()
*   Turn the image into tensor using tf.io.decode_image()
*   Resize the image tensor to be the same size as the images in our model using
    tf.image.resize()
*   Scale the image to get all of the pixel values from 0 to 1 (if necessary)
*   Make prediction on the loaded sample image from the test dataset
*   Plot the image along with the model's prediction
'''
test_images = prep.get_labels(OG_PATH, filename='test.json')
test_images = np.array(list(test_images.values())).flatten()
image_format = np.vectorize(lambda x: x + '.jpg')
test_images = image_format(test_images)

for _ in range(10):
    random_image_path = f'{PATH_10_PERCENT}/test/{np.random.choice(test_images)}'
    print(random_image_path)
    myfunc.predict_and_visualize(model,
                                 labels=food_class_names,
                                 img_path=random_image_path,
                                 title_size=16)

## Finding the most wrong predictions
'''
NOTE:
To find out where our model's worst, let's write some code to find out the following:
1.  Get all of the image file paths in test dataset.
2.  Create a pandas DataFrame of the image file paths, ground truth labels, predicted
    classes (from our model), max prediction probs.
3.  Use our DataFrame to find all the wrong predictions (where the ground truth
    label doesn't match the prediction).
4.  Sort the DataFrame based on the wrong predictions (from the highest prediction
    probability to the lowest).
5.  Visualize the images with the highest prediction probabilities but have the
    wrong prediction.
'''

# Get all the image file paths in test dataset
filepaths = []
for filepath in test_set.list_files(f'{PATH_10_PERCENT}/test/*/*.jpg', shuffle=False):
    filepaths.append(filepath.numpy())
print(filepaths[:5])

# Create DataFrame of different parameters for each of the test images
pred_df = pd.DataFrame({'img_path': filepaths,
                        'y_true': y_labels,
                        'y_pred': pred_classes,
                        'pred_conf': pred_probs.max(axis=1),
                        'y_true_classname': [food_class_names[y] for y in y_labels],
                        'y_pred_classname': [food_class_names[y] for y in pred_classes]})
print(pred_df.head())

# Find out in our DataFrame which prediction are wrong
pred_df['pred_correct'] = pred_df['y_true'] == pred_df['y_pred']
print(pred_df.head())

# Sort the DataFrame to have the worst prediction at the top
worst_100 = pred_df[pred_df['pred_correct'] == False].sort_values('pred_conf',
                                                                  ascending=False)[:100]
print(worst_100.head())

# Visualize the test data samples which has the worst prediction but highest pred probability
myfunc.visualize_image_prediction(worst_100, images_to_view=12)

# Make predictions and plot custom food images
custom_food_images = [f'{CUSTOM_PATH}/{path}' for path in os.listdir(CUSTOM_PATH)]
for img_path in custom_food_images:
    myfunc.predict_and_visualize(model, labels=food_class_names, img_path=img_path)


from django.urls import path, re_path
from django.conf.urls import url
from .views import CategoryList, CategoryImage, FetchProvidersByCategory, \
    FetchAvailableTimeSlot, UserAppVersion, UserNotifications
from django.views.generic import TemplateView

urlpatterns = [
    path('service_list/', CategoryList.as_view(), name='services'),
    path('available_time_slot/', FetchAvailableTimeSlot.as_view(), name='available_time_slot'),
    path('providers_by_categories/<int:category_id>/', FetchProvidersByCategory.as_view(),
         name='providers_by_categories'),
    re_path(r'^uploads/catagories/(?P<filename>[-\w_\\-\\.]+)$', CategoryImage.as_view(),
            name='category_image-download'),
    path('notification/', UserNotifications.as_view(), name='add_notification'),
    path('appversion/', UserAppVersion.as_view(), name='add_notification'),
    path('privacy_policy/',TemplateView.as_view(template_name='policy.html'))
]


from app.models import db, Cart, environment, SCHEMA
from sqlalchemy.sql import text

def seed_carts():

    cart1 = Cart(
        user_id = 1,
        total_price=4.95
    )

    cart2 = Cart(
        user_id=2,
        total_price=2.95
    )

    cart3 = Cart(
        user_id=3,
        total_price=5.59
    )

    cart4 = Cart(
        user_id=4,
        total_price=5.59
    )

    all_carts = [cart1, cart2, cart3, cart4]
    add_carts = [db.session.add(cart) for cart in all_carts]
    db.session.commit()

    return all_carts

def undo_carts():
    if environment == "production":
        db.session.execute(
            f"TRUNCATE table {SCHEMA}.carts RESTART IDENTITY CASCADE;")
    else:
        db.session.execute(text("DELETE FROM carts"))

    db.session.commit()


#!/usr/bin/env python3
"""
Author      : Madhu Babu Kencha
Created on  : 14-sept-2018

1) This program demonstrate how to specify short options
"""
import argparse

def main():
	parser = argparse.ArgumentParser()
	# This means that, if the option is specified, assign the value True to args.verbose
	parser.add_argument( "-v", "--verbosity", help = "Increases the verbosity of output", \
		                 action="store_true" )
	args = parser.parse_args()
	if args.verbosity:
		print( "Verbosity is on" )

if __name__ == '__main__':
	main()


'''
Created on 16 mars 2022

@author: Fab
'''

import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import itertools
import numpy
from gevent.libev.corecext import NONE
from experiments.sugarsocial.analysis.LogAnalyser import LogAnalyser
import random
from matplotlib.ticker import FuncFormatter, MultipleLocator
import datetime
import json
import numpy as np
import matplotlib
from matplotlib import ticker

worksheet = None
wy= 0

def jitter( value , l ):
    ll =[]
    for i in range( len(l) ):
        ll.append( value+ (random.random()-0.5)*0.4 )
    return ll

def noData(ax ,text="no data"):
    ax.text(0.5,0.5,text,horizontalalignment='center', verticalalignment='center', transform = ax.transAxes)

def format_func(x, pos):
    hours = int(x//3600)
    minutes = int((x%3600)//60)
    #seconds = int(x%60)

    return "{:d}h{:02d}".format(hours, minutes)
    #return "{:d}h".format(hours)

def invert( a,b ):
        return b,a

def convert_to_d_h_m_s( frames ):
    """Return the tuple of days, hours, minutes and seconds."""
    #seconds = frames / 30
    seconds, f = divmod( frames, 30)
    minutes, seconds = divmod(seconds, 60)
    hours, minutes = divmod(minutes, 60)
    days, hours = divmod(hours, 24)

    return days, hours, minutes, seconds, f

def frameToTimeTicker(x, pos):

    #    vals= convert_to_d_h_m_s( x*30 )
    #return "D{0} - {1:02d}:{2:02d}".format( int(vals[0])+1, int(vals[1]), int(vals[2]) )
    return str ( int( x/(60*60) ) ).zfill(2)

def compute():

    # batch mode
    from os import listdir
    from os.path import isfile, join
    mypath = "batch social sucrose"
    onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
    print( onlyfiles )

    numberOfAnimals = {}

    data = {}

    for file in onlyfiles:
        if "jamReport" in file:
            continue
        if ".pdf" in file:
            continue
        if ".xls" in file:
            continue
        if ".zip" in file:
            continue
        #processFile( mypath+"/"+file )

        analyser = LogAnalyser( mypath+"/"+file )
        phases = [ "PHASE1" , "PHASE2" , "PHASE3" , "PHASE4","PHASE5","PHASE6"]

        print("---")
        print( "file" , analyser.logFile )
        print( "name", analyser.experimentName )
        print( "geno", analyser.getGenotype() )
        print( "sex", analyser.getSex() )
        print( "age", analyser.getAge() )
        phaseDurationList = []
        for phase in phases:
            analyser.setAnalysisPhase( phase )
            try:
                phaseDurationList.append( analyser.getPhaseDurationS() )
            except:
                phaseDurationList.append( None ) # this phase has not been reached

        data[ analyser.logFile ] = {}
        d = data[ analyser.logFile ]
        d[ "name" ] = analyser.experimentName
        d[ "genotype" ] = analyser.getGenotype()
        d[ "sex" ] = analyser.getSex()
        d[ "age" ] = analyser.getAge()
        d[ "phaseDurations"] = phaseDurationList
        d[ "endTimePhase6S"] = getEndTimePhase6( analyser )

        json.dump(data, open("SugarSocialData.json", 'w'))

        k = f"{analyser.getGenotype()} {analyser.getSex()} {analyser.getAge()}w"
        if k not in numberOfAnimals:
            numberOfAnimals[k] = 0
        numberOfAnimals[k]+=1

    print("Animal list:")
    for k,v in numberOfAnimals.items():
        print(k,"\t",v)

def plot( data, genotype , phase , y2 ):

    x = []
    y = []
    for d in data.values():
        print( d )
        if d["genotype"] == genotype:
            x.append( d["phaseDurations"][phase] )
            y.append( y2 )
    plt.scatter( x , y )

def toHM( seconds ):

    mm, ss = divmod(seconds, 60)
    hh, mm= divmod(mm, 60)
    return f"{int(hh)}:{str(int(mm)).zfill(2)}"

def getEndTimePhase6( analyser ):

    nbValue = 40
    times, ratios, nbValues , notused = analyser.getRatioProgress( "PHASE6", nbValue )
    threshold = 2.*(nbValue/3.)
    for i in range( len( ratios )):
        ratio = ratios[i]
        time = times[i]
        nbVal = nbValues[i] # to check if enough values have been checked ( 20 or 40 ? )
        if ratio > threshold and nbVal > nbValue :
            return time
            break

def analyse():

    data = json.load(open("SugarSocialData.json"))

    '''
    plot( data, "WT" , 0 , 1 )
    plot( data, "KO" , 0 , 2 )
    '''

    animals = []

    plt.figure(figsize=(20,8))
    colors = plt.get_cmap('RdYlGn')( np.linspace(0.15, 0.95, 6 ))
    ax = plt.gca()

    '''
    # filter data
    for k in data.copy():
        d = data[k]
        if not "KO" in d["genotype"]:
            data.pop(k)
    for k in data.copy():
        d = data[k]
        if not "female" in d["sex"]:
            data.pop(k)

    for k in data.copy():
        d = data[k]
        if d["age"] != 12:
            data.pop(k)

    for k in data.copy():
        d = data[k]
        if d["age"] !=12 :
            data.pop(k)

    for d in data:
        #print( d )
        dd = data[d]
        for maxPhase in range( 6 ):
            if dd["phaseDurations"][maxPhase] == None:
                break
        endTime = ""
        if dd["endTimePhase6S"] != None:
            endTime =dd["endTimePhase6S"]

        print( f"{d}{dd['genotype']}\t{dd['sex']}\t{dd['age']}\t{dd['genotype']}\t{maxPhase+1}\t{endTime}" )
    quit()
    '''
    '''

    '''
    files = [
    "batch social sucrose/gateLog - 2022-10-17 malewtda114(3818)8mois.log.txt",

    "batch social sucrose/gateLog - 2022-08-31 femWTda91(5662)8months.log.txt",
    "batch social sucrose/gateLog - 2022-09-19 femWTda92(5605)8months.log.txt",
    "batch social sucrose/gateLog - 2022-10-26 femwtda115(3799)8mois.log.txt",

    "batch social sucrose/gateLog - 2022-10-19 malekoda113(3777)8mois.log.txt",
    "batch social sucrose/gateLog - 2022-11-02 malekoda117(3809)8mois.log.txt",

    "batch social sucrose/gateLog - 2022-09-05 femKOda103(5580)8months.log.txt",
    "batch social sucrose/gateLog - 2022-09-07 femKOda104(5652 blessee)8months.log.txt",
    "batch social sucrose/gateLog - 2022-11-07 femkoda130(5679)8mois phase1.log.txt",

    "batch social sucrose/gateLog - 2022-11-14 femhetda131(5701)8mois.log.txt",
    "batch social sucrose/gateLog - 2022-11-16 femhetda132(5716)8mois.log.txt",
    "batch social sucrose/gateLog - 2022-11-21 femhet146(5720)phase2 8mois.log.txt",
    "batch social sucrose/gateLog - 2022-11-23 femhet147(5691)8mois.log.txt",
    "batch social sucrose/gateLog - 2022-11-28 femhet138(5728)8moisphase2.log.txt",
    "batch social sucrose/gateLog - 2022-11-30 femhet139(5735)8mois phase3.log.txt",
    ]
    '''

    files = [
    "batch social sucrose/gateLog - 2022-09-21 maleWTda226(5669)12w.log.txt",
    "batch social sucrose/gateLog - 2022-12-09 malewtda334(3795)12w.log.txt",
    "batch social sucrose/gateLog - 2023-02-13 malewtda375(2og)12w.log.txt",
    "batch social sucrose/gateLog - 2023-01-09 malewtda323(3806)12wok.log.txt",
    "batch social sucrose/gateLog - 2023-01-11 malewtda324(3780)12wok.log.txt",

    "batch social sucrose/gateLog - 2022-12-14 femwtda313(3802)12w.log.txt",
    "batch social sucrose/gateLog - 2023-01-18 femwtda355(3876)12w.log.txt",

    "batch social sucrose/gateLog - 2022-12-05 femkoda315(3821)12w.log.txt",
    "batch social sucrose/gateLog - 2022-12-16 femkoda337(3820)12wphase3.log.txt",
    "batch social sucrose/gateLog - 2022-12-19 femkoda338(3786)12wphase2.log.txt",
    "batch social sucrose/gateLog - 2023-01-04 femkoda339(3807)12wphase3.log.txt",
    "batch social sucrose/gateLog - 2023-01-06 femkoda340(3801)12wcompleted.log.txt",

    "batch social sucrose/gateLog - 2023-02-10 malekoda367(2od)12w.log.txt",
    "batch social sucrose/gateLog - 2022-09-26 maleKOda227(5584)12w.log.txt",
    "batch social sucrose/gateLog - 2023-02-07 malekoda365(od)12w.log.txt",
    "batch social sucrose/gateLog - 2023-01-16 maleko318(od)12w.log.txt",
    "batch social sucrose/gateLog - 2023-01-16 maleko319(og)12ws2.log.txt",

    "batch social sucrose/gateLog - 2023-01-30 femhetda379(2od)12w.log.txt",
    "batch social sucrose/gateLog - 2023-02-01 femhetda369(og)12w.log.txt",
    "batch social sucrose/gateLog - 2023-02-03 femhetda371(2og)12w.log.txt",
    "batch social sucrose/gateLog - 2023-01-25 femhetda378(og)12w.log.txt",
    ]
    '''

    files=[ "batch social sucrose/gateLog - 2023-02-20 malewtda372(od)12w-setup1.log.txt",
           "batch social sucrose/gateLog - 2023-03-01 malewtda372(od)12w-setup2.log.txt"
    ]

    for d in data:
        print ( d )

    files.reverse()

    i = 0
    #for d in data.values():
    for f in files:

        d = data[f]
        animals.append( f"{i}: {d['genotype']} {d['sex']} {d['age']}w\n{f.split(' ')[-1].split('.')[0]}" )
        x = 0
        endedTooSoon = False
        for p in range( 6 ):
            val = d["phaseDurations"][p]
            if val == None:
                val = 0
                if not endedTooSoon:
                    #ax.barh( y=i, width = 60*10, left=x, height=0.8, color='black' )
                    endedTooSoon = True

            #ax.barh(labels, widths, left=starts, height=0.5, label=colname, color=color)
            color = colors[p]
            rects = ax.barh( y=i, width = val, left=x, height=0.8, color=color, label="test")

            r, g, b, _ = color
            text_color = 'white' if r * g * b < 0.5 else 'darkgrey'
            if p!=5:
                if val!=0:
                    ax.text( x+val/2,i , toHM( val ) ,  ha="center", va="center" , color=text_color )

            #if p == 3: # phase 4
            if p ==5 :

                endPhase6 = d[ "endTimePhase6S"]
                if endPhase6 != None:
                    ax.barh( y=i, width = 600, left=x+endPhase6, height=0.9, color="red", label="end")
                    print( "duration : " , x, endPhase6, endPhase6-x )
                    ax.text( x+endPhase6/2, i , "goal reached in " + toHM( endPhase6 ) ,  ha="center", va="center" , color=text_color )

            x+=val

        i+=1

    animalLabels = []
    for animal in animals:
        animalLabels.append( animal.split(":")[-1] )
    plt.yticks( range( len( animals ) ), animalLabels )
    plt.xlim( 0 , 60*60*48 )

    ''' set x axis '''
    formatter = matplotlib.ticker.FuncFormatter( frameToTimeTicker )
    ax.xaxis.set_major_formatter(formatter)
    ax.tick_params(labelsize=8 )
    ax.xaxis.set_major_locator(ticker.MultipleLocator( 60 * 60 ))
    #ax.xaxis.set_minor_locator(ticker.MultipleLocator( 30 * 60 * 60 ))

    #colors = plt.get_cmap('hsv')( np.linspace(0.15, 0.85, 6 ))
    #print( colors )

    #ax.barh(labels, widths, left=starts, height=0.5, label=colname, color=color)

    '''
    b1 = plt.barh(animals, phases[0], color = colors[0] , stacked=True )
    b2 = plt.barh(animals, phases[1], color = colors[1] , stacked=True  )
    '''
    '''
    b3 = plt.barh(animals, phases[2], color = colors[2] )
    b4 = plt.barh(animals, phases[3], color = colors[3] )
    b5 = plt.barh(animals, phases[4], color = colors[4] )
    b6 = plt.barh(animals, phases[5], color = colors[5] )
    '''

    #plt.gca().axvline( 60 *60 * 47 )
    #plt.text( 1000 + 60 *60 * 48, 0, "47h experiment", rotation=90 )

    #b2 = plt.barh(year, issues_pending, left=issues_addressed, color="yellow")
    #plt.legend([b1, b2,b3,b4,b5,b6], ["Phase 1", "Phase 2","Phase 3","Phase 4", "Phase 5", "Phase 6"], title="Time in phases", loc="upper right")

    plt.tight_layout()
    plt.show()

if __name__ == '__main__':

    #compute()

    analyse()

    print("Done.")
    #plt.show()


import matplotlib.pyplot as plt
import numpy as np
import math
from matplotlib.ticker import FuncFormatter

w200 = np.load('data/da/rugosidade20.npy')

x = np.array(range(len(w200)))
y = w200

print(y);

titulo = 'Deposição Aleatória'
eixox ='Tempo (t)'
eixoy = 'Rugosidade w(L,t)'

plt.title(titulo)
plt.xlabel(eixox)
plt.ylabel(eixoy)

plt.plot(x,y,label='Substrato {0}'.format(200))
plt.legend()
plt.yscale('log')
plt.xscale('log')

plt.show()
# plt.savefig('data/da/' + titulo + '.png', dpi=300)


import random
import open3d as o3d

from grassdata_new import Part, Mesh, PartLabel, GRASSNewDataset
from aggregator import Aggregator

import copy
import numpy as np

from utils import reindex_faces

class RandomizedExtractor(object):
	def __init__(self, dataset):
		self.aggregator = Aggregator()
		self.dataset = dataset
		self.target_index, target = self.__choose_random_sample(dataset)
		self.target = copy.deepcopy(target)
		#self.target.set_mesh_and_parts_colour([1, 0, 0])
		self.set_colour_coded_sources(dataset) ############# ADD TO RESET TARGET?? ##############

	def __choose_random_sample(self, dataset):
		data_size = len(dataset)

		sample_idx = random.randint(0, data_size-1)
		sample = dataset[sample_idx]

		return sample_idx, sample

	def reset_target(self, dataset):
		idx = self.target_index
		while idx == self.target_index:
			self.target_index, target = self.__choose_random_sample(dataset)

		self.target = copy.deepcopy(target)
		#self.set_colour_coded_sources(self.dataset)

	def get_target_labels_with_bounding_box(self):
		assert(self.target is not None)

		bboxes_dict = {}
		for part in self.target.parts:
			if part.label not in bboxes_dict:
				bboxes_dict[part.label] = self.aggregator.get_super_bounding_box(self.target, part.label)

		return bboxes_dict

	def get_target_labels_with_parts(self):
		assert(self.target is not None)

		bboxes_dict = {}
		for part in self.target.parts:
			if part.label not in bboxes_dict:
				bboxes_dict[part.label] = self.aggregator.get_all_parts_by_label(self.target, part.label)

		return bboxes_dict

	def get_target_parts_by_label(self, label):
		return self.aggregator.get_all_parts_by_label(self.target, label)

	def make_target_parts_invisible_by_label(self, label):
		assert(self.target is not None)

		for part in self.target.parts:
			if part.label == label:
				part.render = False

	def add_parts_to_target(self, parts):
		assert(self.target is not None)

		self.target.parts.extend(parts)

	def replace_target_parts_by_label(self, label, parts):
		assert(self.target is not None)

		target_parts = []
		for part in self.target.parts:
			if part.label != label:
				target_parts.append(part)

		target_parts.extend(parts)
		self.target.parts = target_parts

	def find_source_part(self, dataset, label, iter_limit=10):
		bbox = None
		idx = self.target_index

		iter_count = 0
		while bbox is None or idx == self.target_index:
			idx, source_mesh = self.__choose_random_sample(dataset)
			parts, bbox = self.aggregator.get_parts_with_bounding_box(source_mesh, label)

			iter_count += 1
			if iter_count == iter_limit:
				break

		return parts, bbox

	def __reindex_faces(part_faces, new_offset=0):
		part_faces_np = np.asarray(part_faces, dtype=np.int32)
		part_faces_np = part_faces_np - np.amin(part_faces_np) + new_offset

		return part_faces_np

	def get_triangle_part_meshes(self, parts):
		triangle_meshes = []

		for part in parts:
			tri_mesh = o3d.geometry.TriangleMesh()
			tri_mesh.vertices = o3d.utility.Vector3dVector(np.asarray(part.vertices, dtype=np.float64))
			tri_mesh.triangles = o3d.utility.Vector3iVector(np.asarray(part.faces, dtype=np.int32))

			triangle_meshes.append(tri_mesh)

		return triangle_meshes

	def smooth_part_meshes(self, parts):
		triangle_meshes = self.get_triangle_part_meshes(parts)

		for part, mesh in zip(parts, triangle_meshes):
			mesh.filter_smooth_laplacian(number_of_iterations=3)

			part.vertices = np.asarray(mesh.vertices, dtype=np.float64).tolist()
			part.faces = np.asarray(mesh.triangles, dtype=np.int32).tolist()

		return parts

	def set_colour_coded_sources(self, dataset):
		data_size = len(dataset)
		cols = [[1,0,0],[0.2, 0.2, 0.6],[0.2, 0.7, 0.3],[1, 0.7, 0.2],[0.5, 0.1, 0.5],
          [1, 0.4, 0.4],[0.8, 0.5, 0.1],[1, 0, 0.5],[0.5, 0.6, 0.2],[0.3, 0.6, 0.9]]
		# List of colours
		# 1: Dark Blue, 2: Green, 3: Yellow, 4: Purple
		i=0

		for idx in range (data_size):
			if idx == self.target_index: # For target
				self.target.set_mesh_and_parts_colour(cols[i])
				#print("Setting colour for target with colour red at idx ", idx)
				#continue
			mesh = dataset[idx]
			print("Setting colour for ", idx, " with colour number ", i)
			mesh.set_mesh_and_parts_colour(cols[i])
			i = i + 1

	def get_source_meshes(self):
		data_size = len(self.dataset)
		meshes = []
		i=0

		for idx in range (data_size):
			if idx == self.target_index:
				continue
			meshes.append(self.dataset[idx])
		return meshes


from PyQt5.QtWidgets import QMainWindow
from PyQt5 import QtCore
from qt_designer.visual_interface import Ui_MainWindow
from cpf_app import CpfApp

class App(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()

        self.setupUi(self)

        self.cpf_app = CpfApp('')

        self.linedit_display.setReadOnly(True)

        self.btn_generate_cpf.clicked.connect(self.generate_cpf)

        self.btn_validate_cpf.clicked.connect(self.validate_cpf)

        self.btn_reset.clicked.connect(self.reset_app)

        self.linedit_display.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)

        self.linedit_cpf.setInputMask('999.999.999-99')

        self.DISPLAY_COLOR_NORMAL = '#888888'
        self.DISPLAY_COLOR_VALID_CPF = '#5bff5d'
        self.DISPLAY_COLOR_INVALID_CPF = '#ff5f5b'

        self.DISPLAY_TEXT_NORMAL = 'Enter the cpf...'
        self.DISPLAY_TEXT_VALID_CPF = 'Valid cpf.'
        self.DISPLAY_TEXT_INVALID_CPF = 'Invalid cpf.'

        self.reset_app()

    def generate_cpf(self):
        self.cpf_app.generate_cpf()
        self.linedit_cpf.setText(self.cpf_app.cpf)

    def validate_cpf(self):

        if len(self.linedit_cpf.text()) < 11:
            self.display_show('invalid', msg = 'Cpf must have 11 digits.')
            return

        validation = CpfApp.validate_cpf(self.linedit_cpf.text())

        if validation:
            self.display_show('valid')
        else:
            self.display_show('invalid')

    def display_show(self, result, msg = None):

        if result == 'valid':
            self.linedit_display.setStyleSheet(f'background-color: {self.DISPLAY_COLOR_VALID_CPF}')
            self.linedit_display.setText(self.DISPLAY_TEXT_VALID_CPF)
        elif result == 'invalid':
            self.linedit_display.setStyleSheet(f'background-color: {self.DISPLAY_COLOR_INVALID_CPF}')

            if msg:
                self.linedit_display.setText(msg)
            else:
                self.linedit_display.setText(self.DISPLAY_TEXT_INVALID_CPF)

        else:
            self.linedit_display.setStyleSheet(f'background-color: {self.DISPLAY_COLOR_NORMAL}')
            self.linedit_display.setText(self.DISPLAY_TEXT_NORMAL)

    def reset_app(self):
        self.linedit_cpf.setText('')
        self.display_show('normal')


import os
import re
from collections import defaultdict

from pathlib import Path

def process_input(input_path):
    mapping = {}
    with open(input_path, "r") as input_file:
        for line in input_file:
            signal = line.strip()
            match = re.match(r"Sensor at x=(-?\d+), y=(-?\d+): closest beacon is at x=(-?\d+), y=(-?\d+)", signal)
            if match:
                sx, sy, bx, by = map(int, match.groups())
                mapping[(sx, sy)] = (bx, by)
    return mapping

def calculate_distances(mapping):
    distances = {}
    for (sx, sy), (bx, by) in mapping.items():
        distances[(sx, sy)] = abs(sx - bx) + abs(sy - by)
    return distances

def apply_coverage(distances, beacons_map):
    min_i, min_j, max_i, max_j = 1000, 1000, -1000, -1000
    coverage_grid = defaultdict(lambda: defaultdict(lambda: "."))
    for (sj, si), distance in distances.items():
        for idx in range(-distance, distance + 1):
            for jdx in range(-distance, distance + 1):
                if abs(idx) + abs(jdx) > distance:
                    continue

                _i = si + idx
                _j = sj + jdx
                coverage_grid[_i][_j] = "#"

                min_i, min_j = min(min_i, _i), min(min_j, _j)
                max_i, max_j = max(max_i, _i), max(max_j, _j)

    for (sj, si), (bj, bi) in beacons_map.items():
        coverage_grid[si][sj] = "S"
        coverage_grid[bi][bj] = "B"

    return coverage_grid, min_i, min_j, max_i, max_j

def visualize(grid, coverage_grid, min_i, min_j, max_i, max_j):
    for idx in range(min_i, max_i + 1):
        print(f"{idx}:", end="")
        for jdx in range(min_j, max_j + 1):
            if (jdx, idx) in grid:
                print("S", end="")
            else:
                print(coverage_grid[idx][jdx], end="")
        print()

if __name__ == "__main__":
    input_path = os.path.join(Path(__file__).parent.absolute(), "input.txt")

    sensor_beacon_map = process_input(input_path)
    sensor_beacon_distance = calculate_distances(sensor_beacon_map)
    coverage_grid, min_i, min_j, max_i, max_j = apply_coverage(sensor_beacon_distance, sensor_beacon_map)

    query_row = 2000000
    count = 0
    row = coverage_grid[query_row]
    for value in row.values():
        if value == "#":
            count += 1
    # visualize(sensor_beacon_map, coverage_grid, min_i, min_j, max_i, max_j)
    print("1: ", count, min_j, max_j)


import cv2
import cv2.aruco as aruco
import numpy as np

def findArucoMarkers(img, markerSize=6, totalMarkers=250, draw=True):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    key = getattr(aruco, f'DICT_5X5_250')
    arucoDict = aruco.Dictionary_get(key)
    arucoParam = aruco.DetectorParameters_create()
    corners, ids, rejected = aruco.detectMarkers(gray, arucoDict, parameters=arucoParam)

    if len(corners) > 0:
        ids = ids.flatten()

        for (markerCounter, markerID) in zip(corners, ids):
            corners = markerCounter.reshape((4,2))
            (tl, tr, br, bl) = corners

            tr = (int(tr[0]), int(tr[1]))
            tl = (int(tl[0]), int(tl[1]))
            bl = (int(bl[0]), int(bl[1]))
            br = (int(br[0]), int(br[1]))

            cv2.putText(img, str(markerID), tl,cv2.FONT_HERSHEY_COMPLEX, 1, (0,255,0), 2, cv2.LINE_AA)

cap = cv2.VideoCapture(0)

while True:
    check, frame = cap.read()

    if check:
        findArucoMarkers(frame)
        cv2.imshow("image", frame)

    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()