import flexsolve as flx
from scipy.optimize import minimize_scalar
import numpy as np
from thermosteam.exceptions import InfeasibleRegion
from biorefineries.lipidcane import set_lipid_fraction as set_oil_fraction
import flexsolve as flx
import thermosteam as tmo
import biosteam as bst

__all__ = ('OilExtractionSpecification', 'MockExtractionSpecification')

def evaluate_across_oil_content(spec, efficiency, oil_retention,
                                  metrics, oil_content):
    spec.load_specifications(efficiency=efficiency, oil_retention=oil_retention)
    return spec._evaluate_across_oil_content(metrics, oil_content)

evaluate_across_oil_content = np.vectorize(
    evaluate_across_oil_content,
    excluded=['spec', 'metrics', 'oil_content'],
    signature='(),(),(),(m),(p)->(m,p)'
)

def evaluate_across_oil_retention(spec, efficiency, oil_content,
                                    metrics, oil_retention):
    spec.load_specifications(efficiency=efficiency, oil_content=oil_content)
    return spec._evaluate_across_oil_retention(metrics, oil_retention)

evaluate_across_oil_retention = np.vectorize(
    evaluate_across_oil_retention,
    excluded=['spec', 'metrics', 'oil_retention'],
    signature='(),(),(),(m),(p)->(m,p)'
)

class MockExtractionSpecification:

    def load_oil_content(self, oil_content):
        pass

    def load_efficiency(self, efficiency):
        pass

    def load_oil_retention(self, oil_retention):
        pass

    def load_specifications(self,
            efficiency=None,
            oil_retention=None,
            oil_content=None,
        ):
        pass

class OilExtractionSpecification:
    """
    Create a OilExtractionSpecification object for setting process
    specifications related to oil extraction.

    Parameters
    ----------
    system : System
        System associated to feedstocks.
    feedstocks : Stream
        Oilcane feedstocks.
    isplit_efficiency : ChemicalIndexer
        Defines extraction efficiency as a material split.
    isplit_oil_retention : ChemicalIndexer
        Defines bagasse oil retention as a material split.
    oil_content : float
        Oil content of feedstocks [dry wt. %].

    Notes
    -----
    Use the `load_specifications` method to load specifications.
    Setting attributes (i.e. yield_, titer, productivity, production) sets
    defaults for this method, but does not actually load any specifications.

    """

    __slots__ = (
        'system',
        'feedstocks',
        'isplit_efficiency',
        'isplit_oil_retention',
        'efficiency',
        'oil_retention',
        'oil_content',
        'locked_oil_content',
        'isplit_efficiency_is_reversed',
        'FFA_content',
        'PL_content',
    )

    def __init__(self, system, feedstocks, isplit_efficiency, isplit_oil_retention,
                 isplit_efficiency_is_reversed=False, efficiency=0.9,
                 oil_retention=0.9, oil_content=0.1, FFA_content=0.1,
                 PL_content=0.1):
        self.system = system #: [System] System associated to feedstocks
        self.feedstocks = feedstocks #: Stream Oil feedstocks
        self.isplit_efficiency = isplit_efficiency #: [ChemicalIndexer] Defines extraction efficiency as a material split.
        self.isplit_oil_retention = isplit_oil_retention #: [ChemicalIndexer] Defines bagasse oil retention as a material split.
        self.isplit_efficiency_is_reversed = isplit_efficiency_is_reversed #: [bool] Whether oil extraction efficiency is 1 - split.
        self.efficiency = efficiency #: [float] Oil extraction efficiency b
        self.oil_retention = oil_retention #: [float] Oil extraction oil retention
        self.oil_content = oil_content #: [float] Oil content of feedstocks [dry wt. %].
        self.locked_oil_content = False
        self.FFA_content = FFA_content
        self.PL_content = PL_content

    def MFPP(self):
        return self.system.TEA.solve_price(self.feedstocks)

    def dMFPP_over_doil_content_at_efficiency(self, efficiency, doil_content=0.01):
        oil_content = self.oil_content
        system = self.system
        self.load_efficiency(efficiency)
        self.load_oil_content(oil_content + doil_content)
        system.simulate()
        MFPP1 = self.MFPP()
        self.load_oil_content(oil_content)
        system.simulate()
        MFPP0 = self.MFPP()
        return (MFPP1 - MFPP0) / doil_content

    def solve_MFPP_inflection(self, oil_retention=None, oil_content=None):
        if oil_content is not None: self.load_oil_content(oil_content)
        if oil_retention is not None: self.load_oil_retention(oil_retention)
        f = self.dMFPP_over_doil_content_at_efficiency
        x0 = 0.1
        x1 = 1.
        y0 = f(x0)
        y1 = f(x1)
        if not y0 < 0. < y1: return np.nan
        return flx.IQ_interpolation(f, 0.1, 1., y0, y1, xtol=1e-4, ytol=1e-4, checkiter=False,
                                    maxiter=10)

    def load_oil_content(self, oil_content):
        if self.locked_oil_content: return
        for i in self.feedstocks:
            set_oil_fraction(
                oil_content, i, PL_fraction=self.PL_content,
                FFA_fraction=self.FFA_content
            )
        self.oil_content = oil_content

    def load_efficiency(self, efficiency):
        if self.isplit_efficiency is None: return
        self.efficiency = efficiency
        if self.isplit_efficiency_is_reversed:
            self.isplit_efficiency['Oil'] = 1. - efficiency
        else:
            self.isplit_efficiency['Oil'] = efficiency

    def load_oil_retention(self, oil_retention):
        if self.isplit_efficiency is None: return
        self.oil_retention = oil_retention
        self.isplit_oil_retention['Oil'] = oil_retention

    def load_specifications(self,
            efficiency=None,
            oil_retention=None,
            oil_content=None,
        ):
        """
        Load oil extraction specifications.

        Parameters
        ----------
        efficiency : float, optional
            Oil extraction efficiency a.
        oil_retention : float, optional
            Oil extraction efficiency b.
        oil_content : float, optional
            Oil content of feedstocks [dry wt. %].

        """
        if efficiency is None: efficiency = self.efficiency
        if oil_retention is None: oil_retention = self.oil_retention
        if oil_content is None: oil_content = self.oil_content
        self.load_oil_retention(oil_retention)
        self.load_efficiency(efficiency)
        self.load_oil_content(oil_content)

    def _evaluate_across_oil_content(self, metrics, oil_content):
        """
        Evaluate metrics across oil content and return an array with the all
        metric results.

        Parameters
        ----------
        metrics : Iterable[Callable; M elements]
            Should return a number given no parameters.
        oil_content : array_like[P elements]
            Oil contents to evaluate.

        Returns
        -------
        results : array[M x P]
            All metric results.

        """
        M = len(metrics)
        P = len(oil_content)
        data = np.zeros([M, P])
        for i in range(P):
            self.load_oil_content(oil_content[i])
            self.system.simulate()
            data[:, i] = [j() for j in metrics]
        return data

    def _evaluate_across_oil_retention(self, metrics, oil_retention):
        """
        Evaluate metrics across oil retention and return an array with the all
        metric results.

        Parameters
        ----------
        metrics : Iterable[Callable; M elements]
            Should return a number given no parameters.
        oil_retention: array_like[P elements]
            Oil retentions to evaluate.

        Returns
        -------
        results : array[M x P]
            All metric results.

        """
        M = len(metrics)
        P = len(oil_retention)
        data = np.zeros([M, P])
        for i in range(P):
            self.load_oil_retention(oil_retention[i])
            self.system.simulate()
            data[:, i] = [j() for j in metrics]
        return data

    def evaluate_across_oil_content(self,
            efficiency, oil_retention,
            metrics, oil_content
        ):
        """
        Evaluate metrics at given efficiency and oil retention across a set of
        oil contents. Return an array with the all metric results.

        Parameters
        ----------
        efficiency : float
            Oil extraction efficiency.
        oil_retention : float
            Fraction of oil retained in bagasse.
        metrics : Iterable[Callable; M elements]
            Should return a number given no parameters.
        oil_content : array_like[P elements]
            Oil content of feedstocks [dry wt. %].

        Returns
        -------
        results : array[shape x M x P]
            All metric results at given specifications.

        Notes
        -----
        This method is vectorized along titer and yield. If, for example,
        the parameters had the following dimensions:

        efficiency [Y x T], oil_retention [Y x T], metrics [M], oil_content [P]

        This method would return an array with the following dimensions:

        results [Y x T x M x P]

        """
        return evaluate_across_oil_content(self,
                                             efficiency, oil_retention,
                                             metrics, oil_content)
    def evaluate_across_oil_retention(self,
            efficiency, oil_content,
            metrics, oil_retention
        ):
        """
        Evaluate metrics at given efficiency and oil retention across a set of
        oil contents. Return an array with the all metric results.

        Parameters
        ----------
        efficiency : float
            Oil extraction efficiency.
        oil_content : float
            Oil content of feedstocks [dry wt. %].
        metrics : Iterable[Callable; M elements]
            Should return a number given no parameters.
        oil_retention : array_like[P elements]
            Fraction of oil retained in bagasse.

        Returns
        -------
        results : array[shape x M x P]
            All metric results at given specifications.

        Notes
        -----
        This method is vectorized along efficiency and oil_content. If, for example,
        the parameters had the following dimensions:

        efficiency [Y x T], oil_content [Y x T], metrics [M], oil_retention [P]

        This method would return an array with the following dimensions:

        results [Y x T x M x P]

        """
        return evaluate_across_oil_retention(self,
                                               efficiency, oil_content,
                                               metrics, oil_retention)


from sklearn.neighbors import KNeighborsClassifier
import numpy as np
from numpy import loadtxt
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split

data = loadtxt('PhishingData.txt', delimiter=",")

# split data into X and y
X = data[:,0:9]
y = data[:,9]

seed = 7
test_size = 0.3
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=test_size, random_state=seed)

for i in range(1,10):
    neigh = KNeighborsClassifier(n_neighbors=i)
    neigh.fit(X_train, y_train)

    y_pred = neigh.predict(X_test)

    predictions = [round(value) for value in y_pred]
    #verify predictions
    accuracy = accuracy_score(y_test, predictions)
    print("n_neighbors=%s"%(i))
    print("Accuracy: %.2f%% \n" % (accuracy * 100.0))


######################### filtering a bam file by tags
from __future__ import print_function
import pysam
import sys, re
# for fuzzy matching
import regex
import os
import argparse
import collections
#########################################################   HELP   #########################################################################
parser = argparse.ArgumentParser(description='Filter a bam file by read barcodes giving bam files named after the base and the tag sequence. needs the oython packages pysam and regex to be installed. It allows to give a maximal number of substitutions, although that wont work for the first position of the barcode. the default value for permitted substitutions is 1.')

parser.add_argument("--in", dest="infile", help="bam file with tagged reads", required=True)
parser.add_argument("--tags", dest="tags", help="comma separated list of tags (eg: \"TGACCAAT,ACAGTGAT,GCCAATAT,CTTGTAAT\") or pairs of ids and tags (eg: \"light_RI:TGACCAAT,light_RII:ACAGTGAT,dark_RI:GCCAATAT,dark_RII:CTTGTAAT\") or name of tag file", required=True)
parser.add_argument("--subs", dest="subs", type=int, help="maximal number of substitutions in tag sequence (default=1)", default=1)
parser.add_argument("--enz1", dest="enz1",  help="read 1 restr. enzyme overlap (default=TGCAG)", default="TGCAG")
parser.add_argument("--enz2", dest="enz2", help="read 2 restr. enzyme overlap (default=CGG)", default="CGG")
parser.add_argument("--single", dest="single", help="single end reads (default=False)", default=False, action="store_true")

args = parser.parse_args()
infile = vars(args)['infile']
subs = vars(args)['subs']
single=vars(args)['single']
if  os.path.isfile(vars(args)['tags']):
    tags=list()
    with open(vars(args)['tags'], "r") as f:
#    with open(tagf, "r") as f:
        for line in f:
            line = line.rstrip()
            if (re.match("^\s*\#+",line) or re.match("^\s*$",line)):
                continue
            line=re.sub("\s+",":",line)
            tags.append(line)
else:
    tags= vars(args)['tags'].split(",")
ids=list(tags)
enz2=vars(args)['enz2']
enz1=vars(args)['enz1']

for i,tag in enumerate(tags):
	if (re.search(":",tag)):
		(ids[i],tags[i])=tags[i].split(":")
# remove whitespace in tags, if there is any
tags=[ re.sub("\s","",x) for x in tags]
ids=[ re.sub("\s","",x) for x in ids]
outfiles=[]
## index BAM file if necessary
#if not os.path.exists(infile+".bai"):
#	print "indexing "+infile
#	os.system("samtools index "+infile)
base_name=os.path.basename(infile)
# get rid of trailing bam
base_name=re.sub("\.bam(?=$)","",base_name)
samfile=pysam.Samfile(infile,"rb",check_sq=False)
tag_files=collections.defaultdict()
tag_count=collections.defaultdict(int)
tag_pats=collections.defaultdict()
count=0
# open files for tag splitting
for i,tag in enumerate(tags):
	tag_files[tag]=pysam.Samfile(base_name+"_"+ids[i]+".bam","wb",template=samfile)
	tag_pats[tag]=regex.compile("(?:"+tag+enz1+"){s<="+str(subs)+"}")

enz2_pat=regex.compile("(?:"+enz2+"){s<="+str(subs)+"}")
## split BAM file
#import timeit
#start_time = timeit.default_timer()
# code you want to evaluate

for entry in samfile.fetch(until_eof=True):
    if entry.is_read2:
        continue
#    read_tag=entry.qname.split('#')[-1]
    count+=1
    if (count%100000 == 0):
        print(str(count)+' readpairs gone through', file=sys.stderr)
    for tag in tags:
        if regex.match(tag_pats[tag],entry.seq):
            if single:
                tag_count[tag] += 1
                tag_files[tag].write(entry)
                break
            entry2 = samfile.next()
            if (entry2.qname != entry.qname):
                sys.exit("mates not in proper order!")
#            if (entry2.seq[0:len(enz2)] != enz2):
            if not regex.match(enz2_pat,entry2.seq):
                break
            tag_count[tag] += 1
            tag_files[tag].write(entry)
            tag_files[tag].write(entry2)
            break
#elapsed = timeit.default_timer() - start_time

print("read pairs read:\t{}".format(count))
tot_tag=0
for i,tag in enumerate(tags):
    print( "tag {} id {}:\t{}".format(tag,ids[i],tag_count[tag]) )
    tot_tag += tag_count[tag]
    tag_files[tag].close
print("reads not taggged:\t{}".format(count-tot_tag))
samfile.close()


# d = {"name":["mohammad","ali"],"age":30,}

# print(d["name"])
# # d["name"]="mohmmadreza"
# print(d)

# roman_numbers = {
#     "I": 1, "II": 2, "III": 3, "IV": 4, "V": 5,
#     "VI": 6, "VII": 7, "VIII": 8, "IX": 9, "X": 10, }

# key = input()
# if key not in roman_numbers.keys():
#     print("invalid key")
# else:
#     number = roman_numbers[key]
#     print(number)

# abjad = {"ا": 1, "ب": 2, "ج": 3, "د": 4, "ه": 5, "و": 6, "ز": 7, "ح": 8, "ط": 9, "ی": 10, "ک": 20, "ل": 30, "م": 40, "ن": 50, "س": 60,
#          "ع": 70, "ف": 80, "ص": 90, "ق": 100, "ر": 200, "ش": 300, "ت": 400, "ث": 500, "خ": 600, "ذ": 700, "ض": 800, "ظ": 900, "غ": 1000, }

# name = input()
# s = 0
# for i in name:
#     s += abjad[i]
# print(s)
# a = {}
# a["name"]="mohmmad"

# [
#     {
#         "name": "mohammad",
#         "age": 16,
#         "id": "6546985645"
#     },
#     {
#         "name": "ali",
#         "age": 20,
#         "id": "dfdffd"
#     },
#     {
#         "name": "reza",
#         "age": 17,
#         "id": "sdfdfdds"
#     },    {
#         "name": "ahmad",
#         "age": 10,
#         "id": "24541545"
#     }

# ]

n = int(input())
people = []
for i in range(n):
    name = input(f"please enter person{i}'s name")
    age = int(input(f"please enter person{i}'s age"))
    Id = input(f"please enter person{i}'s id")
    person = {"name":name,"age":age,"id":Id}
    people.append(person)
    # people.append({"name":input("name"),"age":int(input("age")),"id":input("id")})

print(people)


"""empty message

Revision ID: 74b4469fdbda
Revises: 3d167a6465d0
Create Date: 2018-12-13 15:26:21.194199

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '74b4469fdbda'
down_revision = '3d167a6465d0'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('stardrive_user',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('last_updated', sa.DateTime(), nullable=True),
    sa.Column('first_name', sa.String(), nullable=True),
    sa.Column('last_name', sa.String(), nullable=True),
    sa.Column('email', sa.String(), nullable=False),
    sa.Column('role', sa.String(), nullable=True),
    sa.Column('password', sa.Binary(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('email')
    )
    op.create_table('email_log',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.Column('type', sa.String(), nullable=True),
    sa.Column('tracking_code', sa.String(), nullable=True),
    sa.Column('viewed', sa.Boolean(), nullable=True),
    sa.Column('date_viewed', sa.DateTime(), nullable=True),
    sa.ForeignKeyConstraint(['user_id'], ['stardrive_user.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.drop_table('user')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('user',
    sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
    sa.Column('last_updated', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.Column('first_name', sa.VARCHAR(), autoincrement=False, nullable=True),
    sa.Column('last_name', sa.VARCHAR(), autoincrement=False, nullable=True),
    sa.Column('email', sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column('password', postgresql.BYTEA(), autoincrement=False, nullable=True),
    sa.Column('role', sa.VARCHAR(), autoincrement=False, nullable=True),
    sa.PrimaryKeyConstraint('id', name='user_pkey'),
    sa.UniqueConstraint('email', name='user_email_key')
    )
    op.drop_table('email_log')
    op.drop_table('stardrive_user')
    # ### end Alembic commands ###


def get_shortest_unique_substring(arr, str):
  arr_map={i:1 for i in arr}
  sub_map={}
  have,want=len(arr),0
  min_l=float('inf')
  l=0
  for r in range(len(str)):
    char=str[r]
    sub_map[char]=1+sub_map.get(char,0)
    if char in arr_map and arr_map[char]==sub_map[char]:
      want+=1
    while have==want:
      if r-l+1<min_l:
        sub_str=[l,r]
        min_l=r-l+1
      sub_map[str[l]]-=1
      l+=1
      if char in arr_map and arr_map[char]>sub_map[char]:
        have-=1
  return str[sub_str[0]:sub_str[1]+1] if min_l != float('inf') else ''

arr = ['x','y','z']
str = "xyyzyzyx"
print(get_shortest_unique_substring(arr,str))


# import wandb
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Lambda
import numpy as np
import os

from base import Algorithm

#

class Actor:
    def __init__(self, state_dim, action_dim, action_bound, std_bound, actor_lr, clip_ratio):
        self.state_dim = state_dim
        self.action_dim = action_dim
        self.action_bound = action_bound
        self.std_bound = std_bound
        self.model = self.create_model()
        self.opt = tf.keras.optimizers.Adam(actor_lr)
        self.clip_ratio = clip_ratio
        tf.keras.backend.set_floatx('float64')
    def get_action(self, state):
        #print(state)
        # state = np.reshape(state, [1, self.state_dim])
        #print(state)
        mu, std = self.model.predict(state)
        #action  = tf.random.normal([1,self.action_dim],mu,std)
        action = np.random.normal(mu[0], std[0], size=self.action_dim)
        action = np.clip(action, -self.action_bound, self.action_bound)
        log_policy = self.log_pdf(mu, std, action)

        return log_policy, action

    def log_pdf(self, mu, std, action):
        std = tf.clip_by_value(std, self.std_bound[0], self.std_bound[1])
        var = std ** 2
        log_policy_pdf = -0.5 * (action - mu) ** 2 / \
                         var - 0.5 * tf.math.log(var * 2 * np.pi)
        return tf.reduce_sum(log_policy_pdf, 1, keepdims=True)

    def create_model(self):
        state_input = Input((self.state_dim,))
        dense_1 = tf.keras.layers.Dense(128, activation='relu')(state_input)
        dense_2 = Dense(128, activation='relu')(dense_1)
        out_mu = Dense(self.action_dim, activation='tanh')(dense_2)
        mu_output = Lambda(lambda x: x * self.action_bound)(out_mu)
        std_output = Dense(self.action_dim, activation='softplus')(dense_2)
        return tf.keras.models.Model(state_input, [mu_output, std_output])

    def compute_loss(self, log_old_policy, log_new_policy, actions, gaes):
        ratio = tf.exp(log_new_policy - tf.stop_gradient(log_old_policy))
        gaes = tf.stop_gradient(gaes)
        clipped_ratio = tf.clip_by_value(
            ratio, 1.0 - self.clip_ratio, 1.0 + self.clip_ratio)
        surrogate = -tf.minimum(ratio * gaes, clipped_ratio * gaes)
        return tf.reduce_mean(surrogate)

    def train(self, log_old_policy, states, actions, gaes):
        with tf.GradientTape() as tape:
            mu, std = self.model(states, training=True)
            log_new_policy = self.log_pdf(mu, std, actions)
            loss = self.compute_loss(
                log_old_policy, log_new_policy, actions, gaes)
        grads = tape.gradient(loss, self.model.trainable_variables)
        self.opt.apply_gradients(zip(grads, self.model.trainable_variables))
        return loss

    def load_weights(self, path):
        self.model.load_weights(path)

    def save_weights(self, path):
        self.model.save_weights(path)

class Critic:
    def __init__(self, state_dim, critic_lr):
        self.state_dim = state_dim
        self.model = self.create_model()
        self.opt = tf.keras.optimizers.Adam(critic_lr)

    def create_model(self):
        return tf.keras.Sequential([
            Input((self.state_dim,)),
            Dense(128, activation='relu'),
            Dense(128, activation='relu'),
            Dense(64, activation='relu'),
            Dense(1, activation='linear')
        ])

    def compute_loss(self, v_pred, td_targets):
        mse = tf.keras.losses.MeanSquaredError()
        return mse(td_targets, v_pred)

    def train(self, states, td_targets):
        with tf.GradientTape() as tape:
            v_pred = self.model(states, training=True)
            assert v_pred.shape[0] == td_targets.shape[0]
            loss = self.compute_loss(v_pred, tf.stop_gradient(td_targets))
        grads = tape.gradient(loss, self.model.trainable_variables)
        self.opt.apply_gradients(zip(grads, self.model.trainable_variables))
        return loss

    def load_weights(self, path):
        self.model.load_weights(path)

    def save_weights(self, path):
        self.model.save_weights(path)

class PPO2(Algorithm):
    def __init__(self, state_dim, action_shape, seed, env, gamma=0.9, clip_ratio=0.2, lamdb=0.95,
                 actor_lr=3e-4, critic_lr=1e-3,update_interval = 10,update_epochs = 5):
        super().__init__(10, action_shape, seed, gamma)

        self.env = env
        self.state_dim = state_dim
        self.action_dim = action_shape
        self.action_bound = 1
        self.std_bound = [1e-2, 1.0]
        self.name = 'ppo2'
        self.lamdb = lamdb
        self.update_interval = update_interval
        self.update_epochs = update_epochs
        self.actor_lr = actor_lr
        self.critic_lr = critic_lr
        self.actor_opt = tf.keras.optimizers.Adam(actor_lr)
        self.critic_opt = tf.keras.optimizers.Adam(critic_lr)
        self.actor = Actor(self.state_dim, self.action_dim,
                           self.action_bound, self.std_bound, actor_lr, clip_ratio)
        self.critic = Critic(self.state_dim, critic_lr)

    def gae_target(self, rewards, v_values, next_v_value, done):
        n_step_targets = np.zeros_like(rewards)
        gae = np.zeros_like(rewards)
        gae_cumulative = 0
        forward_val = 0

        if not done:
            forward_val = next_v_value

        for k in reversed(range(0, len(rewards))):
            delta = rewards[k] + self.gamma * forward_val - v_values[k]
            gae_cumulative = self.gamma * self.lamdb * gae_cumulative + delta
            gae[k] = gae_cumulative
            forward_val = v_values[k]
            n_step_targets[k] = gae[k] + v_values[k]
        return gae, n_step_targets

    def update(self, epochs):

        states, actions, rewards, old_policys = self.buffer.sample()
        next_state, reward, done, _ = self.env.step(actions)
        v_values = self.critic.model.predict(states)
        next_v_value = self.critic.model.predict(next_state)
        gaes, td_targets = self.gae_target(rewards, v_values, next_v_value, done)

        for epoch in range(epochs):
            actor_loss = self.actor.train(
                old_policys, states, actions, gaes)
            critic_loss = self.critic.train(states, td_targets)

    def load_weights(self, path):
        print('load weights success!')
        self.actor.load_weights('{}/ppo_actor.h5'.format(path))
        self.critic.load_weights('{}/ppo_critic.h5'.format(path))

    def save_models(self, save_dir):
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)
        self.actor.save_weights('{}/ppo_actor.h5'.format(save_dir))
        self.critic.save_weights('{}/ppo_critic.h5'.format(save_dir))

    @property
    def networks(self):
        return [
            self.actor.model,
            self.critic.model,
        ]
if __name__ == '__main__':
    gamma = 0.99
    clip_ratio = 0.2
    lamdb = 0.95
    action_bound = 1
    std_bound = [1e-2, 1.0]
    actor = Actor(300, 100,action_bound, std_bound, 1e-3, clip_ratio)
    s = tf.random.uniform(shape=[1,300])
    p,a = actor.get_action(s)
    print(a.shape)
    save_dir = './model'
    actor.save_weights('{}/ppo_actor.h5'.format(save_dir))
    actor.save_weights('{}/ppo_actor.h5'.format(save_dir))


import typing as tp

import aiogram.types as types

class WrappedInlineKeyboardMarkup(types.InlineKeyboardMarkup):
    def __init__(self, symbols_limit: int = 23, count_limit: int = 3) -> None:
        self.symbols_limit = symbols_limit
        super().__init__(row_width=count_limit)

    def add(self, *args: types.InlineKeyboardButton) -> None:
        row: tp.List[types.InlineKeyboardButton] = []
        row_len = 0

        for button in args:
            if row_len + len(button.text) <= self.symbols_limit and len(row) + 1 <= self.row_width:
                row.append(button)
                row_len += len(button.text)
            else:
                self.inline_keyboard.append(row)
                row = [button]
                row_len = len(button.text)

        self.inline_keyboard.append(row)


import cv2
import threading
from tqdm import tqdm
import time

class BackgroundTask(threading.Thread):
    def __init__(self,funcs,cleanup=None,progress_callbacks=[],
            done_callback=lambda s: None):
        super().__init__()
        self.funcs = funcs
        self.progress_callbacks = progress_callbacks
        self.done_callback = done_callback
        self.i = None
        self.t = time.process_time()
        self.kill_flag = False
        self.cleanup = cleanup
    def run(self):
        for self.i,func in tqdm(enumerate(self.funcs)):
            func(self.i)
            t = time.process_time()
            if t-self.t > 1:
                for c in self.progress_callbacks:
                    c()
                self.t = t
            if self.kill_flag:
                break
        if self.cleanup is not None:
            self.cleanup()
        self.done_callback(self)
    def kill(self):
        self.kill_flag = True
    def __len__(self):
        return len(self.funcs)

def bounded(v,min_val,max_val):
    return min(max(v,min_val),max_val)

class State:
    def __init__(self, video, annotations):
        self.video = video
        self.annotations = annotations

        self.annotation_id = 0
        self.paused = True
        self.current_frame_index = 0

        self.zoom = 1
        self.zoom_centre = (self.video.width//2, self.video.height//2)

        self.callbacks = {
                'video': [],
                'annotations': [],
                'pause': [],
                'background': []
        }
        self.background_tasks = []
        self.dirty = False

        self.render_salience = False

    def add_callback(self, key, callback):
        self.callbacks[key].append(callback)
    def call_callbacks(self, key):
        for f in self.callbacks[key]:
            f()
    def launch_bg_task(self, funcs, cleanup=None):
        def done_callback(task):
            print('done',task)
            self.background_tasks.remove(task)
            if len(self.background_tasks) > 0:
                self.background_tasks[0].start()
            self.call_callbacks('background')
        task = BackgroundTask(funcs,cleanup,self.callbacks['background'],done_callback)
        self.background_tasks.append(task)
        if len(self.background_tasks) == 1:
            task.start()
    def kill_current_bg_task(self):
        self.background_tasks[0].kill()

    def save(self):
        self.annotations.save_annotations()
        self.dirty = False

    def delete_keyframe(self):
        self.annotations.remove_annotation(self.current_frame_index, self.annotation_id)
        self.call_callbacks('video')
        self.call_callbacks('annotations')
        self.dirty = True
    def jump_to_keyframe_nearest(self):
        kf_indices = list(self.annotations[self.annotation_id].keys())
        if len(kf_indices) == 0:
            return
        index = self.current_frame_index
        closest_index = min(kf_indices, key=lambda x: abs(index-x))
        self.current_frame_index = closest_index
        print('%d -> %d' % (index, closest_index))
        self.call_callbacks('video')
        self.call_callbacks('annotations')
    def jump_to_keyframe_prev(self):
        index = self.current_frame_index
        kf_indices = self.annotations[self.annotation_id].manual.keys()
        kf_indices = filter(lambda x: x<index, kf_indices)
        kf_indices = list(kf_indices)
        if len(kf_indices) == 0:
            return
        closest_index = min(kf_indices, key=lambda x: abs(index-x))
        self.current_frame_index = closest_index
        print('%d -> %d' % (index, closest_index))
        self.call_callbacks('video')
        self.call_callbacks('annotations')
    def jump_to_prev_frame(self):
        if self.current_frame_index > 0:
            self.current_frame_index -= 1
            self.call_callbacks('video')
            self.call_callbacks('annotations')
    def jump_to_next_frame(self):
        if self.current_frame_index < self.video.frame_count:
            self.current_frame_index += 1
            self.call_callbacks('video')
            self.call_callbacks('annotations')
    def jump_to_keyframe_next(self):
        index = self.current_frame_index
        kf_indices = self.annotations[self.annotation_id].manual.keys()
        kf_indices = filter(lambda x: x>index, kf_indices)
        kf_indices = list(kf_indices)
        if len(kf_indices) == 0:
            return
        closest_index = min(kf_indices, key=lambda x: abs(index-x))
        self.current_frame_index = closest_index
        print('%d -> %d' % (index, closest_index))
        self.call_callbacks('video')
        self.call_callbacks('annotations')

    def generate_annotations(self):
        funcs = self.annotations[self.annotation_id].template_matched.generate2(
                self.current_frame_index)
        self.launch_bg_task(funcs)
    def generate_annotations_optical_flow(self):
        funcs = self.annotations[self.annotation_id].optical_flow.generate2(
                self.current_frame_index)
        self.launch_bg_task(funcs)
    def generate_annotations_cnn(self):
        funcs = self.annotations.predicted.generate2(
                self.current_frame_index)
        self.launch_bg_task(funcs)
    def generate_annotations_cnn2(self):
        funcs = self.annotations.predicted2.generate2(
                self.current_frame_index)
        self.launch_bg_task(funcs, cleanup=self.annotations.predicted2.postprocess)

    def prev_annotation(self):
        ann_ids = sorted(self.annotations.annotations.keys())
        ann_ids.reverse()
        for i in ann_ids:
            if i < self.annotation_id:
                self.annotation_id = i
                print('Selected annotation %d/%d'%(len(ann_ids)-ann_ids.index(self.annotation_id),len(ann_ids)))
                break
        self.call_callbacks('video')
        self.call_callbacks('annotations')
    def next_annotation(self):
        ann_ids = sorted(self.annotations.annotations.keys())
        for i in ann_ids:
            if i > self.annotation_id:
                self.annotation_id = i
                print('Selected annotation %d/%d'%(ann_ids.index(self.annotation_id)+1,len(ann_ids)))
                break
        self.call_callbacks('video')
        self.call_callbacks('annotations')
    def new_annotation(self):
        annotation_id = max(self.annotations.get_ids())+1
        self.annotations[annotation_id] # Access it to create it
        self.annotation_id = annotation_id
        # Console output
        ann_ids = sorted(self.annotations.get_ids())
        print('Selected annotation %d/%d'%(ann_ids.index(self.annotation_id)+1,len(ann_ids)))
        self.call_callbacks('video')
        self.call_callbacks('annotations')
        self.dirty = True
    def delete_annotation(self):
        deleted_id = self.annotation_id
        del self.annotations[deleted_id]
        # Set selected annotation to the previous annotation
        # i.e. Find largest ID that's smaller than the deleted ID
        self.prev_annotation()
        self.next_annotation()
        # Console output
        ann_ids = sorted(self.annotations.get_ids())
        print('Selected annotation %d/%d'%(ann_ids.index(self.annotation_id)+1,len(ann_ids)))
        self.call_callbacks('video')
        self.call_callbacks('annotations')
        self.dirty = True
    def clear_annotation(self):
        self.annotations[self.annotation_id] = {}
        self.call_callbacks('video')
        self.call_callbacks('annotations')
        self.dirty = True

    def inc_window_size(self):
        size = self.annotations[self.annotation_id].get_window_size()[0]
        self.annotations[self.annotation_id].set_window_size(size*2)
        print(size)
        self.call_callbacks('video')
        self.dirty = True
    def dec_window_size(self):
        size = self.annotations[self.annotation_id].get_window_size()[0]
        self.annotations[self.annotation_id].set_window_size(size//2)
        print(size)
        self.call_callbacks('video')
        self.dirty = True
    def inc_template_size(self):
        size = self.annotations[self.annotation_id].get_template_size()[0]
        self.annotations[self.annotation_id].set_template_size(size*2)
        print(size)
        self.call_callbacks('video')
        self.dirty = True
    def dec_template_size(self):
        size = self.annotations[self.annotation_id].get_template_size()[0]
        self.annotations[self.annotation_id].set_template_size(size//2)
        self.call_callbacks('video')
        self.dirty = True

    def seek(self, frame):
        if type(frame) is int:
            self.current_frame_index = frame
        elif type(frame) is float:
            self.current_frame_index = int(frame*self.video.frame_count)
        else:
            raise TypeError('Unsupported type: %s. Expected int or float.' % (type(frame)))
        if self.current_frame_index < 0:
            self.current_frame_index = 0
        if self.current_frame_index > self.video.frame_count:
            self.current_frame_index = self.video.frame_count
        self.call_callbacks('video')
        self.call_callbacks('annotations')

    def toggle_pause(self, p = None):
        if p is None:
            self.paused = not self.paused
        else:
            self.paused = p
        self.call_callbacks('pause')

    def zoom_in(self):
        self.zoom += 0.1
        self.call_callbacks('video')
        print(self.zoom)
    def zoom_out(self):
        self.zoom -= 0.1
        if self.zoom < 1:
            self.zoom = 1
        self.call_callbacks('video')
    def zoom_reset(self):
        self.zoom = 1
        self.call_callbacks('video')
    def zoom_translate(self,dx,dy):
        # Vars
        x,y = self.zoom_centre
        z = self.zoom
        w,h = self.video.width, self.video.height
        # Compute
        x = bounded(x-dx/z,w/z//2,w-w/z//2)
        y = bounded(y-dy/z,h/z//2,h-h/z//2)
        # Save results
        self.zoom_centre = x,y
        print('translate',dx,dy)
        self.call_callbacks('video')

    def get_frame(self, render_annotations=True):
        frame = self.video.get_frame(self.current_frame_index)
        frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
        if render_annotations:
            frame = self.annotations.render(frame, self.current_frame_index, render_salience=self.render_salience)
        # Compute Zoom Size
        h,w,_ = frame.shape
        zx,zy = self.zoom_centre
        zx = int(zx)
        zy = int(zy)
        zw = int(w//self.zoom)
        zh = int(h//self.zoom)
        left = bounded(zx-zw//2,0,w-zw)
        top = bounded(zy-zh//2,0,h-zh)
        cropped_frame = frame[top:top+zh,left:left+zw,:]
        frame = cv2.resize(cropped_frame,(w,h))
        return frame

    def save_video(self, file_name, start_frame=None, end_frame=None):
        if start_frame is None:
            start_frame = self.current_frame_index
        if end_frame is None:
            end_frame = self.video.frame_count
        print('Saving video to',file_name)

        fourcc = cv2.VideoWriter_fourcc(*'XVID')
        output = cv2.VideoWriter(file_name, fourcc, self.video.fps, (self.video.width,self.video.height))
        def save_frame(index):
            frame = self.video.get_frame(index)
            frame = self.annotations.render(frame, index)
            output.write(frame)
        def cleanup():
            output.release()
            print('output file released')
        self.launch_bg_task([lambda i: save_frame(i+start_frame) for _ in range(end_frame-start_frame)],cleanup=cleanup)

    def add_annotation(self,annotation):
        if annotation is not None:
            z = self.zoom
            zx,zy = self.zoom_centre
            w,h = self.video.width, self.video.height
            x,y = annotation
            x = (zx-w/z/2+x*w/z)/w
            y = (zy-h/z/2+y*h/z)/h
            annotation = x,y
        self.annotations.add_annotation(
                frame_index=self.current_frame_index,
                annotation_id=self.annotation_id,
                annotation=annotation)
        self.call_callbacks('video')
        self.call_callbacks('annotations')
        self.dirty = True

    def update(self):
        if self.paused:
            return
        if self.current_frame_index >= self.video.frame_count-1:
            self.paused = True
            return
        self.jump_to_next_frame()


# -*- coding: utf-8 -*-
"""
Created on Tue Apr  5 11:53:03 2016

@author: pellowes
"""
import numpy as np
#import bigfloat
#format 1 digit, then
#n digits
#then
#several data lines (x) based on one of the n digits
def readThroughDataGeneric(filename):
    outputs = []
    f = open(filename,'r')
    lct=0
    for line in f.readlines():
        if lct==0:
            t = int(line.strip())
        else:
            l = line.strip().split(' ')
            n = int(l[0])
            j = int(l[1])
            #we need j, and are working with length n
            for i in range(0,np.power(2,n-2)):#don't need to change first or last
                print(i)
                binrep = bin(i)[2:]
                while len(binrep) < n-2:
                    binrep='0'+binrep
                cointocheck = '1'+binrep+'1'
                #print(cointocheck)
                coinjamout = checkValidCoinJam(cointocheck,n)
                if coinjamout is not None:
                    out = []
                    out.append(cointocheck)
                    out.extend(coinjamout)
                    outputs.append(out)
                    print('--->'+str(len(outputs)))
                    if(len(outputs)==j):
                        return outputs
        lct+=1
    f.close()
    return outputs

def solve(series):
    prev_val = True
    changes = 0
    for i in range(len(series)-1,-1,-1):
        if(prev_val != series[i]):
            changes+=1
            prev_val = series[i]
    return changes

#get number in 01011s of some base, then do long division. return remainder
#divisor assumed to be in base 10
def SimulateLongDivision(toDivide,base,divisor):
    digitstring = str(toDivide)
    currentvalue=0
    for i in range(0,len(digitstring)):
        currentvalue = 2**currentvalue+int(digitstring[i])
        currentvalue = currentvalue%base
    return currentvalue

#assumes it's getting a string of 0s and 1s
def checkValidCoinJam(candidateString,n):
    if candidateString[0] != '1' or candidateString[len(candidateString)-1] != '1':
        return None
    #check each base, keep track of valid divisors
    divisors = []
    for i in range(2,11):
        #num = convertToBase10(int(candidateString),i)
        lvd = lowestValidDivisor(candidateString,i,n)
        if lvd is None:
            return None
        divisors.append(lvd)
    return divisors

def convertToBase10(num,base):
    currentSum = int(0)
    print(base)
    reversestring = str(num)[::-1]
    for i in range(0,len(reversestring)):
    #    print(i)
        if reversestring[i]=='1':
            #manually do the power to prevent overflows in large case
            runningproduct=1
            for j in range(0,i):
                runningproduct*=base
            currentSum+=int(runningproduct)
    #print (currentSum)
    return currentSum

#get whether a valid divisor can be found
def lowestValidDivisor(num,base,n):
    #print(num)
    for i in range(2,int(np.floor(np.sqrt(float(base**(n+1)))))+1):
        if SimulateLongDivision(num,base,i) == 0:
            #print(i)
            return i
    return None

#infile_name = '/Users/pellowes/Downloads/B-small-attempt0.in'
#infile_name = '/Users/pellowes/Downloads/B-large.in'
infile_name = '/Users/pellowes/dummydata'
outputs = readThroughDataGeneric(infile_name)
print(len(outputs))
outfile_name = '/Users/pellowes/Downloads/long.out'
f = open(outfile_name,'w')
f.write("Case #1: ")
for i in range(0,len(outputs)):
    f.write('\n')
    f.write(outputs[i][0])
    for j in range(1,10):
        f.write(' ')
        f.write(str(outputs[i][j]))
f.close()


# encoding: utf-8
"""
@author: github/100101001
@contact: 17702113437@163.com
@time: 2020/4/16 上午3:06
@file: DistanceService.py
@desc:
"""

import math
from typing import List

import numpy as np

from application import app
from common.models.ciwei import Goods

class DistanceService:
    def __init__(self):
        """
        获得拟合函数
        """
        inv = 50 / 10000
        x = [10 + i * inv for i in range(10000)]
        y = [math.cos(i * math.pi / 180) for i in x]
        res = np.polyfit(x, y, 5)
        self.cos = np.poly1d(res)

    def calSimplifyDistance(self, lng1, lat1, lng2, lat2):
        """
        计算GPS间米制距离
        :param lng1:
        :param lat1:
        :param lng2:
        :param lat2:
        :return:
        """
        # 1) 三个参数
        dx = lng1 - lng2  # 经度差
        dy = lat1 - lat2  # 纬度差
        b = (lat1 + lat2) / 2  # 平均纬度

        # 角度转弧度值
        def toRadians(angle):
            return math.pi * angle / 180

        # 2) 计算东西方向距离和南北方向距离(单位：米)，东西距离采用三阶多项式
        # 夹角在一定范围内时,cos(x)可由泰勒多项式推导
        lx = 6367000.0 * toRadians(dx) * self.cos(b)
        # 夹角较小时 sin(x) ~ x
        ly = 6367000.0 * toRadians(dy)
        # 3) 用平面的矩形对角距离公式计算总距离
        return math.sqrt(lx * lx + ly * ly)

    def filterNearbyGoods(self, goods_list: List[Goods] = None, location: str = "") -> List[Goods]:
        """
        从匹配的列表中筛选出距离20m内的

        :param goods_list: [{id, lng, lat}, {id,lng,lat}]
        :param location: "上海市黄浦区南京西路399号###上海明天广场JW万豪酒店###31.23038###121.4697"
        :return: [] 符合距离条件的物品
        """
        if location == app.config['CONSTANTS']['default_lost_loc']:
            # 遗失地址不知道，那么所有匹配上的拾物都返回
            return goods_list
        found_gps = location.split("###")[-2:]
        ret_list = []
        for item in goods_list:
            if item.os_location == app.config['CONSTANTS']['default_lost_loc']:
                # 失主不知道丢哪里了
                ret_list.append(item)
                continue
            gps = item.os_location.split("###")[-2:]
            distance = self.calSimplifyDistance(lng1=eval(found_gps[1]), lat1=eval(found_gps[0]),
                                                lng2=eval(gps[1]), lat2=eval(gps[0]))
            app.logger.warn('物品' + str(item.id) + '距离配对的物品距离为: ' + str(distance))
            if distance < 20:
                # 直线距离20m内的才算数
                ret_list.append(item)
        return ret_list

if __name__ == "__main__":
    pass


from sys import argv
import time as tiempo
import RPi.GPIO as GPIO
from sys import exit
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

foco1 = 22
foco2 = 27
foco3 = 17
foco4 = 4
foco5 = 3
foco6 = 2
foco7 = 23
foco8 = 18

boton1 = 21
boton2 = 20
boton3 = 16
boton4 = 12
boton5 = 7
boton6 = 8
boton7 = 25
boton8 = 24

motora = 26
motorb = 19
motorc = 13
motord = 6

GPIO.setup(foco1, GPIO.OUT)
GPIO.setup(foco2, GPIO.OUT)
GPIO.setup(foco3, GPIO.OUT)
GPIO.setup(foco4, GPIO.OUT)
GPIO.setup(foco5, GPIO.OUT)
GPIO.setup(foco6, GPIO.OUT)
GPIO.setup(foco7, GPIO.OUT)
GPIO.setup(foco8, GPIO.OUT)

GPIO.setup(boton1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(boton2, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(boton3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(boton4, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(boton5, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(boton6, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(boton7, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(boton8, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.add_event_detect(boton1, GPIO.RISING, bouncetime=300)
GPIO.add_event_detect(boton2, GPIO.RISING, bouncetime=300)
GPIO.add_event_detect(boton3, GPIO.RISING, bouncetime=300)
GPIO.add_event_detect(boton4, GPIO.RISING, bouncetime=300)
GPIO.add_event_detect(boton5, GPIO.RISING, bouncetime=300)
GPIO.add_event_detect(boton6, GPIO.RISING, bouncetime=300)
GPIO.add_event_detect(boton7, GPIO.RISING, bouncetime=300)
GPIO.add_event_detect(boton8, GPIO.RISING, bouncetime=300)

def acciona (txt, foco, act, mensaje1, mensaje2):
	focotxt = open(txt,'r')

	if (focotxt.read() == '0'):
		log.write(mensaje1)
		GPIO.output(foco, GPIO.HIGH)
		focotxt.close()
		focotxt = open(txt,'w')
		focotxt.write('1')
	else:
		log.write(mensaje2)
		GPIO.output(foco, GPIO.LOW)
		focotxt.close()
		focotxt = open(txt,'w')
		focotxt.write('0')

	focotxt.close()
	act.close()
	act = open('act.txt','w')
	act.write('0')

while(True):
	acttxt = open('act.txt','r')
	log = open('frame2.html', 'a')
	lectura = acttxt.read()
	if GPIO.event_detected(boton1):
		GPIO.remove_event_detect(boton1)
		acciona('foco1.txt', foco1, acttxt, '
 foco1 prendido', '
 foco1 apagado')
		GPIO.add_event_detect(boton1, GPIO.RISING, bouncetime=300)
	elif GPIO.event_detected(boton2):
		GPIO.remove_event_detect(boton2)
		acciona('foco2.txt', foco2, acttxt, '
 foco2 prendido', '
 foco2 apagado')
		GPIO.add_event_detect(boton2, GPIO.RISING, bouncetime=300)
	elif GPIO.event_detected(boton3):
		GPIO.remove_event_detect(boton3)
		acciona('foco3.txt', foco3, acttxt, '
 foco3 prendido', '
 foco3 apagado')
		GPIO.add_event_detect(boton3, GPIO.RISING, bouncetime=300)
	elif GPIO.event_detected(boton4):
		GPIO.remove_event_detect(boton4)
		acciona('foco4.txt', foco4, acttxt, '
 foco4 prendido', '
 foco4 apagado')
		GPIO.add_event_detect(boton4, GPIO.RISING, bouncetime=300)
	elif GPIO.event_detected(boton5):
		GPIO.remove_event_detect(boton5)
		acciona('foco5.txt', foco5, acttxt, '
 foco5 prendido', '
 foco5 apagado')
		GPIO.add_event_detect(boton5, GPIO.RISING, bouncetime=300)
	elif GPIO.event_detected(boton6):
		GPIO.remove_event_detect(boton6)
		acciona('foco6.txt', foco6, acttxt, '
 foco6 prendido', '
 foco6 apagado')
		GPIO.add_event_detect(boton6, GPIO.RISING, bouncetime=300)
	elif GPIO.event_detected(boton7):
		GPIO.remove_event_detect(boton7)
		acciona('foco7.txt', foco7, acttxt, '
 foco7 prendido', '
 foco7 apagado')
		GPIO.add_event_detect(boton7, GPIO.RISING, bouncetime=300)
	elif GPIO.event_detected(boton8):
		GPIO.remove_event_detect(boton8)
		acciona('foco8.txt', foco8, acttxt, '
 foco8 prendido', '
 foco8 apagado')
		GPIO.add_event_detect(boton8, GPIO.RISING, bouncetime=300)
	elif(lectura == '1'):
		acciona('foco1.txt', foco1, acttxt, '
 foco1 prendido', '
 foco1 apagado')

	elif(lectura == '2'):
		acciona('foco2.txt', foco2, acttxt, '
 foco2 prendido', '
 foco2 apagado')

	elif(lectura == '3'):
		acciona('foco3.txt', foco3, acttxt, '
 foco3 prendido', '
 foco3 apagado')

	elif(lectura == '4'):
		acciona('foco4.txt', foco4, acttxt, '
 foco4 prendido', '
 foco4 apagado')

	elif(lectura == '5'):
		acciona('foco5.txt', foco5, acttxt, '
 foco5 prendido', '
 foco5 apagado')

	elif(lectura == '6'):
		acciona('foco6.txt', foco6, acttxt, '
 foco6 prendido', '
 foco6 apagado')

	elif(lectura == '7'):
		acciona('foco7.txt', foco7, acttxt, '
 foco7 prendido', '
 foco7 apagado')

	elif(lectura == '8'):
		acciona('foco8.txt', foco8, acttxt, '
 foco8 prendido', '
 foco8 apagado')

	acttxt.close()


import json  # библиотека для парсинга json файлов
import lxml.etree  # библиотека для парсинга xml файлов
import requests  # библиотека для работы с интернет-запросами
import tickers  # файл с тикерами
import finviz  # библиотека для связи с сервисом finviz
import lxml.html as LH  # модуль для парсинга xml страниц
import re  # модуль для работы со строками
import datetime  # модуль для получения времени
from bs4 import BeautifulSoup  # Модуль для работы с HTML

header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36',
'upgrade-insecure-requests': '1',
'cookie': 'mos_id=CllGxlx+PS20pAxcIuDnAgA=; session-cookie=158b36ec3ea4f5484054ad1fd21407333c874ef0fa4f0c8e34387efd5464a1e9500e2277b0367d71a273e5b46fa0869a; NSC_WBS-QUBG-jo-nptsv-WT-443=ffffffff0951e23245525d5f4f58455e445a4a423660; rheftjdd=rheftjddVal; _ym_uid=1552395093355938562; _ym_d=1552395093; _ym_isad=2'
}

# получение цены бумаги с московской биржи
def get_moex_price(ticker):
    url = "https://iss.moex.com/iss/securities/" + ticker + ".xml?iss.meta=off&iss.only=boards&boards.columns=secid," \
                                                            "is_primary,boardid "
    answer = requests.get(url).content
    xml = lxml.etree.XML(answer)
    level = xml.xpath("//document//data//rows//row[@is_primary=1]/@boardid")[0]

    if level in ["TQOB", "EQOB", "TQOD", "TQCB", "EQQI", "TQIR"]:
        param = "bonds"
    else:
        param = "shares"

    url = "https://iss.moex.com/iss/engines/stock/markets/" + param + "/boards/" + level + "/securities.xml?iss.meta=off&iss" \
                                                                                ".only=securities&securities" \
                                                                                ".columns=SECID,PREVADMITTEDQUOTE "
    answer = requests.get(url).content
    xml = lxml.etree.XML(answer)
    return xml.xpath("//row[@SECID='" + ticker + "']/@PREVADMITTEDQUOTE")[0]

# получение цены бумаги с Yahoo Finance по тикеру
def get_yahoo_price(ticker):
    answer = requests.get(
        "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + "?modules=price", headers=header).content
    return json.loads(answer)["quoteSummary"]["result"][0]["price"]["regularMarketPrice"]["raw"]

# получение валюты бумаги с Yahoo Finance по тикеру
def get_yahoo_wallet(ticker):
    answer = requests.get(
        "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + "?modules=price", headers=header).content
    return json.loads(answer)["quoteSummary"]["result"][0]["price"]["currency"]

# получение ранга Zacks.com
def zacks_rank(ticker):
    answer = requests.get("https://quote-feed.zacks.com/" + ticker).content
    return json.loads(answer)[ticker]["zacks_rank"]

# получение названия биржи
def exchange(ticker):
    if ticker in tickers.moex_tickers:
        answer = requests.get(
            f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}.ME?modules=price", headers=header).content
    else:
        answer = requests.get(f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}?modules=price", headers=header).content
    return json.loads(answer)["quoteSummary"]["result"][0]["price"]["exchange"]

# получение дохода с начала года
def ytd_return(ticker):
    try:
        if ticker in tickers.moex_tickers:
            answer = requests.get(
                f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}.ME?modules=defaultKeyStatistics", headers=header).content
        else:
            answer = requests.get(f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}?modules=defaultKeyStatistics", headers=header).content
        return "\nДоход с начала года: "+json.loads(answer)["quoteSummary"]["result"][0]["defaultKeyStatistics"]["ytdReturn"]["fmt"] + "\n\n"
    except:
        return ""

# получение дивидендной доходности
def dividend(ticker):
    try:
        answer = requests.get(
            f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}?modules=defaultKeyStatistics", headers=header).content
        return "\nДивидендная доходность:" + json.loads(answer)["quoteSummary"]["result"][0]["defaultKeyStatistics"]["yield"]["fmt"] + "\n"
    except:
        return ""

# получение названия компании
def long_name(ticker):
    if ticker in tickers.moex_tickers:
        answer = requests.get(
            "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + ".ME?modules=price", headers=header).content
    else:
        answer = requests.get("https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + "?modules=price", headers=header).content
    return json.loads(answer)["quoteSummary"]["result"][0]["price"]["longName"]

# объединение функций получения цены с Мосбиржи и Yahoo Finance для справок
def price_spr(ticker):
    if ticker in tickers.moex_tickers:
        return str(get_moex_price(ticker)) + " RUB"
    else:
        return str(get_yahoo_price(ticker)) + " " + str(get_yahoo_wallet(ticker))

# объединение функций получения цены с Мосбиржи и Yahoo Finance для расчётов
def price(ticker):
        if ticker in tickers.moex_tickers:
            return get_moex_price(ticker)
        elif ticker == "money":
            return 1
        else:
            return get_yahoo_price(ticker)

# объединение функций YF и мосбиржи для получения валюты
def wallet(ticker):
    if ticker in tickers.moex_tickers:
        return "RUB"
    else:
        return get_yahoo_wallet(ticker)

# проверка существования тикера
def ticker_exists(ticker):
    try:
        price_spr(ticker)
        return True
    except:
        return False

# получение значения volume из finviz
def finviz_volume(ticker):
    volume = int(str(finviz.get_stock(ticker)["Volume"]).replace(",", ""))
    return volume

# получение значения average volume из finviz
def finviz_avg_volume(ticker):
    if str(finviz.get_stock(ticker)["Avg Volume"])[-1] == "M":
        return int(str(finviz.get_stock(ticker)["Avg Volume"]).replace("M", "").replace(".", "")) * 10000
    elif str(finviz.get_stock(ticker)["Avg Volume"])[-1] == "K":
        return int(str(finviz.get_stock(ticker)["Avg Volume"]).replace("K", "").replace(".", "")) * 10
    else:
        return int(str(finviz.get_stock(ticker)["Avg Volume"]))

# сравнение дневного объёма со стандартным
def finviz_volume_compare(ticker):
    return finviz_volume(ticker)/finviz_avg_volume(ticker)

# редактирует введенное значение
def make_value(value):
    if "," in value:
        value = value.replace(",", ".")
    if " " in value:
        value = value.replace(" ", "")
    if "%" in value:
        value = value. replace("%", "")
    return ''.join(i for i in value if not i.isalpha())

# является ли значением
def is_value(value):
    try:
        float(make_value(value))
        return True
    except:
        return False

# дневное измененеие цены
def day_price_change(ticker):
    if ticker in tickers.moex_tickers:
        answer = requests.get(
            "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + ".ME?modules=price", headers=header).content
        return float(json.loads(answer)["quoteSummary"]["result"][0]['price']['regularMarketChange']['fmt'])
    else:
        answer = requests.get(
            "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + "?modules=price", headers=header).content
        return float(json.loads(answer)["quoteSummary"]["result"][0]['price']['regularMarketChange']['fmt'])

# дневное изменение цены в процентах
def day_price_change_percent(ticker):
    if ticker in tickers.moex_tickers:
        answer = requests.get(
            "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + ".ME?modules=price", headers=header).content
        return float(str(json.loads(answer)["quoteSummary"]["result"][0]['price']['regularMarketChangePercent']['fmt']).replace("%",""))
    else:
        answer = requests.get(
            "https://query1.finance.yahoo.com/v10/finance/quoteSummary/" + ticker + "?modules=price", headers=header).content
        return float(str(json.loads(answer)["quoteSummary"]["result"][0]['price']['regularMarketChangePercent']['fmt']).
                     replace("%",""))

# попытка сделать из числа float
def try_float(string):
    try:
        if "," in string:
            string = string.replace(",",".")
        if " " in string:
            string = string.replace(" ","")
        return float(string)
    except:
        return False

# получение отрасли по тикеру
def sector_by_ticker(ticker):
    if ticker in tickers.moex_tickers:
        answer = requests.get(
            f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}.ME?modules=assetProfile", headers=header).content
        return json.loads(answer)["quoteSummary"]["result"][0]["assetProfile"]["sector"]
    else:
        answer = requests.get(
            f"https://query1.finance.yahoo.com/v10/finance/quoteSummary/{ticker}?modules=assetProfile", headers=header).content
        return json.loads(answer)["quoteSummary"]["result"][0]["assetProfile"]["sector"]

# очистка кэша finviz
def finviz_clear_cache():
    finviz.main_func.STOCK_PAGE.clear()

# получение курса валюты
def currency_price(wallet):

	wallet_url = ''
	# Заголовки для передачи вместе с URL
	headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'}

	current_converted_price = 0
	if wallet == "USD":
		wallet_url = 'https://www.google.com/search?sxsrf=ALeKk01NWm6viYijAo3HXYOEQUyDEDtFEw%3A1584716087546&' \
						'source=hp&ei=N9l0XtDXHs716QTcuaXoAg&q=%D0%B4%D0%BE%D0%BB%D0%BB%D0%B0%D1%80+%D0%BA+%D1%80%D1' \
						'%83%D0%B1%D0%BB%D1%8E&oq=%D0%B4%D0%BE%D0%BB%D0%BB%D0%B0%D1%80+&gs_l=psy-ab.3.0.35i39i70i258' \
						'j0i131l4j0j0i131l4.3044.4178..5294...1.0..0.83.544.7......0....1..gws-wiz.......35i39.5QL6' \
						'Ev1Kfk4'
	if wallet == "EUR":
		wallet_url = 'https://www.google.com/search?sxsrf=ALeKk01ZFuaBqz-hrNipwKI9Ay3_kxuhsw%3A1612675635328&ei' \
						'=M3ofYKi2E-zJrgS79YPICQ&q=евро+к+рублю&oq=tdhjк+рублю&gs_lcp=CgZwc3ktYWIQAxgAMgQIABANMgQIA' \
						'BANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANOgcIABCwAxBDOgYIABAHEB46' \
						'CAgAEAcQChAeOgQIABBDOgoIABAHEAoQHhAqUJKiB1iRtwdg0cIHaAJwAngAgAGTAYgB-AWSAQMyLjWYAQCgAQGqAQ' \
						'dnd3Mtd2l6yAEKwAEB&sclient=psy-ab'
	if wallet == "GBP":
		wallet_url = 'https://www.google.com/search?sxsrf=ALeKk02MiLG7ZghcxBO6ecMbtgqod7jACQ%3A1612675759581&ei' \
						'=r3ofYJiMI8rrrgT3-KCoCw&q=фунт+к+рублю&oq=aeynк+рублю&gs_lcp=CgZwc3ktYWIQAxgAMgQIABANMgQIA' \
						'BANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANMgQIABANOgcIABCwAxBDOgYIABAHE' \
						'B46CAgAEAcQChAeOgoIABAHEAoQHhAqULeFBljWiwZglpYGaAJwAngAgAFsiAGPBJIBAzAuNZgBAKABAaoBB2d3cy' \
						'13aXrIAQrAAQE&sclient=psy-ab'
	if wallet == "RUB":
		return float(1)
	full_page = requests.get(wallet_url, headers=headers)

	# Разбираем через BeautifulSoup
	soup = BeautifulSoup(full_page.content, 'html.parser')

	# Получаем нужное для нас значение и возвращаем его
	convert = soup.findAll("span", {"class": "DFlfde", "class": "SwHCTb", "data-precision": 2})
	return float(convert[0].text.replace(",", "."))


"""
Module to create datasets from the raw JHU data for interactive plotting
of the coronavirus-related data. These datasets will then flow into the
dashboard(s) create to illustrate the data in a better manner than simple
plots in my Jupyter notebooks.
"""
import os

import pandas as pd
from pycountry_convert import country_alpha2_to_continent_code, country_name_to_country_alpha2

from src.corona_analysis.corona_transformations import CoronaTransformations

class CoronaAnalysis:
    """
    Class containing methods to create datasets that allow for
    dashboarding of data pertaining to the Corona-virus pandemic of 2020.
    """

    def __init__(self, data_type: str, case_type: str, processing_date: str):
        self.data_type = data_type
        self.case_type = case_type
        self.processing_date = processing_date

    def load_raw_data(self) -> pd.DataFrame:
        """
        Method to load the raw data into a dataframe.
        or the USA-specific data.
        :return: A Pandas DataFrame containing the raw data.
        """

        if self.data_type == 'world' and self.case_type == 'case':
            raw_data = pd.read_csv(
                f'~/PyCharmProjects/covid-19-analysis/data/COVID-19/csse_covid_19_data/'
                f'csse_covid_19_time_series/time_series_covid19_confirmed_global.csv')
        elif self.data_type == 'world' and self.case_type == 'death':
            raw_data = pd.read_csv(
                f'~/PyCharmProjects/covid-19-analysis/data/COVID-19/csse_covid_19_data/'
                f'csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
        elif self.data_type == 'usa' and self.case_type == 'death':
            raw_data = pd.read_csv(
                f'~/PyCharmProjects/covid-19-analysis/data/COVID-19/csse_covid_19_data/'
                f'csse_covid_19_time_series/time_series_covid19_deaths_US.csv')
        elif self.data_type == 'usa' and self.case_type == 'case':
            raw_data = pd.read_csv(
                '~/PyCharmProjects/covid-19-analysis/data/COVID-19/csse_covid_19_data/'
                'csse_covid_19_time_series/time_series_covid19_confirmed_US.csv')
        elif self.data_type == 'aus' and self.case_type == 'case':
            raw_data = pd.read_csv(
                f'~/PyCharmProjects/covid-19-analysis/data/COVID-19/csse_covid_19_data/'
                f'csse_covid_19_time_series/time_series_covid19_confirmed_global.csv')
            raw_data = raw_data.loc[raw_data['Country/Region'] == 'Australia']
        elif self.data_type == 'aus' and self.case_type == 'death':
            raw_data = pd.read_csv(
                f'~/PyCharmProjects/covid-19-analysis/data/COVID-19/csse_covid_19_data/'
                f'csse_covid_19_time_series/time_series_covid19_deaths_global.csv')
            raw_data = raw_data.loc[raw_data['Country/Region'] == 'Australia']

        # Default to worldwide cases.
        else:
            raw_data = pd.read_csv(
                f'~/PyCharmProjects/covid-19-analysis/data/COVID-19/csse_covid_19_data/'
                f'csse_covid_19_time_series/time_series_covid19_confirmed_global.csv')

        raw_data_filtered = pd.DataFrame

        if self.data_type == 'world':
            useful_cols = [col for col in raw_data.columns if col not in ['Lat', 'Long']]
            raw_data_filtered = raw_data[useful_cols]
            countries_to_drop = ['Holy See', 'Congo (Brazzaville)', 'Congo (Kinshasa)',
                                 'Diamond Princess',
                                 'MS Zaandam', 'Kosovo', 'Timor-Leste', 'West Bank and Gaza',
                                 'Western Sahara']
            raw_data_filtered = raw_data_filtered.loc[
                ~raw_data_filtered['Country/Region'].isin(countries_to_drop)]

        elif self.data_type == 'usa' and self.case_type == 'case':
            useful_cols = [col for col in raw_data.columns if
                           col not in ['UID', 'iso2', 'iso3', 'code3',
                                       'FIPS', 'Admin2', 'Country_Region',
                                       'Long_', 'Lat', 'Combined_Key']]
            raw_data_filtered = raw_data[useful_cols]

        elif self.data_type == 'usa' and self.case_type == 'death':
            useful_cols = [col for col in raw_data.columns if
                           col not in ['UID', 'iso2', 'iso3', 'code3',
                                       'FIPS', 'Admin2', 'Country_Region',
                                       'Long_', 'Lat', 'Combined_Key', 'Population']]
            raw_data_filtered = raw_data[useful_cols]

        elif self.data_type == 'aus' and self.case_type == 'case':
            useful_cols = [col for col in raw_data.columns if
                           col not in ['Lat', 'Long', 'Country/Region']]
            raw_data_filtered = raw_data[useful_cols]

        elif self.data_type == 'aus' and self.case_type == 'death':
            useful_cols = [col for col in raw_data.columns if
                           col not in ['Lat', 'Long', 'Country/Region']]
            raw_data_filtered = raw_data[useful_cols]

        return raw_data_filtered

    @staticmethod
    def melt_df(raw_data: pd.DataFrame, id_vars: list) -> pd.DataFrame:
        """
        Method to turn a raw dataframe (with state, country, date_1, ..., date_n)
        into a dataframe with a date column and the total number of cases/deaths/etc.
        :param raw_data: The Pandas DataFrame to melt.
        :param id_vars: The columns to group by to create melted DataFrame with.
        :return: A pivoted Pandas DataFrame with a date column.
        """
        world_data = (raw_data
                      .melt(id_vars=id_vars,
                            var_name="Date",
                            value_name='total_cases')
                      )
        world_data.Date = pd.to_datetime(world_data.Date)
        return world_data

    def run_corona_analysis(self):
        """
        Main function to run analyses of World, USA, and Australian corona virus data from
        the JHU database
        """
        cts = CoronaTransformations(case_type=self.case_type, data_type=self.data_type)

        raw_data = self.load_raw_data()

        if self.data_type == 'world':
            groupby_list = ['Country/Region']
            groupby_list_cases_per_day = ['Date', 'Country/Region']
            id_vars = ["Province/State", 'Country/Region']
        elif self.data_type == 'usa' and self.case_type == 'death':
            groupby_list_cases_per_day = ['Date', 'Province_State']
            groupby_list = ['Province_State']
            id_vars = ["Province_State"]
        elif self.data_type == 'aus' and self.case_type == 'case':
            groupby_list_cases_per_day = ['Date', 'Province/State']
            groupby_list = ['Province/State']
            id_vars = ["Province/State"]
        elif self.data_type == 'aus' and self.case_type == 'death':
            groupby_list_cases_per_day = ['Date', 'Province/State']
            groupby_list = ['Province/State']
            id_vars = ["Province/State"]
        else:
            groupby_list_cases_per_day = ['Date', 'Province_State']
            groupby_list = ['Province_State']
            id_vars = ["Province_State"]

        melted_data = self.melt_df(raw_data=raw_data, id_vars=id_vars)

        print(f"Creating total number of {self.case_type}s for data type {self.data_type}...")
        total_cases_df = cts.create_cases_per_day(df_to_transform=melted_data,
                                                  groupby_list=groupby_list_cases_per_day)
        print("done.")

        print(f"Creating number of {self.case_type}s per period")
        period = 1
        cases_per_period = cts.create_cases_per_period(df_to_transform=total_cases_df,
                                                       groupby_list=groupby_list,
                                                       case_column='Total cases')
        print("done.")

        print(f"Creating rolling average of {self.case_type}s per period")
        rolling_avg = cts.create_rolling_average(df_to_transform=cases_per_period,
                                                 groupby_list=groupby_list,
                                                 period=7)
        print("done.")

        print(f"Creating power-law data products for {self.case_type}s")
        power_law = cts.calculate_power_law_columns(df_to_transform=rolling_avg,
                                                    cols_to_logify=['Total cases',
                                                                    'New cases per week'])

        pl_slope = cts.calculate_power_law_slope(df_to_transform=power_law,
                                                 period=10,
                                                 groupby_list=groupby_list,
                                                 rise='log10(New cases per week)',
                                                 run='log10(Total cases)')

        pl_acceleration = cts.calculate_power_law_acceleration(df_to_transform=pl_slope,
                                                               period=period,
                                                               groupby_list=groupby_list,
                                                               rise=f'slope of log10'
                                                                    f'(New cases per week)',
                                                               run='log10(Total cases)')
        pl_acceleration = \
            (pl_acceleration
             .rename(columns={"slope of slope of log10(New cases per week)":
                              "Acceleration of power-law",
                              "slope of log10(New cases per week)":
                                  "Slope of power-law"})
             )
        print("done.")
        print(f"Creating growth rates and doubling times for {self.case_type}s.")
        df_gr = cts.calculate_growth_rate(df_to_transform=pl_acceleration,
                                          period=5,
                                          groupby_list=groupby_list,
                                          new_cases='New cases',
                                          total_cases='Total cases')

        df_dbl_time = cts.calculate_doubling_time(df_to_transform=df_gr,
                                                  period=5,
                                                  groupby_list=groupby_list)
        print("done.")

        result_df_path = f'processed_data/'
        self.write_to_csv(df_to_write=df_dbl_time,
                          path_to_write_to=result_df_path,
                          file_name='result.csv')

        # Add continent to the data
        print(f"Adding continents to the {self.case_type}s data")
        df_dbl_time_with_cont = self.assign_continent_to_df(df_add_continent=df_dbl_time)
        print("done.")

        # Stack the DF to get data into format for the dashboard
        print(f"Preparing data for {self.case_type}s for dashboard")
        stacked = self.stack_data_for_dashboard(df_dbl_time_with_cont)

        stacked_df_path = f'stacked/'
        self.write_to_csv(df_to_write=stacked,
                          path_to_write_to=stacked_df_path,
                          file_name='result.csv')

        # pivot data for dashboard
        df_total_new_cases = stacked.loc[(stacked.indicator == 'Total cases') |
                                         (stacked.indicator == 'New cases') |
                                         (stacked.indicator == 'Growth Rate')]

        if self.data_type == 'world':
            pivoted = (df_total_new_cases
                       .set_index(['Date', 'Country/Region', 'Continent', 'Days'])
                       .pivot_table(values='value',
                                    index=['Date', 'Country/Region', 'Continent', 'Days'],
                                    columns='indicator',
                                    aggfunc='mean',
                                    fill_value=0)
                       .reset_index()
                       )
        elif self.data_type == 'aus' and self.case_type == 'case':
            pivoted = (df_total_new_cases
                       .set_index(['Date', 'Province/State', 'Days'])
                       .pivot_table(values='value',
                                    index=['Date', 'Province/State', 'Days'],
                                    columns='indicator',
                                    aggfunc='mean',
                                    fill_value=0)
                       .reset_index()
                       )
        elif self.data_type == 'aus' and self.case_type == 'death':
            pivoted = (df_total_new_cases
                       .set_index(['Date', 'Province/State', 'Days'])
                       .pivot_table(values='value',
                                    index=['Date', 'Province/State', 'Days'],
                                    columns='indicator',
                                    aggfunc='mean',
                                    fill_value=0)
                       .reset_index()
                       )
        else:
            pivoted = (df_total_new_cases
                       .set_index(['Date', 'Province_State', 'Days'])
                       .pivot_table(values='value',
                                    index=['Date', 'Province_State', 'Days'],
                                    columns='indicator',
                                    aggfunc='mean',
                                    fill_value=0)
                       .reset_index()
                       )
        print("done.")
        pivoted_data_path = f'pivoted/'
        self.write_to_csv(df_to_write=pivoted,
                          path_to_write_to=pivoted_data_path,
                          file_name='result_pivoted.csv')

    def stack_data_for_dashboard(self, df_to_stack):
        """
        Method to arrange data in a dataframe in a way that allows for representation in the
        dashboard.
        :param df_to_stack:
        :return:
        """
        if self.data_type == 'world':
            # Need to fillna to 0s
            df_to_stack = df_to_stack.fillna(0)
            stacked = (df_to_stack
                       .set_index(['Date', 'Country/Region', 'Continent'])
                       .stack()
                       .reset_index()
                       )
            stacked = stacked.rename(columns={"level_3": "indicator", 0: "value"})

            stacked['Days'] = (stacked
                               .groupby(['Country/Region', 'Continent'])['Date']
                               .transform(lambda x: (x - x.min()).dt.days)
                               )

        elif self.data_type == 'aus' and self.case_type == 'case':
            # Need to fillna to 0s
            df_to_stack.drop(columns={'Continent'}, inplace=True)
            df_to_stack = df_to_stack.fillna(0)
            stacked = (df_to_stack
                       .set_index(['Date', 'Province/State'])
                       .stack()
                       .reset_index()
                       )
            stacked = stacked.rename(columns={"level_2": "indicator", 0: "value"})

            stacked['Days'] = (stacked
                               .groupby(['Province/State'])['Date']
                               .transform(lambda x: (x - x.min()).dt.days)
                               )
        elif self.data_type == 'aus' and self.case_type == 'death':
            # Need to fillna to 0s
            df_to_stack.drop(columns={'Continent'}, inplace=True)
            df_to_stack = df_to_stack.fillna(0)
            stacked = (df_to_stack
                       .set_index(['Date', 'Province/State'])
                       .stack()
                       .reset_index()
                       )
            stacked = stacked.rename(columns={"level_2": "indicator", 0: "value"})

            stacked['Days'] = (stacked
                               .groupby(['Province/State'])['Date']
                               .transform(lambda x: (x - x.min()).dt.days)
                               )
        else:
            # Need to fillna to 0s
            df_to_stack.drop(columns={'Continent'}, inplace=True)
            df_to_stack = df_to_stack.fillna(0)
            stacked = (df_to_stack
                       .set_index(['Date', 'Province_State'])
                       .stack()
                       .reset_index()
                       )
            stacked = stacked.rename(columns={"level_2": "indicator", 0: "value"})

            stacked['Days'] = (stacked
                               .groupby(['Province_State'])['Date']
                               .transform(lambda x: (x - x.min()).dt.days)
                               )
        return stacked

    def assign_continent_to_df(self, df_add_continent: pd.DataFrame) -> pd.DataFrame:
        """
        Method to assign a continent to a country in the given dataframe. Some
        alterations have had to be made due to the absence of them in the ISO codes.
        This in NO way is a political statement from the author.
        :param df_add_continent:
        :return:
        """

        if self.data_type == 'world':
            df_add_continent.loc[
                df_add_continent['Country/Region'] == 'US', 'Country/Region'] = 'USA'
            df_add_continent.loc[
                df_add_continent['Country/Region'] == 'Burma', 'Country/Region'] = 'Myanmar'
            df_add_continent.loc[
                df_add_continent[
                    'Country/Region'] == 'Cote d\'Ivoire', 'Country/Region'] = 'Ivory Coast'
            df_add_continent.loc[df_add_continent[
                                     'Country/Region'] == 'Korea, South', 'Country/Region'] = \
                'South Korea'
            df_add_continent.loc[
                df_add_continent['Country/Region'] == 'Taiwan*', 'Country/Region'] = 'Taiwan'

            df_add_continent['Continent'] = (
                df_add_continent.apply(
                    lambda x: self.apply_continent_to_country(x['Country/Region']),
                    axis=1
                )
            )
        elif self.data_type == 'aus':
            df_add_continent['Continent'] = 'Australasia'
        else:
            df_add_continent['Continent'] = 'North America'

        return df_add_continent

    @staticmethod
    def apply_continent_to_country(country):
        continents = {
            'NA': 'North America',
            'SA': 'South America',
            'AS': 'Asia',
            'OC': 'Australasia',
            'AF': 'Africa',
            'EU': 'Europe'
        }
        return continents[country_alpha2_to_continent_code(country_name_to_country_alpha2(country))]

    def write_to_csv(self, df_to_write: pd.DataFrame, path_to_write_to: str, file_name: str):

        if self.data_type == 'world':
            if self.case_type == 'case':
                write_path_cases = f"../data/output/world/{self.processing_date}/" \
                                   f"cases/{path_to_write_to}"
                if os.path.exists(write_path_cases):
                    print(f'Writing data out to path: {write_path_cases}')
                    df_to_write.to_csv(write_path_cases + f'/{file_name}')
                else:
                    print(f"Making directory to write out to...")
                    os.makedirs(write_path_cases)
                    print(f'Writing data out to path: {write_path_cases}')
                    df_to_write.to_csv(write_path_cases + f'/{file_name}')

            if self.case_type == 'death':
                write_path_deaths = f"../data/output/world/{self.processing_date}/" \
                                    f"deaths/{path_to_write_to}"
                if os.path.exists(write_path_deaths):
                    print(f'Writing data out to path: {write_path_deaths}')
                    df_to_write.to_csv(write_path_deaths + f'/{file_name}')
                else:
                    print(f"Making directory to write out to...")
                    os.makedirs(write_path_deaths)
                    print(f'Writing data out to path: {write_path_deaths}')
                    df_to_write.to_csv(write_path_deaths + f'/{file_name}')
        elif self.data_type == 'aus' and self.case_type == 'case':
            write_path_cases = f"../data/output/aus/{self.processing_date}/cases/{path_to_write_to}"
            if os.path.exists(write_path_cases):
                print(f'Writing data out to path: {write_path_cases}')
                df_to_write.to_csv(write_path_cases + f'/{file_name}')
            else:
                print(f"Making directory to write out to...")
                os.makedirs(write_path_cases)
                print(f'Writing data out to path: {write_path_cases}')
                df_to_write.to_csv(write_path_cases + f'/{file_name}')
        elif self.data_type == 'aus' and self.case_type == 'death':
            write_path_cases = f"../data/output/aus/{self.processing_date}/" \
                               f"deaths/{path_to_write_to}"
            if os.path.exists(write_path_cases):
                print(f'Writing data out to path: {write_path_cases}')
                df_to_write.to_csv(write_path_cases + f'/{file_name}')
            else:
                print(f"Making directory to write out to...")
                os.makedirs(write_path_cases)
                print(f'Writing data out to path: {write_path_cases}')
                df_to_write.to_csv(write_path_cases + f'/{file_name}')
        else:
            if self.case_type == 'case':
                write_path_cases = f"../data/output/usa/{self.processing_date}/" \
                                   f"cases/{path_to_write_to}"
                if os.path.exists(write_path_cases):
                    print(f'Writing data out to path: {write_path_cases}')
                    df_to_write.to_csv(write_path_cases + f'/{file_name}')
                else:
                    print(f"Making directory to write out to...")
                    os.makedirs(write_path_cases)
                    print(f'Writing data out to path: {write_path_cases}')
                    df_to_write.to_csv(write_path_cases + f'/{file_name}')

            if self.case_type == 'death':
                write_path_deaths = f"../data/output/usa/{self.processing_date}/" \
                                    f"deaths/{path_to_write_to}"
                if os.path.exists(write_path_deaths):
                    print(f'Writing data out to path: {write_path_deaths}')
                    df_to_write.to_csv(write_path_deaths + f'/{file_name}')
                else:
                    print(f"Making directory to write out to...")
                    os.makedirs(write_path_deaths)
                    print(f'Writing data out to path: {write_path_deaths}')
                    df_to_write.to_csv(write_path_deaths + f'/{file_name}')

        print("done.")


#TBD
# PEP8 Linting
# Argparse
#/usr/bin/env python
from  __future__ import print_function
import numpy as np
import torch

# neural network class
import torch.nn as nn

# activation functions
import torch.nn.functional as F

# different optimisation techniques
import torch.optim as optim

# support for automatically getting the gradients
from torch.autograd import Variable

import  matplotlib.pyplot as plt

# Debug
debug = 0

# real data paramters
mean = 4
variance = 1.25

# generator parameters
genInputSize = 1
genHiddenSize = 50
genOutputSize = 1
genIter = 1

# discriminator parameters
discInputSize = 100
discHiddenSize = 50
discOutputSize = 1
discIter = 1

# discriminator output weather the generator is producing real/fake data
miniBatchSize = discInputSize

# optimiser parameters ( adam optimiser )
learningRate = 2e-4
optimBetas = (0.9,0.999)
epochs = 30000

# other parameters
print_stat = 200

# initial noise vector defined as a uniform distribution here
def noise_samples(M,N):
    return torch.rand(M,N)

# real samples need to be defined as gaussian
# need to convert it in a Tensor before passing on to a Pytorch Variable
def real_samples(mean, variance, N):
    return torch.Tensor(np.random.normal(mean, variance, (1,N)))

class Generator(nn.Module):
    def __init__(self):
        # do not understand super
        super(Generator, self).__init__()
        self.layer1 = nn.Linear(genInputSize, genHiddenSize)
        self.layer2 = nn.Linear(genHiddenSize, genHiddenSize)
        self.layer3 = nn.Linear(genHiddenSize, genOutputSize)

    def forward(self, inputMatrix):
        inputMatrix = inputMatrix.view(-1,genInputSize)
        x = F.elu(self.layer1(inputMatrix))
        x = F.sigmoid(self.layer2(x))
        x = self.layer3(x)
        return x

class Discriminator(nn.Module):
    # contains more non linearity to make it stronger than the generator
    def __init__(self):
        super(Discriminator, self).__init__()
        self.layer1 = nn.Linear(discInputSize, discHiddenSize)
        self.layer2 = nn.Linear(discHiddenSize, discHiddenSize)
        self.layer3 = nn.Linear(discHiddenSize, discOutputSize)

    def forward(self, inputMatrix):
        inputMatrix = inputMatrix.view(-1,discInputSize)
        x = F.elu(self.layer1(inputMatrix))
        x = F.elu(self.layer2(x))
        x = F.sigmoid(self.layer3(x))
        return x

def convertToList(tensor):
    return tensor.data.storage().tolist()

def findMetrics(tensor):
    return [np.mean(convertToList(tensor)), np.std(convertToList(tensor))]

def train():
    # create an instance of both discriminator and generator
    D = Discriminator()
    G = Generator()

    # define a optimisation method to be used
    discOptimiser = optim.Adam(D.parameters(), lr=learningRate, betas = optimBetas)
    genOptimiser = optim.Adam(G.parameters(), lr=learningRate, betas = optimBetas)

    # using the binary cross-entropy loss function
    lossFunction = nn.BCELoss()
    discRealLossList = []
    discFakeLossList = []
    genLossList = []

    for epoch in range(epochs):

        for i in range (discIter):
            # for each step, set the gradient to zero
            D.zero_grad()

            # train discriminator on real data
            discRealInput = Variable(real_samples(mean,variance,discInputSize))
            if debug:
                print (discRealInput.size())
            discRealOutput = D(discRealInput)
            if debug:
                print (discRealOutput.size())

            # loss function
            target = Variable(torch.ones(discOutputSize))
            discRealLoss = lossFunction(discRealOutput, target)
            if debug:
                print(discRealLoss.size())
                print (discRealLoss)
            discRealLoss.backward()

            # train discriminacor on fake data
            discFakeInput = Variable(noise_samples(discInputSize,genInputSize))
            if debug:
                print (discFakeInput.size())

            discFakeInput = G(discFakeInput).detach() #??
            if debug:
                print (discFakeInput.size())

            discFakeOutput = D(discFakeInput)
            if debug:
                print (discFakeOutput.size())

            # loss function
            target = Variable(torch.zeros(discOutputSize))
            discFakeLoss = lossFunction(discFakeOutput, target)
            discFakeLoss.backward()

            # backpropagation for discriminator
            # update the weights
            discOptimiser.step()

        for i in range(genIter):
            # for each step, set the gradient to zero
            G.zero_grad()

            # train generator
            # generator takes input of the form 1x1 as input
            # miniBatchSize = 1 and dimension = 1
            genInput = Variable(noise_samples(miniBatchSize, genInputSize))
            if debug:
                print (genInput.size())
            genOutput = G(genInput)
            if debug:
                print (genOutput.size())
            # generator gives the image to generator for prediction
            discOutput = D(genOutput)
            if debug:
                print (discOutput.size())

            # to fool the discriminator, all the samples are genuine
            target = Variable(torch.ones(genOutputSize))

            #loss function and backpropagation
            genLoss = lossFunction(discOutput, target)
            if debug:
                print (genLoss.size())

            genLoss.backward()
            # update the weights
            genOptimiser.step()

        listDiscRealLoss = convertToList(discRealLoss)
        listDiscFakeLoss = convertToList(discFakeLoss)
        listGenLoss = convertToList(genLoss)

        discRealLossList.append(listDiscFakeLoss[0])
        discFakeLossList.append(listDiscRealLoss[0])
        genLossList.append(listGenLoss[0])

        if epoch % print_stat == 0:
            print  ("%s D_Real:%s D_Fake:%s G:%s StatReal:%s StatFake:%s" %
                    (epoch,
                    listDiscRealLoss,
                    listDiscFakeLoss,
                    listGenLoss,
                    findMetrics(discRealInput),
                    findMetrics(genOutput)
                    ))
    plt.plot(discRealLossList, color='green', alpha=0.5, label='Discriminator Real')
    plt.plot(discFakeLossList, color='blue', alpha=0.5, label='Discriminator Fake')
    plt.plot(genLossList, color='red', alpha=0.5, label='Generator')
    plt.legend(loc = 'upper right')
    name = 'uniformtoGaussianLoss'+str(epochs)+'.png'
    plt.savefig(name)
    plt.show()
    plot_distribution(discRealInput, genInput, genOutput)

def plot_distribution(discRealInput, genInput, genOutput):

    # plot the distribution for real samples, must be Gaussian
    count, bins, ignored = plt.hist(convertToList(discRealInput), 30,
            normed=True, color = 'green', alpha=0.5, label='Real Distribution')

    # plot the distribution for noise, must be uniform
    count, bins, ignored = plt.hist(convertToList(genInput), 30, normed=True,
            color = 'blue', alpha=0.5, label='Noise')

    # the generated distribution must be similar to real distribution
    count, bins, ignored = plt.hist(convertToList(genOutput), 30, normed=True,
            color = 'red', alpha=0.5, label='Generated Distribution')

    plt.legend(loc = 'upper right')

    name = 'uniformToGaussian'+str(epochs)+'.png'
    plt.savefig(name)

    plt.show()
if __name__=="__main__":
    #plot_distribution()
    train()


# Encapsulation

class Student:
    school = "HBK"   # class Variable

    def __init__(self, iddd, nameee, marksss):   # Constructor
        self.__id = iddd   # Private
        self.name = nameee   # public
        self._marks = marksss  # protected

    def display(self):   # Instance Method
        print(self.__id,'----',self.name,'----',self._marks)

    @classmethod   # decorator
    def change_school(cls):
        cls.school = input("Enter New School: ")
        print("School record Updated!!")

    @staticmethod
    def show_school():
        print(Student.school)

jeet = Student(100, "Jeet Popat", 900)
mihir = Student(200, "Mihir Thakkar", 910)

jeet.display()
mihir.display()

print(jeet.school)
print(mihir.school)

# jeet.marks = 1000
# print(jeet.marks)  # 1000

Student.change_school()
print(mihir.school)   # class Variable
print(jeet.school)    # class Variable
print(Student.school)  # class Variable

# print(Student.id)  # Error

print(jeet._marks)   # 900  # Protected

jeet.show_school()  # static Method

# print(jeet.id)  # Error
# print(jeet.__id)  # Error


import numpy as np
import pandas as pd
from collections import Counter
from random import shuffle

train_data = np.load('training_data.npy')
data_frame = pd.DataFrame(train_data)

W = []
A = []
D = []

print(Counter(data_frame[1].apply(str)))
shuffle(train_data)

for data in train_data:
    game_frame = data[0]
    key = data[1]

    if key == [1,0,0]:
        A.append([game_frame, key])
    if key == [0,1,0]:
        W.append([game_frame, key])
    if key == [0,0,1]:
        D.append([game_frame, key])

w = W[:len(A)][:len(D)]
A = A[:len(W)]
D = D[:len(D)]

final_data = W+A+D
shuffle(final_data)
print(len(final_data))
np.save('final_data.npy', final_data)


import sys
from Bio import SeqIO

def window(fasta):
	""" window divides a fasta file into 10kb fragments with 5kb overlap
	input fasta: fasta file
	"""
	seqDict = {}
	fragment_length = 10000
	overlap_length = 5000
	for seq_record in SeqIO.parse(fasta, "fasta"):
		sequence = seq_record.seq
	fileNumber = int((len(sequence) / overlap_length))
	for x in range(fileNumber):
		n = x * overlap_length
		newFasta = sequence[n:n + fragment_length]
		seqDict[x] = newFasta 	# change
	return seqDict

def writeFasta(seqDict, fastaFolder):
	""" writeFasta writes each shorter sequence into a new fasta file
	input seqDict: dictionary containing loci ids and corresponding sequences
	input fastaFolder: directory to store new fasta files
	"""
	for id, seq in seqDict.items():
		f = open(mypath + "lociFolder/chrom12_{0}.fa".format(id), "w") # change
		f.write('> ' + str(id) + '\n')
		f.write(str(seq))
		f.close()

def writeID(seqDict, id_file):
	""" writeID creates a new file containing all the loci ids
	input seqDict: dictionary containing loci ids and corresponding sequences
	input id_file: path to new file containing all loci ids
	"""
	f = open(id_file, "w")
	for id in seqDict.keys():
		f.write(str(id) + '\n')
	f.close()

def main():
	seqDict = window(sys.argv[1])
	writeFasta(seqDict, sys.argv[2])
	writeID(seqDict, sys.argv[3])

main()

# edit ids for specific loci


def main():
	s = 0
	while True:
		val = input("Uneti broj: ")
		if val == "":
			break
		try:
			s += float(val)
			print(s)
		except ValueError:
			print("Unos", val, "nije validan")

if __name__ == '__main__':
	main()


from PPlay.window import *
from PPlay.sprite import *

janela = Window(600, 600)

janela.set_background_color([0, 0, 0])
janela.set_title("Bernardo Mendes")
ball = Sprite("pongball.png")
ball2 = Sprite("pongball.png")
iniciox = janela.width / 2 - ball.width / 2
inicioy = janela.height / 2 - ball.height / 2
ball.set_position(iniciox, inicioy)
ball2.set_position(200, 300)
velox = 400
veloy = 300
velox2 = 600
veloy2 = 500

while True:
    ball.x = ball.x + velox * janela.delta_time()
    ball.y = ball.y + veloy * janela.delta_time()

    if ball.x >= janela.width - ball.width:
        ball.x = janela.width - ball.width
        velox *= -1
    elif ball.x <= 0:
        ball.x = 0
        velox *= -1

    if ball.y >= janela.height - ball.height:
        ball.y = janela.height - ball.height
        veloy *= -1
    elif ball.y <= 0:
        ball.y = 0
        veloy *= -1

    ball2.x = ball2.x + velox2 * janela.delta_time()
    ball2.y = ball2.y + veloy2 * janela.delta_time()

    if ball2.x >= janela.width - ball2.width:
        ball2.x = janela.width - ball2.width
        velox2 *= -1
    elif ball2.x <= 0:
        ball2.x = 0
        velox2 *= -1

    if ball2.y >= janela.height - ball2.height:
        ball2.y = janela.height - ball2.height
        veloy2 *= -1
    elif ball2.y <= 0:
        ball2.y = 0
        veloy2 *= -1
    if(ball.collided(ball2)):
        velox *= -1
        velox2 *= -1
        veloy *= -1
        veloy2 *= -1

    janela.set_background_color([0, 100, 100])
    ball.draw()
    ball2.draw()
    janela.update()


""" contains QueryObject class.

It defines the QueryObject class. It contains the query information.
e.g. query statements, some specific parameters for an execution, etc.
It is served for being an data object.

@author: Thanakorn Sueverachai
"""

from pprint import pformat

class QueryObject(object):
    """ The query object. """

    def __init__(self, match_statement, parameters = {}):

        # collect information
        self.match_statement = match_statement

        default_parameters = {
                              "limit" : None,
                              "isRank" : True,
                              "isApprox" : True,
                              "weightScore" : { "tf" : 5,
                                                "nr" : 5,
                                                "tr" : 5,
                                                "ks" : 5,
                                                "ds" : 5,
                                                "fs" : 5
                                              },
                              "vicinity-precision":False,
                              "hop": 1,
							  "isVicinity":False,
							  "vicinity":{"distance_measure":None,"distance_unit":None,"location":None}
                              }
        self.parameters = default_parameters
        self.parameters.update(parameters)
    def __str__(self):
        # for better presentation
        return pformat(self.__dict__)