import uuid
from datetime import datetime

from pytz import UTC

def datetime_utc(dt=None):
    if not dt:
        dt = datetime.utcnow()
    return dt.replace(tzinfo=UTC)

def date_id(prefix=""):
    def call(pre=prefix):
        suf = datetime_utc().replace(tzinfo=None).isoformat().replace(".", ":")
        suf = suf + "_" + str(uuid.uuid4())
        suf = suf or suf
        if pre:
            pre = pre + "::"
        return pre + suf

    return call


from flask import Blueprint, render_template, request, flash, jsonify, url_for, redirect, send_from_directory, current_app
from flask_login import login_required, current_user
from models import Note, Restaurant
from . import db, generate_text, generate_image, transcribe_audio, generate_speech, generate_chaos, your_friend_snoopy
import json
import time
import os
import random

views = Blueprint('views', __name__)

@views.route('/', methods=['GET', 'POST'])
@login_required
def home():
    images = ['1.png', '2.png', '3.png', '4.png', '5.png', '6.png', '7.png', '8.png', '9.png']
    if request.method == 'POST':
        note = request.form.get('note')
        if len(note) < 1:
            flash('Note is too short!', category='error')
        else:
            new_note = Note(data=note, user_id=current_user.id)
            db.session.add(new_note)
            db.session.commit()
            flash('Note added!', category='success')

    return render_template("home.html", user=current_user, images=images)

@views.route('/chaos', methods=['GET', 'POST'])
@login_required
def chaos():
    ends = ["Explosion","Pandemic","Invasion","Apocalypse","Cataclysm","Annihilation","Extinction","Obliteration","Destruction","Collapse"]
    if request.method == 'POST':
        text = request.form.get("text")
        if text:
            response = generate_chaos(text)

        image = generate_image(f"Realistic, Cinematic, 8k, Real Textures, {response}")
        final_text = generate_text(f"Generate a short back story of this character: {response} and the end of the story should be about {random.choice(ends)}")
        audio = generate_speech(final_text)
        return render_template("chaos.html", user=current_user, image=image, text=final_text, audio=audio )
    else:
        return render_template("chaos.html", user=current_user, image=None, text=None, audio=None)

@views.route('/texttos', methods=['GET', 'POST'])
def texttos():
    if request.method == 'POST':
        text = request.form.get("text")
        response = None
        if text:
            file_name = generate_speech(text)
            response =  f"static/audio_files/{file_name}"
        return render_template("texttos.html", user=current_user, response=response)
    else:
        return render_template("texttos.html", user=current_user, response=None)

@views.route('/davince', methods=['GET', 'POST'])
@login_required
def index():
    text = request.form.get("text")
    if text:
        response = generate_text(text)
    else:
        response = None
    return render_template("davince.html", user=current_user, response=response )

@views.route('/future', methods=['GET', 'POST'])
@login_required
def future():
    text = request.form.get("text")
    if text:
        response = your_friend_snoopy(text)
    else:
        response = None
    return render_template("future.html", user=current_user, response=response )

@views.route('/dalle', methods=['GET', 'POST'])
@login_required
def dalle():
    text = request.form.get("text")
    if text:
        response = generate_image(text)
    else:
        response = None
    return render_template("dalle.html", user=current_user, response=response, text=text)

@views.route("/rev", methods=['GET','POST'])
@login_required
def upload_file():
    if request.method == 'POST':
        f = request.files['file']
        transcript = transcribe_audio(f)
    else:
        transcript = None
    return render_template("rev.html", user=current_user, transcript=transcript)

@views.route('/delete-note', methods=['POST'])
def delete_note():
    note = json.loads(request.data)
    noteId = note['noteId']
    note = Note.query.get(noteId)
    if note:
        if note.user_id == current_user.id:
            db.session.delete(note)
            db.session.commit()

    return jsonify({})

@views.route('/restaurant/add', methods=['GET', 'POST'])
@login_required
def add_restaurant():
    form = RestaurantForm()
    if form.validate_on_submit():
        restaurant = Restaurant(name=form.name.data, description=form.description.data, rating=form.rating.data)
        db.session.add(restaurant)
        db.session.commit()
        flash('Restaurant added successfully', 'success')
        return redirect(url_for('dashboard'))
    return render_template('add_restaurant.html', form=form, user=current_user)

from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, FloatField
from wtforms.validators import DataRequired

class RestaurantForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    description = TextAreaField('Description', validators=[DataRequired()])
    rating = FloatField('Rating', validators=[DataRequired()])


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

import sys
import os
import urllib
import tarfile
import zipfile

class Download:
    """
    classe per gestire i download del dataset

    """

    def __init__(self):

        pass

    def maybe_downlaod_and_extract(self,url,download_dir):

        """

        :param url: url per scaricare il dataset
        :param download_dir: Cartella dove sono salvati i file scaricati
        :return:
        """

        filename= url.split('/')[-1]
        #path alla cartella dove salverò il dataset
        file_path=os.path.join(download_dir,filename)

        if not os.path.exists(file_path):

            #verfico se esiste la cartella di download
            if not os.path.exists(download_dir):
                os.makedirs(download_dir)

        #downlaod the file from the internet

            file_path, =urllib.urlretrieve(url=url,
                                               filename=file_path,
                                               reporthook=self._print_download_progress)

            if file_path.endswith(".zip"):
                zipfile.ZipFile(file=file_path,mode="r").extractall(download_dir)
            elif file_path.endswith((".tar.gz",".tgz")):
                tarfile.open(name=file_path,mode="r:gz").extractall(download_dir)

        else:
            print ("I dati sembrano essere già stati scaricati")

    def _print_download_progress(self,count, block_size, total_size):
        """
        Function used for printing the download progress.
        Used as a call-back function in maybe_download_and_extract().
        """

        # Percentage completion.
        pct_complete = float(count * block_size) / total_size

        # Status-message. Note the \r which means the line should overwrite itself.
        msg = "\r- Download progress: {0:.1%}".format(pct_complete)

        # Print it.
        sys.stdout.write(msg)
        sys.stdout.flush()


# import tnreason.logic.expression_calculus as ec
import tnreason.logic.coordinate_calculus as cc
import tnreason.logic.expression_generation as eg

import tnreason.representation.factdf_to_cores as ftoc
import tnreason.representation.sampledf_to_cores as stoc
import tnreason.representation.pairdf_to_cores as ptoc

import tnreason.optimization.weight_estimation as wees
import tnreason.optimization.expression_refinement as er

import tnreason.contraction.expression_evaluation as ee

import tnreason.learning.expression_learning as el

from tnreason.model import tensor_network_mln as mln

import numpy as np

class SampleBasedMLNLearner:
    def __init__(self, sampleDf=None):
        self.weightedFormulas = []
        if sampleDf is not None:
            self.load_sampleDf(sampleDf)

    def load_sampleDf(self, sampleDf):
        self.sampleDf = sampleDf
        self.create_atomDict()

    def create_atomDict(self):
        atoms = list(self.sampleDf.columns)
        self.atomDict = {
            atom: cc.CoordinateCore(stoc.sampleDf_to_universal_core(self.sampleDf, [atom]).flatten(), ["j"])
            for atom in atoms
        }

    def learn_implication(self, positiveExpression, skeletonExpression, candidatesDict,
                          refinementNum=0, refinementCriterion="weight>1", acceptanceCriterion="weight>0"):
        self.learn(positiveExpression, skeletonExpression, candidatesDict, boostNum=1, saveMod="imp",
                   refinementNum=refinementNum,
                   refinementCriterion=refinementCriterion,
                   acceptanceCriterion=acceptanceCriterion
                   )

    def learn_equivalence(self, positiveExpression, skeletonExpression, candidatesDict,
                          refinementNum=0, refinementCriterion="weight>1", acceptanceCriterion="weight>0"):
        self.learn(positiveExpression, skeletonExpression, candidatesDict, boostNum=1, saveMod="eq",
                   refinementNum=refinementNum,
                   refinementCriterion=refinementCriterion,
                   acceptanceCriterion=acceptanceCriterion
                   )

    def learn_tautology(self, skeletonExpression, candidatesDict,
                        refinementNum=0, refinementCriterion="weight>1", acceptanceCriterion="weight>0"):
        self.learn("Thing", skeletonExpression, candidatesDict, boostNum=1, saveMod="direct",
                   refinementNum=refinementNum,
                   refinementCriterion=refinementCriterion,
                   acceptanceCriterion=acceptanceCriterion
                   )

    def learn(self, positiveExpression, skeletonExpression, candidatesDict,
              boostNum=1, saveMod="eq",
              refinementNum=0, refinementCriterion="weight>1",
              balance=True,
              acceptanceCriterion="weight>0"):
        if saveMod == "eq" or saveMod == "imp":
            # positiveCore = ec.evaluate_expression_on_sampleDf(self.sampleDf, positiveExpression)
            positiveCore = ee.ExpressionEvaluator(positiveExpression, sampleDf=self.sampleDf).evaluate()
        else:
            # positiveCore = ec.evaluate_expression_on_sampleDf(self.sampleDf, "Thing")
            positiveCore = ee.ExpressionEvaluator("Thing", sampleDf=self.sampleDf).evaluate()

        solutionExpressions = self.boost(skeletonExpression, candidatesDict, positiveCore, boostNum=boostNum,
                                         refinementNum=refinementNum, refinementCriterion=refinementCriterion,
                                         balance=balance)
        ## Adding the formulas to the model
        for learnedPremise in solutionExpressions:
            if saveMod == "eq" or saveMod == "imp":
                solutionExpression = eg.generate_from_generic_expression([learnedPremise, saveMod, positiveExpression])
                self.add_independent_formula(solutionExpression, criterion=acceptanceCriterion)
            else:
                self.add_independent_formula(learnedPremise, criterion=acceptanceCriterion)

    def boost(self, skeletonExpression, candidatesDict, positiveCore, boostNum=1, refinementNum=0,
              refinementCriterion="weight>1",
              balance=True):
        solutionExpressions = []
        for boostPos in range(boostNum):
            print("## Boost number {} ##".format(boostPos))
            refiningExpression = "Thing"
            for solutionExpression in solutionExpressions:
                refiningExpression = [refiningExpression, "and", ["not", solutionExpression]]
            # refiningCore = ec.evaluate_expression_on_sampleDf(self.sampleDf, refiningExpression)
            refiningCore = ee.ExpressionEvaluator(refiningExpression, sampleDf=self.sampleDf).evaluate()
            positiveCore = positiveCore.compute_and(refiningCore)
            negativeCore = positiveCore.negate()

            solutionExpressions.append(self.refine(skeletonExpression, candidatesDict, positiveCore, negativeCore,
                                                   refinementLeft=refinementNum,
                                                   acceptanceCriterion=refinementCriterion,
                                                   balance=balance))
        return solutionExpressions

    def refine(self, skeletonExpression, candidatesDict, positiveCore, negativeCore,
               refinementLeft=0, acceptanceCriterion="weight>0.5",
               balance=True):
        solutionExpression = self.optimize_formula(skeletonExpression, candidatesDict, positiveCore, negativeCore,
                                                   balance=balance)
        empRate, satRate, weight = self.learn_independent_weight(solutionExpression)
        if refinementLeft > 0 and not criterion_satisfied(empRate, satRate, weight, acceptanceCriterion):
            print("# Refining since criterion not satisfied, {} tries left #".format(refinementLeft))
            newSkeleton = er.add_leaf_atom(skeletonExpression)
            refinementLeft -= 1
            return self.refine(newSkeleton, candidatesDict, positiveCore, negativeCore,
                               refinementLeft)
        else:
            print("# Solution is {} #".format(solutionExpression))
            return solutionExpression

    def optimize_formula(self, skeletonExpression, candidatesDict, positiveCore, negativeCore, optimizationInstructions = ["als2","project","als2","project","als2","project"], balance=True):
        exLearner = el.SampleBasedOptimizer(skeletonExpression, candidatesDict)

        exLearner.generate_fixedCores_sampleDf(self.sampleDf)
        exLearner.generate_target_and_filterCore_from_exampleCores(positiveCore, negativeCore)
        if balance:
            exLearner.balance_importance(positiveCore=positiveCore, negativeCore=negativeCore)
        exLearner.random_initialize_variableCoresDict()
        for optInstruction in optimizationInstructions:
            if optInstruction.startswith("als"):
                exLearner.als(int(optInstruction[3:]))
            if optInstruction == "project":
                exLearner.get_solution(adjustVariablesCoresDict=True)
        exLearner.get_solution()

        return exLearner.solutionExpression

    def add_independent_formula(self, expression, criterion=""):
        empRate, satRate, weight = self.learn_independent_weight(expression)
        if criterion_satisfied(empRate, satRate, weight, criterion):
            self.weightedFormulas.append([expression, weight])
            print("The expression {} with weight {} passed criterion {} and has been added.".format(expression, weight,
                                                                                criterion))
        else:
            print(
                "Expression {} with weight {} does not satisfy the criterion {}.".format(expression, weight, criterion))

    def learn_independent_weight(self, expression, verbose=False):
        return wees.calculate_weight(expression, self.atomDict, verbose=verbose)

    def alternating_weight_optimization(self, sweepNum):
        estimator = wees.WeightEstimator([weightedFormula[0] for weightedFormula in self.weightedFormulas])
        estimator.alternating_optimization(self.atomDict, sweepNum)
        self.weightedFormulas = [[estimator.formulaDict[formulaKey][0], estimator.formulaDict[formulaKey][3]] for
                                 formulaKey in estimator.formulaDict]

    def generate_mln(self):
        return mln.TensorMLN(expressionsDict=
                             {str(i): [self.weightedFormulas[i][0], self.weightedFormulas[i][1]]
                              for i in range(len(self.weightedFormulas))})

## Older name of the class
AtomicMLNLearner = SampleBasedMLNLearner

def criterion_satisfied(empRate, satRate, weight, criterion):
    criteria = criterion.split(",")
    for criterion in criteria:
        if criterion.startswith("weight"):
            threshold = float(criterion.split(">")[1])
            if weight < threshold:
                return False
        elif criterion.startswith("empRate"):
            threshold = float(criterion.split(">")[1])
            if empRate < threshold:
                return False
        elif criterion.startswith("satRate"):
            threshold = float(criterion.split("<")[1])
            if satRate > threshold:
                return False
        else:
            raise ValueError("Acceptance Criterion {} not understood.".format(criterion))
    return True


import discord
from discord.ext import commands
import urllib
from .utils.dataIO import dataIO
from urllib.request import urlopen

try: # check if BeautifulSoup4 is installed
	from bs4 import BeautifulSoup
	soupAvailable = True
except:
	soupAvailable = False
import aiohttp

class Mycog:
    """My custom cog that does stuff!"""

    def __init__(self, bot):
        self.bot = bot
        self.countComs = dataIO.load_json("data/countcoms/countcoms.json")

    @commands.command()
    async def xander(self):

        #Prints all Xander face emojis in a line
        await self.bot.say("<:xhearteyes:283866074980810752> <:xandercool:235634201678839809> <:xandertilted:235633458779521024> <:xander:235610087190822913> <:hueh:235633477179932672> <:LUL:235611940590845952> <:xhearteyes:283866074980810752>")

    @commands.command()
    async def wiff(self):
        w = "wiff"

        if w in self.countComs:
            wiffnum = int(self.countComs["wiff"])
        else:
            wiffnum = 0
        wiffnum = wiffnum+1
        self.countComs["wiff"] = str(wiffnum)
        dataIO.save_json("data/countcoms/countcoms.json", self.countComs)
        await self.bot.say("We have collectively whiffed " + str(wiffnum) + " times")

    @commands.command(pass_context=True)
    async def echo(self, ctx, message):

        author = ctx.message.author
        myString = ctx.message.content
        await self.bot.say("{} {}".format(author.mention, myString[6:]))

    @commands.command()
    async def rlnow(self):
        """How many players are online atm?"""

        #Your code will go here
        url = "https://steamdb.info/app/252950/graphs/" #build the web adress
        async with aiohttp.get(url) as response:
            soupObject = BeautifulSoup(await response.text(), "html.parser")
        try:
            online = soupObject.find(class_='home-stats').find('li').find('strong').get_text()
            await self.bot.say(online + ' players are playing Rocket League at the moment')
        except:
           await self.bot.say("Couldn't load amount of players. No one is playing this game anymore or there's an error.")

    #@commands.command()
    #async def hours(self, user):
        #"""Returns hours played by a user"""

        #link = user
        #substringCheck = "https://steamcommunity.com/profiles/"
        #substringCheck2 = "https://steamcommunity.com/id/"
        #if substringCheck in link:
        #    url = link + "/games/?tab=all"  # build the web address
        #if substringCheck2 in link:
        #    url = link + "/games/?tab=all"  # build the web address
        #else:
        #    url = substringCheck2 + link + "/games/?tab=all"

        #url = "http://steamcommunity.com/id/xanderdagr8/games/?tab=all"

        #await self.bot.say(url)
        #async with aiohttp.get(url) as response:
            #soup = BeautifulSoup(await response.text(), "html.parser")
            #await self.bot.say(soup.renderContents())
        #try:
            #name_box = soup.find('h5').get_text()
            #await self.bot.say(name_box)
        #except:
           #await self.bot.say("This user does not own Rocket League")

def setup(bot):
	if soupAvailable:
		bot.add_cog(Mycog(bot))
	else:
		raise RuntimeError("You need to run `pip3 install beautifulsoup4`")


import socket
from DH import dh_
import json

class ClientSocket:
	def __init__(self, debugflag):
		self.__dh = dh_.DH()
		self.__debugflag = debugflag

	def initDiffieHellman(self, socket):
		socket.send("connected".encode())
		step1 = socket.recv(1024)
		if self.__debugflag:
			print(step1)
		jsonData = json.loads(step1.decode())
		jsonData = jsonData["dh-keyexchange"]
		self.__dh.base = int(jsonData["base"])
		self.__dh.sharedPrime = int(jsonData["prime"])
		publicSecret = int(jsonData["publicSecret"])
		calcedPubSecret = str(self.__dh.calcPublicSecret())
		step2 = "{"
		step2 += "\"dh-keyexchange\":"
		step2 += "{"
		step2 += "\"step\": {},".format(2)
		step2 += "\"publicSecret\": {}".format(calcedPubSecret)
		step2 += "}}"
		socket.send(step2.encode())
		self.__dh.calcSharedSecret(publicSecret)

	def start_client(self, ip):
		sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		try:
			sock.connect((ip, 50000));
			self.initDiffieHellman(sock)
			print("The secret key is {}".format(self.__dh.key))
		finally:
			sock.close()


# -*- coding: utf-8 -*-
import scrapy

class CarsSpider(scrapy.Spider):
    name = 'cars'
    allowed_domains = ['cars.av.by']
    start_urls = ['https://cars.av.by/audi']

    def parse(self, response):

        # cars = response.xpath('//div[@class="listing-item"]')
        cars = response.css('div.listing-item')

        for car in cars:

            # TITLE
            title = car.xpath('.//div[@class="listing-item__about"]/h3/a/span').get()
            title = title.replace('', '').replace('', '').replace('', '').split()

            made = {
                "brand": title[0],
                "model": title[1],
                "submodel": title[2]
            }

            # LINK
            link = car.xpath('.//div[@class="listing-item__about"]/h3/a/@href').get()

            # IMAGE
            image = car.xpath('.//div[@class="listing-item__photo"]/img/@data-src').get()

            # LOCATION
            location = car.xpath('.//div[@class="listing-item__location"]/text()').get()

            # TIME
            time = car.xpath('.//div[@class="listing-item__date"]/text()').get()

            # YEAR
            year = car.xpath('.//div[@class="listing-item__params"]/div[1]/text()').get()
            year = year.replace('г.', '').strip()

            # ENGINE
            engine = car.xpath('.//div[@class="listing-item__params"]/div[2]').get()
            engine = engine.replace('
', '').replace('', '').replace('
', '').replace('л,', '').replace(',', '').split()

            engine = {
                "transmision": engine[0],
                "volume": float(engine[1]),
                "type": engine[2]
            }

            # MILES
            miles = car.xpath('.//div[@class="listing-item__params"]/div[3]/span/text()').get()
            try:
                miles = miles.replace('км', '')
                miles = miles.split()

                for x in miles:
                    x = int(x)

                miles = miles[0] + miles[1]
                miles = int(miles)
                # print(type(fmiles))
            except:
                miles = 0

            # PRICE BY
            price_by = car.xpath('.//div[@class="listing-item__price"]/text()').get()
            price_by = price_by.replace('р.', ' ').strip().split()
            try:
                for x in price_by:
                    x = int(x)
                price_by = price_by[0] + price_by[1]
                price_by = int(price_by)
                # print(type(price_ru))
            except:
                price_by = 0

            # PRICE USD
            price_usd = car.xpath('.//div[@class="listing-item__priceusd"]/text()').get()
            price_usd = price_usd.replace('≈', ' ').replace('$', ' ').strip().split()
            try:
                for x in price_usd:
                    x = int(x)
                price_usd = price_usd[0] + price_usd[1]
                price_usd = int(price_usd)
            except:
                price_usd = 0

            # absolute_url = f"https://cars.av.by{link}"
            absolute_url = response.urljoin(link)

            # yield response.follow(url=link)
            # print(response.follow(url=link))

            yield {
                'made': made,
                'link': absolute_url,
                'image': image,
                'location': location,
                'time': time,
                'year': year,
                'engine': engine,
                'miles': miles,
                'price_by': price_by,
                'price_usd': price_usd,
            }

        # next = response.xpath('//div[@class="paging__button"]/a/@href').get()
        # next_page = response.urljoin(next)
        # print(next_page)

        # if next_page is not None:
        #     yield response.follow(url=next_page, callback=self.parse)


import news_classes
import numpy as np
import os
import pandas as pd
import pickle
import sys
import tensorflow as tf
import time

from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
#from tensorflow.contrib.learn.python.learn.estimators import model_fn
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

from keras.preprocessing.sequence import pad_sequences
from tensorflow import keras
from keras.utils import to_categorical
from keras.layers import LSTM

# import packages in trainer
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'trainer'))
#import news_cnn_model

#learn = tf.contrib.learn

SERVER_HOST = 'localhost'
SERVER_PORT = 6060

MODEL_DIR = '../model'
MODEL_UPDATE_LAG_IN_SECONDS = 10

TOKENIZER_SAVE_FILE = '../model/tokenizer.pickle'
#DATA_SET_FILE = '../data/DATA_SET_FILE.csv'
DATA_SET_FILE  = '../data/labeled_news.csv'
MAX_SEQUENCE_LENGTH = 100 # maximum length of a sentence
EMBEDDING_DIM = 100 # word dimensions
VALIDATION_SPLIT = 0.16 # the proportion of validation set to all set
TEST_SPLIT = 0.2 # the proportion of test set to all set
LEARNING_RATE = 0.01
EPOCHS = 2
BATCH_SIZE = 256

#N_CLASSES = 8

VARS_FILE = '../model/vars'
# VOCAB_PROCESSOR_SAVE_FILE = '../model/vocab_procesor_save_file'
TOKENIZER_SAVE_FILE = '../model/tokenizer.pickle'

#n_words = 0

#MAX_DOCUMENT_LENGTH = 500
#vocab_processor = None

#classifier = None

"""
def restoreVars():
    with open(VARS_FILE, 'rb') as f:
        global n_words
        n_words = pickle.load(f)

    global vocab_processor
    vocab_processor = learn.preprocessing.VocabularyProcessor.restore(
        VOCAB_PROCESSOR_SAVE_FILE)
"""
def restoreVars():
    global tokenizer
    # loading
    with open(TOKENIZER_SAVE_FILE, 'rb') as handle:
        tokenizer = pickle.load(handle)
"""
def loadModel():
    global classiﬁer
    # use n_words to initialize the model
    classiﬁer = learn.Estimator(
        model_fn=news_cnn_model.generate_cnn_model(N_CLASSES, n_words),
        model_dir=MODEL_DIR)
"""
def loadModel():
    global model
    model = keras.models.load_model(VARS_FILE)

    # Prepare training and testing
    """
    df = pd.read_csv('../data/labeled_news.csv', header=None)

    # TODO: fix this until https://github.com/tensorflow/tensorflow/issues/5548 is solved.
    # We have to call evaluate or predict at least once to make the restored Estimator work.
    train_df = df[0:400]
    x_train = train_df[1]
    x_train = np.array(list(vocab_processor.transform(x_train)))
    y_train = train_df[0]
    classifier.evaluate(x_train, y_train)
    """
restoreVars()
loadModel()

class ReloadModelHandler(FileSystemEventHandler):
    def on_any_event(self, event):
        # Reload model
        print("Model update detected. Loading new model.")
        time.sleep(MODEL_UPDATE_LAG_IN_SECONDS)
        retoreVars()
        loadModel()

observer = Observer()
observer.schedule(ReloadModelHandler(), path=MODEL_DIR, recursive=False)
observer.start()

def classify(text):
    # get row of text
    #text_series = pd.Series([text])
    # vocab_processor is stored when we training the data
    """
    predict_x = np.array(list(vocab_processor.transform(text_series)))
    print(predict_x)

    y_predicted = [
        p['class'] for p in classifier.predict(
            predict_x, as_iterable=True)
    ]
    print(y_predicted[0])
    """
    text_list = []
    text_list.append(text)
    predict_x = tokenizer.texts_to_sequences(text_list)
    predict_x = pad_sequences(predict_x, maxlen=MAX_SEQUENCE_LENGTH)
    #y_predicted = model.predict_classes(predict_x)
    y_predicted = np.argmax(model.predict(predict_x), axis=-1)
    print(y_predicted)
    print('------------------')
    topic = news_classes.class_map[str(y_predicted[0])]
    print('news type'+topic)
    return topic

sentence = 'I like sports, for example nba and football'
classify(sentence)

RPC_SERVER = SimpleJSONRPCServer((SERVER_HOST, SERVER_PORT))
RPC_SERVER.register_function(classify, 'classify')

print(("Starting RPC server on %s:%d" % (SERVER_HOST, SERVER_PORT)))

RPC_SERVER.serve_forever()


from hashlib import sha256
import rsa
import json
from random import randint
import binascii
from pprint import pprint

"""
what to do
1. make 3 signed transaction
2. create a merkle root
3. hash the header, not the whole block
4. set a target difficulty (not in hex) and mine it

there are 2 important things to keep in mind
- the metadata of the block
- the data of the transaction

it doesn't need to inlcude everything
your goal is to make cool block using the merkle tree
"""

def edit_json(msg, attr, attr_data):
    new_data = json.loads(msg.decode())
    new_data[attr] = attr_data
    new_json_data = json.dumps(new_data)
    return str.encode(new_json_data)

def gen_key_list(amount):
    # key_dict = {}
    key_list = []

    for i in range(amount):
        key_dict = {}
        (pub, priv) = rsa.newkeys(512)
        key_dict['public'] = pub
        key_dict['private'] = priv

        key_list.append(key_dict)

    return key_list

def get_hex(key):
    # export the key to DER format
    der = key.save_pkcs1('DER')

    # since DER is a binary, it can be translated
    # to hex using hexlify
    hex = binascii.hexlify(der)
    # print(public_hex.decode())
    return hex.decode()

keys = gen_key_list(3)

# ===== make the transaction =====
"""
key 0 -> key 1 x amount
key 1 -> key 2 x amount
key 2 -> key 0 x amount
"""
transaction_list = []
for i in range(len(keys)):
    data = {}
    sender_public = keys[i]['public']
    sender_private = keys[i]['private']
    try:
        receiver_public = keys[i+1]['public']
    except IndexError:
        receiver_public = keys[0]['public']

    data['sender'] = get_hex(sender_public)
    data['receiver'] = get_hex(receiver_public)
    data['amount'] = randint(1, 5)

    # sign the transaction
    temp_message = json.dumps(data).encode()
    signature = rsa.sign(temp_message, sender_private, 'SHA-256')
    data['signature'] = binascii.hexlify(signature).decode()

    transaction_list.append(data)

# ===== find merkle root =====
# if the transaction is odd, then duplicate the last index
"""
the reason you use merkle root is to proove that a transaction is
present on the block without checking one by one, i actually need
to read more about this
"""

total_length = len(transaction_list)
if total_length % 2 != 0:
    transaction_list.append(transaction_list[-1])
# print(transaction_list)

# change name to make it understandable
hash_list = transaction_list
if len(hash_list) == 0:
    # return error or some shit
    pass
elif len(hash_list) == 2:
    # hash that one transaction
    pass
else:
    while len(hash_list) != 1:
        # every iteration starts with empty temp list
        # that will be filled with the combination of the current
        # hash list
        temp_list = []
        for i in range(0, len(hash_list), 2):
            # combine the hash here
            json_tx1 = json.dumps(hash_list[i])
            tx1 = json_tx1.encode()

            json_tx2 = json.dumps(hash_list[i+1])
            tx2 = json_tx2.encode()

            """
            for some reason, the bitcoin protocol requires the transactions to be
            hashed twice, the digest here is a function that returns the
            binary of the hash
            """
            hash1 = sha256(sha256(tx1).digest()).digest()
            hash2 = sha256(sha256(tx2).digest()).digest()

            parent_hash = sha256(sha256(hash1 + hash2).digest()).hexdigest()
            temp_list.append(parent_hash)

        # the temp list is a list of calculated parent hashes
        # put it in the main hash list so it can be processed next
        hash_list = temp_list

    root_merkle_hash = hash_list[0]

# ===== make block ======
block = {}
block['header'] = {
    'merkle_root': root_merkle_hash,
    'nonce': 0,
    # the target is just a random hex that starts with three 0s converted to int
    'target': 15802950234683020252676755972449664373407456225394263496399282190354680851
    }
block['transaction'] = transaction_list

# ===== mine ======
# the hash result is hex, turn it into a int first
# int(sha.hexdigest(), 16) -> you can do it like this
while True:
    target = block['header']['target']
    nonce = block['header']['nonce']

    block_msg = json.dumps(block['header']).encode()
    # lmao for some reason when I do it manually it doesn't work
    header_hash = sha256(sha256(block_msg).digest()).hexdigest()
    # print(header_hash)

    hash_int = int(header_hash, 16)
    if hash_int < target:
        print('nonce is: ', nonce)
        print(sha256(block_msg).digest())
        print(header_hash)
        break
    else:
        block['header']['nonce'] += 1

# print(block)


#%% Import section
import numpy as np
import cv2
#%%
reference_file = open('Reference.txt', 'w')
test_file = open('Test.txt', 'w')
#%% define centroid function:
def centroid(moments):
    """Returns centroid based on moments"""
    if moments['m00'] == 0:
        print('Zero Value')
        return 0,0
    x_centroid = round(moments['m10'] / moments['m00'])
    y_centroid = round(moments['m01'] / moments['m00'])
    return x_centroid, y_centroid
def draw_contour_outline(img, cnts, color, thickness=1):
    """Draws contours outlines of each contour"""

    for cnt in cnts:
        cv2.drawContours(img, [cnt], 0, color, thickness)
#%% Opening Image
reference_image = cv2.imread('ReferenceImages/rearCIC.jpg', cv2.IMREAD_GRAYSCALE)
test_image = cv2.imread('TestImages/rear/a-petrelli-rearCIC.jpg', cv2.IMREAD_GRAYSCALE)
#%% Thresholding images
#thresh, reference_image_binary = cv2.threshold(reference_image, 127, 255, 0)
#thresh, test_image_binary = cv2.threshold(test_image, 127, 255, 0)
#%% Bluring
reference_image = cv2.blur(reference_image, (3,3))
test_image = cv2.blur(test_image, (3,3))
#%% Bilateral filter #TODO da capire bene come usarlo potrebbe essere migliore del gaussian
test_image = cv2.bilateralFilter(test_image, 9, 9, 9)
#%% Canny
reference_image_canny = cv2.Canny(reference_image, 100, 200)
test_image_canny = cv2.Canny(test_image, 100, 200)
#%% Morphological operation
kernel = np.ones((5,5),np.uint8)
reference_image_canny_morph = cv2.morphologyEx(reference_image_canny, cv2.MORPH_CLOSE, kernel)
test_image_canny_morph = cv2.morphologyEx(test_image_canny, cv2.MORPH_CLOSE, kernel)
#%% Finding Contours on binary image
#test_image_connected = cv2.connectedComponents(test_image_canny)
reference_contours, reference_hierarchy = cv2.findContours(reference_image_canny, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
test_contours, test_hierarchy = cv2.findContours(test_image_canny, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
reference_contours = sorted(reference_contours, key=cv2.contourArea, reverse= True)
test_contours = sorted(test_contours, key=cv2.contourArea, reverse= True)
#%% Computing reference Moments
reference_hu_moment_dict = {}
for index, contour in enumerate(reference_contours):
    reference_hu_moment_dict[index] = { 'moment': cv2.moments(contour),
                                        'hu_moment': cv2.HuMoments(cv2.moments(contour)),
                                        #'log_hu_moment': -np.sign(cv2.HuMoments(cv2.moments(contour)))*np.log10(np.abs(cv2.HuMoments(cv2.moments(contour))))
                                        }
#%% Computing test Moments
test_hu_moment_dict = {}
for index, contour in enumerate(test_contours):
    test_hu_moment_dict[index] = { 'moment': cv2.moments(contour),
                                   'hu_moment': cv2.HuMoments(cv2.moments(contour)),
                                   #'log_hu_moment': -np.sign(cv2.HuMoments(cv2.moments(contour)))*np.log10(np.abs(cv2.HuMoments(cv2.moments(contour))))
                                   }
#%% Computing Reference Centroid of the moments
reference_centroid = {}
for index in reference_hu_moment_dict.keys():
    reference_centroid[index] = centroid(reference_hu_moment_dict[index]['moment'])
#%% Computing Test Centroid of the moments
test_centroid = {}
for index in test_hu_moment_dict.keys():
    reference_centroid[index] = centroid(test_hu_moment_dict[index]['moment'])
#%% Print Result:
for index in reference_hu_moment_dict.keys():
    print('Reference Moment at contour index: ', index, file= reference_file)
    print(reference_hu_moment_dict[index], file= reference_file)
for index in test_hu_moment_dict.keys():
    print('Test Moment at contour index: ', index, file= test_file)
    print(test_hu_moment_dict[index], file= test_file)
for index in reference_centroid.keys():
    print('Reference centroid at contour index: ', index, file= reference_file)
    print(reference_centroid[index], file= reference_file)
for index in test_centroid.keys():
    print('Test centroid at contour index: ', index, file= test_file)
    print(test_centroid[index], file= test_file)
#%% Sercing Hu Moment Matches
matched_contours = {}
for i, ref_c in enumerate(reference_contours):
    for k, test_c in enumerate(test_contours):
        matched_contours[(i,k)] = cv2.matchShapes(ref_c, test_c, 3, 0)

#%% Showing Contours:
# Draw the outline of the detected contour:
#draw_contour_outline(reference_image, reference_contours, (255, 0, 0), 10)
#draw_contour_outline(test_image, test_image, (255, 0, 0), 10)
cv2.imwrite('ContoursHU/Reference_CannyBlur.jpg', reference_image_canny)
cv2.imwrite('ContoursHU/Test_cannyBlur.jpg', test_image_canny)
reference_image_copy = reference_image.copy()
test_image_copy = test_image.copy()
cv2.drawContours(reference_image_copy, reference_contours[0], -1, (0, 255, 0), 2)
cv2.drawContours(test_image_copy, test_contours[0], -1, (0, 255, 0), 2)
cv2.imwrite('ContoursHU/Reference_ContoursBlur.jpg', reference_image)
cv2.imwrite('ContoursHU/Test_ContoursBlur.jpg', test_image)
# cv2.imshow('Reference Canny', reference_image_canny)
# cv2.imshow('Test Canny', test_image_canny)
# cv2.imshow("Reference Image", reference_image)
# cv2.imshow("Test Image", test_image)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
#%% Bounding rect usage:
x, y, w, h = cv2.boundingRect(reference_contours[0])
cv2.rectangle(reference_image, (x,y), (x+w, y+h),(255,0,255), 5)
x, y, w, h = cv2.boundingRect(test_contours[0])
cv2.rectangle(test_image, (x,y), (x+w,y+h), (255,0,255), 5)
cv2.imshow('Reference', reference_image)
cv2.imshow('Test', test_image)
cv2.waitKey(0)
cv2.destroyAllWindows()


import requests
import asyncio
from aiohttp import ClientSession
from functools import wraps
from time import time

URL = "https://httpbin.org/delay/{}"

def duration(func):
    async def helper(func, *args, **kwargs):
        if asyncio.iscoroutinefunction(func):
            print(f"this function is a coroutine: {func.__name__}")
            return await func(*args, **kwargs)
        else:
            print(f"not a coroutine: {func.__name__}")
            return func(*args, **kwargs)

    @wraps(func)
    async def wrapper(*args, **kwargs):
        start_ts = time()
        result = await helper(func, *args, **kwargs)
        dur = time() - start_ts
        print("{} took {:.2} seconds".format(func.__name__, dur))

        return result

    return wrapper

@duration
async def _get_completed():
    async with ClientSession() as session:
        tasks = [
            session.get(URL.format(delay)) for delay in [2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        ]
        responses = await asyncio.gather(*tasks)
        rs = [await response.json() for response in responses]
    return rs

def get_completed():
    """async call to get all of the completed challanges and their metadata in json format."""
    return asyncio.get_event_loop().run_until_complete(_get_completed())

@duration
def sync_get():
    resp = [requests.get(URL.format(delay)) for delay in [1, 1, 1, 1, 1]]
    return resp

if __name__ == "__main__":
    get_completed()


import logging
from uuid import UUID

from pydantic import BaseModel

from ipaddress import IPv4Address

_LOGGER = logging.getLogger(__name__)

class Stats():
    def __init__(self, accounts, services, uuid, remote_addr, dns_update):
        self.accounts = accounts
        self.services = services
        self.uuid = uuid
        self.remote_addr = remote_addr
        self.dns_update = dns_update

    def __repr__(self):
        return (
            f'<Stats(accounts={self.accounts},services={self.services},'
            f'uuid={self.uuid},remote_addr={self.remote_addr},'
            f'dns_update={self.dns_update})>'
        )

    def as_dict(self):
        return {
            'accounts': self.accounts,
            'services': self.services,
            'uuid': self.uuid,
            'remote_addr': self.remote_addr,
            'dns_update': self.dns_update
        }

class StatsResponseModel(BaseModel):
    accounts: int
    services: int
    dns_update: bool
    remote_addr: IPv4Address
    uuid: UUID | None = None


import logging
from aio_pika import IncomingMessage, Message, connect_robust as pika_connect
from fastapi import Body, HTTPException

exchange_name = 'teste'
routing_key = 'teste'
logger = logging.getLogger('uvicorn')

async def publish_message(msg: IncomingMessage = Body(...)):
    try:
        connection = await pika_connect("amqp://guest:guest@localhost:5672/teste")
        async with connection:
            channel = await connection.channel()
            queue = await channel.declare_queue("teste", durable=True)
            await channel.declare_exchange(name=exchange_name, type='topic', durable=True)
            await channel.default_exchange.publish(Message(bytes(msg,'UTF-8')),routing_key=queue.name,)
            logger.info("%r sent to exchange %r with data: %r" % (routing_key, exchange_name, msg))
    except Exception as ex:
        logger.error("Problema para postar a mensagem %r" % (ex))
        raise HTTPException(
            status_code=400,
            detail="Problema para postar a mensagem: " + ex,)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 17 22:21:54 2018

@author: haithem.afli
"""

from gensim.models import Word2Vec
from sklearn.decomposition import PCA
from matplotlib import pyplot

# define training data
sentences = [['this', 'is', 'the', 'second', 'lecture', 'about', 'word2vec'],
			['this', 'is', 'the', 'first', 'slide'],
			['yet', 'another', 'slide'],
			['one', 'more', 'sentence'],
			['and', 'the', 'final', 'sentence']]

# train model
model = Word2Vec(sentences, min_count=1)
# summarize the loaded model
print(model)

# fit a 2d PCA model to the vectors
X = model[model.wv.vocab]
pca = PCA(n_components=2)
result = pca.fit_transform(X)
# create a scatter plot of the projection
pyplot.scatter(result[:, 0], result[:, 1])

# summarize vocabulary
words = list(model.wv.vocab)
print(words)

for i, word in enumerate(words):
	pyplot.annotate(word, xy=(result[i, 0], result[i, 1]))
pyplot.show()

# access vector for one word
print(model['sentence'])
# save model
model.save('model.bin')
# load model
new_model = Word2Vec.load('model.bin')
print(new_model)


from typing import List

from pytest import mark

class Solution:
    def restoreIpAddresses(s: str) -> List[str]:
        ans = []

        def backtrack(index: int, path: List[str]) -> None:
            if index > len(s) or len(path) > 4:
                return
            if index == len(s) and len(path) == 4:
                ans.append('.'.join(path))
                return
            for i in range(1,4):
                if (index + i) <= len(s) and int(s[index:index+i]) <= 255:
                    if not (s[index] == '0' and i > 1):
                        backtrack(index+i, path+[s[index:index+i]])
        backtrack(0, [])
        return ans

@mark.parametrize('s, expected', [
        ("0000", ["0.0.0.0"]),
        ("1111", ["1.1.1.1"]),
        ("010010", ['0.10.0.10', '0.100.1.0']),
        ("101023", ["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"])
    ])

def test_restoreIpAddresses(s, expected):
    ans_brute = Solution.restoreIpAddresses(s)
    assert ans_brute == expected


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def findDuplicateSubtrees(self, root: Optional[TreeNode]) -> List[Optional[TreeNode]]:
        cache = collections.defaultdict(set)
        ans = {}
        def dfs(cur, i):
            if cur == None:
                return tuple()
            res = []
            res.extend(dfs(cur.left, i+1))
            res.append( (cur.val, i) )
            res.extend(dfs(cur.right, i+1))
            compare = tuple( map( lambda x: (x[0], x[1]-i) , res ) )
            length = len(compare)
            if compare in cache[length]:
                ans[compare] = cur
            else:
                cache[length].add(compare)
            return tuple(res)
        dfs(root, 0)
        return ans.values()


from requests import get
from lib.auth import Authentication
from lib.config import server
from json import loads, dumps
from ipaddress import ip_address
from time import sleep

class GetData(object):

    def __init__(self, username, password):
        self.token = Authentication(username, password).logon()
        self.headers = {'Authorization': 'Bearer {}'.format(self.token)}

    def get_groups(self):
        list_groups = {}
        response = get(server + '/sepm/api/v1/groups', headers=self.headers, verify=False)
        group_list = loads(response.text)['content']
        for x in group_list:
            list_groups[x['name']] = x['id']
        f = open('list_group.json','w+')
        f.write(dumps(list_groups))
        f.close()
        return group_list

    def get_computers_from_group(self, group_id):
        response = get(server + '/sepm/api/v1/groups/{}/computers'.format(group_id), headers=self.headers, verify=False)
        computer_list = loads(response.text)['content']
        f = open('computers_from_group.json','w+')
        f.write(dumps(computer_list))
        f.close()
        return computer_list

    def get_computers(self, pageIndex=1):
        response = get(server + '/sepm/api/v1/computers/?pageSize=100&pageIndex={}'.format(pageIndex), headers=self.headers, verify=False)
        return loads(response.text)

    def get_all_computers(self):
        hosts = {}
        response = self.get_computers()
        for i in range(1,response['totalPages']+1):
            response = self.get_computers(i)
            for x in response['content']:
                hosts[x['computerName']] = {'macAddress': x['macAddresses'][0], 'hardwareKey': x['hardwareKey'],
                                            'ipAddress': []}
                for k in x['ipAddresses']:
                    if ip_address(k).version == 4:
                        hosts[x['computerName']]['ipAddress'].append(k)
            sleep(3)
        f = open('list_computers.json','w+')
        f.write(str(dumps(hosts)))
        f.close()

    def get_all_computers_pendent_reboot(self):
        hosts = {}
        response = self.get_computers()
        for i in range(1, response['totalPages'] + 1):
            response = self.get_computers(i)
            for x in response['content']:
                if x['rebootRequired'] == 1:
                    hosts[x['computerName']] = {'ipAddresses':x['ipAddresses']}
            sleep(3)
        return hosts

    def get_servers(self):
        response = get(server + '/sepm/api/v1/admin/servers', headers=self.headers, verify=False)
        return response.text

    def get_version(self):
        response = get(server + '/sepm/api/v1/version', headers=self.headers, verify=False)
        return response.text

    def get_computer_info(self, computer_name):
        response = get(server + '/sepm/api/v1/computers/?computerName={}'.format(computer_name), headers=self.headers, verify=False)
        return response.text


import pandas as pd
data = pd.read_table('C:\\Users\\123\\Desktop\\files\\beijing_wangjing_125.txt', sep = ',')
data['daily_10min'] = data['daily_10min'].astype(str)
data['daily_10min'] = pd.to_datetime(data['daily_10min'])
df_group = data.groupby(['id'])
key_list = list(df_group.groups.keys())
temp = df_group.get_group(137)
temp = temp.sort_values(by='daily_10min')
# temp.set_index('daily_10min', inplace=True, drop=False)
# temp = temp.resample('10Min').ffill()
# temp = temp.between_time(start_time='00:00:00', end_time='23:50:00')
# nan = temp['real_speed'].isnull().sum(axis=0)
# per = temp['real_speed'].isnull().mean()
# temp = temp.drop(labels='id',axis=1)
# temp = temp.drop(labels='free_speed',axis=1)
# temp = temp.drop(labels='idx',axis=1)
temp.to_csv('C:\\Users\\123\\Desktop\\files\\{}.csv'.format(137), sep=',', index=False)
#print(nan,per)


"""
@author: Brett Settle
@Department: UCI Neurobiology and Behavioral Science
@Lab: Parker Lab
@Date: August 6, 2015
"""
import tifffile
from .bin2mat import *
#from PyQt4.QtCore import *
#from PyQt4.QtGui import *
from qtpy.QtCore import *
from qtpy.QtGui import *
from qtpy import QtWidgets
import xlrd, re, os
import numpy as np
import flika
from flika import global_vars as g
from flika.window import Window

try:
	from scipy.ndimage import imread
except:
	print("Imread could not be loaded. Some image files will not be openable")
import sys
#from PyQt4.QtCore import pyqtSignal as Signal
from qtpy.QtCore import Signal
last_dir = ''

def getHeaders(fname, delimiter='\t'):
	return [s.strip() for s in open(fname, 'r').readline().split(delimiter)]

def export3DArray(fname, arr, header = '', fmt='%-7.2f'):
	with open(fname, 'w') as outfile:
		outfile.write('%s\n' % header)
		for sub in arr:
			for row in sub:
				outfile.write(['\t'.join([fmt % i for i in row])])

def export3DArray_2(fname, arr, header = '', fmt='%-7.2f'):
	with open(fname, 'w') as outfile:
		outfile.write('%s\n' % header)
		for sub in arr:
			sub = np.array2string(sub, separator='\t',formatter={'float_kind':lambda x: fmt % x}).replace("[", "").replace("]","")
			#sub = np.array2string(sub, precision=4, separator='\t',suppress_small=True).replace("[", "").replace("]","")
			outfile.write('%s\n' % sub)

def export_arr(arr, header = '', fmt='%-7.2f'):
	savename = getSaveFilename()
	export3DArray_2(savename, arr, header = header, fmt=fmt)
	g.m.statusBar().showMessage('coordiates exported') #send completion message to flika
	return

def exportDictionaryList(filename, dict_list, delimiter="\t", order=None):
	'''export a list of dictionaries with similar keys '''
	if order == None:
		order = set(dict_list[0].keys())
		for d in dict_list:
			order &= set(d.keys())
		order = list(order)
	with open(filename, 'w') as outf:
		outf.write("%s\n" % delimiter.join(order))
		for d in dict_list:
			outf.write("%s\n" % delimiter.join([str(d[name]) for name in order]))

def getFilename(title='Select a file to open', **args):
	global last_dir
	to_ret = str(QtWidgets.QFileDialog.getOpenFileName(caption=title, directory=last_dir, **args)[0])
	last_dir = os.path.dirname(to_ret)
	return to_ret

def getFilenames(title='Select a file to open', **args):
	global last_dir
	to_ret = [str(i) for i in QtWidgets.QFileDialog.getOpenFileNames(caption=title, directory=last_dir, **args)]
	if len(to_ret) == 0:
		return
	last_dir = os.path.dirname(to_ret[0])
	return to_ret

def getSaveFilename(title='Save to file...', initial='', **args):
	global last_dir
	if initial != '':
		last_dir = os.path.join(last_dir, initial) if "\\" not in initial else initial
	savename = str(QtWidgets.QFileDialog.getSaveFileName(caption=title, directory = last_dir, **args)[0])
	last_dir = os.path.dirname(savename)
	return savename

def getDirectory(caption, initial=''):
	return QtWidgets.QFileDialog.getExistingDirectory(None, caption, directory=initial)

def readTif(fname=''):
	if fname == '':
		fname = getFilename(filter = "All files (*.*);;TIF Files (*.tif)")
	if not os.path.isfile(fname):
		raise Exception("No File Selected")
	tif = tifffile.TIFFfile(fname).asarray().astype(np.float32)
	img = np.squeeze(tif)
	return img

def fileToArray(f=''):
	arr = []
	def fix_str_type(s):
		if re.match(r'^[\d\.]+$', s):
			return float(s)
		else:
			return str(s)
	if f == '':
		f = getFilename(filter = "All files (*.*);;Image Files (*.jpg, *.png);;TIF Files (*.tif);;Other Files (*.stk, *.lsm, *.nih)")
	if f.endswith(('.tif', '.nd2', '.nih', '.stk')):
		return read_tif(f)
	elif f.endswith(('.jpg', '.png')):
		arr = imread(f)
	elif f.endswith('.txt'):
		try:
			arr = np.loadtxt(f)
			breaks = [i for i, line in enumerate(open(f, 'r')) if line.strip() == '']
			breaks = np.subtract(breaks, range(len(breaks)))
			if len(breaks) > 0:
				arr = [a for a in np.split(arr, breaks) if a.size > 0]
		except Exception as e:
			l = 0
			for i, line in enumerate(open(f)):
				arr.append([fix_str_type(l.strip()) for l in line.split('\t')])
	elif f.endswith(('.xls', 'xlsx')):
		workbook = xlrd.open_workbook(f)
		arr = []
		for sheet in workbook.sheets():
			num_rows = sheet.nrows - 1
			curr_row = -1
			while curr_row < num_rows:
				curr_row += 1
				row = sheet.row(curr_row)
				arr.append([float(fix_str_type(str(s.value))) for s in row])
	elif f.endswith(('.npy', '.npz')):
		arr = np.load(f)
		if arr.ndim == 2 and arr.shape[0] > arr.shape[1]:
			arr = arr.transpose()
	else:
		print('Failed to open')
		return

	if type(arr) == list and any([type(j) == str for j in arr[0]]):
		names = arr[0]
		arr_dict = {n : [[]] for n in arr[0]}
		count = 0
		for row in arr[1:]:
			if all([i == '' for i in row]):
				count += 1
				for n in names:
					arr_dict[n].append([])
			else:
				for i, j in enumerate(row):
					arr_dict[names[i]][count].append(j)

		return {k: np.squeeze(v) for k,v in arr_dict.items()}
	else:
		return np.array(arr)

class ImageImporter(QThread):
	done = Signal(object)
	def __init__(self, filename=''):
		super(ImageImporter, self).__init__()
		if filename == '':
			filename = getFilename(filter = "All files (*.*);;Image Files (*.jpg, *.png);;TIF Files (*.tif);;Other Files (*.stk, *.lsm, *.nih)")
		self.filename = filename
		if self.filename == '':
			raise Exception('No file selected')

	def run(self):
		if self.filename.endswith(('.tif', '.nd2', '.nih', '.stk')):
			image = tifffile.TIFFfile(self.filename).asarray().astype(np.float32)
			image = np.squeeze(np.swapaxes(image, 2, 1))
		elif self.filename.endswith(('.jpg', '.png')):
			image = imread(self.filename).swapaxes(0, 1)
		elif self.filename.endswith(('.npy', '.npz')):
			image = np.load(self.filename)
			if simage.ndim == 2 and image.shape[0] > image.shape[1]:
				image = self.image.transpose()
		self.done.emit(image)
		del image
		self.terminate()

class TiffExporter(QThread):
	done = Signal()
	def __init__(self, fname, tiff):
		super(TiffExporterd, self).__init__()
		self.filename = fname
		self.tiff = tiff

	def run(self):
		tifffile.imsave(self.filename, self.tiff)
		self.done.emit()
		self.terminate()

def importDictionary(filename='', mode='columns'):
	if filename == '':
		filename = getFilename(filter = "Text files (*.txt)")
	keys = []
	data = []
	for i, line in enumerate(open(filename, 'r')):
		if i == 0:
			keys = line.split()
			if k[0].startswith('# '):
				k[0] = k[0][2:]
		else:
			data.append([float(j) for j in line.split()])
	data = np.array(data)
	if mode == 'columns':
		data = data.transpose()
		return OrderedDict([(keys[i], data[i]) for i in range(len(keys))])
	elif mode == 'rows':
		return [dict(zip(keys, i)) for i in data]

def importFile(filename, delimiter="\t", columns=[], evaluateLines=True, skipFirstRow=False, encoding=False):
	'''read info from a file, into a list of columns (specified by args) or dictionaries (specified by kargs)'''
	data = []

	if evaluateLines:
		if encoding==False:
			lines = [[evaluate(i) for i in line.split(delimiter)] for line in open(filename, 'r')]
		else:
			lines = [[evaluate(i) for i in line.split(delimiter)] for line in open(filename, 'r', encoding=encoding)]
	else:
		if encoding==False:
			lines = [[i for i in line.split(delimiter)] for line in open(filename, 'r')]
		else:
			lines = [[i for i in line.split(delimiter)] for line in open(filename, 'r', encoding=encoding)]

	if skipFirstRow:
		lines.pop(0)

	if len(columns) == 0: # no columns given, return data as it is read from file
		return lines
	else:
		names = lines[0]    # read data to dictionary given columns
		lines = lines[1:]
		if all([type(i) == str for i in columns]):
			data = {}
			for n in columns:
				data[n] = [lines[i][names.index(n)] for i in range(len(lines))]
		elif all([type(i) == int for i in columns]):
			data = {}
			for i in columns:
				n = names[i]
				data[n] = [lines[j][i] for j in range(len(lines))]
		return data

def evaluate(i):
	try:
		return eval(i)
	except:
		return i


# напиши здесь код основного приложения и первого экрана
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QPushButton
from instr import *
import second_win

class MainWin(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.connects()
        self.set_appear()
        self.show()
    def initUI(self):
        self.btn_next = QPushButton(txt_next)
        self.hello_text = QLabel(txt_hello)
        self.instruction = QLabel(txt_instruction)
        self.laoyut_line = QVBoxLayout()
        self.laoyut_line.addWidget(self.hello_text, alignment = Qt.AlignLeft)
        self.laoyut_line.addWidget(self.instruction, alignment = Qt.AlignLeft)
        self.laoyut_line.addWidget(self.btn_next, alignment = Qt.AlignCenter)
        self.setLayout(self.laoyut_line)
    def next_click(self):
        self.hide()
        self.tw = second_win.TestWin()
    def connects(self):
        self.btn_next.clicked.connect(self.next_click)
    def set_appear(self):
        self.setWindowTitle(txt_title)
        self.resize(win_width, win_height)
        self.move(win_x, win_y)

app = QApplication([])
mv = MainWin()
app.exec_()


from __future__ import print_function

# A card is "3B", where the first char is 1-5 and the second char is the color
# (RGBYW)

import random
random.seed(0)

def assert_is_upper(*possibles):
  for s in possibles:
    assert(s.upper() == s)

COLOR_LETTERS = "RGBYW"

def make_deck():
  deck = [n + c for n in "12345" for c in COLOR_LETTERS]
  random.shuffle(deck)
  return deck

NUM_CARDS_IN_HAND = {
  2: 5,
  3: 5,
  4: 4,
  5: 4
}

def is_color(char):
  assert_is_upper(char)
  return char in COLOR_LETTERS

def get_color(card):
  return card[1]

def get_number(card):
  return int(card[0])

class Hints:
  @classmethod
  def empty(cls):
    return cls([], [])

  def __init__(self, known, impossibles):
    self.known = known
    self.impossibles = impossibles

  def add_hint(self, card, hint):
    assert_is_upper(card, hint)
    if hint in card:
      self.known.append(hint)
    else:
      self.impossibles.append(hint)

  def __repr__(self):
    knowns = "".join([str(k) for k in self.known])
    impossibles = "".join([str(i) for i in self.impossibles])
    # TODO: sort knowns into number then color
    # TODO: don't print redundant impossibles
    return "is {}, not {}".format(knowns, impossibles)

class GameState:

  @classmethod
  def start_game(cls, num_players = 3):
    deck = make_deck()
    cards_in_hand = NUM_CARDS_IN_HAND[num_players]
    hands = []
    for i in range(num_players):
      hand = [(d, Hints.empty()) for d in deck[:cards_in_hand]]
      hands.append(hand)
      del deck[:cards_in_hand]

    played = dict([(i, 0) for i in COLOR_LETTERS])
    return GameState(deck, hands, played, [], 0, 8, 0)

  def __init__(self, deck, hands, played, discarded, num_mistakes, num_tokens, current_player):
    self.deck = deck
    self.hands = hands
    self.played = played
    self.discarded = discarded
    self.num_mistakes = num_mistakes
    self.num_tokens = num_tokens
    self.current_player = 0

  def print_state(self, player_index = None):
    if player_index is None:
      player_index = self.current_player
    for other_player in range(self.num_players):
      hand = self.hands[other_player]
      if other_player == player_index:
        print("{} (your) hand".format(other_player))
        for _, hints in hand:
          print(hints)
      else:
        print("{} hand".format(other_player))
        for card, hint in hand:
          print("{} [{}]".format(card, hint))

    print("discarded {}".format(" ".join(self.discarded)))
    played = []
    for color in COLOR_LETTERS:
      played.append("{}{}".format(self.played[color], color))

    print("played {}".format(" ".join(played)))
    print("{} hints left".format(self.num_tokens))
    print("{} mistakes made".format(self.num_mistakes))

  @property
  def current_hand(self):
    return self.hands[self.current_player]

  @property
  def num_players(self):
    return len(self.hands)

  @property
  def hand_size(self):
    return NUM_CARDS_IN_HAND[self.num_players]

  def are_plays_remaining(self):
    return len(self.current_hand) == self.hand_size

  def is_complete(self):
    return (all([v == 5 for v in self.played.values()]) or
            self.num_mistakes >= 3 or
            (len(self.deck) == 0 and
             all([len(h) < self.hand_size for h in self.hands])))

  # game actions

  def hint(self, player_index, hint):
    if player_index == self.current_player:
      assert('TODO - self-hint...')

    if self.num_tokens <= 0:
      assert('TODO - no hint tokens')

    self.num_tokens -= 1
    for c in self.hands[player_index]:
      c[1].add_hint(c[0], hint)

    self.next_player()

  def play(self, card_index):
    if not self.are_plays_remaining():
      assert('TODO - no more plays')

    hand = self.current_hand
    card = hand.pop(card_index)[0]
    self.draw()

    if not self.is_playable(card):
      self.num_mistakes += 1
      self.discarded.append(card)
      self.next_player()
      return

    self.played[get_color(card)] += 1
    self.next_player()

  def discard(self, card_index):
    if not self.are_plays_remaining():
      assert('TODO - no more plays')

    if self.num_tokens >= 8:
      assert('TODO - full hint tokens')

    hand = self.current_hand
    card = hand.pop(card_index)
    self.discarded.append(card[0])
    self.draw()
    self.num_tokens += 1
    self.next_player()

  # internal
  def draw(self):
    hand = self.current_hand
    card = self.deck.pop()
    hand.append((card, Hints.empty()))

  def next_player(self):
    self.current_player = (self.current_player + 1) % self.num_players

  def is_playable(self, card):
    highest_played = self.played[get_color(card)]
    return get_number(card) == highest_played + 1


from models.layers import mean_pooling, BiAttention, LSTMWrapper, GatedAttention
from jdmodels.jdlayers import GraphBlock, encoder_graph_node_feature, PredictionLayer, ParaSentEntPredictionLayer
from torch import nn

class HierarchicalGraphNetwork(nn.Module):
    """
    Packing Query Version
    """
    def __init__(self, config):
        super(HierarchicalGraphNetwork, self).__init__()
        self.config = config
        self.max_query_length = self.config.max_query_length

        self.bi_attention = BiAttention(input_dim=config.input_dim,
                                        memory_dim=config.input_dim,
                                        hid_dim=config.hidden_dim,
                                        dropout=config.bi_attn_drop)
        self.bi_attn_linear = nn.Linear(config.hidden_dim * 4, config.hidden_dim)
        self.hidden_dim = config.hidden_dim
        self.sent_lstm = LSTMWrapper(input_dim=config.hidden_dim,
                                     hidden_dim=config.hidden_dim,
                                     n_layer=1,
                                     dropout=config.lstm_drop) ### output: 2 * self.hidden_dim

        q_dim = self.hidden_dim if config.q_update else config.input_dim
        self.q_map = nn.Linear(in_features=q_dim, out_features=self.hidden_dim * 2)
        if self.q_map:
            nn.init.xavier_uniform_(self.q_map.weight, gain=1.414)

        self.graph_blocks = nn.ModuleList()
        self.graph_blocks.append(GraphBlock(self.config.q_attn, config, input_dim=self.hidden_dim * 2, hidden_dim=self.hidden_dim))
        for _ in range(self.config.num_gnn_layers-1):
            self.graph_blocks.append(GraphBlock(self.config.q_attn, config, input_dim=self.hidden_dim, hidden_dim=self.hidden_dim))

        self.ctx_attention = GatedAttention(input_dim=config.hidden_dim*2,
                                            memory_dim=config.hidden_dim,
                                            hid_dim=self.config.ctx_attn_hidden_dim,
                                            dropout=config.bi_attn_drop,
                                            gate_method=self.config.ctx_attn)
        self.para_sent_ent_predict_layer = ParaSentEntPredictionLayer(self.config, hidden_dim=self.hidden_dim)
        self.predict_layer = PredictionLayer(self.config)

    def forward(self, batch, return_yp):
        query_mapping = batch['query_mapping']
        context_encoding = batch['context_encoding']
        # extract query encoding
        trunc_query_mapping = query_mapping[:, :self.max_query_length].contiguous()
        trunc_query_state = (context_encoding * query_mapping.unsqueeze(2))[:, :self.max_query_length, :].contiguous()
        # bert encoding query vec
        query_vec = mean_pooling(trunc_query_state, trunc_query_mapping)
        attn_output, trunc_query_state = self.bi_attention(context_encoding,
                                                           trunc_query_state,
                                                           trunc_query_mapping)
        input_state = self.bi_attn_linear(attn_output) # N x L x d
        input_state = self.sent_lstm(input_state, batch['context_lens'])
        if self.config.q_update:
            query_vec = mean_pooling(trunc_query_state, trunc_query_mapping)

        query_vec = self.q_map(query_vec)
        ################################################################################################################
        graph_state_dict = encoder_graph_node_feature(batch=batch, input_state=input_state, hidden_dim=self.hidden_dim)
        graph_state, graph_mask = None, None
        ################################################################################################################
        for l in range(self.config.num_gnn_layers):
            graph_state, graph_state_dict, graph_mask, query_vec = self.graph_blocks[l](batch=batch,
                                                                                graph_state_dict=graph_state_dict,
                                                                                query_vec=query_vec)
        input_state, _ = self.ctx_attention(input_state, graph_state, graph_mask.squeeze(-1))
        para_logit, sent_logit, ent_logit = self.para_sent_ent_predict_layer.forward(batch=batch,
                                                                                graph_state_dict=graph_state_dict,
                                                                                query_vec=query_vec)
        predictions = self.predict_layer(batch, input_state, sent_logit, packing_mask=query_mapping,
                                         return_yp=return_yp)
        if return_yp:
            start, end, q_type, yp1, yp2 = predictions
            return start, end, q_type, para_logit, sent_logit, ent_logit, yp1, yp2
        else:
            start, end, q_type = predictions
            return start, end, q_type, para_logit, sent_logit, ent_logit


from FHanalyze.error_handling import handle_exception
from pymongo import MongoClient
from pymongo.errors import ConfigurationError
from bson.objectid import ObjectId
from datetime import datetime, timedelta, date
import pandas as pd
import time
import logging
logger = logging.getLogger(__name__)

ALL_READINGS = '*'

class Analyze:
    """The Analyze class connects to the mongodb collection that
    contains the power readings saved by the
    `FHmonitor <https://fhmonitor.readthedocs.io/en/latest/>`_.

    To get an instance of the Analyze class, pass into __init__:

    :param mongodb_path: The mongodb connection string.  See the
        `connection string
        <https://docs.mongodb.com/manual/reference/connection-string/>`_
        documentation.  Defaults to "mongodb://127.0.0.1:27017".

    :param db_str: The database within mongodb that holds the readings.
        Defaults to "FitHome".

    :param collection_name: The collection within the database where the
        readings are stored. Defaults to "aggregate".
    """

    def __init__(self, mongodb_path="mongodb://127.0.0.1:27017",
                 db_str="FitHome", collection_name="aggregate"):
        self.mongodb_path = mongodb_path
        self.db_str = db_str
        self.collection_name = collection_name
        self.collection = None

    def get_isodate_list(self):
        """Get the list of dates in isodate format that contain active and
        reactive power readings.

        :return: list of isodates that contain power readings.
        """
        self._connect_to_collection()  # Will error out if can't connect.
        # Will error out is can't get first, last date from mongodb.
        isodate_first, isodate_last = self._get_first_and_last_isodate()

        iso_days_list = self._filter_out_dates_with_no_readings(isodate_first,
                                                                isodate_last)
        logger.debug(f'first date: {isodate_first} Last date: {isodate_last}')
        return iso_days_list

    def get_DataFrame_for_date(self, date_str=ALL_READINGS):
        """Return the active Power readings for a
        specific date or for all dates.

        :param date: isodate formatted date or "*".
            Defaults to "*"
        :return: A pandas DataFrame with a dateindex and a
            column named 'pA' of active power readings.
        """

        df = self._get_df_no_datetimeindex(date_str)
        if df.empty:
            handle_exception(
                f'There are no readings in the database for {date_str}')
        return self._set_datetimeindex(df)

    def get_always_on_watts(self, date_str=ALL_READINGS, start_time='*',
                            end_time='*', quantile=.3):
        """Return the amount of power (in watts) that are wasted by appliances that
        are always plugged in and use electricity, even when the appliance is
        not being used.

        :param date_str: Either a date in isodate format to use readings in the
            calculation for that date or '*' to use all available dates for
            the calculation.  Defaults to '*'
        :param start_time: Use readings that are taken at this time.  The
            start_time is the beginning of an amount of time to filter
            results.  Defaults to '*'
        :param end_time: Use readings that are taken before this time.
            end_time is used with start_time to filter readings to be
            within the time between start_time and end_time.  Defaults to '*'
        :param quantile: A floating point number between 0 and 1 that cuts
            the distribution of readings.  For example, a value of .3 means
            the always_on_watts value is taken at the place where 30% of the
            readings are found.  Defaults to .3.
        """
        if date_str not in ALL_READINGS:
            self._check_good_isodate(date_str)  # If not errors out.
        always_on_watts = self._calc_always_on(
            date_str, start_time, end_time, quantile)
        return always_on_watts
    #############################################################
    # Internal methods
    #############################################################

    def _connect_to_collection(self):
        """Internal method that connects to the mongo database using The path,
        database name, and collection name the instance of Analyze was
        initialized with.

        This method doesn't do anything if there is already a connection
        to the database.
        """
        if self.collection is None:
            # Create a connection and attempt to access mongod
            client = MongoClient(self.mongodb_path)
            try:
                client.server_info()  # Exception thrown if can't connect.
            except ConfigurationError as e:
                handle_exception(e)
            db = client[self.db_str]
            self.collection = db[self.collection_name]

    def _get_first_and_last_isodate(self):
        """Internal method that finds the first date and last date in which
        there are readings within the mongo db.

        Dates are in isodate format.
        """
        try:
            first_record = self.collection.find_one()
            last_record = list(self.collection.find().sort(
                [('_id', -1)]).limit(1))[0]
            isodate_first = self._id_to_isodate(first_record['_id'])
            isodate_last = self._id_to_isodate(last_record['_id'])
        except Exception as e:
            handle_exception(e)
        return isodate_first, isodate_last

    def _id_to_isodate(self, id):
        """The first 8 bits of the object id in each record is the timestamp
        when the reading was put into the database.

        :param id: object id of the mongodb record.
        """
        id_str = str(id)
        hex_str = id_str[0:8]
        ts = int(hex_str, 16)
        return datetime.fromtimestamp(ts).isoformat()

    def _filter_out_dates_with_no_readings(self, first_isodate, last_isodate):
        """This internal method checks the mongo db to see if the dates in the
        first_isodate and last_isodates range have power readings.

        :param first_isodate: first date in isodate format that should
        be checked until the last_isodate.
        :param last_isodate: the last date between the first date in
        isodate format.
        :return: lists of dates in isodate format that have power readings.
        """
        isodates_list = []
        try:
            # First get the string isodates into date types.
            start_date = datetime.fromisoformat(first_isodate).date()
            end_date = datetime.fromisoformat(last_isodate).date()
            # Create a general expresiion to enumerate through all the
            # possible dates between the start and end dates.
            gen_expr = (start_date + timedelta(n)
                        for n in range(int((end_date-start_date).days)+1))
            # Go through each date and see if there are readings available.
            # If readings are available for the date, append the date to
            # the isodate list in isodate format.

            for dt in gen_expr:
                if self._there_is_a_reading(dt):
                    # Is there at least one reading for this date?
                    isodates_list.append(dt.isoformat())
        except Exception as e:
            handle_exception(e)
        return isodates_list

    def _there_is_a_reading(self, dt):
        """An internal method that determines if there are power
        readings for the date being passed in.
        :param dt: A date in (python) date format
        :return: True if there is a reading for the date.
        """

        # Make an object ID using the date.
        day_id = self._make_objectid(dt)
        dt_next = dt + timedelta(days=1)
        next_day_id = self._make_objectid(dt_next)
        # Get a connection to mongodb if it doesn't exist.
        self._connect_to_collection()
        # Find out if there are any readings.
        # It seems more intuitive to me for the query to use equal
        # instead of lt and gt, but I couldn't find an eq?
        count = self.collection.count(
            {"_id": {'$gt': day_id, '$lt': next_day_id}})
        if count > 0:
            return True
        return False

    def _make_objectid(self, d):
        """An internal method that takes in an isodate and returns an object id
        that can be used to query readings of that date. The object id in the
        mongodb is a string of 12 bytes.  The first 4 bytes is the unix
        timestamp when the entry  was made.  We use these bytes to get readings
        of a specific date.  Once we have the 4 bytes, we put the string '00'in
        the remaining 8 characters.

        :param isodate_string: The isodate that will be turned into an object
        id.date.
        """
        # Get the timestamp as a 4 byte hex string
        ts_string = '{:x}'.format(int(time.mktime(d.timetuple())))
        # Create an object id starting with the time stamp string then padded
        # with 00's to have 12 hex bytes represented within the object id
        # string.
        object_id = ObjectId(ts_string + "0000000000000000")
        return object_id

    def _get_df_no_datetimeindex(self, date_str):
        """An internal method that returns a DataFrame that includes mongo db's
        object id.  The object id has not been coverted to a datetimeindex.

        :param date_str: Either a date in isodate format to use readings in the
            calculation for that date or '*' to use all available dates for
            the calculation.  Defaults to '*'
        :raises a: Exception if the records can't be retrieved or the date_str
            isn't of isodate format (or '*').
        :return: [description]
        :rtype: [type]
        """
        df = pd.DataFrame()
        self._connect_to_collection()
        if date_str not in ALL_READINGS:  # Get eadings for a specific isodate.
            # Check to make sure the date_str is a valid isodate.
            try:
                # Will raise a ValueError if cannot
                # convert from date_str to date datetype.
                dt = self._check_good_isodate(date_str)
                day_id = self._make_objectid(dt)
                dt_next = dt + timedelta(days=1)
                next_day_id = self._make_objectid(dt_next)
                try:
                    df = pd.DataFrame.from_records(self.collection.find(
                        {"_id": {'$gt': day_id, '$lt': next_day_id}},
                        {'_id': 1, 'Pa': 1}))
                except Exception as e:
                    handle_exception(e)
            except ValueError as e:
                handle_exception(e)
        else:
            try:
                df = pd.DataFrame.from_records(
                    self.collection.find(projection={'_id': 1, 'Pa': 1}))
            except Exception as e:
                handle_exception(e)
        return df

    def _set_datetimeindex(self, df):
        """internal method to convert the object id column (_id)
        into a datetimeindex for the power readings.
        :param df: DataFrame created by calling the
        _get_df_no_datetimeindex() method.
        :type df: A pandas DataFrame where one of the columns is
        the mongodb object id labeled as _id.
        :return: A DataFrame with the _id column making up the
        datetimeindex and then removed from the DataFrame.
        """
        df['timestamp'] = df['_id'].astype('|S').str.slice(
            start=0, stop=8).apply(int, base=16)
        df.index = pd.to_datetime(df['timestamp'], unit='s')
        df.index = df.index.tz_localize('UTC').tz_convert('US/Pacific')
        df.index = df.index.round('s').tz_localize(None)
        df.drop(['timestamp', '_id'], axis=1, inplace=True)
        return df

    def _check_good_isodate(self, date_str):
        """internal method that returns a Date datatype
        by converting the isodate date_str into a Date.
        An exception is raised if the date_str is not
        isodate formatted.

        :param date_str: isodate formatted date string.

        """
        dt = None
        try:
            dt = date.fromisoformat(date_str)
        except ValueError as e:
            handle_exception(e)
        return dt

    def _calc_always_on(self,
                        date_str, start_time, end_time, quantile):
        """ Internal method to determine how much of the electricity used
        during the date_str dates and start_time end_time time period
        is wasted.
        :param date_str: Either a date in isodate format to use readings in the
            calculation for that date or '*' to use all available dates for
            the calculation.
        """
        df = self.get_DataFrame_for_date(date_str)
        # If filtering on a time range, both start and end time need
        # to be defined.
        if start_time not in '*' and end_time not in '*':
            df = df.between_time(start_time, end_time)
        watt_leakage = float(df.quantile(quantile))
        return watt_leakage


"""
GMM Accuracy with 200 features 0.33 with k fold
GMM Accuracy with 400 features 0.24 with k fold

Bayes GMM with 200 features 0.23
Bayes GMM with 400 features 0.24

"""

from sklearn.mixture import GaussianMixture
from sklearn.mixture import BayesianGaussianMixture
from sklearn.model_selection import train_test_split
import pandas
import numpy as np
import sklearn
from sklearn.model_selection import StratifiedKFold

file_path_200f = "/home/k_mathin/PycharmProjects/DataMiningClass/datasets/classification/object_classification/yin_airpl_m_sun/target_6_4_101_91_MICC_F220_bow_200.csv"

caltech_binary = '/Users/Srikanth/PycharmProjects/COMP551_Projects/DataMiningClass_v4/datasets/classification/aero_bike/with_targets/MICC_F220_bow_200.csv'
#
# data = pandas.read_csv("/home/k_mathin/PycharmProjects/DataMiningClass/datasets/classification/heart.csv",
#                        header=None,
#                        skiprows=1)
data = pandas.read_csv(caltech_binary, header=None, skiprows=1)

X = data.iloc[:, 0:len(data.keys()) - 1]  # slicing: all rows and 1 to 4 cols
# store response vector in "y"
y = data.iloc[:, len(data.keys()) - 1]
k = len(np.unique(y))
X = np.asarray(X)
y = np.asarray(y)
skf = StratifiedKFold(n_splits=4)
skf.get_n_splits(X, y)
accuracy_list = []

for train_index, test_index in skf.split(X, y):
    # print("TRAIN:", train_index, "TEST:", test_index)

    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

    # X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

    X_train = np.asarray(X_train)
    X_test = np.asarray(X_test)
    y_train = np.asarray(y_train)
    y_test = np.asarray(y_test)

    # X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1)

    # mixture_model = GaussianMixture(n_components=k)
    mixture_model = BayesianGaussianMixture(n_components=k)
    mixture_model.fit(X_train, y_train)
    predictions = mixture_model.predict(X_test)

    accuracy_list.append(sklearn.metrics.accuracy_score(y_test, predictions))
print(accuracy_list)
print("Final acc: ", np.asarray(accuracy_list).mean())


from dataset import MangoDataset,Dataloader,make_dataset
from options import opt
from pathlib import Path
import torch
import torch.nn as nn
from torch.autograd import Variable
from torchvision import transforms
import numpy as np
from PIL import Image

label_dict={
    'A':0,
    'B':1,
    'C':2
}

def evaluation():
	eval_set=MangoDataset(Path(opt.data_root).joinpath('C1-P1_Dev'))
	# data_loader=Dataloader(dataset=eval_set,batch_size=opt.eval_batch_size,shuffle=False,num_workers=opt.eval_num_workers)
	weight_path = Path(opt.checkpoint_dir).joinpath(opt.weight_path)

	model = torch.load(weight_path)
	model = model.cuda(opt.cuda_devices)
	model.eval()

	criterion = nn.CrossEntropyLoss()

	evaluation_loss = 0.0
	evaluation_corrects = 0

	for i,(image,label) in enumerate(eval_set):
		image_1, image_2, image_3 = eval_data_transform(image)
		label=np.asarray([label])
		label=torch.from_numpy(label)

		input_1 = Variable(image_1.cuda(opt.cuda_devices))
		input_2 = Variable(image_2.cuda(opt.cuda_devices))
		input_3 = Variable(image_3.cuda(opt.cuda_devices))
		label=Variable(label.cuda(opt.cuda_devices))

		output_1 = model(input_1)
		output_2 = model(input_2)
		output_3 = model(input_3)

		output = output_1+output_2+output_3

		_, preds = torch.max(output.data, 1)
		output/=3
		loss = criterion(output/3, label)

		evaluation_loss += loss.item() * input_1.size(0)
		evaluation_corrects += torch.sum(preds == label.data)

	evaluation_loss = evaluation_loss / len(eval_set)
	evaluation_acc = float(evaluation_corrects) / len(eval_set)

	print(f'Evaluation loss: {evaluation_loss:.4f}\taccuracy: {evaluation_acc:.4f}\n')


#
# https://leetcode.com/problems/number-of-nodes-in-the-sub-tree-with-the-same-label/
# Medium
# Topics: Hash Table, Tree, Depth-First Search, Breadth-First Search, Counting
#
# This is a graph traversal problem. We'll choose Depth-First Search as the search to use. A key detail to note
# is that these are undirected graphs. This becomes important because a graph with edges defined as follows:
#
# {{0, 2}, {0, 3}, {1, 2}}
#
# if one was ignoring the unidirection, would look like
#
# 1   0
#  \ / \
#   2   3
#
# which is wrong, it actually looks like this
#
#     0
#    / \
#   2   3
#  /
# 1
#
# As we build our adjacency list, we need to add both edges to the adjacency list.
#
# Time Complexity: O(n), O(26n) -> O(n)
# Space Complexity: O(n), O(26n) -> O(n)
#
# Breadth-First Search may also be employed here. When used, we will be moving bottom up, as opposed to top to bottom, as we traditionally do.
# This way, as we move upwards, we can populate the results. To do this, we need to isolate all leafs. As we work upwards, we will be pruning our
# leafs, which in turn will create more leafs that we will need to process.
#
# Time Complexity: O(n), O(26n) -> O(n)
# Space Complexity: O(n), O(26n) -> O(n)
#

from collections import Counter
from collections import defaultdict
from typing import Dict
from typing import List

import unittest

BRUTE = False

if BRUTE:
    class Solution:
        def dfs(self, node: int, parent: int, adj: Dict[int, List[int]], labels: str, results: List[int]):
            counts: List[int] = [0] * 26
            counts[ord(labels[node]) - ord('a')] = 1
            for child in adj[node]:
                if child == parent:
                    continue
                totals = self.dfs(child, node, adj, labels, results)
                for i in range(26):
                    counts[i] += totals[i]
            results[node] = counts[ord(labels[node]) - ord('a')]
            return counts

        def countSubTrees(self, n: int, edges: List[List[int]], labels: str):
            adj: Dict[int, List[int]] = defaultdict(list)
            for e in edges:
                adj[e[0]].append(e[1])
                adj[e[1]].append(e[0])

            results = [0] * n
            self.dfs(0, -1, adj, labels, results)
            return results
else:
    class Solution:
        def dfs(self, node: int, parent: int, adj: Dict[int, List[int]], labels: str, results: List[int]):
            counts = Counter()
            for child in adj[node]:
                if child == parent:
                    continue
                counts += self.dfs(child, node, adj, labels, results)
            counts[labels[node]] += 1
            results[node] = counts[labels[node]]
            return counts

        def countSubTrees(self, n: int, edges: List[List[int]], labels: str):
            adj: Dict[int, List[int]] = defaultdict(list)
            for e in edges:
                adj[e[0]].append(e[1])
                adj[e[1]].append(e[0])

            results = [0] * n
            self.dfs(0, -1, adj, labels, results)
            return results

class TestSolution(unittest.TestCase):
    def setUp(self):
        self.soln = Solution()

    def test_case0(self):
        edges0: List[List[int]] = [[0, 1], [0, 2], [1, 4], [1, 5], [2, 3], [2, 6]]
        labels0 = "abaedcd"
        self.assertEqual(self.soln.countSubTrees(7, edges0, labels0), [2, 1, 1, 1, 1, 1, 1])

    def test_case1(self):
        edges1: List[List[int]] = [[0, 1], [1, 2], [0, 3]]
        labels1 = "bbbb"
        self.assertEqual(self.soln.countSubTrees(4, edges1, labels1), [4, 2, 1, 1])

    def test_case2(self):
        edges2: List[List[int]] = [[0, 2], [0, 3], [1, 2]]
        labels2 = "aeed"
        self.assertEqual(self.soln.countSubTrees(4, edges2, labels2), [1, 1, 2, 1])


import os
import pandas as pd
import numpy as np
import argparse

import baxus
from baxus.util.behaviors import BaxusBehavior
from baxus.util.behaviors.gp_configuration import GPBehaviour
from baxus.baxus import BAxUS
from baxus.util.parsing import embedding_type_mapper, acquisition_function_mapper, mle_optimization_mapper

from envs.spark import SparkParameters
from models.utils import get_logger, get_foldername, get_filename
from models.bench import SparkBench
from models.configs import baxus_params as bp
import models.configs as cfg

parser = argparse.ArgumentParser()
parser.add_argument('-b', '--bo', type=str, default='baxus')
# parser.add_argument('-t', '--test', type=str, default='test', help='description for this parameter')
# parser.add_argument('-i', '--ints', type=int, default=5, help='description for this parameter')
# parser.add_argument('-f', '--floats', type=float, default=0.5, help='description for this parameter')
logger = get_logger()
os.system('clear')
opt = parser.parse_args()
logger.info("## ARGUMENT INFORMATION ##")
for _ in vars(opt):
    logger.info(f"{_}: {vars(opt)[_]}")

os.makedirs(cfg.INCUMBENTS_RESULTS_PATH, exist_ok=True)

def main():
    bin_sizing_method = embedding_type_mapper[bp['embedding_type']]
    acquisition_function = acquisition_function_mapper[bp['acquisition_function']]
    mle_optimization_method = mle_optimization_mapper[bp['mle_optimization']]

    behavior = BaxusBehavior(n_new_bins=bp['new_bins_on_split'],
                            initial_base_length=bp['l_init'],
                            min_base_length=bp['l_min'],
                            max_base_length=bp['l_max'],
                            acquisition_function=acquisition_function,
                            embedding_type=bin_sizing_method,
                            adjust_initial_target_dim=bp['adjust_initial_target_dim'],
                            noise=bp['noise_std'],
                            budget_until_input_dim=bp['budget_until_input_dim']
                            )

    gp_behaviour = GPBehaviour(
        mll_estimation=mle_optimization_method,
        n_initial_samples=bp['multistart_samples'],
        n_best_on_lhs_selection=bp['multistart_after_samples'],
        n_mle_training_steps=bp['mle_training_steps'],
    )

    sp = SparkParameters()

    input_dim = len(sp) # args.input_dim
    ub = sp.ub
    lb = sp.lb

    f = SparkBench(dim=input_dim, ub=ub, lb=lb, sp=sp)

    optim = BAxUS(f=f,
                n_init=bp['n_init'],
                max_evals=bp['max_evals'],
                target_dim=bp['target_dim'],
                behavior=behavior,
                gp_behaviour=gp_behaviour,
                run_dir=get_foldername(os.path.join('bo-results', opt.bo))
                )

    optim.optimize()

    incumbent_configs, incumbent_results = optim.optimization_results_incumbent()
    np.save(get_filename(cfg.INCUMBENTS_RESULTS_PATH,'tuned_configs', '.npy'), incumbent_configs)
    np.save(get_filename(cfg.INCUMBENTS_RESULTS_PATH,'tuned_results', '.npy'), incumbent_results)

    # np.save(os.path.join(cfg.INCUMBENTS_RESULTS_PATH, 'tuned_configs.npy'), incumbent_configs)
    # np.save(os.path.join(cfg.INCUMBENTS_RESULTS_PATH, 'tuned_results.npy'), incumbent_results)

if __name__ == '__main__':
    try:
        main()
    except:
        logger.exception("ERROR!!")
    else:
        logger.handlers.clear()