import pygame
from ClsMenu import *
import sys
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD) #Define pinagem física (outra opção BCM)

GPIO.setup(8, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(10, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(40, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
class Game():
    #Tamanho da tela do jogo.
    DISPLAY_W, DISPLAY_H = 800, 600

    def __init__(self):
        pygame.init()
        self.running, self.playing = True, False
        self.UP_KEY, self.DOWN_KEY, self.START_KEY, self.BACK_KEY = False, False, False, False
        self.size = width, height = self.DISPLAY_W, self.DISPLAY_H
        self.display = pygame.Surface((self.DISPLAY_W,self.DISPLAY_H))
        self.window = pygame.display.set_mode(((self.DISPLAY_W,self.DISPLAY_H)))
        #self.font_name = '8-BIT WONDER.TTF'
        self.font_name = pygame.font.get_default_font()
        self.BLACK, self.WHITE = (0, 0, 0), (255, 255, 255)
        self.main_menu = MainMenu(self)
        self.options = OptionsMenu(self)
        self.credits = CreditsMenu(self)
        self.curr_menu = self.main_menu

    def game_loop(self):
        while self.playing:
            self.check_events()
            if self.START_KEY:
                self.playing= False
            self.display.fill(self.BLACK)
            self.draw_text('Thanks for Playing', 20, self.DISPLAY_W/2, self.DISPLAY_H/2)
            self.window.blit(self.display, (0,0))
            pygame.display.update()
            self.reset_keys()
            self.in_game_loop()

    def check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running, self.playing = False, False
                self.curr_menu.run_display = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    self.START_KEY = True
                if event.key == pygame.K_BACKSPACE:
                    self.BACK_KEY = True
                if event.key == pygame.K_DOWN:
                    self.DOWN_KEY = True
                if event.key == pygame.K_UP:
                    self.UP_KEY = True

    def reset_keys(self):
        self.UP_KEY, self.DOWN_KEY, self.START_KEY, self.BACK_KEY = False, False, False, False

    def draw_text(self, text, size, x, y ):
        font = pygame.font.Font(self.font_name,size)
        text_surface = font.render(text, True, self.WHITE)
        text_rect = text_surface.get_rect()
        text_rect.center = (x,y)
        self.display.blit(text_surface,text_rect)

    def in_game_loop(self):
        from ClsHand import Hand
        from ClsPizza import Pizza
        from ClsIngrediente import Ingrediente
        pegou = False #AJUSTAR VARIAVEL
        ingrediente =""
        Pizza = Pizza([(self.DISPLAY_W / 1.9), (self.DISPLAY_W * 1/6)])
        Hand = Hand([self.DISPLAY_H/10,self.DISPLAY_W/1.5])
        Molho = Ingrediente([self.DISPLAY_H/1.5,self.DISPLAY_W/1.7],"MolhoTomate.png")
        calabresa = Ingrediente([self.DISPLAY_H/2.0,self.DISPLAY_W/1.7],"calabresa.png")
        cogumelo = Ingrediente([self.DISPLAY_H/1.2,self.DISPLAY_W/1.7],"cogumelo.png")
        tomate = Ingrediente([self.DISPLAY_H / 3, self.DISPLAY_W / 1.7],"tomate.png")
        massa = Ingrediente([self.DISPLAY_H/6,self.DISPLAY_W/1.7],"massa.png")
        pygame.display.set_caption('Hand!')
        clock = pygame.time.Clock()
        screen = pygame.display.set_mode(self.size)
        black = 255, 255, 255
        delay = 0
        trava = 0
        entrou = False
        segurando = False
        while 1:
            # garante que o programa nao vai rodar a mais que 120fps
            clock.tick(120)
            delay +=1
            # checa eventos de teclado
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        Hand.move("LEFT","DOWN",self.size)
                    if event.key == pygame.K_RIGHT:
                        Hand.move("RIGHT","DOWN",self.size)
                    if event.key == pygame.K_SPACE:
                        if Hand.rect.colliderect(Molho.rect):
                            Hand.pega_ingrediente("molho")
                            pegou = True
                            ingrediente = "molho"
                        elif Hand.rect.colliderect(massa.rect):
                            Hand.pega_ingrediente("massa")
                            pegou = True
                            ingrediente = "massa"
                        elif Hand.rect.colliderect(cogumelo.rect):
                            Hand.pega_ingrediente("cogumelo")
                            pegou = True
                            ingrediente = "cogumelo"
                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_LEFT:
                        Hand.move("LEFT","UP",self.size)
                    if event.key == pygame.K_RIGHT:
                        Hand.move("RIGHT","UP",self.size)
                    if event.key == pygame.K_SPACE:
                        if pegou:
                            pegou = False
                            if Pizza.rect.colliderect(Hand.rect):
                                Hand.solta_ingrediente()
                                Pizza.solta_ingrediente(ingrediente)
                            else:
                                Hand.solta_ingrediente()
            if (GPIO.input(40) == 1) & (delay > trava):
                Hand.move("LEFT","DOWN",self.size)
                print("ESQUERDA")
                entrou = True
                trava = delay
            if (GPIO.input(8) == 1) & (delay > trava):
                Hand.move("RIGHT","DOWN",self.size)
                print("DIREITA")
                trava = delay
                entrou = True
            if (GPIO.input(10) == 1) & (delay > trava):
                print("MEIO")
                segurando = True
                if Hand.rect.colliderect(Molho.rect) & (ingrediente != "cogumelo"): #TA BATENDO NO MOLHO DE TOMATE AO PEGR COGUMELO
                    Hand.pega_ingrediente("molho")
                    pegou = True
                    ingrediente = "molho"
                elif Hand.rect.colliderect(massa.rect):
                    Hand.pega_ingrediente("massa")
                    pegou = True
                    ingrediente = "massa"
                elif Hand.rect.colliderect(cogumelo.rect):
                    Hand.pega_ingrediente("cogumelo")
                    pegou = True
                    ingrediente = "cogumelo"
            if pegou & (segurando == False):
                pegou = False
                if Pizza.rect.colliderect(Hand.rect):
                    Hand.solta_ingrediente()
                    Pizza.solta_ingrediente(ingrediente)
                else:
                    Hand.solta_ingrediente()
            # atualiza os  objetos
            print("velocidade:"+ str(Hand.velocidade_x))
            if (delay > trava) & (entrou == True) & (segurando == False):
                Hand.para_mao()
                entrou = False
            segurando = False
            Hand.update()
            # atualiza os objetos
            Hand.update()
            print(ingrediente)
            # redesenha a tela
            screen.fill(black)
            screen.blit(Pizza.image, Pizza.rect)
            screen.blit(Molho.image, Molho.rect)
            screen.blit(calabresa.image,calabresa.rect)
            screen.blit(cogumelo.image,cogumelo.rect)
            screen.blit(tomate.image,tomate.rect)
            screen.blit(massa.image,massa.rect)
            screen.blit(Hand.image, Hand.rect)

            pygame.display.flip()


# Copyright (C) 2023 by Nikodem "Med0kin" Kuliś
# This file is part of the intentsCreator project,
# and is released under the "MIT License Agreement".
# Please see the LICENSE file that should have been included
# as part of this package.

import json

def new_json() -> dict:
    intents = {
        "intents": []
    }
    return intents

def import_json(file_name: str) -> dict:
    with open(file_name, encoding='utf-8') as f:
        intents = json.load(f)
    existing_tags = [intent['tag'] for intent in intents['intents']]
    return intents

def export_json(file_name: str, intents: dict) -> None:
    with open(file_name, 'w', encoding='utf-8') as f:
        json.dump(intents, f, indent=4, ensure_ascii=False)

def add_tag(intents: dict, tag: str) -> dict:
    existing_tags = [intent['tag'] for intent in intents['intents']]
    if tag not in existing_tags:
        existing_tags.append(tag)
        # append tag, pattern and response to intents
        intents["intents"].append(
            {"tag": tag,
             "patterns": [],
             "responses": [],
             "context_set": ""}
            )
        return intents
    return False

def add_pattern(intents: dict, tag: str, pattern: str) -> dict:
    add_tag(intents, tag)
    # find the tag in intents
    for intent in intents["intents"]:
        if intent["tag"] == tag:
            # check if pattern already exists
            if pattern not in intent["patterns"]:
                intent["patterns"].append(pattern)
                return intents
    # return intents if pattern already exists
    return intents

def add_response(intents: dict, tag: str, response: str) -> dict:
    add_tag(intents, tag)
    # find the tag in intents
    for intent in intents["intents"]:
        if intent["tag"] == tag:
            # check if pattern already exists
            if response not in intent["responses"]:
                intent["responses"].append(response)
                return intents
    # return intents if pattern already exists
    return intents

def delete_tag(intents: dict, tag: str) -> dict:
    # find the tag in intents
    for intent in intents["intents"]:
        if intent["tag"] == tag:
            # delete tag
            intents["intents"].remove(intent)
            return intents
    # return intents if tag not exists
    return intents

def delete_pattern(intents: dict, tag: str, pattern: str) -> dict:
    # find the tag in intents
    for intent in intents["intents"]:
        if intent["tag"] == tag:
            # delete pattern
            intent["patterns"].remove(pattern)
            return intents
    # return intents if tag not exists
    return intents

def delete_response(intents: dict, tag: str, response: str) -> dict:
    # find the tag in intents
    for intent in intents["intents"]:
        if intent["tag"] == tag:
            # delete response
            intent["responses"].remove(response)
            return intents
    # return intents if tag not exists
    return intents

def get_tags(intents: dict) -> list:
    tags = []
    for intent in intents["intents"]:
        tags.append(intent["tag"])
    return tags

def get_patterns(intents: dict, tag: str) -> list:
    for intent in intents["intents"]:
        if intent["tag"] == tag:
            return intent["patterns"]

def get_responses(intents: dict, tag: str) -> list:
    for intent in intents["intents"]:
        if intent["tag"] == tag:
            return intent["responses"]

if __name__ == '__main__':
    # create new json file
    intents = new_json()
    intents = add_tag(intents, "greewting")
    intents = add_pattern(intents, "greeting", "hello there")
    intents = add_pattern(intents, "greeting", "howdy")
    intents = add_response(intents, "greeting", "Hello, thanks for asking")
    intents = add_response(intents, "greeting", "Hello, thanks for asking")
    intents = delete_pattern(intents, "greeting", "howdy")
    # write to json file
    export_json("intents.json", intents)


import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(1, 2, 100)

y = x**3 + 2*x*x - 6

plt.plot(x, y, color="blue", linewidth=2.0, linestyle='-',label="cosine")

# Establecer limites
plt.xlim(x.min() * 0.9, x.max() * 1.1)
plt.ylim(y.min() * 0.9, y.max() * 1.1)

## Moviendo los ejes al centro

ax = plt.gca()  # gca stands for 'get current axis'
ax.spines['right'].set_color('none') #borra eje derecho
ax.spines['top'].set_color('none')   #borra eje superior
ax.xaxis.set_ticks_position('bottom')  #mueve rayitas
ax.spines['bottom'].set_position(('data',0)) #mueve eje x
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',1)) # mueve eje y

## Mejorando las etiquetas

# fondo blancusco semi-transparente para las etiquetas
for label in ax.get_xticklabels() + ax.get_yticklabels():
    label.set_fontsize(16)
    label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.6))

## Ticks
#pl.xticks([],[])
#pl.yticks([],[])
#pl.legend(loc=0)

plt.show()


import torch
import torch.nn as nn

class TactileNet(nn.Module):

    def __init__(self, in_dim, out_dim):
        super(TactileNet, self).__init__()
        self.input_size = in_dim
        self.output_size = out_dim
        self.n_filters = 512

        self.lstm_layer = nn.LSTM(input_size=in_dim, hidden_size=in_dim, num_layers=1, batch_first=True)
        self.linear1 = nn.Linear(in_dim, self.n_filters)
        self.linear2 = nn.Linear(self.n_filters, self.n_filters // 4)
        self.linear3 = nn.Linear(self.n_filters // 4, out_dim)
        self.relu = nn.ReLU()

    def forward(self, x, hidden_state, cell_state):
        lstm_out, _ = self.lstm_layer(x, (hidden_state, cell_state))

        # Pass the data through all the linear layers
        lin_out = self.relu(self.linear1(lstm_out[:, -1, :]))
        lin_out = self.relu(self.linear2(lin_out))
        lin_out = self.relu(self.linear3(lin_out))

        return lin_out

    def init_hidden_states(self, device):
        h = torch.zeros(1, 1, self.input_size).float().to(device)
        c = torch.zeros(1, 1, self.input_size).float().to(device)

        return h, c


from tracardi.service.plugin.service.plugin_runner import run_plugin
from tracardi.domain.session import Session, SessionMetadata
from tracardi.process_engine.action.v1.strings.url_parser.plugin import ParseURLParameters

def test_url_plugin_fail():
    init = {
        "url": 'session@context.page.url'
    }
    payload = {}
    session = Session(
        id='1',
        metadata=SessionMetadata(),
        context={
            'page': {
                'none': "http://test.url/path/?param=1#hash"
            }
        }
    )
    try:
        run_plugin(ParseURLParameters, init, payload, session=session)
        assert False
    except KeyError:
        assert True

def test_url_parser_plugin_ok():
    init = {
        "url": 'session@context.page.url'
    }
    payload = {}
    session = Session(
        id='1',
        metadata=SessionMetadata(),
        context={
            'page': {
                'url': "http://test.url/path/?param=1#hash"
            }
        }
    )
    result = run_plugin(ParseURLParameters, init, payload, session=session)
    assert result.output.value == {'url': 'http://test.url/path/?param=1#hash', 'scheme': 'http',
                                   'hostname': 'test.url', 'path': '/path/', 'query': 'param=1',
                                   'params': {'param': '1'}, 'fragment': 'hash'}


import os
import re
import itertools
import logging
import pandas as pd
from slugify import slugify

from labonneboite.conf import settings
from labonneboite.common import mapping as mapping_util
from labonneboite.common import hiring_type_util
from labonneboite.common import geocoding
from labonneboite.common.search import HiddenMarketFetcher

logging.basicConfig(level=logging.INFO)

INPUT_FILENAME = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mailing_data/users_sample.csv')
INPUT_FILE_CSV_DELIMITER = ','
OUTPUT_FILENAME = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mailing_data/users_sample_prepared.csv')

COMMUNE_COLUMN = 'Code INSEE commune'
ROME_1_COLUMN = 'ROME'
ROME_2_COLUMN = 'ROME 2'

COLUMNS_FOR_EACH_OFFICE = ['siret', 'name', 'commune_id', 'url']
OFFICES_PER_USER = 5
ADDITIONAL_COLUMNS = ['search_url', 'used_distance', 'used_rome_id'] + \
    [
        'office%s_%s' % (1 + office_index, column_name)
    for office_index in range(OFFICES_PER_USER)
    for column_name in COLUMNS_FOR_EACH_OFFICE
] + \
    ['INFO1']  # stands for 'main_text'

DISTANCE_ATTEMPTS = [10, 20, 30, 50, 100, 200]

# is this mailing wip or for real?
IS_THIS_MAILING_WORK_IN_PROGRESS = False

# Google Analytics tracking
GA_TRACKING_MEDIUM = 'mailing'
GA_TRACKING_SOURCE = 'mailing_20180209_chaumont'  # FIXME carefully update date for every mailing

if IS_THIS_MAILING_WORK_IN_PROGRESS:
    GA_TRACKING_MEDIUM = "%s_wip" % GA_TRACKING_MEDIUM
    GA_TRACKING_SOURCE = "%s_wip" % GA_TRACKING_SOURCE

GA_TRACKING_SEARCH = 'utm_medium=%s&utm_source=%s&utm_campaign=%s_search' % (
    GA_TRACKING_MEDIUM, GA_TRACKING_SOURCE, GA_TRACKING_SOURCE)
GA_TRACKING_DETAIL = 'utm_medium=%s&utm_source=%s&utm_campaign=%s_detail' % (
    GA_TRACKING_MEDIUM, GA_TRACKING_SOURCE, GA_TRACKING_SOURCE)

SEND_ALL_EMAILS_TO_DEBUG_EMAIL = IS_THIS_MAILING_WORK_IN_PROGRESS

ENABLE_FAKE_METZ_INSEE_CODE_FOR_ALL = False  # sometimes convenient while working on local dev
METZ_INSEE_CODE = '57463'

def get_results(commune_id, rome_1_id, rome_2_id):
    """
    Try to find enough offices matching this commune_id,
    for either of the two provided rome_ids,
    and within as small of a distance as possible.

    The result is a dictionary:
    - offices found
    - distance which was eventually used for the result
    - rome_id which was eventually used for the result
    """
    if ENABLE_FAKE_METZ_INSEE_CODE_FOR_ALL:
        commune_id = METZ_INSEE_CODE

    city = geocoding.get_city_by_commune_id(commune_id)

    if city is None:
        return {'offices': [], 'distance': settings.DISTANCE_FILTER_DEFAULT, 'rome_id': rome_1_id}

    latitude = city['coords']['lat']
    longitude = city['coords']['lon']

    offices = []

    # the only case where those two stay None is if there is no result at all
    used_distance = None
    used_rome_id = None

    # itertools.product iterates over all combinations of values in multiple lists, see:
    # https://stackoverflow.com/questions/16384109/iterate-over-all-combinations-of-values-in-multiple-lists-in-python
    for distance, rome_id in itertools.product(DISTANCE_ATTEMPTS, [rome_1_id, rome_2_id]):
        if mapping_util.rome_is_valid(rome_id):
            naf_code_list = mapping_util.map_romes_to_nafs([rome_id])
            # FIXME randomize per user to avoid spamming companies
            fetcher = HiddenMarketFetcher(
                naf_codes=naf_code_list,
                romes=[rome_id],
                latitude=latitude,
                longitude=longitude,
                distance=distance,
                from_number=1,
                to_number=OFFICES_PER_USER,
                hiring_type=hiring_type_util.DPAE,
            )
            offices, _ = fetcher.get_offices()
            if len(offices) >= 1:
                used_rome_id = rome_id
                used_distance = distance
            if len(offices) >= OFFICES_PER_USER:
                break

    return {'offices': offices, 'distance': used_distance, 'rome_id': used_rome_id}

def get_search_url(commune_id, distance, rome_id):
    """
    Build search URL for given commune_id, distance and rome_id
    """
    if mapping_util.rome_is_valid(rome_id):
        rome_description = settings.ROME_DESCRIPTIONS[rome_id.upper()]
        slugified_rome_description = slugify(rome_description)
        city = geocoding.get_city_by_commune_id(commune_id)
        if city:
            # Here we hardcode the URL since this script typically runs in staging
            # for data confidentiality reasons and not in production.
            # However we need the resulting URLs to be pointing to production,
            # this is why we do not use `url_for`.
            search_url = 'https://labonneboite.pole-emploi.fr/entreprises/%s-%s/%s?d=%s&%s' % (
                city['slug'],
                city['zipcode'],
                slugified_rome_description,
                distance,
                GA_TRACKING_SEARCH,
            )
            return search_url
        else:
            logging.info("WARNING city not found : %s", commune_id)
    else:
        logging.info("WARNING invalid rome_code : %s", rome_id)

    return None

def compute_additional_data(commune_id, rome_1_id, rome_2_id):
    """
    Compute value of all additional CSV columns for a given commune_id and rome_id.
    """
    results = get_results(commune_id, rome_1_id, rome_2_id)
    offices = results['offices']
    distance = results['distance']
    rome_id = results['rome_id']

    search_url = get_search_url(commune_id, distance, rome_id)
    values = [search_url, distance, rome_id]

    def url_from_siret(siret):
        return 'https://labonneboite.pole-emploi.fr/%s/details?%s' % (
            siret,
            GA_TRACKING_DETAIL,
        )

    for i in range(OFFICES_PER_USER):
        # about try except else
        # see https://stackoverflow.com/questions/16138232/is-it-a-good-practice-to-use-try-except-else-in-python
        try:
            office = offices[i]
        except IndexError:
            values += [''] * len(COLUMNS_FOR_EACH_OFFICE)
        else:
            office_url = url_from_siret(office.siret)
            # names of these columns are in COLUMNS_FOR_EACH_OFFICE
            values += [office.siret, office.name, office.city_code, office_url]

    list_text = ''.join(
        ["
%s
" % (url_from_siret(o.siret), o.name) for o in offices]
    )

    # For the record GMS does not directly support utf8 characters with accent (e.g. 'é').
    # It also does not support html encoding (e.g. 'é') as it breaks at the `;`.
    main_text = "
%s
" % list_text

    # remove new lines
    main_text = main_text.strip().replace('\n', '').replace('\r', '')
    # remove duplicate spaces
    main_text = re.sub(' +', ' ', main_text)
    values += [main_text]

    return values

def prepare_mailing_data():
    """
        Enrich CSV user data in order to prepare mailing.
    """
    df = pd.read_table(INPUT_FILENAME, sep=INPUT_FILE_CSV_DELIMITER)

    # compute additional columns and add them to initial dataframe
    # inspired by
    # https://stackoverflow.com/questions/16236684/apply-pandas-function-to-column-to-create-multiple-new-columns
    # and https://stackoverflow.com/questions/13331698/how-to-apply-a-function-to-two-columns-of-pandas-dataframe
    temp = list(zip(*df[[COMMUNE_COLUMN, ROME_1_COLUMN, ROME_2_COLUMN]
                        ].apply(lambda x: compute_additional_data(*x), axis=1)))
    for index, column in enumerate(ADDITIONAL_COLUMNS):
        df[column] = temp[index]

    raw_total_rows = len(df)

    # delete rows with empty or buggy results
    # df = df[condition] will remove from df all rows which do not match condition
    df = df[df.search_url.isnull() == False]  # noqa
    df = df[df.office1_url.isnull() == False]  # noqa

    net_total_rows = len(df)
    empty_rows = raw_total_rows - net_total_rows
    logging.info("deleted %s empty rows out of %s", empty_rows, raw_total_rows)

    # custom manipulation of email column
    if 'Courriel' not in df.columns:
        raise Exception('required column Courriel is missing')
    df.rename(columns={'Courriel': 'EMAIL1'}, inplace=True)
    if SEND_ALL_EMAILS_TO_DEBUG_EMAIL:
        df.EMAIL1 = "labonneboite.pe@gmail.com"

    # index=False avoids writing leading index column
    # encoding='ascii' is the default, see
    # https://stackoverflow.com/questions/31331358/unicode-encode-error-when-writing-pandas-df-to-csv
    df.to_csv(OUTPUT_FILENAME, sep=',', index=False, encoding='utf-8')

    logging.info("please consult result in file %s", OUTPUT_FILENAME)

if __name__ == '__main__':
    prepare_mailing_data()


from arizona.asr.learner import Wav2AsrLearner

learner = Wav2AsrLearner(
    pretrain_model='path/to/pretrain.pt',
    finetune_model='path/to/finetune.pt',
    dictionary='path/to/dict.ltr.txt',
    lm_type='kenlm',
    lm_lexicon='path/to/lm/lexicon.txt',
    lm_model='path/to/lm/lm.bin',
    lm_weight=1.5,
    word_score=-1,
    beam_size=50
)

hypos = learner.transcribe([
    './data/test_1.wav',
    './data/test_1.wav'
])

print("===")
print(hypos)


import os

from ml_project.train_pipeline import train_pipeline
from ml_project.entities import read_training_pipeline_params

CONFIG_PATH = "ml_project/configs/test_config.yaml"

def test_train_metrics():

    params = read_training_pipeline_params(CONFIG_PATH)
    metrics = train_pipeline(params)

    assert {"precision", "recall", "f1_score"} == metrics.keys(), f"Unexpected metrics output {metrics.keys()}"
    assert metrics["f1_score"] > .5, f"F1 score {metrics['f1_score']} < 0.5"
    assert os.path.isfile(params.output_model_path), f"No such file {params.output_model_path}"
    assert os.path.isfile(params.metric_path), f"No such file {params.metric_path}"


import threading
import time
import random

class BankAccount(threading.Thread):

    account_balance = 100

    def __init__(self, name, money_request):
        threading.Thread.__init__(self)

        self.name=name
        self.money_request = money_request

    def run(self):
        account_lock.acquire()

        BankAccount.get_money(self)

        account_lock.release()

    @staticmethod
    def get_money(customer):
        print("{} tries to withdraw ${} at {}".format(customer.name,
                                                      customer.money_request,
                                                      time.strftime("%H:%M:%S",time.gmtime())))

        if BankAccount.account_balance - customer.money_request > 0:
            BankAccount.account_balance -= customer.money_request
            print("Refreshed account balance: PLN{}".format(BankAccount.account_balance))

        else:
            print("No money")
            print("Current balance is PLN {}".format(BankAccount.account_balance))

        time.sleep(3)

account_lock = threading.Lock()

adams_account = BankAccount("Adam", 1)
beatas_account = BankAccount("Beata", 100)
celinas_account = BankAccount("Celina", 50)

adams_account.start()
beatas_account.start()
celinas_account.start()

adams_account.join()
beatas_account.join()
celinas_account.join()

print("end of program")


from utils import get_centroids, get_cossim, calc_loss
import torch
import torch.nn as nn
import torch.nn.functional as F

class FeatureExtractionCNN(nn.Module):
    def __init__(self, input_size, num_classes):
        super(FeatureExtractionCNN, self).__init__()
        self.conv1 = nn.Conv1d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv1d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1)
        self.pool = nn.MaxPool1d(kernel_size=2, stride=2)
        self.fc1 = nn.Linear(input_size // 2 * 64, 512)  # Adjust the input size based on the pooling
        self.fc2 = nn.Linear(512, num_classes)

    def forward(self, x):
        x = x.view(x.size(0), 1, -1)  # reshape to (batch_size, num_channels, length)
        x = self.pool(nn.functional.relu(self.conv1(x)))
        x = self.pool(nn.functional.relu(self.conv2(x)))
        x = x.view(x.size(0), -1)  # flatten
        x = nn.functional.relu(self.fc1(x))
        x = self.fc2(x)
        x = nn.functional.normalize(x, p=2, dim=1)
        return x

class Conv1DNet(nn.Module):
    def __init__(self, input_size, num_classes=512, dropout_prob=0.5):
        super(Conv1DNet, self).__init__()
        self.conv1 = nn.Conv1d(1, 16, kernel_size=4, stride=4, padding=1)
        self.conv2 = nn.Conv1d(16, 32, kernel_size=3, stride=2, padding=1)
        self.fc1 = nn.Linear(input_size // 8 * 32, 1024)
        self.fc2 = nn.Linear(1024, num_classes)
        self.dropout = nn.Dropout(dropout_prob)

    def forward(self, x):
        x = x.view(x.size(0), 1, -1)  # reshape to (batch_size, num_channels, length)
        x = F.relu(self.conv1(x))
        # x = self.pool1(x)
        x = self.dropout(x)
        x = F.relu(self.conv2(x))
        # x = self.pool2(x)
        x = self.dropout(x)
        x = x.view(x.size(0), -1)  # flatten
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        # x = F.normalize(x, p=2, dim=1)
        return x

class Conv1DDecoder(nn.Module):
    def __init__(self, input_size, num_classes=512, dropout_prob=0.5):
        super(Conv1DDecoder, self).__init__()
        self.fc1 = nn.Linear(num_classes, 1024)
        self.fc2 = nn.Linear(1024, input_size // 8 * 32)
        self.deconv1 = nn.ConvTranspose1d(32, 32, kernel_size=3, stride=2, padding=1, output_padding=1)
        self.deconv2 = nn.ConvTranspose1d(32, 1, kernel_size=4, stride=4, padding=0, output_padding=0)
        self.dropout = nn.Dropout(dropout_prob)

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = F.relu(self.fc2(x))
        x = x.view(x.size(0), 32, -1)  # reshape to (batch_size, num_channels, length)
        x = F.relu(self.deconv1(x))
        x = self.dropout(x)
        x = F.relu(self.deconv2(x))
        x = x.view(x.size(0), -1)  # flatten
        return x

class Conv1DAutoencoder(nn.Module):
    def __init__(self, input_size, num_feature=256, dropout_prob=0.5):
        super(Conv1DAutoencoder, self).__init__()
        self.encoder = Conv1DNet(input_size, num_feature, dropout_prob)
        self.decoder = Conv1DDecoder(input_size, num_feature, dropout_prob)

    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return encoded, decoded

class Conv1DExtractor(nn.Module):
    def __init__(self, input_size, dim_features=49):
        super(Conv1DExtractor, self).__init__()
        self.conv1 = nn.Conv1d(1, 64, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv1d(64, 128, kernel_size=3, stride=1, padding=1)
        self.fc1 = nn.Linear(input_size * 128, 256)  # input_size * output channels of last Conv1d layer
        self.fc2 = nn.Linear(256, dim_features)

    def forward(self, x):
        x = x.view(x.size(0), 1, -1)  # reshape to (batch_size, num_channels, length)
        x = nn.functional.relu(self.conv1(x))
        x = nn.functional.relu(self.conv2(x))
        x = x.view(x.size(0), -1)  # flatten
        x = nn.functional.relu(self.fc1(x))
        x = self.fc2(x)
        return x

class Classifier(nn.Module):
    def __init__(self, input_size, num_classes=10):
        super(Classifier, self).__init__()

        self.layers = nn.Sequential(
            nn.Linear(input_size, 64),
            nn.ReLU(),
            nn.Linear(64, num_classes)
        )

    def forward(self, x):
        x = x.view(x.size(0), -1)
        x = self.layers(x)
        return x

class GE2ELoss(nn.Module):

    def __init__(self, device):
        super(GE2ELoss, self).__init__()
        self.w = nn.Parameter(torch.tensor(10.0).to(device), requires_grad=True)
        self.b = nn.Parameter(torch.tensor(-5.0).to(device), requires_grad=True)
        self.device = device

    def forward(self, embeddings):
        torch.clamp(self.w, 1e-6)
        centroids = get_centroids(embeddings)
        cossim = get_cossim(embeddings, centroids)
        sim_matrix = self.w * cossim.to(self.device) + self.b
        loss, _, _, _ = calc_loss(sim_matrix)
        return loss

class STFTFeatureExtractor2D(nn.Module):
    def __init__(self, input_shape, num_classes=256, lstm_hidden_size=1024):
        super(STFTFeatureExtractor2D, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)

        # Add LSTM layer
        self.lstm = nn.LSTM(input_size=800,
                            hidden_size=lstm_hidden_size,
                            num_layers=1,
                            batch_first=True)  # Set batch_first to True

        self.fc1 = nn.Linear(lstm_hidden_size, 512)
        self.fc2 = nn.Linear(512, num_classes)

    def forward(self, x):
        # Add a single channel dimension to the input (batch_size, 1, w, l)
        x = x.unsqueeze(1)

        # Apply convolutional layers
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, kernel_size=2, stride=2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, kernel_size=2, stride=2)

        # Transpose the input to (batch_size, l, w*32)
        x = x.transpose(1, 2).contiguous()
        x = x.view(x.size(0), x.size(1), -1)

        # Apply LSTM layer along the time dimension
        x, _ = self.lstm(x)

        # Apply fully connected layers
        x = x[:, -1, :]  # Use only the last output of the LSTM as the feature representation
        x = F.relu(self.fc1(x))
        x = self.fc2(x)

        return x

class CNNModule(nn.Module):
    def __init__(self):
        super(CNNModule, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, kernel_size=3, stride=1, padding=1)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1)

    def forward(self, x):
        # Add a single channel dimension to the input (batch_size, 1, w, l)
        x = x.unsqueeze(1)

        # Apply convolutional layers
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, kernel_size=2, stride=2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, kernel_size=2, stride=2)

        # Transpose the input to (batch_size, l, w*32)
        x = x.transpose(1, 2).contiguous()
        x = x.view(x.size(0), x.size(1), -1)

        return x

class LSTMModule(nn.Module):
    def __init__(self, lstm_hidden_size):
        super(LSTMModule, self).__init__()
        self.lstm = nn.LSTM(input_size=800,
                            hidden_size=lstm_hidden_size,
                            num_layers=1,
                            batch_first=True)  # Set batch_first to True

    def forward(self, x):
        # Apply LSTM layer along the time dimension
        x, _ = self.lstm(x)
        return x

class FCModule(nn.Module):
    def __init__(self, input_size, num_classes):
        super(FCModule, self).__init__()
        self.fc1 = nn.Linear(input_size, 512)
        self.fc2 = nn.Linear(512, num_classes)

    def forward(self, x):
        # Apply fully connected layers
        x = x[:, -1, :]  # Use only the last output of the LSTM as the feature representation
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

class SpeechEmbedder(nn.Module):

    def __init__(self, n_stft=84, n_hidden=256, num_layers=3, n_features=128):
        super(SpeechEmbedder, self).__init__()
        self.LSTM_stack = nn.LSTM(n_stft, n_hidden, num_layers=num_layers, batch_first=True)
        for name, param in self.LSTM_stack.named_parameters():
            if 'bias' in name:
                nn.init.constant_(param, 0.0)
            elif 'weight' in name:
                nn.init.xavier_normal_(param)
        self.projection = nn.Linear(n_hidden, n_features)

    def forward(self, x):
        x, _ = self.LSTM_stack(x.float())  # (batch, frames, n_mels)
        # only use last frame
        x = x[:, x.size(1) - 1]
        x = self.projection(x.float())
        x = x / torch.norm(x, dim=1).unsqueeze(1)
        return x


import time
from lib.loss_interface import LossInterface
from lib.loss_interface import Loss

class DeepfaceeditingLoss(LossInterface):
    def __init__(self, args):
        super(DeepfaceeditingLoss,self).__init__(args)

    def get_loss_G(self, G_dict):
        L_G = 0.0
        if self.args.W_recon:
            L_recon = Loss.get_cycle_loss(self.args, G_dict["I_target"], G_dict["I_target_recon"])
            L_G += self.args.W_recon * L_recon

        if self.args.W_swap:
            L_swap = Loss.get_swap_loss(self.args, G_dict["I_source"], G_dict["I_source_recon"])
            L_G += self.args.W_swap * L_swap

        if self.args.W_adv:
            L_adv = Loss.get_hinge_loss(G_dict["g_result"], True)
            L_G += self.args.W_adv * L_adv

        # save in dict
        self.loss_dict["L_G"] = round(L_G.item(), 4)
        self.loss_dict["L_recon"] = round(L_recon.item(), 4)
        self.loss_dict["L_swap"] = round(L_swap.item(), 4)
        self.loss_dict["L_adv"] = round(L_adv.item(), 4)

        return L_G

    def get_loss_D(self, D_dict):
        # L_real = Loss.get_hinge_loss(D_dict["d_target"], True)
        # L_fake = Loss.get_hinge_loss(D_dict["d_result"], False)
        # L_D_real_t = Loss.get_BCE_loss(D_dict["d_target"], True)
        # L_D_real_s = Loss.get_BCE_loss(D_dict["d_source"], True)
        # L_D_fake = Loss.get_BCE_loss(D_dict["d_result"], False)
        # L_D_fake_t_recon = Loss.get_BCE_loss(D_dict["d_target_recon"], False)
        # L_D_fake_s_recon = Loss.get_BCE_loss(D_dict["d_source_recon"], False)
        L_D_real_t = Loss.get_hinge_loss(D_dict["d_target"], True)
        L_D_real_s = Loss.get_hinge_loss(D_dict["d_source"], True)
        L_D_fake = Loss.get_hinge_loss(D_dict["d_result"], False)
        # L_D_fake_t_recon = Loss.get_hinge_loss(D_dict["d_target_recon"], False)
        # L_D_fake_s_recon = Loss.get_hinge_loss(D_dict["d_source_recon"], False)

        # L_reg = Loss.get_r1_reg(L_D_real, D_dict["I_target"])
        L_D = (L_D_real_t + L_D_real_s + L_D_fake)*0.3333# + L_D_fake_t_recon + L_D_fake_s_recon# + L_reg

        # L_D = self.args.W_adv * (L_real + L_fake) * 0.5
        self.loss_dict["L_D"] = round(L_D.item(), 4)

        return L_D

    def print_loss(self, global_step):
        seconds = int(time.time() - self.start_time)

        print("")
        print(f"[ {seconds//3600//24:02}d {(seconds//3600)%24:02}h {(seconds//60)%60:02}m {seconds%60:02}s ]")
        print(f'steps: {global_step:06} / {self.args.max_step}')
        # print(f'lossG: {self.loss_dict["L_G"]}')
        print(f'lossD: {self.loss_dict["L_D"]} | lossG: {self.loss_dict["L_G"]}')


from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['a'].append(4)

print(d)

d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)

print(d)

# 注意, py的dict如果key不存在直接append会有异常抛出


import os, sys, binascii
from shutil import copyfile

def main():

    #command line arguments:
    #  /exe (default)
    #  /lib
    #  projectName
    srcDir    = '.\\';
    outputExe  = True;
    outputLib  = False;
    outputDll  = False;
    includeAdd = False;
    mocDir     = "";
    projectDir = srcDir;
    projectName = "Unnamed";
    mixFiles   = False;
    winNaming  = True;
    embNaming  = False;

    cfgType = 1;

    if (len(sys.argv)==1):
        print("");
        print("vcproj (c) 2021 Ondrej Sterba, osterba@atlas.cz");
        print("       (visual studio project generator)       ");
        print("");
        print('Command line arguments:');
        print('  /exe  - executable project');
        print('  /dll  - dynamic library project');
        print('  /lib  - static library project');
        print('  (choose just one from those three)');
        print('  ----------------------------------');
        print("  /incl - adds all header directories into project settings");
        print("  /mix  - dont separate header files and source files");
        print("  /win  - windows naming conventions");
        print("  /emb  - embedded systems naming conventions");
        print('  /moc:filepath - directory with qt moc_* files');
        print('  ----------------------------------');
        print("  projectname   - last parameter is a project name");
        print("  -----------------------------------'");
        print("  Examples how to use vcproj.py:");
        print("  vcproj.py");
        print("    -shows this help");
        print("  vcproj.py test");
        print("    -generates test.vcproj executable project file with default settings");
        print("  vcproj.py /lib test");
        print("    -generates static library project named test.vcproj");
        print("  vcproj.py /dll /target:.\\ide\\vs2008");
        print("    -generates dll project and stores it into ide\\vs2008 directory");
        print("  vcproj.py /lib /moc:.\\build myproject");
        print("    -generates static lib and also adds Qt MOC files into project");
        print("  vcproj.py /lib /src:.\\lib_test /moc:.\\build");
        print("    -generates static lib, source codes from lib_test directory, qt moc files are read from .\\build directory");
        return;

    first = True;
    for arg in sys.argv:
        if not first:
            if (arg.startswith('/')):
                if (arg.startswith('/src:')):
                    srcDir = arg[5:];
                    if (not srcDir.endswith('\\')):
                        srcDir = srcDir + '\\';
                if (arg.startswith('/target:')):
                    projectDir = arg[8:];
                    if (not projectDir.endswith('\\')):
                        projectDir = projectDir + '\\';
                if (arg=="/exe"):
                    outputExe = True;
                    cfgType = 1;
                if (arg=='/lib'):
                    outputLib = True;
                    cfgType = 4;
                if (arg=='/dll'):
                    outputDll = True;
                    cfgType = 2;
                if (arg=="/incl"):
                    includeAdd = True;
                if (arg=="/mix"):
                    mixFiles = True;
                if (arg=="/win"):
                    winNaming = True;
                    embNaming = False;
                if (arg=="/emb"):
                    embNaming = True;
                    winNaming = False;
                if (arg.startswith('/moc:')):
                    mocDir = arg[5:];
            else:
                projectName = arg;
        first = False;

    #debugging commands:

    #end of debugging commands
    if (outputExe==False) and (outputLib==False) and (outputDll == False):
        outputExe=True;

    if (outputExe):
        cfgType = 1;
    if (outputLib):
        cfgType = 4;
    if (outputDll):
        cfgType = 2;

    if (len(srcDir) > 0):
        if (srcDir[-1]!='\\'):
            srcDir = srcDir + '\\';

    if (len(projectDir) > 0):
        if (projectDir[-1]!='\\'):
            projectDir = projectDir + '\\';

    if (len(mocDir) > 0):
        if (mocDir[-1]!='\\'):
            mocDir = mocDir + '\\';

    projectFile = projectName + ".vcproj";
    if (outputExe==True):
       outputFile = projectName + ".exe"
    if (outputLib==True):
        outputFile = projectName + ".lib"
    if (outputDll==True):
        outputFile = projectName + ".dll"

    #searhing for include directories
    dirs = [""];
    if (includeAdd):
        print("Scanning headers in ...");
        scanheaders(srcDir, dirs);

    #serching result is written to includeDirs variable
    includeDirs = "";
    first = True;
    basedir = "$(ProjectDir)";
    for dir in dirs:
        if not first:
            includeDirs = includeDirs + ";";
        if (len(dir)==0):
            includeDirs = includeDirs + basedir;
        else:
            includeDirs = includeDirs + basedir + dir[1:];
        first = False;

    includeLibs = "";
    includeLibDirs = ".\\libs";

    guid = "{";
    guid = guid + os.urandom(4).hex().upper() + '-';
    guid = guid + os.urandom(2).hex().upper() + '-';
    guid = guid + os.urandom(2).hex().upper() + '-';
    guid = guid + os.urandom(2).hex().upper() + '-';
    guid = guid + os.urandom(6).hex().upper() + '}';

    projectFile = projectDir + projectFile;

    f = open(projectFile, "w+");
    f.write('<VisualStudioProject\n');
    f.write('	ProjectType="Visual C++"\n');
    f.write('   Version="9.00"\n');
    f.write('   Name="' + projectName + '"\n');
    f.write('   ProjectGUID="' + guid + '"\n');
    f.write('   RootNamespace="' + projectName +'"\n');
    f.write('   Keyword="Win32Proj"\n');
    f.write('   TargetFrameworkVersion="196613">\n');
    f.write('   <Platforms>\n');
    f.write('   	<Platform Name="Win32" />\n');
    f.write('   </Platforms>\n');
    f.write('   <ToolFiles>\n');
    f.write('   </ToolFiles>\n');
    f.write('   <Configurations>\n');
    f.write('       <Configuration\n');
    f.write('           Name="Debug|Win32"\n');
    if (winNaming):
        f.write('           OutputDirectory="$(ProjectDir)\\$(ConfigurationName)"\n');
        f.write('           IntermediateDirectory="$(ProjectDir)\\$(ConfigurationName)\\obj"\n');
    if (embNaming):
        f.write('           OutputDirectory="$(ProjectDir)\\bin"\n');
        f.write('           IntermediateDirectory="$(ProjectDir)\\obj"\n');
    f.write('           ConfigurationType="' + str(cfgType) + ' "\n');
    f.write('           CharacterSet="1">\n');
    f.write('           <Tool\n');
    f.write('               Name="VCCLCompilerTool"\n');
    f.write('               Optimization="0"\n');
    f.write('               AdditionalIncludeDirectories="' + includeDirs + '"\n');
    f.write('               PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS"\n');
    f.write('               MinimalRebuild="true"\n');
    f.write('               BasicRuntimeChecks="3"\n');
    f.write('               RuntimeLibrary="1"\n');
    f.write('               UsePrecompiledHeader="0"\n');
    f.write('               WarningLevel="3"\n');
    f.write('               DebugInformationFormat="4" />\n');
    f.write('           <Tool\n');
    f.write('               Name="VCLinkerTool"\n');
    f.write('               AdditionalDependencies="' + includeLibs + '"\n');
    f.write('               OutputFile="$(OutDir)\\' + outputFile + '"\n');
    f.write('               LinkIncremental="2"\n');
    f.write('               AdditionalLibraryDirectories="' + includeLibDirs + '"\n');
    f.write('               GenerateDebugInformation="true"\n');
    f.write('               SubSystem="2"\n');
    f.write('               TargetMachine="1" />\n');
    f.write('       </Configuration>\n');
    f.write('       <Configuration\n');
    f.write('           Name="Release|Win32"\n');
    if (winNaming):
        f.write('           OutputDirectory="$(ProjectDir)\\$(ConfigurationName)"\n');
        f.write('           IntermediateDirectory="$(ProjectDir)\\$(ConfigurationName)\\obj"\n');
    if (embNaming):
        f.write('           OutputDirectory="$(ProjectDir)\\bin"\n');
        f.write('           IntermediateDirectory="$(ProjectDir)\\obj"\n');
    f.write('           ConfigurationType="' + str(cfgType) + '"\n');
    f.write('           CharacterSet="1"\n');
    f.write('           WholeProgramOptimization="1">\n');
    f.write('			<Tool\n');
    f.write('               Name="VCCLCompilerTool"\n');
    f.write('               Optimization="2"\n');
    f.write('               AdditionalIncludeDirectories="' + includeDirs + '"\n');
    f.write('               EnableIntrinsicFunctions="true"\n');
    f.write('               PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS"\n');
    f.write('               RuntimeLibrary="2"\n');
    f.write('               EnableFunctionLevelLinking="true"\n');
    f.write('               UsePrecompiledHeader="0"\n');
    f.write('               WarningLevel="3"\n');
    f.write('               DebugInformationFormat="3" />\n');
    f.write('           <Tool\n');
    f.write('               Name="VCLinkerTool"\n');
    f.write('               LinkIncremental="1"\n');
    f.write('               GenerateDebugInformation="true"\n');
    f.write('               SubSystem="2"\n');
    f.write('               OptimizeReferences="2"\n');
    f.write('               EnableCOMDATFolding="2"\n');
    f.write('               TargetMachine="1" />\n');
    f.write('       </Configuration>\n');
    f.write('   </Configurations>\n');
    f.write('   <Files>\n');

    print("Project directory: " + projectDir);
    print("Source code directory: " + srcDir);
    if (len(mocDir) > 0):
        print("Meta-object-class directory: " + mocDir);

    baseDir = os.path.relpath(srcDir, projectDir);
    if (len(baseDir)>0):
        if (baseDir[-1]!='\\'):
            baseDir = baseDir + '\\';

    os.chdir(projectDir);

    #searching for moc files and copying them to source files
    if (len(mocDir)>0):
        mocDir  = os.path.relpath(mocDir, projectDir);

    if (len(mocDir) > 0):
        if (mocDir[-1]!='\\'):
            mocDir = mocDir + '\\';

    mocFiles = {};
    if (len(mocDir)>0):
        print("Scanning qt Meta-Object-Class files...");
        scanmocfiles(mocDir, mocFiles);

    print("Scanning source files...");
    if (mixFiles == True):
        scansources(f, baseDir, mocFiles, {'.c', '.cpp', '.h', '.hpp'}, '    ');
    else:
        tabs = '    ';
        f.write(tabs+'<Filter\n'+tabs+'    Name="Header Files"\n'+tabs+'    >\n');
        scansources(f, baseDir, mocFiles, {'.h', '.hpp'}, '        ');
        f.write(tabs+"</Filter>\n");
        f.write(tabs  +'<Filter\n'+tabs+'    Name="Resource Files"\n'+tabs+'    >\n');
        scansources(f, baseDir, mocFiles, {'.bmp', '.ico', '.png', '.ico', '.jpg', '.jpeg'}, '        ');
        f.write(tabs+"</Filter>\n");
        f.write(tabs+'<Filter\n'+tabs+'    Name="Source Files"\n'+tabs+'    >\n');
        scansources(f, baseDir, mocFiles, {'.c', '.cpp', '.s', '.txt', '.ico'}, '        ');
        f.write(tabs+"</Filter>\n");

    f.write('   </Files>\n');
    f.write('</VisualStudioProject>\n');
    f.close();
    print("Project file created.");

def scanmocfiles(relpath, dirs):
    with os.scandir(relpath) as entries:
        for entry in entries:
            if (entry.is_dir()):
                if not (entry.name.startswith('.')):
                    scanmocfiles(relpath+entry.name+"\\", dirs);
            elif (entry.is_file()):
                if (entry.name.startswith('moc_')):
                        name = entry.name[4:];
                        dirs[name] = relpath + entry.name;

def scanheaders(relpath, dirs):
    with os.scandir(relpath) as entries:
        for entry in entries:
            if (entry.is_dir()):
                if not (entry.name.startswith('.')):
                    scanheaders(relpath+entry.name+"\\", dirs);
            elif (entry.is_file()):
                if (entry.name.endswith('.h')) or (entry.name.endswith('.hpp')):
                    if (not (relpath in dirs)):
                        dirs.append(relpath);

def filecount(path, extensions):
    count = 0;
    with os.scandir(path) as entries:
        for entry in entries:
            if (entry.is_dir()):
                count = count + filecount(path+entry.name+"\\", extensions);
            else:
                fileextpos = entry.name.rfind('.');
                fileext = entry.name[fileextpos:].lower();
                if (fileext in extensions):
                    count = count + 1;
    return count;

def scansources(projectFile, relpath, mocfiles, extensions, tabs):
    with os.scandir(relpath) as entries:
        mocs  = {};
        files = [];
        #scanning src files and moc files
        for entry in entries:
            if (entry.is_dir()):
                if not (entry.name.startswith('.')):
                    if (filecount(relpath+entry.name+"\\", extensions)>0):
                        projectFile.write(tabs+'<Filter\n'+tabs+'    Name="' + entry.name + '"\n'+tabs+'    >\n');
                        scansources(projectFile, relpath+entry.name+"\\", mocfiles, extensions, tabs + "    ");
                        projectFile.write(tabs+"</Filter>\n");
                    #end if
            elif (entry.is_file()):
                fileextpos = entry.name.rfind('.');
                fileext = entry.name[fileextpos:].lower();
                if (fileext in extensions):
                    files.append(relpath + entry.name);
                    if (entry.name in mocfiles.keys()):
                        mocs[entry.name] = mocfiles[entry.name];

        #adding moc files to project file
        if (len(mocs)>0):
            projectFile.write(tabs+'<Filter\n'+tabs+'    Name=".moc"\n'+tabs+'    >\n');
            newdir = relpath + '.moc';
            if (not os.path.isdir(newdir)):
                os.mkdir(newdir);
            for mockey in mocs.keys():
                moc_copy = newdir+ '\\moc_' + mockey;
                copyfile(mocfiles[mockey], moc_copy);
                projectFile.write(tabs+'    <File\n' +tabs+ '        RelativePath="' + moc_copy + '"\n' + tabs +'        >\n' +tabs+ '        </File>\n');
            projectFile.write(tabs+"</Filter>\n");

        #adding src files to project file
        if (len(files)>0):
            for file in files:
                projectFile.write(tabs+'<File\n' +tabs+ '    RelativePath="' + file + '"\n' + tabs +'    >\n' +tabs+ '</File>\n');
        #done

if __name__ == "__main__":
  main()


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

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

import os
import sys
sys.path.append('../../../..')

import argparse
import math
import cv2
import numpy as np
import csv
import glob
import yaml
import pickle
from multiprocessing import Pool
import shutil
import pickle
import copy
from sklearn.cluster import KMeans

from mysettings import FileManager, DLConfig
import align2d_merge
import align2d_config

import logging
from logging import basicConfig, Formatter, FileHandler, getLogger, DEBUG
# log_format = '[%(asctime)s %(levelname)s] %(name)s: %(message)s'
log_format = '[%(asctime)s %(levelname)s] %(message)s'
formatter = Formatter(log_format)
basicConfig(level=DEBUG, format=log_format, datefmt="%Y-%m-%d %H:%M:%S")
logger = getLogger(__name__)
fh = FileHandler('./log.txt')
fh.setFormatter(formatter)
logger.addHandler(fh)

def on_floor_height(z, floor_height, height):
    return z - floor_height >= 0 and z - floor_height < height

def fetch_on_floor_shots(tra_dict, center, height):
    shot_list = []
    for k in tra_dict:
        if on_floor_height(tra_dict[k][2], center - height/2, height):
            shot_list.append(k)
    return shot_list

def find_floors(tra_dict, height):
    z_list = []
    for k in tra_dict:
        z_list.append(tra_dict[k][2])

    # prepare for clustering
    z_list = np.array(z_list)
    z_list = np.c_[z_list, np.zeros(z_list.shape[0])]    # expand axis

    for clu_num in range(1, 6):
        km = KMeans(n_clusters=clu_num)
        km.fit(z_list)
        centers = km.cluster_centers_[:, 0]
        centers.sort()

        floor_heights = [centers[i + 1] - centers[i] for i in range(clu_num-1)]
        shot_nums = [len(fetch_on_floor_shots(tra_dict, centers[i], height)) for i in range(clu_num)]
        if clu_num == 1:
            c = centers[0]
            floor_candidates = centers
        if clu_num != 1 and all([height > 15 for height in floor_heights]) and all([n > 100 for n in shot_nums]) :
            floor_candidates = []
            floor_candidates = centers
            # print(clu_num, centers, shot_nums)

    floor_candidates.sort()
    floor_candidates = [math.floor(h - height/2 + 0.5) for h in floor_candidates]
    return floor_candidates

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='create score map')
    parser.add_argument('test_num_dir', help='path to data dir to be processed')
    parser.add_argument('-d', '--data', nargs='?', type=str, default='data.yaml', help='load data yaml file(default=data.yaml)')
    parser.add_argument('-f', '--target_floors', nargs='*', type=str, help='target floor names')
    parser.add_argument('-t', '--targets', nargs='*', type=str, help='target data names')
    parser.add_argument('-c', '--config', nargs='?', type=str, default='alignment2d_config.yaml', help='load config yaml file(defalut=alignment2d_config.yaml)')
    # parser.add_argument('-a', '--plot_all', default=False, action='store_true', help='create for all floor(default=False)')
    parser.add_argument('-j', '--process_num', nargs='?', type=int, default='4', help='process number(default=4)')
    # parser.add_argument('-m', '--mask_dir', nargs='?', type=str, default=None, help='path to walkable mask dir')
    # parser.add_argument('--load_align_result', default=False, action='store_true', help='load align result(default=False)')
    # parser.add_argument('--sort_by_z', default=False, action='store_true', help='sort by z(default=False)')
    # parser.add_argument('--merge', default=False, action='store_true', help='merge results(default=False)')
    parser.add_argument('--merge', default=False, action='store_true', help='run_merge(default=False)')
    # parser.add_argument('--eval_voxel', default=False, action='store_true', help='calc score by each voxel. non floor shot cannot be evaluated(20180521). (default=False).')
    args = parser.parse_args()

    run_merge = args.merge

    # set args
    config = align2d_config.Align2dConfig(args)
    # get target pairs
    target_pairs = config.get_target_pairs()
    for dn in target_pairs:
        logger.info('target pairs: {}'.format(dn))
        for floor in target_pairs[dn]:
            logger.info('    {}'.format(floor))

    for data_name in target_pairs:
        distribution_plot_data = {}

        # load trajectory
        tra_fn = config.fm.trajectory_fp(data_name)
        tra_dict = {}
        with open(tra_fn, 'r') as f:
            reader = csv.reader(f)
            for row in reader:
                k = row[0]
                x = int(row[1])
                y = int(row[2])
                z = float(row[4]) * config.pix_per_meter    # z will come in meter
                tra_dict[k] = [x, y, z]
        logger.info('load {} trajectory points from {}'.format(len(tra_dict), tra_fn))

        # calc trajectory size
        minx, miny, minz = 1000000000, 1000000000, 1000000000
        maxx, maxy, maxz = 0, 0, 0
        for shot in tra_dict:
            x, y, z = tra_dict[shot]
            minx, miny, minz = min(minx, x), min(miny, y), min(minz, z)
            maxx, maxy, maxz = max(maxx, x), max(maxy, y), max(maxz, z)
        logger.info('trajectory size = ({}, {}, {})'.format(maxx-minx, maxy-miny, int(math.ceil(maxz-minz))))

        # find floor heights
        floor_heights = find_floors(tra_dict, config.align_voxel_size[2])
        for h in floor_heights:
            logger.info('floor heights: {}'.format(h))

        actual_result = {}

        # calc soore for each floor
        for floor in target_pairs[data_name]:
            target_floor_dir = config.fm.t_floor_dir(data_name, floor)
            if not os.path.exists(target_floor_dir):
                logger.info('target floor not found: {}'.format(target_floor_dir))
                continue
            logger.info('target floor: {}'.format(floor))

            fp_fn = config.fm.floorplan_fp(floor)
            fp_img = cv2.imread(fp_fn)

            # load score
            score_fn_list = config.fm.score_fp_list(data_name, floor)
            score_fn_list.sort()
            score_fn_list = score_fn_list[::config.decimate]
            logger.info('load {} scores'.format(len(score_fn_list)))

            logger.info('create align result...')
            target_tra_dict = {}
            range_x, range_y = None, None
            score_yxz_dict = {}
            floormask_yxz_dict = {}
            score_map_count = None

            # create range_x and range_y
            floor_minx, floor_miny = 1000000000, 1000000000
            floor_maxx, floor_maxy = 0, 0
            ##  get floor mask size
            if config.load_wmask:
                if config.create_mask_from_score:    # create  load mask from score
                    score_fn = score_fn_list[0]
                    with open(score_fn, 'r') as f:
                        reader = csv.reader(f)
                        for row in reader:
                            x = int(row[0])
                            y = int(row[1])
                            floor_minx, floor_miny = min(floor_minx, x), min(floor_miny, y)
                            floor_maxx, floor_maxy = max(floor_maxx, x), max(floor_maxy, y)
                else:    # create mask from mask image
                    mask_fn = config.fm.wmask_fp(floor)
                    mask_img = cv2.imread(mask_fn)
                    mask_img = cv2.cvtColor(mask_img, cv2.COLOR_BGR2GRAY)
                    # mask_img = cv2.dilate(mask_img, np.ones((5, 5), np.uint8), iterations=1)
                    # mask_img = cv2.dilate(mask_img, np.ones((5, 5), np.uint8), iterations=1)

                    mask_map = np.zeros((fp_img.shape[0]//config.align_voxel_size[0], fp_img.shape[1]//config.align_voxel_size[1]), dtype=bool)
                    mask_map_voxel = np.zeros((fp_img.shape[0], fp_img.shape[1]), dtype=bool)
                    for y in range(config.crop_voxel_ratio_y//2, mask_map.shape[0], config.crop_voxel_ratio_y):
                        for x in range(config.crop_voxel_ratio_y//2, mask_map.shape[1], config.crop_voxel_ratio_x):
                            if np.sum(mask_img[y*config.align_voxel_size[1]-config.crop_step//2: y*config.align_voxel_size[1]+config.crop_step//2,
                                    x*config.align_voxel_size[0]-config.crop_step//2: x*config.align_voxel_size[0]+config.crop_step//2] > 0) > 0:
                                mask_map[y-config.crop_voxel_ratio_y//2:y+config.crop_voxel_ratio_y//2, x-config.crop_voxel_ratio_x//2:x+config.crop_voxel_ratio_x//2] = True
                                # mask_map_voxel[y*align_voxel_size[1]-crop_step//2: y*align_voxel_size[1]+crop_step//2, x*align_voxel_size[0]-crop_step//2: x*align_voxel_size[0]+crop_step//2] = True

                    # create range_x and range_y
                    ##  get walkable area mask size
                    mask_i = np.where(mask_map == True)
                    floor_minx, floor_miny = min(mask_i[1]) * config.align_voxel_size[1], min(mask_i[0]) * config.align_voxel_size[0]
                    floor_maxx, floor_maxy = max(mask_i[1]) * config.align_voxel_size[1], max(mask_i[0]) * config.align_voxel_size[0]
                    # create not floor map
                    not_floor = mask_map == False

                    # cv2.imwrite('/mnt/host/share/tmp/{}_mask_map.png'.format(floor), mask_map*255)
                    # cv2.imwrite('/mnt/host/share/tmp/{}_mask_ori.png'.format(floor), mask_img)
                    # cv2.imwrite('/mnt/host/share/tmp/{}_mask.png'.format(floor), mask_map_voxel*255)
                    # cv2.imwrite('/mnt/host/share/tmp/{}_mask.png'.format(floor), cv2.addWeighted(fp_img, 0.5, cv2.cvtColor((mask_map_voxel*255).astype(np.uint8), cv2.COLOR_GRAY2BGR), 0.5, 0.0))
                    # cv2.imwrite('/mnt/host/share/tmp/{}_mask_ori.png'.format(floor), cv2.addWeighted(fp_img, 0.5, cv2.cvtColor(mask_img.astype(np.uint8), cv2.COLOR_GRAY2BGR), 0.5, 0.0))
                    # cv2.imwrite('/mnt/host/share/tmp/{}.png'.format(floor), fp_img)
            else:    # not load wmask
                pass

            floor_minx -= int(config.crop_step/2)
            floor_miny -= int(config.crop_step/2)
            floor_maxx += int(config.crop_step/2)
            floor_maxy += int(config.crop_step/2)
            range_x = list(range(-(maxx-floor_minx), floor_maxx-minx, config.align_step[0]))
            range_y = list(range(-(maxy-floor_miny), floor_maxy-miny, config.align_step[1]))

            logger.info('floor mask size = ({}, {})'.format(floor_maxx - floor_minx, floor_maxy - floor_miny))
            logger.info('range x: {} to {}'.format(range_x[0], range_x[-1]))
            logger.info('range y: {} to {}'.format(range_y[0], range_y[-1]))
            # print(floor_heights)
            logger.info('total num: {}x{}x{}={}'.format(len(range_x), len(range_y), len(floor_heights), len(range_x)*len(range_y)*len(floor_heights)))

            ## load score map from csv
            logger.info('loading score map from csv...')
            score_map_dict = {}
            for score_fn in score_fn_list:
                shot_name = os.path.splitext(os.path.basename(score_fn))[0]+'.png'
                # score_map = np.zeros((fp_img.shape[0], fp_img.shape[1], 1), dtype=float)
                score_map = np.zeros((fp_img.shape[0]//config.align_voxel_size[1], fp_img.shape[1]//config.align_voxel_size[0], 1), dtype=float)

                score_map_voxel = np.zeros((fp_img.shape[0], fp_img.shape[1]), dtype=float)    # for debug
                if config.load_wmask and config.create_mask_from_score:
                    score_map += -1    # for out-range of floormask
                with open(score_fn, 'r') as f:
                    reader = csv.reader(f)
                    for row in reader:
                        x = (int(row[0]) - config.crop_step//2)//config.align_voxel_size[0]    # center to topleft
                        y = (int(row[1]) - config.crop_step//2)//config.align_voxel_size[1]    # center to topleft

                        if config.load_wmask and not config.create_mask_from_score and mask_map[y][x] == False:
                            # score_map[int(y-crop_step/2)//align_voxel_size[1]:int(y+crop_step/2)//align_voxel_size[1],
                            #           int(x-crop_step/2)//align_voxel_size[0]:int(x+crop_step/2)//align_voxel_size[0]] = -1
                            score_map[y: y + config.crop_voxel_ratio_y,
                                    x: x + config.crop_voxel_ratio_x] = -1
                            continue

                        score = float(row[2])
                        # score_map[int(y-crop_step/2):int(y+crop_step/2), int(x-crop_step/2):int(x+crop_step/2)] = score
                        # score_map[int(y-crop_step/2)//align_voxel_size[1]:int(y+crop_step/2)//align_voxel_size[1],
                        #           int(x-crop_step/2)//align_voxel_size[0]:int(x+crop_step/2)//align_voxel_size[0]] = score
                        score_map[y: y + config.crop_voxel_ratio_y,
                                x: x + config.crop_voxel_ratio_x] = score    # center to topleft
                        score_map_voxel[y*config.align_voxel_size[1]:y*config.align_voxel_size[1]+config.crop_step,
                                        x*config.align_voxel_size[0]:x*config.align_voxel_size[0]+config.crop_step] = score

                if config.load_wmask and not config.create_mask_from_score:
                    score_map[not_floor] = -1
                score_map_dict[shot_name] = score_map
                # cv2.imwrite('/mnt/host/share/tmp/{}_score_index.png'.format(shot_name), score_map*255)
                # cv2.imwrite('/mnt/host/share/tmp/{}_score_single.png'.format(shot_name), cv2.addWeighted(fp_img, 0.5, cv2.cvtColor((score_map_voxel*255).astype(np.uint8), cv2.COLOR_GRAY2BGR), 0.5, 0.0))
                # cv2.imwrite('/mnt/host/share/tmp/{}_score.png'.format(shot_name), score_map_voxel*255)

            # create score map of each translation(len(range_y)*len(range_x))
            logger.info('start to create score map of each translation')
            results = [[] for z in range(len(floor_heights))]

            def calc_score(arg):
                tra_y = arg[0]
                tra_x = arg[1]
                result = [None for z in range(len(floor_heights))]

                # count number of shots which hit floor
                hit_shot_list = []
                not_hit_shot_list = []
                for score_fn in score_fn_list:
                    shot_name = os.path.splitext(os.path.basename(score_fn))[0]+'.png'
                    if shot_name not in tra_dict:
                        continue
                    xyz = tra_dict[shot_name]
                    y = (xyz[1] + tra_y) // config.align_voxel_size[1]
                    x = (xyz[0] + tra_x) // config.align_voxel_size[0]
                    if y < 0 or y >= score_map_dict[shot_name].shape[0] or \
                                    x < 0 or x >= score_map_dict[shot_name].shape[1] or \
                                    score_map_dict[shot_name][y][x] < 0:    # out of range
                        not_hit_shot_list.append(shot_name)
                    else:
                        hit_shot_list.append(shot_name)
                if len(hit_shot_list) < config.hit_shot_count_threshold:
                    return result
                # count number of shots which hit each voxel
                # count_yxz = np.zeros((fp_img.shape[0], fp_img.shape[1], len(range_z)), dtype=int)
                count_yxz = np.zeros((fp_img.shape[0]//config.align_voxel_size[1], fp_img.shape[1]//config.align_voxel_size[0], len(floor_heights)), dtype=int)
                hit_voxel_count = [0 for z in range(len(floor_heights))]
                hit_shot_z_list = [[] for z in range(len(floor_heights))]
                for shot_name in hit_shot_list:
                    xyz = tra_dict[shot_name]
                    # y = ((xyz[1] + tra_y)//crop_step) * crop_step
                    # x = ((xyz[0] + tra_x)//crop_step) * crop_step
                    y = (xyz[1] + tra_y)//config.align_voxel_size[1]
                    x = (xyz[0] + tra_x)//config.align_voxel_size[0]

                    for z, floor_height in enumerate(floor_heights):
                        if on_floor_height(xyz[2], floor_height, config.align_voxel_size[2]):
                            # print(xyz[2], floor_height, shot_name)
                            hit_shot_z_list[z].append(shot_name)
                            if count_yxz[y, x, z] == 0:
                                hit_voxel_count[z] += 1
                            count_yxz[y, x, z] += 1

                # sum scores for each voxel
                for z in range(len(floor_heights)):
                    if hit_voxel_count[z] < config.floor_voxel_count_threshold:
                        continue

                    # print('z: ', z, ', len: ', len(hit_shot_z_list[z]), ', hit_shot_len: ', len(hit_shot_list), 'not_hit_shot_len', len(not_hit_shot_list))
                    score = 0.0
                    in_floor = hit_shot_z_list[z]
                    fire = []
                    c = 0
                    for shot_name in hit_shot_z_list[z]:
                        xyz = tra_dict[shot_name]
                        y = (xyz[1] + tra_y) // config.align_voxel_size[1]
                        x = (xyz[0] + tra_x) // config.align_voxel_size[0]
                        s = score_map_dict[shot_name][y][x]
                        if s > config.fire_threshold:
                            fire.append(shot_name)
                        # score += s/float(count_yxz[y][x][z]) if config.eval_voxel else s
                        score += s

                    # add non floor shot score
                    score += config.non_floor_score * len(not_hit_shot_list)

                    # average
                    # score /= float(floor_voxel_count[z]) if config.eval_voxel else float(len(score_fn_list))
                    score /= float(len(score_fn_list))

                    # print(score)

                    if score < config.good_consistency_threshold:
                        continue
                    sub_result = {}
                    sub_result['x'] = int(tra_x)
                    sub_result['y'] = int(tra_y)
                    sub_result['z'] = - int(floor_heights[z])
                    sub_result['score'] = float(score)
                    sub_result['in_floor'] = in_floor
                    sub_result['fire'] = fire
                    result[z] = sub_result
                return result

            # calc score for each

            for tra_y in range_y:
                arg = []
                for tra_x in range_x:
                    arg.append([tra_y, tra_x])
                p = Pool(config.process_num)
                result = p.map_async(calc_score, arg).get(9999999)
                for r in result:
                    for z in range(len(floor_heights)):
                        if r[z] is not None:
                            results[z].append(r[z])
                p.close()

            logger.info('finish to count number of shots 2d!!')

            logger.info('creating result dict to save')
            align_result = []
            for z, floor_height in enumerate(floor_heights):
                results[z].sort(key=lambda x: -x['score'])
                if len(results[z]) == 0:
                    continue
                logger.info('max score in z={:3d} is {:.8f}({}, {})(in {} candidates)'.format(-floor_height, results[z][0]['score'], results[z][0]['x'], results[z][0]['y'], len(results[z])))
                for i, result in enumerate(results[z]):
                    # if i > max_save_znum - 1:
                    #     break
                    align_result.append(result)

            if config.calc_correct:
                # get tra_x, tra_y, tra_z
                tra_floor_fn = config.fm.trajectory_floor_fp(data_name, floor)
                tra_fn = config.fm.trajectory_fp(data_name)    # for getting tra_z
                if not os.path.exists(tra_floor_fn) or not os.path.exists(tra_fn):
                    logger.info('{} does not belong to {}'.format(data_name, floor))
                else:
                    tra_floor_dict = {}
                    c = 0
                    tra_x, tra_y, tra_z = 0, 0, 0
                    #  calc tra_x and tra_y and tra_z
                    with open(tra_floor_fn, 'r') as f:
                        reader = csv.reader(f)
                        for row in reader:
                            k = row[0]
                            tra_x += int(row[1]) - tra_dict[k][0]
                            tra_y += int(row[2]) - tra_dict[k][1]
                            tra_z += float(row[4]) * config.pix_per_meter - tra_dict[k][2]
                            c += 1
                    tra_x /= c
                    tra_y /= c
                    tra_z /= c
                    tra_z += config.align_voxel_size[2]/2
                    tra_x, tra_y, tra_z = int(tra_x), int(tra_y), int(tra_z)
                    # print('actual tranclation ', tra_x, tra_y, tra_z)
                    # tra_z = - range_z[int((- tra_z - range_z[0])//config.align_step[2])]

                    actual = calc_score([tra_y, tra_x])
                    # actual = [tmp for tmp in actual if tmp is not None]
                    for r in actual:
                        if r is not None:
                            logger.debug('actual result cand: {} ({}, {}, {})'.format(r['score'], r['x'], r['y'], r['z']))

                    # get actual z
                    min_diff = 1000000000000000
                    act_z = None
                    for z, floor_height in enumerate(floor_heights):
                        diff = abs(tra_z + floor_height)
                        if diff < min_diff:
                            min_diff = diff
                            act_z = z
                        # print(z, floor_height, diff)
                    if actual[act_z] is None:
                        logger.warning('actual score not found: {} - {}'.format(data_name, floor))
                    else:
                        logger.info('actual score on {}: {:.8f} ({}, {}, {})'.format(floor, actual[act_z]['score'], actual[act_z]['x'], actual[act_z]['y'], actual[act_z]['z']))
                        actual = [actual[act_z]]
                        actual_result[floor] = actual

            data = {'align_result': align_result, 'actual_result': actual_result, 'range_x': range_x, 'range_y': range_y, 'range_z': None, 'floor_heights': floor_heights}
            config.fm.save_align_result(data_name, floor, data)
            logger.info('save align result to {}'.format(config.fm.align_result_fp(data_name, floor)))

        if run_merge:
            logger.info('select and plot candidates: {}'.format(config.fm.align_result_fp(data_name, floor)))
            config_tmp = copy.copy(config)
            config_tmp.targets = [data_name]
            config_tmp.target_floors = target_pairs[data_name]
            align2d_merge.run(config_tmp)


# import sys
# sys.path.insert(0, '/home/liheng/Desktop/protocol')
from core import Contract_pb2
import grpc
import api_pb2_grpc
import Tron_pb2
import api_pb2
from pprint import pprint

class GrpcServer:
    """
    grpc:通过protocbuf协议生成grpc.py文件,调用对应的功能接口
    """

    # def __init__(self, config):
    #     self.config = config

    def generateaddress(self):
        """
        生成充币钱包地址和私钥
        :return: private key, address
        """
        empty = api_pb2.EmptyMessage()
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = api_pb2_grpc.WalletStub(channel)
            response = stub.GenerateAddress(empty)
            # print('--------address%s' % response.address)
            # print(f'private key {response.privateKey}')
        return response

    def getaccount(self, account_address):
        """
        查询账号信息  account.address: b'TLCjmH6SqGK8twZ9XrBDWpBbfyvEXihhNS'
        :return:
        """
        # NOTE(gRPC Python Team): .close() is possible on a channel and should be
        # used in circumstances in which the with statement does not fit the needs
        # of the code.
        account = Tron_pb2.Account()
        account.address = account_address
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = api_pb2_grpc.WalletStub(channel)
            response = stub.GetAccount(account)
        return response

    def createtransaction(self, owner_address, to_address, amount):
        """
        创建一个转账的交易
        :return: 返回转账合约对象
        {
        "transaction" :
            {"txID":"454f156bf1256587ff6ccdbc56e64ad0c51e4f8efea5490dcbc720ee606bc7b8",
            "raw_data":
                {"contract":
                    [{"parameter":
                        {"value":
                            {"amount":1,
                             "owner_address":"41235d90e1d0a0ccfa268781f464e0252ba6112993",
                             "to_address":"41d1e7a6bc354106cb410e65ff8b181c600ff14292"
                            },
                            "type_url":"type.googleapis.com/protocol.TransferContract"
                        },
                        "type":"TransferContract"
                    }],
                    "ref_block_bytes":"267e",
                    "ref_block_hash":"9a447d222e8de9f2",
                    "expiration":1530893064000,
                    "timestamp":1530893006233
                }
            }
            ,"privateKey": "your private key"
        }
        """
        transfer = Contract_pb2.TransferContract()
        transfer.owner_address = owner_address.encode()
        transfer.to_address = to_address.encode()
        transfer.amount = amount
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = api_pb2_grpc.WalletStub(channel)
            response = stub.CreateTransaction2(transfer)
        return response

    def gettransactionsign(self, private_key):
        """
        对交易签名
        :return:
        """
        transsign = Tron_pb2.TransactionSign()
        transsign.privateKey = private_key
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = api_pb2_grpc.WalletStub(channel)
            response = stub.GetTransactionSign2(transsign)
        return response

    def broadcasttransaction(self, contract):
        """
        对签名后的transaction进行广播
        :return: 是否广播成功
        response_code {
                        SUCCESS = 0;
                        SIGERROR = 1; // error in signature
                        CONTRACT_VALIDATE_ERROR = 2;
                        CONTRACT_EXE_ERROR = 3;
                        BANDWITH_ERROR = 4;
                        DUP_TRANSACTION_ERROR = 5;
                        TAPOS_ERROR = 6;
                        TOO_BIG_TRANSACTION_ERROR = 7;
                        TRANSACTION_EXPIRATION_ERROR = 8;
                        SERVER_BUSY = 9;
                        OTHER_ERROR = 20;
                      }
        """
        transaction = Tron_pb2.Transaction()
        transaction.Contract = contract
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = api_pb2_grpc.WalletStub(channel)
            response = stub.BroadcastTransaction(transaction)
        return response

    def createaccount(self, from_address, account_address, ac_type):
        """
        创建账户
        :return: account 对象
        """
        accontract = Contract_pb2.AccountCreateContract()
        accontract.owner_address = from_address.encode()
        accontract.account_address = account_address.encode()
        accontract.tpye = Tron_pb2.AccountType()
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = api_pb2_grpc.WalletStub(channel)
            response = stub.CreateAccount2(accontract)
        return response

    def getaccountinfo(self, account_address):
        """
        查询账号信息  account.address: b'TLCjmH6SqGK8twZ9XrBDWpBbfyvEXihhNS'
        :return: 返回一个包含Account信息的对象
        """

        account = Tron_pb2.Account()
        account.address = account_address.encode()
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = api_pb2_grpc.WalletStub(channel)
            response = stub.GetAccount(account)
            print(type(response))
        return response

grpc1 = GrpcServer()
address = grpc1.generateaddress()
pprint(address)
rv = grpc1.getaccountinfo('TDCCjrC66CqCKvz55FUNa4r8x7xjrnopbv')
print(rv, '****************')
print('>>>>>>')

# rv = grpc1.createaccount('TDCCjrC66CqCKvz55FUNa4r8x7xjrnopbv', 'TGkX2DzfYNG11aV2Z3MC65Gvuexig11ctj', None)
# rv = grpc1.createtransaction('TGkX2DzfYNG11aV2Z3MC65Gvuexig11ctj', 'TTt6dZJjmk2gjCK5h739Pxjuq6gPMv7zjR', 1)
pprint(rv)


import numpy as np

# Check if all entries from file are numbers
def isAllNum(text):
    for i in text:
        if not i.isnumeric():
            return False
    return True

# Change a list of string to numbers
def strToNum(numlist):
    for i in range(0, len(numlist)):
        numlist[i] = int(numlist[i])
    return numlist

# Calculate standard deviation
def stddev(numbers):
    avg = np.average(numbers)
    std = 0
    for i in numbers:
        std += (i - avg) ** 2
    std /= len(numbers) - 1
    return np.sqrt(std)

# Take list of strings, make everything lowercase
def lowerlist(txtlist):
    text = ' '.join(txtlist)
    text = text.lower()
    return text.split()

# Create a dictionary object with words and how often they occur
def wordCount(txtlist):
    count = {}
    for word in txtlist:
        if word not in count:
            count[word] = 1
        else:
            count[word] += 1
    return count

# Get the 5 most occurred words
def getMostOccurred(txtlist):
    wcount = wordCount(txtlist)

    # Dictionary sort by value from: https://www.python.org/dev/peps/pep-0265/
    items = [(v, k) for k, v in wcount.items()]
    items.sort()
    items.reverse()
    items = [(k, v) for v, k in items]

    retlist = items[0:5]
    return retlist

# Get name of file to read from
fname = input("Type filename: ")
f = open(fname, 'r')
text = f.read()
# Split input from file, make a list
inplist = text.split()

if isAllNum(inplist):
    # Change input list to numbers and calculate relevant information
    inplist = strToNum(inplist)
    print("min = {}".format(np.min(inplist)))
    print("max = {}".format(np.max(inplist)))
    print("average = {}".format(np.average(inplist)))
    print("median = {}".format(np.median(inplist)))
    print("stddev = {}".format(stddev(inplist)))
else:
    # Change to lowercase, and use set to find unique words
    txtlist = lowerlist(inplist)
    inpset = set(txtlist)
    print("Number of unique words: {}".format(len(inpset)))

    # Get five most occurred words, see relevant functions.
    mostoccurred = getMostOccurred(txtlist)
    print("Five most occurred words, from most occured to least occured:")
    for i in mostoccurred:
        print(i[0])


class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def oddEvenList(self, head: ListNode) -> ListNode:
        if not head or not head.next or not head.next.next:
            return head
        phead = ListNode(-1)
        phead.next = head
        j, ou = head, head.next
        nj = ou.next
        while ou and nj:
            ou.next = nj.next
            nj.next = j.next
            j.next = nj
            j = nj
            ou = ou.next
            if ou:
                nj = ou.next
        return phead.next
def create_list(s):
    head = ListNode(s[0])
    last = head
    for i in range(1, len(s)):
        now = ListNode(s[i])
        last.next = now
        last = now
    return head
def show_list(head):
    arr = []
    while head is not None:
        arr.append(head.val)
        head = head.next
    print(arr)

if __name__ == '__main__':
    s = Solution()
    arr = [1,2,3,4,5,6]
    head = create_list(arr)
    head = s.oddEvenList(head)
    show_list(head)


import torch
import torch.nn as nn
from torchvision import models
from torch.nn import functional as F

def get_backbone(name, pretrained=True):

    """ Loading backbone, defining names for skip-connections and encoder output. """

    # loading backbone model
    if name == 'resnet18':
        backbone = models.resnet18(pretrained=pretrained)
    elif name == 'resnet34':
        backbone = models.resnet34(pretrained=pretrained)
    elif name == 'resnet50':
        backbone = models.resnet50(pretrained=pretrained)
    elif name == 'resnet101':
        backbone = models.resnet101(pretrained=pretrained)
    elif name == 'resnet152':
        backbone = models.resnet152(pretrained=pretrained)
    elif name == 'vgg16':
        backbone = models.vgg16_bn(pretrained=pretrained).features
    elif name == 'vgg19':
        backbone = models.vgg19_bn(pretrained=pretrained).features
    elif name == 'densenet121':
        backbone = models.densenet121(pretrained=True).features
    elif name == 'densenet161':
        backbone = models.densenet161(pretrained=True).features
    elif name == 'densenet169':
        backbone = models.densenet169(pretrained=True).features
    elif name == 'densenet201':
        backbone = models.densenet201(pretrained=True).features
    elif name == 'unet_encoder':
        from unet_backbone import UnetEncoder
        backbone = UnetEncoder(3)
    else:
        raise NotImplemented('{} backbone model is not implemented so far.'.format(name))

    # specifying skip feature and output names
    if name.startswith('resnet'):
        feature_names = [None, 'relu', 'layer1', 'layer2', 'layer3']
        backbone_output = 'layer4'
    elif name == 'vgg16':
        feature_names = ['5', '12', '22', '32', '42']
        backbone_output = '43'
    elif name == 'vgg19':
        feature_names = ['5', '12', '25', '38', '51']
        backbone_output = '52'
    elif name.startswith('densenet'):
        feature_names = [None, 'relu0', 'denseblock1', 'denseblock2', 'denseblock3']
        backbone_output = 'denseblock4'
    elif name == 'unet_encoder':
        feature_names = ['module1', 'module2', 'module3', 'module4']
        backbone_output = 'module5'
    else:
        raise NotImplemented('{} backbone model is not implemented so far.'.format(name))

    print(feature_names)
    return backbone, feature_names, backbone_output

""" U-Net (https://arxiv.org/pdf/1505.04597.pdf) implementation with pre-trained torchvision backbones."""
class Encoder(nn.Module):

    """
    Convolutional batch norm block with relu activation (main block used in the encoding steps)
    """
    def __init__(self,
                 backbone_name='resnet50',
                 pretrained=True,
                 encoder_freeze=False,
                 shortcut_features='default'):
        super(Encoder,self).__init__()
        self.backbone_name = backbone_name
        self.backbone, self.shortcut_features, self.bb_out_name = get_backbone(backbone_name, pretrained=pretrained)
        if shortcut_features != 'default':
            self.shortcut_features = shortcut_features
            print('shortcut_features:')
            print(shortcut_features)

        if encoder_freeze:
            self.freeze_encoder()

    def freeze_encoder(self):

        """ Freezing encoder parameters, the newly initialized decoder parameters are remaining trainable. """

        for param in self.backbone.parameters():
            param.requires_grad = False

    def forward(self, x):

        """ Forward propagation in backbone encoder network.  """

        features = {None: None} if None in self.shortcut_features else dict()
        for name, child in self.backbone.named_children():
            x = child(x)
            if name in self.shortcut_features:
                features[name] = x
            if name == self.bb_out_name:
                break

        return x, features

class UpsampleBlock(nn.Module):

    def __init__(self, ch_in, ch_out=None, skip_in=0, use_bn=True, parametric=False):
        super(UpsampleBlock, self).__init__()

        self.parametric = parametric
        ch_out = ch_in/2 if ch_out is None else ch_out

        # first convolution: either transposed conv, or conv following the skip connection
        if parametric:
            # versions: kernel=4 padding=1, kernel=2 padding=0
            self.up = nn.ConvTranspose2d(in_channels=ch_in, out_channels=ch_out, kernel_size=(4, 4),
                                         stride=2, padding=1, output_padding=0, bias=(not use_bn))
            self.bn1 = nn.BatchNorm2d(ch_out) if use_bn else None
        else:
            self.up = None
            ch_in = ch_in + skip_in
            self.conv1 = nn.Conv2d(in_channels=ch_in, out_channels=ch_out, kernel_size=(3, 3),
                                   stride=1, padding=1, bias=(not use_bn))
            self.bn1 = nn.BatchNorm2d(ch_out) if use_bn else None

        self.relu = nn.ReLU(inplace=True)

        # second convolution
        conv2_in = ch_out if not parametric else ch_out + skip_in
        self.conv2 = nn.Conv2d(in_channels=conv2_in, out_channels=ch_out, kernel_size=(3, 3),
                               stride=1, padding=1, bias=(not use_bn))
        self.bn2 = nn.BatchNorm2d(ch_out) if use_bn else None

    def forward(self, x, skip_connection=None):

        x = self.up(x) if self.parametric else F.interpolate(x, size=None, scale_factor=2, mode='bilinear',
                                                             align_corners=None)
        if self.parametric:
            x = self.bn1(x) if self.bn1 is not None else x
            x = self.relu(x)

        if skip_connection is not None:
            x = torch.cat([x, skip_connection], dim=1)

        if not self.parametric:
            x = self.conv1(x)
            x = self.bn1(x) if self.bn1 is not None else x
            x = self.relu(x)
        x = self.conv2(x)
        x = self.bn2(x) if self.bn2 is not None else x
        x = self.relu(x)

        return x

class Decoder(nn.Module):

    def __init__(self,
                 backbone_name='resnet50',
                 pretrained=True,
                 classes=21,
                 decoder_filters=(256, 128, 64, 32, 16),
                 parametric_upsampling=True,
                 shortcut_features='default',
                 decoder_use_batchnorm=True):
        super(Decoder, self).__init__()
        self.backbone_name = backbone_name
        self.backbone, self.shortcut_features, self.bb_out_name = get_backbone(backbone_name, pretrained=pretrained)
        shortcut_chs, bb_out_chs = self.infer_skip_channels()
        # build decoder part
        self.upsample_blocks = nn.ModuleList()
        decoder_filters = decoder_filters[:len(self.shortcut_features)]  # avoiding having more blocks than skip connections
        decoder_filters_in = [bb_out_chs] + list(decoder_filters[:-1])
        num_blocks = len(self.shortcut_features)

        #print(shortcut_chs)
        #print(decoder_filters_in)
        #print(decoder_filters)
        for i, [filters_in, filters_out] in enumerate(zip(decoder_filters_in, decoder_filters)):
            print('upsample_blocks[{}] in: {}   out: {}'.format(i, filters_in, filters_out))

            self.upsample_blocks.append(UpsampleBlock(filters_in, filters_out,
                                                      skip_in=shortcut_chs[num_blocks-i-1],
                                                      parametric=parametric_upsampling,
                                                      use_bn=decoder_use_batchnorm))

        self.final_conv = nn.Conv2d(decoder_filters[-1], classes, kernel_size=(1, 1))

    def infer_skip_channels(self):

        """ Getting the number of channels at skip connections and at the output of the encoder. """

        x = torch.zeros(1, 3, 224, 224)
        has_fullres_features = self.backbone_name.startswith('vgg') or self.backbone_name == 'unet_encoder'
        channels = [] if has_fullres_features else [0]  # only VGG has features at full resolution

        # forward run in backbone to count channels (dirty solution but works for *any* Module)
        for name, child in self.backbone.named_children():
            x = child(x)
            if name in self.shortcut_features:
                channels.append(x.shape[1])
            if name == self.bb_out_name:
                out_channels = x.shape[1]
                break
        return channels, out_channels

    def forward(self, x, features):

        """ Forward propagation in U-Net. """

        for skip_name, upsample_block in zip(self.shortcut_features[::-1], self.upsample_blocks):
            skip_features = features[skip_name]
            x = upsample_block(x, skip_features)

        x = self.final_conv(x)
        return x

class UNaah(nn.Module):

    def __init__(self,
                 backbone_name='resnet50',
                 pretrained=True,
                 encoder_freeze=False,
                 shortcut_features='default',
                 classes=21,
                 decoder_filter_block=64,
                 parametric_upsampling=True,
                 decoder_use_batchnorm=True):
        super(UNaah,self).__init__()
        decoder_filters = (decoder_filter_block*16,decoder_filter_block*8,decoder_filter_block*4,
        decoder_filter_block*2,decoder_filter_block)
        self.encoder = Encoder(backbone_name=backbone_name,
                 pretrained=pretrained,
                 encoder_freeze=encoder_freeze,
                 shortcut_features=shortcut_features)
        self.decoder1 = Decoder(backbone_name=backbone_name,
                 pretrained=pretrained,
                 classes=classes,
                 decoder_filters=decoder_filters,
                 parametric_upsampling=parametric_upsampling,
                 shortcut_features=shortcut_features,
                 decoder_use_batchnorm=decoder_use_batchnorm)
        self.decoder2 = Decoder(backbone_name=backbone_name,
                 pretrained=pretrained,
                 classes=classes,
                 decoder_filters=decoder_filters,
                 parametric_upsampling=parametric_upsampling,
                 shortcut_features=shortcut_features,
                 decoder_use_batchnorm=decoder_use_batchnorm)

    def forward(self, x):
        x, features = self.encoder(x)
        out1 = self.decoder1(x, features)
        out2 = self.decoder2(x, features)
        return out1, out2

if __name__ == "__main__":

    # simple test run
    net = UNaah(backbone_name='resnet50')

    criterion = nn.MSELoss()
    optimizer = torch.optim.Adam(net.parameters())
    print('Network initialized. Running a test batch.')
    for _ in range(1):
        with torch.set_grad_enabled(True):
            batch = torch.empty(1, 3, 224, 224).normal_()
            targets = torch.empty(1, 21, 224, 224).normal_()

            o = net(batch)
            loss1 = criterion(o, targets)
            loss1.backward()
            optimizer.step()
        #print(out.shape)

    print('fasza.')


"""
计算三角形的三边，然后计算三角形的周长和面积，
需要些两个函数
    1、校验三条边是否满足条件   check_input
    2、计算三角形周长面积    get_perimeter_area
"""
import math
def input_number():
    """
    输入三角形的遍
    :return:
    """
    while True:
        number_str = input("请输入三角形的边：")
        # 判断是否是数字
        try:
            number = float(number_str)
            if number <= 0:
                print("输入的数必须为整数")
                continue
            return number
        except:
            print("输入的必须为数字")

def check_edge(num01, num02, num03):
    """
    校验三条边能否构成三角形
    :param num01:
    :param num02:
    :param num03:
    :return:
    """
    if num01 + num02 < num03:
        return False
    if num01 + num03 < num02:
        return False
    if num03 + num02 < num01:
        return False
    return True

def get_perimeter_area(num01, num02, num03):
    """
    计算三角形周长面积
    :param num01:
    :param num02:
    :param num03:
    :return:
    """
    perimeter = num01 + num02 + num03
    area = math.sqrt((perimeter/2) * (perimeter/2 - num01)* (perimeter/2 - num02)* (perimeter/2 - num03))
    return perimeter, area

if __name__ == "__main__":
    # 输入三角形的三条边
    edge01 = input_number()
    edge02 = input_number()
    edge03 = input_number()
    if check_edge(edge01, edge02, edge03) == False:
        print("三条边不能构成三角形")
    else:
        permetre, area = get_perimeter_area(edge01, edge02, edge03)
        print("三角形的周长为：%.2f  面积为：%.2f" % (permetre, area))