'''
testing strftime.
'''

import time

def run (autoTester):
    t = [2000, 1, 1, 1, 1, 1, 1, 1, 0]
    def check(fmt):
        s = time.mktime(tuple(t))
        autoTester.check('gmtime'   , tuple(time.gmtime(int(s))))
        autoTester.check('localtime', tuple(time.localtime(int(s))))
        autoTester.check('mktime'   , int(s))
        autoTester.check('ctime'    , int(s))

    for hour in (0, 1, 12, 14, 23):
        t[3] = hour
        for f in (
             '%p %I.%d.%Y'
            ,'%b .%d.%y'
            ,'%b .%d.%Y'
            ,'%d%m%Y%H:%M:%S%p'
            ,'%b .%d.%Y'
            ,'M%m.%d.%Y'
            ,'%m.%d.%Y'
            ,'%m.%d.%Y'
            ,'%b .%d.%Y'
            ,'%m.%d.%Y'
            ,'%B %d.%Y'
            ,'%a %b %d %H:%M:%S %Y'
            ,'%d.%m.%Y %I:%M:%S%p'
            ,'%a%b %d %H:%M:%S %Y'
            ,'%a%b%d %H:%M:%S %Y'
            ,'%a%b%d%H:%Mx%S%Y'
            ,'%a%b%d%H:%Mxx%S%Y'
            ,'%a%b%d%H:%Mxx%S%Y +000'
            ,' %a%b%d%H:%Mxx%S%Y +000 '
            ): check(f)

    autoTester.check('asctime', t)


# -*- coding: utf-8 -*-
"""
Created on Wed Sep 29 15:39:57 2021

@author: norab
"""

import sys
import yaml
from treeRun import treeRun
import timeit

def main(configFilepath=None):

    """
    Function:
        - call function to run program
        - path to configuration file given as 1st argument

    """

    print("Job initiated")

    # Read configfile argument
    if configFilepath:
        configFilepath = configFilepath.strip()
    else:
        configFilepath = sys.argv[1]   # uncomment this to run from terminal

    with open(configFilepath, 'r') as c:
        configFile = yaml.safe_load(c)

    # Run
    treeRun(configFile)

if __name__ == '__main__':

    #### Bash run
    #main()

    #### Run in IDE:
    # Test job:
    # configFilepath = 'C:/Users/norab/Master/WillowProject/Willow1.0/jobs/test_GDR_10genes/job_input/main_config.yml'

    # GDR calculation job:
    #configFilepath = 'C:/Users/norab/Master/WillowProject/Willow1.0/jobs/GDRcalculation/job_input/main_config.yml'

    # nullGDR calculation job:
    #configFilepath = 'C:/Users/norab/Master/WillowProject/Willow1.0/jobs/GDRcalculation/job_input/main_config.yml'

    # non-zero phydists job:
    #configFilepath = 'C:/Users/norab/Master/WillowProject/Willow1.0/jobs/GDRcalculation/job_input/main_config.yml'

    # Run
    #starttime = timeit.default_timer()
    # main(configFilepath)
    #endtime = timeit.default_timer()

    # Testrun 25.03.22
    configFilepath = 'C:/Users/norab/Master/WillowProject/testRuns/testRun25.03/main_config.yml'
    main(configFilepath)

    # Testrun GDRnull 01.04.2022


import tensorflow as tf
import numpy as np

def quantize(x, n):
	@tf.custom_gradient
	def _quantize(x):
		return tf.round(x * n) / n, lambda dy: dy
	return _quantize(x)

def fw(x,bitW=8):
	if bitW == 32:
		return x
	if bitW == 1:   # BWN
		E = tf.stop_gradient(tf.reduce_mean(tf.abs(x)))
		@tf.custom_gradient
		def _sign(x):
			return tf.where(tf.equal(x, 0), tf.ones_like(x), tf.sign(x / E)) * E, lambda dy: dy
		return _sign(x)
	x = tf.tanh(x)
	x = x / tf.reduce_max(tf.abs(x)) * 0.5 + 0.5
	n = float(2 ** bitW - 1)
	return 2 * quantize(x,n) - 1

def activate(input, num_bits):
	with tf.variable_scope('alpha'):
		alpha = tf.Variable(8.0,dtype=tf.float32,trainable=True,name='alpha')
	num_bits = num_bits
	input = tf.nn.relu(input)
	input = tf.clip_by_value(input, 0, alpha)
	scale = (2**num_bits-1)/alpha
	input = quantize(input,scale)
	return input

def activate_ADC (input, num_bits):
	alpha = tf.Variable(8.0,dtype=tf.float32,trainable=True,name='rram_alpha')
	input = tf.clip_by_value(input, -alpha, alpha)
	scale = (2**(num_bits-1)-1)/(2*alpha)
	input = quantize(input,scale)
	return input

# def quantize(x, k):
#         n = 2 ** k - 1
#         print("n :",n)
#         n= tf.cast(n,tf.float32)
#         print("Float n:",sess.run(n))
#         @tf.custom_gradient
#         def _quantize(x):
#             print("y:",sess.run(tf.round(x * n) / n, lambda dy: dy))
#             return tf.round(x * n) / n, lambda dy: dy
#         return _quantize(x)

# def _quantize(x):
#     n=3.0
#     print(type(x))
#     return tf.round(x[0] * n) / n, lambda dy: dy
# # Initialize the variables
# init = tf.global_variables_initializer()

# sess=tf.Session()
# sess.run(init)
# np.random.seed(0)
# input = {0:np.random.randn(64, 10, 30)}
# q=_quantize(input)
# #print("quantized value:",sess.run(q))
# sess.close()
# def fw(x):
#     if bitW == 32:
#         return x

#     if bitW == 1:   # BWN
#         E = tf.stop_gradient(tf.reduce_mean(tf.abs(x)))

#         @tf.custom_gradient
#         def _sign(x):
#             return tf.where(tf.equal(x, 0), tf.ones_like(x), tf.sign(x / E)) * E, lambda dy: dy

#         return _sign(x)

#     x = tf.tanh(x)
#     x = x / tf.reduce_max(tf.abs(x)) * 0.5 + 0.5
#     return 2 * quantize(x, bitW) - 1


# _*_ coding:utf-8 _*_
__author__ = 'meto'
__date__ = '2018/11/16 11:08'
import os
import unittest

class RunCase(unittest.TestCase):
    def test_case01(self):
        case_path = os.path.join(os.getcwd())
        print(case_path)
        suite = unittest.defaultTestLoader.discover(case_path,'unittest*.py')
        unittest.TextTestRunner().run(suite)

if __name__ == '__main__':
    unittest.main()
    # RunCase().test_case01()


########
# comms
######
import sys
from plugins import PluginResponse, Plugin

class tell(Plugin):
    def __init__(self, **kwargs):
        self.keyword = ("tell","text")
        self.response = PluginResponse()
        self.error = ""
        self.bot = ""
        self.builtin = 1
        self.level = -1
        self.usage = "nfi"

    def command(self, args):
        self.response.setText(self.usage)
        text = args.text.split(" ")
        target = text[0]
        message = " ".join(text[1:])
        if (self.bot.send_im(target, message)):
            self.response.setText("Told {} about {}".format(target, message))
        else:
            self.response.setText("Could not tell {} about {}".format(target, message))

        return self.response


import datetime as dt
import logging
import os
from typing import List, Tuple, Optional
from stocker import FundNotFoundException, add_indicators, Stock, StockServer

import matplotlib.pyplot as plt

logger = logging.getLogger()

def setup_loggers(args_parsed):
	""" Funkcija namesti izpisovanje v datoteko in na konzolo """
	uniquestr = dt.datetime.now().strftime("%d-%m-%Y_%H%M%S")
	dbg_log_formatter = logging.Formatter(
		fmt='%(asctime)-15s (%(relativeCreated)-8d ms) | %(levelname)-7s | %(threadName)-12.12s | %(name)15.15s | %(message)s',
		datefmt='%Y-%m-%d %H:%M:%S')
	info_log_formatter = logging.Formatter(
		fmt='%(asctime)-15s | %(message)s',
		datefmt='2020-%b-%d %H:%M:%S')
	os.makedirs(args_parsed.log_dir, exist_ok=True)

	file_handler = logging.FileHandler(
		os.path.join(args_parsed.log_dir, 'file-%s.log' % uniquestr),
		mode='a')

	global logger
	logger.setLevel(logging.DEBUG)
	console_handler = logging.StreamHandler()
	console_handler.setFormatter(dbg_log_formatter if args_parsed.log_level == logging.DEBUG else info_log_formatter)
	file_handler.setFormatter(dbg_log_formatter)
	console_handler.setLevel(args_parsed.log_level)
	file_handler.setLevel(logging.DEBUG)

	logger.addHandler(console_handler)
	logger.addHandler(file_handler)
	logger.debug(str(args_parsed))

def get_tickers(wws, *fund_tickers):
	# type: (StockServer, List[Tuple[str, Optional[str]]]) -> List[Stock]
	all_data = []
	for _ticker, _name in fund_tickers:
		try:
			all_data.append(wws[_ticker])
		except FundNotFoundException as fnfe:
			logging.exception(fnfe)
	return all_data

def display_command(wss, parsed_args):
	from stocker import stock_display
	stocks = {}

	for stock_query in parsed_args.stocks:
		stock = wss[stock_query]
		stocks[stock.ticker] = stock

	for k, stock in stocks.items():
		add_indicators(stock, parsed_args.markers)
		stock.calculate_total_investments()
		stock.write()
		stock_display.graph_stock(stock)
	plt.show()

def prediction_command(wss, parsed_args):
	from data_analysis import main as data_analysis_on
	seq_len = 48
	epochs = 50
	batch_size = 64
	stock = wss[parsed_args.stock]
	verbosity = 0 if parsed_args.log_level == logging.WARNING else 10
	data_analysis_on(stock, seq_len, epochs, batch_size, action=parsed_args.analysis_command, show=parsed_args.show_model, verbose=verbosity)

def main():
	from arguments import get_arg_parser
	parser = get_arg_parser()
	args_parsed = parser.parse_args()

	if args_parsed.command is None or args_parsed.command == 'help':
		parser.print_help()
		exit(0)
	setup_loggers(args_parsed)
	world_stock_server = StockServer()
	if args_parsed.command == 'display':
		display_command(world_stock_server, args_parsed)
	elif args_parsed.command == 'predict':
		prediction_command(world_stock_server, args_parsed)

if __name__ == '__main__':
	main()


from django.conf.urls import url
from django.urls import path

from book import views

app_name = 'book'

urlpatterns = [
    path('<slug:slug>/', views.BookViewSet.as_view(), name='book_detail'),
    path('<slug:slug>/readers/', views.ReadersOfBook.as_view(), name='readers_of_book'),
    path('<slug:slug>/reviews/', views.BookReviewViewSet.as_view(), name='reviews'),
    path('<slug:slug>/review/<int:pk>/', views.ReviewDetailViewSet.as_view(), name='review_detail'),
    path('search/title/', views.SearchViewSet.as_view(), name='search'),
    path('search/adv/', views.AdvSearchViewSet.as_view(), name='search_adv'),
    # Publishers
    path('publisher/<name>/', views.PublisherBooks.as_view(), name='publisher_books'),
    path('category/<name>/', views.CategoryBooks.as_view(), name='category_books'),
]


import torch
import torch.nn as nn
import torch.nn.functional as F
import math

init = nn.init.xavier_uniform_
uniform_init = nn.init.uniform

def sparse_dropout(x, keep_prob):
    msk = (torch.rand(x._values().size()) + keep_prob).floor().type(torch.bool)
    idx = x._indices()[:, msk]
    val = x._values()[msk]
    return torch.sparse.FloatTensor(idx, val, x.shape).to(x.device)

class Encoder(nn.Module):

    def __init__(self, cfg):
        super(Encoder, self).__init__()

        self.item_emb = nn.Parameter(init(torch.empty(cfg.num_items, cfg.hidden_size))) # cfg.item = num_real_item + 1
        self.gcn_layers = nn.Sequential(*[GCNLayer() for i in range(cfg.num_gcn_layers)])

    def get_ego_embeds(self):
        return self.item_emb

    def forward(self, encoder_adj):
        embeds = [self.item_emb]
        for i, gcn in enumerate(self.gcn_layers):
            embeds.append(gcn(encoder_adj, embeds[-1]))
        return sum(embeds), embeds

class TrivialDecoder(nn.Module):

    def __init__(self, cfg):
        super(TrivialDecoder, self).__init__()

        self.MLP = nn.Sequential(
            nn.Linear(cfg.hidden_size * 3, cfg.hidden_size, bias=True),
            nn.ReLU(),
            nn.Linear(cfg.hidden_size, 1, bias=True),
            nn.Sigmoid()
        )
        self.apply(self.init_weights)

    def forward(self, embeds, pos, neg):
        # pos: (batch, 2), neg: (batch, num_reco_neg, 2)
        pos_emb, neg_emb = [], []
        pos_emb.append(embeds[-1][pos[:,0]])
        pos_emb.append(embeds[-1][pos[:,1]])
        pos_emb.append(embeds[-1][pos[:,0]] * embeds[-1][pos[:,1]])
        neg_emb.append(embeds[-1][neg[:,:,0]])
        neg_emb.append(embeds[-1][neg[:,:,1]])
        neg_emb.append(embeds[-1][neg[:,:,0]] * embeds[-1][neg[:,:,1]])
        pos_emb = torch.cat(pos_emb, -1) # (n, hidden_size * 3)
        neg_emb = torch.cat(neg_emb, -1) # (n, num_reco_neg, hidden_size * 3)
        pos_scr = torch.exp(torch.squeeze(self.MLP(pos_emb))) # (n)
        neg_scr = torch.exp(torch.squeeze(self.MLP(neg_emb))) # (n, num_reco_neg)
        neg_scr = torch.sum(neg_scr, -1) + pos_scr
        loss = -torch.sum(pos_scr / (neg_scr + 1e-8) + 1e-8)
        return loss

    def init_weights(self, module):
        if isinstance(module, nn.Linear):
            init(module.weight)
            if module.bias is not None:
                module.bias.data.zero_()

class Decoder(nn.Module):

    def __init__(self, cfg):
        super(Decoder, self).__init__()

        self.cfg = cfg

        self.MLP = nn.Sequential(
            nn.Linear(cfg.hidden_size * cfg.num_gcn_layers ** 2, cfg.hidden_size * cfg.num_gcn_layers, bias=True),
            nn.ReLU(),
            nn.Linear(cfg.hidden_size * cfg.num_gcn_layers, cfg.hidden_size, bias=True),
            nn.ReLU(),
            nn.Linear(cfg.hidden_size, 1, bias=True),
            nn.Sigmoid()
        )
        self.apply(self.init_weights)

    def forward(self, embeds, pos, neg):
        # pos: (batch, 2), neg: (batch, num_reco_neg, 2)
        pos_emb, neg_emb = [], []
        for i in range(self.cfg.num_gcn_layers):
            for j in range(self.cfg.num_gcn_layers):
                pos_emb.append(embeds[i][pos[:,0]] * embeds[j][pos[:,1]])
                neg_emb.append(embeds[i][neg[:,:,0]] * embeds[j][neg[:,:,1]])
        pos_emb = torch.cat(pos_emb, -1) # (n, hidden_size * num_gcn_layers ** 2)
        neg_emb = torch.cat(neg_emb, -1) # (n, num_reco_neg, hidden_size * num_gcn_layers ** 2)
        pos_scr = torch.exp(torch.squeeze(self.MLP(pos_emb))) # (n)
        neg_scr = torch.exp(torch.squeeze(self.MLP(neg_emb))) # (n, num_reco_neg)
        neg_scr = torch.sum(neg_scr, -1) + pos_scr
        loss = -torch.sum(pos_scr / (neg_scr + 1e-8) + 1e-8)
        return loss

    def init_weights(self, module):
        if isinstance(module, nn.Linear):
            init(module.weight)
            if module.bias is not None:
                module.bias.data.zero_()

class GCNLayer(nn.Module):
    def __init__(self):
        super(GCNLayer, self).__init__()

    def forward(self, adj, embeds):
        return torch.spmm(adj, embeds)

class SASRec(nn.Module):
    def __init__(self, cfg):
        super(SASRec, self).__init__()

        self.pos_emb = nn.Parameter(init(torch.empty(cfg.maxlen, cfg.hidden_size)))
        self.layers = nn.Sequential(*[TransformerLayer(cfg) for i in range(cfg.num_trm_layers)])
        self.LayerNorm = nn.LayerNorm(cfg.hidden_size)
        self.dropout = nn.Dropout(cfg.hidden_dropout_prob)
        self.apply(self.init_weights)

    def get_seq_emb(self, sequence, item_emb):
        seq_len = sequence.size(1)
        pos_ids = torch.arange(seq_len, dtype=torch.long, device=sequence.device)
        pos_ids = pos_ids.unsqueeze(0).expand_as(sequence)
        itm_emb = item_emb[sequence]
        pos_emb = self.pos_emb[pos_ids]
        seq_emb = itm_emb + pos_emb
        seq_emb = self.LayerNorm(seq_emb)
        seq_emb = self.dropout(seq_emb)
        return seq_emb

    def forward(self, input_ids, item_emb):
        attention_mask = (input_ids > 0).long()
        extended_attention_mask = attention_mask.unsqueeze(1).unsqueeze(2) # torch.int64
        max_len = attention_mask.size(-1)
        attn_shape = (1, max_len, max_len)

        subsequent_mask = torch.triu(torch.ones(attn_shape, device=item_emb.device), diagonal=1) # torch.uint8
        subsequent_mask = (subsequent_mask == 0).unsqueeze(1)
        subsequent_mask = subsequent_mask.long()

        extended_attention_mask = extended_attention_mask * subsequent_mask
        extended_attention_mask = extended_attention_mask.to(dtype=next(self.parameters()).dtype) # fp16 compatibility
        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0

        seq_embs = [self.get_seq_emb(input_ids, item_emb)]
        for trm in self.layers:
            seq_embs.append(trm(seq_embs[-1], extended_attention_mask))
        seq_emb = sum(seq_embs)

        return seq_emb

    def init_weights(self, module):
        if isinstance(module, nn.Linear):
            init(module.weight)
            if module.bias is not None:
                module.bias.data.zero_()

class TransformerLayer(nn.Module):

    def __init__(self, cfg):
        super(TransformerLayer, self).__init__()

        self.attention = SelfAttentionLayer(cfg)
        self.intermediate = IntermediateLayer(cfg)

    def forward(self, hidden_states, attention_mask):
        attention_output = self.attention(hidden_states, attention_mask)
        intermediate_output = self.intermediate(attention_output)
        return intermediate_output

class SelfAttentionLayer(nn.Module):

    def __init__(self, cfg):
        super(SelfAttentionLayer, self).__init__()

        self.num_attention_heads = cfg.num_heads
        self.attention_head_size = int(cfg.hidden_size / cfg.num_heads)
        self.all_head_size = self.num_attention_heads * self.attention_head_size

        self.query = nn.Linear(cfg.hidden_size, self.all_head_size)
        self.key = nn.Linear(cfg.hidden_size, self.all_head_size)
        self.value = nn.Linear(cfg.hidden_size, self.all_head_size)

        self.attn_dropout = nn.Dropout(cfg.attention_probs_dropout_prob)

        self.dense = nn.Linear(cfg.hidden_size, cfg.hidden_size)
        self.LayerNorm = nn.LayerNorm(cfg.hidden_size)
        self.out_dropout = nn.Dropout(cfg.hidden_dropout_prob)

        self.apply(self.init_weights)

    def transpose_for_scores(self, x):
        new_x_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size)
        x = x.view(*new_x_shape)
        return x.permute(0, 2, 1, 3)

    def forward(self, input_tensor, attention_mask):
        mixed_query_layer = self.query(input_tensor)
        mixed_key_layer = self.key(input_tensor)
        mixed_value_layer = self.value(input_tensor)

        query_layer = self.transpose_for_scores(mixed_query_layer)
        key_layer = self.transpose_for_scores(mixed_key_layer)
        value_layer = self.transpose_for_scores(mixed_value_layer)

        attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))

        attention_scores = attention_scores / math.sqrt(self.attention_head_size)
        attention_scores = attention_scores + attention_mask

        attention_probs = nn.Softmax(dim=-1)(attention_scores)
        attention_probs = self.attn_dropout(attention_probs)
        context_layer = torch.matmul(attention_probs, value_layer)
        context_layer = context_layer.permute(0, 2, 1, 3).contiguous()
        new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,)
        context_layer = context_layer.view(*new_context_layer_shape)
        hidden_states = self.dense(context_layer)
        hidden_states = self.out_dropout(hidden_states)
        hidden_states = self.LayerNorm(hidden_states + input_tensor)

        return hidden_states

    def init_weights(self, module):
        if isinstance(module, nn.Linear):
            init(module.weight)
            if module.bias is not None:
                module.bias.data.zero_()

class IntermediateLayer(nn.Module):

    def __init__(self, cfg):
        super(IntermediateLayer, self).__init__()

        self.layers = nn.Sequential(
            nn.Linear(cfg.hidden_size, cfg.hidden_size * 4, bias=True),
            nn.GELU(),
            nn.Linear(cfg.hidden_size * 4, cfg.hidden_size, bias=True),
            nn.Dropout(cfg.hidden_dropout_prob),
            nn.LayerNorm(cfg.hidden_size)
        )

    def forward(self, x):
        return self.layers(x)

class LocalGraph(nn.Module):

    def __init__(self, cfg):
        super(LocalGraph, self).__init__()

        self.cfg = cfg

    def make_noise(self, scores):
        noise = torch.rand(scores.shape, device=scores.device)
        # EPS = 1.e-8
        # It is different from the official code wherein EPS = 0.
        noise = -torch.log(-torch.log(noise + 1.e-8).add(1.e-8))
        return scores + noise

    def forward(self, adj, embeds, foo=None):
        order = torch.sparse.sum(adj, dim=-1).to_dense().view([-1, 1])
        fstEmbeds = torch.spmm(adj, embeds) - embeds
        fstNum = order

        emb = [fstEmbeds]
        num = [fstNum]

        for i in range(self.cfg.mask_depth):
            adj = sparse_dropout(adj, self.cfg.path_prob ** (i + 1))
            emb.append((torch.spmm(adj, emb[-1]) - emb[-1]) - order * emb[-1])
            num.append((torch.spmm(adj, num[-1]) - num[-1]) - order)
            order = torch.sparse.sum(adj, dim=-1).to_dense().view([-1, 1])

        subgraphEmbeds = sum(emb) / (sum(num) + 1e-8)
        subgraphEmbeds = F.normalize(subgraphEmbeds, p=2)

        embeds = F.normalize(embeds, p=2)
        scores = torch.sum(subgraphEmbeds * embeds, dim=-1)
        scores = self.make_noise(scores)

        _, candidates = torch.topk(scores, self.cfg.num_mask_cand)

        return scores, candidates

class RandomMaskSubgraphs(nn.Module):

    def __init__(self, cfg):
        super(RandomMaskSubgraphs, self).__init__()

        self.cfg = cfg

    def normalize(self, adj):
        degree = torch.pow(torch.sparse.sum(adj, dim=1).to_dense() + 1e-12, -0.5)
        newRows, newCols = adj._indices()[0, :], adj._indices()[1, :]
        rowNorm, colNorm = degree[newRows], degree[newCols]
        newVals = adj._values() * rowNorm * colNorm
        return torch.sparse.FloatTensor(adj._indices(), newVals, adj.shape)

    def forward(self, adj, seeds):
        rows = adj._indices()[0, :]
        cols = adj._indices()[1, :]

        masked_rows = []
        masked_cols = []
        masked_idct = []

        for i in range(self.cfg.mask_depth):
            curSeeds = seeds if i == 0 else nxtSeeds
            nxtSeeds = list()
            idct = None
            for seed in curSeeds:
                rowIdct = (rows == seed)
                colIdct = (cols == seed)
                if idct == None:
                    idct = torch.logical_or(rowIdct, colIdct)
                else:
                    idct = torch.logical_or(idct, torch.logical_or(rowIdct, colIdct))
            nxtRows = rows[idct]
            nxtCols = cols[idct]
            masked_rows.extend(nxtRows)
            masked_cols.extend(nxtCols)
            rows = rows[torch.logical_not(idct)]
            cols = cols[torch.logical_not(idct)]
            nxtSeeds = nxtRows + nxtCols
            if len(nxtSeeds) > 0 and i != self.cfg.mask_depth - 1:
                nxtSeeds = torch.unique(nxtSeeds)
                cand = torch.randperm(nxtSeeds.shape[0])
                nxtSeeds = nxtSeeds[cand[:int(nxtSeeds.shape[0] * self.cfg.path_prob ** (i + 1))]] # the dropped edges from P^k

        masked_rows = torch.unsqueeze(torch.LongTensor(masked_rows), -1)
        masked_cols = torch.unsqueeze(torch.LongTensor(masked_cols), -1)
        masked_edge = torch.hstack([masked_rows, masked_cols])
        encoder_adj = self.normalize(torch.sparse.FloatTensor(torch.stack([rows, cols], dim=0), torch.ones_like(rows), adj.shape))

        return encoder_adj, masked_edge


import sys
from setuptools import find_packages, setup

assert sys.version_info >= (3,), 'Python 3 is required'

VERSION = '1.0'

setup(
    name='automation-exercise',
    version=VERSION,
    description='Automation example',
    author='Heber Parrucci',
    author_email='heber013@gmail.com',
    url='',
    packages=find_packages(),
    package_data={
        '': []
    },
    entry_points={
        'console_scripts': [
            ''
        ]
    },
    test_suite=''
)


from pylab import *
from scipy.stats import spearmanr
from utils.read_data import read_from_csv
import modules.infotheo.info_theo as info

def get_high_entropy_atts(data, start=0.3, end=0.4, steps=0.01, cut=0.0001, alpha=0.01, debug=False):
    # treatment="'"+treatment+"'"
    samplesizez = []
    dic = dict()
    black = []
    white = []
    basesample = data.sample(frac=0.3, replace=False)
    features=data.columns.values
    size = len(data.index)
    while start <= end:
        start = start + steps
        sample = basesample.sample(frac=start, replace=False)
        samplesizez.insert(0, (len(sample.index)))
        inf=info.Info(sample)
        for col in features:
            if col in dic:
                list = dic[col]
                list.insert(0, inf.entropy(col, size))
                dic[col] = list
            else:
                dic[col] = [inf.entropy(col, size)]

    for col in features:
        if not any(dic[col]):
            continue
        rho, pval1 = spearmanr(samplesizez, dic[col])
        if debug == True:
            print(col)
            print(pval1)
            print("#####")
            plt.plot(dic[col])
            plt.show()
        if pval1 <= alpha:
            black.insert(0, col)
        else:
            white.insert(0, col)
    # self.features=np.array(white)
    return black

def get_fds(data, targets, cut=0.0001, debug=False, blacklist=None):
          fds=list()
          features = data.columns.values
          size = len(data.index)
          inf = info.Info(data)
          if not blacklist:
              blacklist=[]
          for att in targets:
              for col in features:
                  if  col not in att and col not in blacklist:
                      x = inf.CH(att, col)
                      if debug:
                           print('#############')
                           print(col)
                           print(x)
                      if x <= cut:
                          fds.insert(0, col)
                          if debug:
                              print('Functional depedancy detected'+ str(col))
                              print('#############')
                      y = inf.CH(col,att)
                      if debug:
                           print('#############')
                           print(col)
                           print(y)
                      if y <= cut:
                          fds.insert(0, col)
                          if debug:
                              print('Functional depedancy detected'+ str(col))
                              print('#############')
          return fds

if __name__ == '__main__':
    data=read_from_csv('/Users/babakmac/Documents/XDBData/binadult.csv')
    treatment = ['sex']
    outcome = ['income']
    X=get_high_entropy_atts(data)
    X=get_fds(data,treatment, debug=True)
    print(X)


import json
from typing import List

from cluster_migration_core.cluster_management.docker_framework_client import DockerFrameworkClient, DockerVolume
from cluster_migration_core.cluster_management.cluster import Cluster
from cluster_migration_core.cluster_management.cluster_objects import ClusterSnapshot
from cluster_migration_core.core.test_config_wrangling import TestConfig
from cluster_migration_core.core.expectation import Expectation
from cluster_migration_core.robot_actions.cluster_action_executor import ClusterActionExecutor

"""
The long-term trajectory of this class is a bit unclear.  We currently store both key/value pairs in a dictionary as
well as specifically declared/assigned objects.  That works for us currently, but we should be open to moving entirely
to one or the other approach if we see the need/opportunity.  KV-pairs are better for quick assignment if we have a
bunch of things to assign/re-use, but declared objects are better for code clarity and make using an IDE easier.  We'll
likely learn more about what this *should* be once we start running real tests through the UTF and support multiple
upgrade styles, as that should force changes in this class.

In general though, it is recommended that this be an append-only data store for the application.
"""

class FrameworkState:
    def __init__(self, state: dict):
        self._app_state = state

        # The fact that we need to store these in our FrameworkState means we probably need to be more sophisticated in
        # order to support multiple use cases.  Since we're only supporting upgrade testing for Snapshot/Restore for
        # now, we can solve that problem later.  It's likely we'll end up making use-case specific State types and
        # sticking their definition in the Python package that uses them (such as the Upgrade Testing Framework).
        self.docker_client: DockerFrameworkClient = None
        self.test_config: TestConfig = None
        self.source_cluster: Cluster = None
        self.target_cluster: Cluster = None
        self.shared_volume: DockerVolume = None
        self.snapshot: ClusterSnapshot = None
        self.eligible_expectations: List[Expectation] = []
        self.pre_upgrade_actions: ClusterActionExecutor = None
        self.post_upgrade_actions: ClusterActionExecutor = None

    def to_dict(self) -> dict:
        return {
            "app_state": self._app_state,
            "shared_volume": self.shared_volume.to_dict() if self.shared_volume else None,
            "source_cluster": self.source_cluster.to_dict() if self.source_cluster else None,
            "target_cluster": self.target_cluster.to_dict() if self.target_cluster else None,
            "snapshot": self.snapshot.to_dict() if self.snapshot else None,
            "test_config": self.test_config.to_dict() if self.test_config else None,
            "eligible_expectations": [e.to_dict() for e in self.eligible_expectations],
            "pre_upgrade_actions": self.pre_upgrade_actions.to_dict() if self.pre_upgrade_actions else None,
            "post_upgrade_actions": self.post_upgrade_actions.to_dict() if self.post_upgrade_actions else None
        }

    def __str__(self) -> str:
        return json.dumps(self.to_dict(), sort_keys=True, indent=4)

    def get_key(self, key: str) -> any:
        return self._app_state.get(key, None)

    def set_key(self, key: str, value: any) -> any:
        self._app_state[key] = value
        return value

def get_initial_state(test_config_path: str) -> FrameworkState:
    beginning_state = {}
    beginning_state['test_config_path'] = test_config_path

    return FrameworkState(beginning_state)


import functions.Response
import os
import time
import random
import assistant

class UserCheck:
    def __init__(self):
        pass
    def add_user(self,command):
        f=open("functions/Text_file/user.txt","a")
        f.write(command)
        f.close()

def rand():
    lines=open("functions/Text_file/greetings.txt","r").read().splitlines()
    greetings=str(random.choice(lines)).split(",")
    return greetings

def check():
    user=UserCheck()
    if (os.stat("functions/Text_file/user.txt").st_size==0):
        functions.Response.say("Greetings Sir, I just checked my database and I can't seem to recognize you")
        functions.Response.say("What should i call you then?please state your name only")
        command=functions.Response.listen()
        user.add_user(command)
        functions.Response.say("Welcome Mister" + command)
        assistant.pre_initial()
    else:
        f=open("functions/Text_file/user.txt")
        name=f.readline()
        greet=rand()
        functions.Response.say(greet[0] + name)
        time.sleep(0.05)
        functions.Response.say(greet[1])


# coding=utf-8
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Element
import os

# 批量修改整个文件夹所有的xml文件
def change_all_xml(xml_path):
    filelist = os.listdir(xml_path)
    #print(filelist)
    # 打开xml文档
    cnt=0
    for xmlfile in filelist:
        doc = ET.parse(xml_path + xmlfile)
        #print(xmlfile)
        root = doc.getroot()
        sub0 = root.findall('object')  # 找到filename标签，
        #print(sub0)
        for subs in sub0:
            #if subs.find('difficulty'):

                #a=subs.find('difficulty')
                #a.text=0
            #else:
                #model=Element('difficulty')
                #model.text=0
                #subs.append(model)
            sub=subs.find('bndbox')

            sub1 = sub.find('x1')
            sub.remove(sub1)
            sub2 = sub.find('x2')
            sub.remove(sub2)
            sub3 = sub.find('x3')
            sub.remove(sub3)
            sub4 = sub.find('x4')
            sub.remove(sub4)
            suy1 = sub.find('y1')
            sub.remove(suy1)
            suy2 = sub.find('y2')
            sub.remove(suy2)
            suy3 = sub.find('y3')
            sub.remove(suy3)
            suy4 = sub.find('y4')
            sub.remove(suy4)
            xmax,ymax=str(max(int(sub1.text),int(sub2.text),int(sub3.text),int(sub4.text))),str(max(int(suy1.text),int(suy2.text),int(suy3.text),int(suy4.text)))
            xmin,ymin=str(min(int(sub1.text),int(sub2.text),int(sub3.text),int(sub4.text))),str(min(int(suy1.text),int(suy2.text),int(suy3.text),int(suy4.text)))
            xmi=Element('xmin')
            xmi.text=xmin
            xma=Element('xmax')
            xma.text=xmax
            ymi=Element('ymin')
            ymi.text=ymin
            yma=Element('ymax')
            yma.text=ymax
            for i in (xmi,ymi,xma,yma):
                sub.append(i)
        doc.write(xml_path + xmlfile)  # 保存修改
        cnt+=1
        print(cnt)
xml_path ='./Annotation/'
change_all_xml(xml_path)


import numpy as np
from heapq import heappush, heappop
f = [x for x in open("input.txt").read().strip().split("\n")]

def solve(targetx, targety):
    board = []
    for line in f:
        a = list(line)
        a = [int(x) for x in a]
        board.append(a)
    board = np.array(board)

    heap = [(0,0,0)]
    seen = {(0,0)}
    dirs = [(-1,0), (1, 0), (0, 1), (0, -1)]

    while heap:
        d, x, y = heappop(heap)
        if x == targetx and y == targety:
            return d
        for dx, dy in dirs:
            nx, ny = dx + x, dy + y
            if 0 <= nx <= targetx and 0 <= ny <= targety:
                i_x, i_xoffset = divmod(nx, len(board))
                i_y, i_yoffset = divmod(ny, len(board[0]))
                nd = (board[i_xoffset][i_yoffset] + i_x + i_y)
                nd = nd % 10 + nd // 10 + d
                if (nx, ny) not in seen:
                    heappush(heap, (nd, nx, ny))
                    seen.add((nx, ny))

print(solve(99,99))
print(solve(499,499))


from rsf.proj import *

def angle(zx,zy):
    return 'angle2 zx=%g zy=%g nx=601 ny=601' % (zx,zy)

def contour(col,fat):
    return '''
    contour c0=10 dc=10 nc=10 transp=n yreverse=n wanttitle=n
    scalebar=y barlabel=" " plotcol=%d plotfat=%d wantaxis=n
    '''% (col,fat)

for a in [0,45]:
    for b in [0,45]:
        angl = 'angl%d-%d' % (a,b)
        grey = 'grey%d-%d' % (a,b)
        cont = 'cont%d-%d' % (a,b)
        Flow(angl,None,angle(a,b))
        Plot(grey,angl,
             '''
             grey allpos=y transp=n yreverse=n Xcolor=j
             scalebar=y barlabel="Reflection Angle (degrees)"
             title="In-line dip: %d, Cross-line dip: %d"
             ''' % (a,b))
        Plot(cont+'a',angl,contour(0,6))
        Plot(cont+'b',angl,contour(7,1))
        Result(angl,[grey,cont+'a',cont+'b'],'Overlay')

###########################################################################

End()


ret = '今天星期四'
# for i in ret:
    # print(i)

i = 0
while i < len(ret):
    print(ret[i])
    i += 1
# print(ret[0])

# type查看数据类型
# # capitalize将首字母变成大写，其余变成小写
set1 = ret.capitalize()
#
# # index返回字符串出现的最低下标如果不存在就会报错 rindex返回最高下标
# set2 = ret.rindex('i')
#
# count某个字符串出现次数
set3 = ret.count('i')
#
# # find与index相同如果不存在就返回-1，rfind返回最高下标
# set4 = ret.rfind('o')
#
# # upper将所有字母变成大写
# set5=ret.upper()

yel=ret.center(41,'*')
print(yel)

# yel1 = ret.endswith('n')

# yel2 = ret.startswith('t')
# print(yel2)
# print(len(ret))
# print(ret.lower())
sere = ret.encode('utf-8')
sere1 = ret.encode('gbk')
# go = ret.expandtabs()
# print('gbk编码:',sere1)
# print('utf-8编码:',sere)


#####################################################
# Camada Física da Computação
#Carareto
#11/08/2020
#Aplicação
####################################################

#esta é a camada superior, de aplicação do seu software de comunicação serial UART.
#para acompanhar a execução e identificar erros, construa prints ao longo do código!

from enlace import *
import time
import numpy as np
import os

# voce deverá descomentar e configurar a porta com através da qual ira fazer comunicaçao
#   para saber a sua porta, execute no terminal :
#   python -m serial.tools.list_ports
# se estiver usando windows, o gerenciador de dispositivos informa a porta

#use uma das 3 opcoes para atribuir à variável a porta usada
#serialName = "/dev/ttyACM0"           # Ubuntu (variacao de)
#serialName = "/dev/tty.usbmodem1411" # Mac    (variacao de)
serialName2 = "COM4"                  # Windows(variacao de)

def main():
    try:
        #declaramos um objeto do tipo enlace com o nome "com". Essa é a camada inferior à aplicação. Observe que um parametro
        #para declarar esse objeto é o nome da porta.
        com2 = enlace(serialName2)

        # Ativa comunicacao. Inicia os threads e a comunicação seiral
        com2.enable()
        print("primeiro checkpoint, comunicação aberta")
        #Se chegamos até aqui, a comunicação foi aberta com sucesso. Faça um print para informar.

        #aqui você deverá gerar os dados a serem transmitidos.
        #seus dados a serem transmitidos são uma lista de bytes a serem transmitidos. Gere esta lista com o
        #nome de txBuffer. Esla sempre irá armazenar os dados a serem enviados.

        #txBuffer = imagem em bytes!

        #faça aqui uma conferência do tamanho do seu txBuffer, ou seja, quantos bytes serão enviados.

        #finalmente vamos transmitir os tados. Para isso usamos a funçao sendData que é um método da camada enlace.
        #faça um print para avisar que a transmissão vai começar.
        #tente entender como o método send funciona!
        #Cuidado! Apenas trasmitimos arrays de bytes! Nao listas!

        head = 'Mandando!!'
        EOP = b'\x00\x00\x00\x00'

        head = bytes(head, encoding = 'utf-8')

        rxmensagem = b""

        print("-------------------------")
        print("Iniciando o handshake")
        print("-------------------------")

        while rxmensagem == b"":
            rxmensagem, nRxmensagem = com2.getData(14)
            print(rxmensagem)

            print("Handshake recebido!")

            if rxmensagem == b'Mandando!!\x00\x00\x00\x00':
                answer = head+EOP
                com2.sendData(answer)

                print("Handshake enviado")
            else:
                pass

        pacote_recebido = 1
        terminou = False
        rxBuffer = b""

        print("-------------------------")
        print("Iniciando o recebimento do datagrama")
        print("-------------------------")

        while not terminou:
            rxTamPacoteAt,rxTamPacoteAtSize = com2.getData(16)

            print(rxTamPacoteAt)

            pacote_size = rxTamPacoteAt[10:12]
            print(pacote_size)
            pacote_size = int.from_bytes(pacote_size, "big")

            print("Tamanho do pacote ", pacote_size)

            print("Verificando Tamanho")

            com2.sendData(rxTamPacoteAt)

            print("Recebendo o pacote")

            rxPacote, rxPacotesize = com2.getData(pacote_size)

            pacote = rxPacote[0]
            pacote_final = rxPacote[2]
            print("Serao recebidos {} pacotes".format(pacote_final))
            rxPacote_str = rxPacote.decode("utf-8")

            print("Recebi pacote {}".format(pacote))

            rxBuffer = rxBuffer + rxPacote[10:-4]

            if pacote == pacote_recebido:
                print("Pacote {} recebido".format(pacote))
            else:
                print("Erro, pacote recebido diferente do esperado. Aguardando novo envio")
                redlight = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'+b'nao'+EOP
                com2.sendData(redlight)
                continue

            print("Enviando confirmação")

            if rxPacote[-4:] == EOP:
                greenlight = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'+b'sim'+EOP
                com2.sendData(greenlight)
                print("Tudo certo, pacote enviado completo")
                print("-------------------------")
            else:
                redlight = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'+b'nao'+EOP
                com2.sendData(redlight)
                print("Deu erro, pacote enviado incompleto. Aguardando novo envio")
                continue

            if pacote_recebido == pacote_final:
                terminou = True
            else:
                pacote_recebido+=1

        print("-------------------------")
        print("Transmissão encerrada")
        print("-------------------------")

        print("-------------------------")
        print("Reagrupando o arquivo enviado")
        print("-------------------------")

        imgWrite = "Payload_Novo.txt"

        with open(imgWrite, "wb") as imagem:
            imagem.write(rxBuffer)
            imagem.close()

        # Encerra comunicação
        print("-------------------------")
        print("Comunicação encerrada")
        print("-------------------------")
        com2.disable()

    except Exception as erro:
        print("ops! :-\\")
        print(erro)
        com2.disable()

    #so roda o main quando for executado do terminal ... se for chamado dentro de outro modulo nao roda
if __name__ == "__main__":
    main()


import sys

# Given an integer k and text, compute the frequency
# array, in lexicographic order, of the k-mers in the text.
# run `python main.py filepath` where the first line contains
# the text, and the second contains the parameter k for kmer length.

def main():
    file = open(sys.argv[1], "r")
    text = file.readline().strip()
    k = int(file.readline().strip())
    frequency_array = count(text, k)
    print(' '.join([str(num) for num in frequency_array]))

def make_kmer_counter(k):
    return [0] * (4 ** k)

bases_list = ['A', 'C', 'G', 'T']

def kmer_to_num(kmer):
    num = 0
    for i in range(len(kmer)):
        num = num * len(bases_list) + bases_list.index(kmer[i])
    return num

def num_to_kmer(num):
    kmer = ""
    while num > 0:
        base = bases_list[num % len(bases_list)]
        kmer = base + kmer
        num = int(num / len(bases_list))
    return(kmer)

def count(text, k):
    counter = make_kmer_counter(k)
    for i in range(len(text) - k + 1):
        counter[kmer_to_num(text[i : i + k])] += 1
    return counter

def top_kmers(counter):
    max_ct = 0
    indices = []
    for i in range(len(counter)):
        if counter[i] > max_ct:
            max_ct = counter[i]
            indices = []
        if counter[i] == max_ct:
            indices.append(i)
    return(map(num_to_kmer, indices))

if __name__ == "__main__":
    main()

1. patterns & skew/11. frequency array.py


"""
Given a list_of_ints, find the highest_product you can get from k of the integers.
"""
from helpers.TestSuite import Assert
from helpers.TraceCalls import TraceCalls

def memoize(f):
    memo = dict()

    def helper(*x):
        if x not in memo:
            memo[x] = f(*x)
        return memo[x]
    return helper

def highest_prod_k(arr, k):
    @memoize
    def f(i, k):
        if i == len(arr):
            return 1, 1
        elif k == 0:
            return 1, 1
        else:
            res1, res2 = f(i + 1, k - 1)
            res3, res4 = f(i+1, k)
            return max(arr[i] * res1, arr[i]*res2, res3, res4), \
                min(arr[i] * res1, arr[i]*res2, res3, res4)
    return max(f(0, k))

def test():
    f = highest_prod_k
    arr = [2, 1, 4, 6, 5, 5, 3]
    Assert(150, f, arr, 3)
    Assert(600,f, arr, 4)
    arr = [-1,-100,3,4,2,4,5]
    Assert(500, f, arr, 3)
    Assert(2000, f, arr, 4)
    arr = [1, 2, 3, -10, 1, -10, 1, -10, 2, -10]
    Assert(30000, f, arr, 5)
    Assert(300, f, arr, 3)
    arr = [-100, -100, 4, 2, 3, 8]
    Assert(80000, f, arr, 3)

if __name__ == '__main__':
    test()

from timeit import Timer
setup = """
from __main__ import highest_prod_k
arr = [1, 2, 3, -10, 1, -10, 1, -10, 2, -10, 4, 3, 5, 1, 2, 6, 10, -2, 10, 9, -9, 1, 2, 3, 4, 5]
"""
t = Timer(setup=setup, stmt="highest_prod_k(arr, 5)").timeit(100)
print(t)


def ChangeMap(filename):
    filedata = ""
    f = open(filename, "r")
    for line in f:
        if line.split()[0] == 'map_Kd':
            line = line.replace(line, "map_Kd " + line.split()[1].split('\\')[-1] + "\n")
        # print(line)
        filedata += line

    f = open(filename, "w")
    f.write(filedata)

ChangeMap("sources/test_module/Butcher_intermediate1.mtl")


import requests
import pandas as pd
header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36 OPR/82.0.4227.33"
}
url = "https://api.github.com/users/aytiqaqash/repos"

response = requests.get(url, headers=header).json()

print(response)

pd.DataFrame(response).to_json('aytiqaqashGitHubRepos')


import io
import logging
import threading
import time
from datetime import datetime

import aiohttp
import pandas
import plotly.express as px
import requests
from aiocache import cached
from aiohttp import ContentTypeError

STARTUP_DEBOUNCE = True
COINS = requests.get("https://api.coingecko.com/api/v3/coins/list").json()

def stop_debounce():
    global STARTUP_DEBOUNCE
    time.sleep(5)
    STARTUP_DEBOUNCE = False

def startup_debounce(func):
    global STARTUP_DEBOUNCE

    async def inner(*args, **kwargs):
        if not STARTUP_DEBOUNCE:
            return await func(*args, **kwargs)

    return inner

threading.Thread(target=stop_debounce).start()

CACHE = None

@startup_debounce
@cached(ttl=120)
async def request_market_chart(days=1):
    global CACHE
    async with aiohttp.ClientSession() as session:
        async with session.get(f"https://api.coingecko.com/api/v3/coins/kaspa/market_chart?vs_currency=usd&days={days}",
                               timeout=10) as resp:
            try:
                CACHE = await resp.json()
            except ContentTypeError:
                if not CACHE:
                    logging.exception('Error reading market chart.')
                    raise
    return CACHE

async def get_coin_info_from_ticker(symbol):
    symbol = symbol.lower()
    filtered_coins = [x for x in COINS if x["symbol"].lower() == symbol] or \
                     [x for x in COINS if x["name"].lower() == symbol]

    if not filtered_coins:
        return

    coin_list = []
    for coin in filtered_coins:
        async with aiohttp.ClientSession() as session:
            async with session.get(f"https://api.coingecko.com/api/v3/coins/{coin['id']}",
                                   params={"tickers": "false",
                                           "community_data": "false",
                                           "developer_data": "false"},
                                   timeout=10) as resp:
                coin_list.append(await resp.json())

    return sorted(coin_list, key=lambda x: (x['coingecko_rank'] or 999999))[0]

async def get_image_stream(days=1):
    d = await request_market_chart(days)
    data = [(datetime.utcfromtimestamp(x[0] / 1000), x[1]) for x in d["prices"]]
    a = pandas.DataFrame(data, columns=["Time", "USD"])

    basic_plot = px.line(
        a,
        x="Time",
        y="USD",
        template="plotly_dark"
    )
    label_days = "24h" if days == 1 else f"{days}d"
    basic_plot.update_xaxes(title_font_size=15)
    basic_plot.update_yaxes(title_font_size=15)
    basic_plot.update_layout(
        title=f"KAS / USD chart - {label_days}",
        font={
            "size": 15,
            "color": "#F6F5F4"
        }
    )
    basic_plot.update_traces(line={
        "color": "#14F1D9"
    })

    # basic_plot.update_xaxes(linecolor="#ff0000")
    # basic_plot.update_layout(linecolor="#ff0000")

    # [datetime.fromtimestamp(x[0] / 1000) for x in d["prices"]],
    # symbol = "KAS"
    # y = [x[1] for x in d["prices"]]

    f = io.BytesIO()

    basic_plot.write_image(f)

    f.seek(0)

    return f


#!/opt/Tools/anaconda3/envs/hysplit/bin/python
# -----------------------------------------------------------------------------
# Air Resources Laboratory
#
# rundispersion.py - run HYSPLIT dispersion model
#
# 05 Jun  2023 (AMC) -
# 27 Jun  2023 (AMC) - Added 'source description' to inp hash for more flexibility in
#                      labeling the source. Added particularly for inversion runs.
# 29 Jun  2023 (AMC) - Allow input area to be diameter in km.
#
# -----------------------------------------------------------------------------
# Run specifically for traditional volcanic ash with line source from vent
# to input plume height.
#
# TODO - look at how SO2 functionality is incoporated. This needs to be updated.
# TODO - update how vertical levels are specified.
# -----------------------------------------------------------------------------

# from abc mport ABC, abstractmethod
import datetime
import logging
import os

import numpy as np

from utilhysplit import hcontrol
from utilhysplit.metfiles import MetFileFinder
from utilvolc.runhelper import is_input_complete, Helper, JobFileNameComposer
from ashapp.ashruninterface import ModelRunInterface
from ashapp.level_setter import get_levelsetter

# from runhandler import ProcessList
# from utilvolc.volcMER import HT2unit

logger = logging.getLogger(__name__)

def FL2meters(flight_level):
    meters = flight_level * 100 / 3.28084
    return int(meters)
    # return int(np.ceil(flight_level / 10.0) * 10)

def make_chemrate(wdir):
    fname = "CHEMRATE.TXT"
    fstr = "1 2 0.01 1.0"
    fpath = os.path.join(wdir, fname)
    with open(fpath, "w") as fid:
        fid.write(fstr)

class RunDispersion(ModelRunInterface):
    ilist = [
        ("meteorologicalData",'req'),
        ("forecastDirectory",'req'),
        ("archivesDirectory",'req'),
        ("WORK_DIR",'req'),
        ("HYSPLIT_DIR",'req'),
        ("jobname",'req'),
        ("durationOfSimulation",'req'),
        ("latitude",'req'),
        ("longitude",'req'),
        ("bottom",'req'),
        ("top",'req'),
        ("emissionHours",'req'),
        ("rate",'req'),
        ("area",'req'),
        ("start_date",'req'),
        ("samplingIntervalHours",'req'),
        ("qvaflag",'req'),
        ("jobid",'req'),
        ("source description",'req'),
        ("dzconcgrid",'opt'), #vertical resolution of concentration grid in meters.
    ]

    def __init__(self, inp):
        """
        A volcanic ash run from inputs
        """

        # 16 instance attributes  may be too many?

        self.JOBID = "999"
        # list of keywords the inp dictionary should contain.

        self._inp = {}
        self.inp = inp

        self._status = "Initialized"
        self._history = [self._status]

        self.default_control = "CONTROL.default"
        self.default_setup = "SETUP.default"
        self.set_default_control()
        self.set_default_setup()
        self._control = hcontrol.HycsControl(
            fname=self.default_control,
            working_directory=self.inp["DATA_DIR"],
            rtype="dispersion",
        )
        self._setup = hcontrol.NameList(
            fname=self.default_setup, working_directory=self.inp["DATA_DIR"]
        )
        self._metfilefinder = MetFileFinder(inp["meteorologicalData"])
        self._metfilefinder.set_forecast_directory(inp["forecastDirectory"])
        self._metfilefinder.set_archives_directory(inp["archivesDirectory"])

        self._levelsetter = get_levelsetter(self.inp)
        print('LEVELS', self._levelsetter.levlist)

        # self._filehash and self_filelist are
        # set in the filelocator setter method.
        self._filehash = {}
        self._filelist = []
        self.filelocator = inp
        self.so2 = False

    @property
    def levelsetter(self):
        return self._levelsetter

    @staticmethod
    def help():
        helphash = {}
        helphash["jobname"] = "str : user input string to identify run"
        helphash["jobid"] = "usually an integer assigned by the system for the job"
        helphash["emissionHours"] = "int : time for emissions to last "

    # no setter
    @property
    def status(self):
        return (self._status, self._history)

    # no setter
    @property
    def control(self):
        return self._control

    # no setter
    @property
    def setup(self):
        return self._setup

    @property
    def inp(self):
        return self._inp

    @inp.setter
    def inp(self, inp):
        self._inp.update(inp)

        if "source description" not in self._inp.keys():
            source = "Line to {:1.0f} km".format(self.inp["top"] / 1000.0)
            self._inp["source description"] = source

        complete = is_input_complete(self.ilist,self._inp)

        if "jobid" in self._inp.keys():
            self.JOBID = self._inp["jobid"]
        self.set_default_control()
        self.set_default_setup()
        if complete:
            logger.info("Input contains all fields")
        else:
            logger.warning('Input incomplete')
        # self._inp.update(inp)

    @property
    def filelocator(self):
        self._filelist = list(set(self._filelist))
        return self._filelocator

    @filelocator.setter
    def filelocator(self, finp):
        """
        input dictionary  with WORK_DIR, jobid, jobname
        or MetFileFinder object.
        """
        if isinstance(finp, dict):
            self._filelocator = JobFileNameComposer(
                finp["WORK_DIR"], finp["jobid"], finp["jobname"]
            )
        else:
            # TO DO? add test for type.
            self._filelocator = finp
        # after the filelocator is set, need to redo the filenames
        self._get_filenames()

    @property
    def metfilefinder(self):
        return self._metfilefinder

    @metfilefinder.setter
    def metfilefinder(self, metinp):
        """
        input dictionary with meteorologicalData, forecastDirectory, archivesDirectory
        or MetFileFinder object.
        """
        if isinstance(metinp, dict):
            self._metfilefinder = MetFileFinder(metinp["meteorologicalData"])
            self._metfilefinder.set_forecast_directory(metinp["forecastDirectory"])
            self._metfilefinder.set_archives_directory(metinp["archivesDirectory"])
        else:
            # TO DO? add test for type.
            self._metfilefinder = metinp

    @property
    def filelist(self):
        cdump = self._filehash["cdump"]

        metfile = self._metfilefinder.metid
        if isinstance(self._metfilefinder.suffix, str):
            if self.metfilefinder.suffix not in metfile:
                metfile += self._metfilefinder.suffix
        source = self.inp["source description"]
        self._filelist = [(cdump, source, metfile)]
        return self._filelist

    @property
    def filehash(self):
        return self._filehash

    def _get_filenames(self):
        fhash = {}
        fhash["control"] = self.filelocator.get_control_filename()
        fhash["setup"] = self.filelocator.get_setup_filename()
        fhash["pardump"] = self.filelocator.get_pardump_filename()
        fhash["cdump"] = self.filelocator.get_cdump_filename()
        self._filehash = fhash

    def set_default_setup(self):
        if "setup" in self.inp.keys():
            self.default_setup = self.inp["setup"]
        # else:
        #    self.default_setup = 'SETUP.default'
        # logger.warning("Using setup {}".format(self.default_setup))

    def set_default_control(self):
        if "control" in self.inp.keys():
            self.default_control = self.inp["control"]
        # else:
        #    self.default_control = 'CONTROL.default'
        # logger.warning("Using control {}".format(self.default_control))

    def compose_control(self, rtype):
        self._setup_basic_control()
        self._additional_control_setup()
        cdumpfiles = [x.outfile for x in self.control.concgrids]
        self.control.write()
        if os.path.isfile(self.filehash["control"]):
            self._history.append("CONTROL exists")
        else:
            self._status = "FAILED to write control file"
            self._history.append(self._status)
        return cdumpfiles

    def compose_setup(self):
        self._setup = self.setup_setup()
        self._setup.write(verbose=False)
        if os.path.isfile(self.filehash["setup"]):
            self._history.append("SETUP exists")
        else:
            self._status = "FAILED to write setup file"
            self._history.append(self._status)
        # return cdumpfiles

    def create_run_command(self):
        command = [
            os.path.join(self.inp["HYSPLIT_DIR"], "exec", "hycs_std"),
            str(self.filelocator.job),
        ]
        return command

    def check_status(self):
        if os.path.isfile(self.filelist["cdump"]):
            complete = "COMPLETE cdump exists"
            self._status = complete
            if self._history[-1] != complete:
                self._history.append(self._status)

    def run(self, overwrite=False):
        command = self.run_model(overwrite=overwrite)
        if isinstance(command, list):
            logger.info("execute {}".format(type(command)))
            Helper.execute(command)
        else:
            logger.info("No run to execture")

    def run_model(self, overwrite=False):
        # make control and setup files
        cdumpfiles = self.compose_control(rtype="dispersion")
        self.compose_setup()
        # start run and wait for it to finish..
        run = False
        command = None
        for cdump in cdumpfiles:
            if not os.path.isfile(cdump):
                run = True
                break
            logger.warning("CDUMP file already created {}".format(cdump))
            if not overwrite:
                self._status = "COMPLETE cdump exists"
                self._history.append(self._status)
        if run or overwrite:
            command = self.create_run_command()
        return command

    # Additional methods below.
    def setup_setup(self):
        duration = self.inp["durationOfSimulation"]
        # TO DO - may calculate particle number based on MER.
        setup = hcontrol.NameList(
            fname=self.default_setup, working_directory=self.inp["DATA_DIR"]
        )
        setup.read(case_sensitive=False)

        setup.rename(
            name=self.filehash["setup"], working_directory=self.inp["WORK_DIR"]
        )
        setup.add("poutf", self.filehash["pardump"])

        # setup.add("numpar", "2000")
        # setup.add("numpar", "20000")
        setup.add("numpar", "10000")
        # setup.add("maxpar", "500000")

        # base frequency of pardump output on length of simulation.
        if duration < 6:
            setup.add("ncycl", "1")
            setup.add("ndump", "1")
        elif duration < 12:
            setup.add("ncycl", "2")
            setup.add("ndump", "2")
        else:
            setup.add("ndump", "3")
            setup.add("ncycl", "3")

        keys = list(setup.nlist.keys())
        self.so2 = False
        if "ichem" in keys:
            if int(setup.nlist["ichem"]) == 2:
                make_chemrate(self.inp["WORK_DIR"])
                logger.warning("creating chemrate file for SO2")
                self.so2 = True
        return setup

    def _setup_basic_control(self, rtype="dispersion"):
        """
        inp : dictionary with inputs
        used for both dispersion and trajectory runs.
        """
        duration = self.inp["durationOfSimulation"]
        stime = self.inp["start_date"]
        metfiles = self.metfilefinder.find(stime, duration)
        self._control = hcontrol.HycsControl(
            fname=self.default_control,
            working_directory=self.inp["DATA_DIR"],
            rtype=rtype,
        )
        self._control.read()
        self._control.rename(self.filehash["control"], self.inp["WORK_DIR"])
        # set start date
        self._control.date = stime

        # add met files
        self._control.remove_metfile(rall=True)
        # metfiles = self.metfilefinder.find(stime, duration)
        for mfile in metfiles:
            logger.debug(os.path.join(mfile[0], mfile[1]))
            self._control.add_metfile(mfile[0], mfile[1])
        if not metfiles:
            logger.warning("TERMINATED. missing met files")
            self._status = "FAILED. missing meteorological files"
            self._history.append(self._status)
            # self.update_run_status(self.JOBID, "TERMINATED. missing met files")
        # add duration of simulation
        self._control.add_duration(duration)
        return self._control

    def _additional_control_setup(self):
        # for dispersion control file
        # if setting levels here then need to use the set_levels
        # function and also adjust the labeling for the levels.

        # round to nearest latitude longitude point.
        # this is for better matching with gridded volcat data.
        lat = self.inp["latitude"]
        lon = self.inp["longitude"]
        vent = self.inp["bottom"]
        height = self.inp["top"]
        emission = self.inp["emissionHours"]
        rate = self.inp["rate"]
        area = self.inp["area"]
        # assume that area is the diameter in km if it is smaller
        # than 1000. 250000 = (0.5*1000)^2
        # convert to square meters here.
        if area < 1000:
           area = np.pi * 250000 * area * area
           diameter = area
        else:
           diameter = 2*np.sqrt(area*1e-3 / np.pi)
        logger.info('Area is set at {:0.3e} m^2'.format(area))
        logger.info('Diameter at {} km'.format(diameter))

        # add location of eruption
        # with uniform vertical line source
        self._control.remove_locations()
        self._control.add_location((lat, lon), vent, rate=rate, area=area)
        self._control.add_location((lat, lon), height, rate=0.0001, area=area)
        # rename cdump file
        self._control.concgrids[0].outdir = self.inp["WORK_DIR"]
        self._control.concgrids[0].outfile = self.filehash["cdump"]
        logger.info("output file set as {}".format(self._control.concgrids[0].outfile))
        # center concentration grid near the volcano
        self._control.concgrids[0].centerlat = int(lat)
        self._control.concgrids[0].centerlon = int(lon)
        # set a global grid
        self._control.concgrids[0].latspan = 180.0
        self._control.concgrids[0].lonspan = 360.0
        # set the levels
        self._control.concgrids[0].set_levels(self._levelsetter.levlist)

        # add emission duration
        rate_test = 0
        if not self.so2:
            for spec in self._control.species:
                spec.duration = emission
                rate_test += spec.rate
        # for so2, the sulfate emission has 0 emissions.
        else:
            spec = self._control.species[0]
            spec.duration = emission
            spec2 = self._control.species[1]
            spec2.duration = 0
            rate_test = spec.rate + spec2.rate

        if np.abs(1 - rate_test) > 0.01:
            logger.warning("Non unit emision rate {}".format(rate_test))

        # TO DO
        # set sample start to occur on the hour.
        stime = self.inp["start_date"]
        # if start past the half hour mark, set sample start at next hour.
        if stime.minute > 30:
            stime = stime + datetime.timedelta(hours=1)
        sample_start = stime.strftime("%y %m %d %H 00")
        # logger.debug("Setting sample start {}".format(sample_start))
        self._control.concgrids[0].sample_start = sample_start

        self._control.concgrids[0].interval = (self.inp["samplingIntervalHours"], 0)
        self._control.concgrids[0].sampletype = -1


"""
(10 баллов) Текстовый файл Оценки.txt содержит строки вида «Иванов: 100, 45, 89, 789».
Используя данные этого файла создайте словарь, у которого ключом является фамилия, значением – кортеж из трех чисел (оценки).

(15 баллов) Напишите функцию, которая для словаря указанного вида находит максимальную и минимальную оценку
по заданной дисциплине.
Параметрами функции являются словарь и номер дисциплины (от 1 до 3).
По умолчанию номер дисциплины равен 1.
Функция возвращает кортеж из двух чисел.
"""

def counter(input_dict, subj_number=1):
    """
    Входные данные:
    - input_dict - исходный словарь
    - subj_number - номер предмета
    """

    # Изначальные данные для max и min
    max_result, min_result = 0, 99999

    # Для каждого значения в словаре цикл
    for value in input_dict.values():

        # Фикс индекса т.к. индексирование в python с 0
        locale_index = subj_number - 1

        # Если значение больше текущего максимального
        if value[locale_index] > max_result:
            # То это значение и становится максимальным
            max_result = value[locale_index]

        # Если значение меньше текущего минимального
        if value[locale_index] < min_result:
            # То это значение и становится минимальным
            min_result = value[locale_index]

    # Возврат значений
    return (max_result, min_result)

if __name__ == "__main__":

    # Финальный словарь
    this_dict = {}

    # Открываем файл оценки.txt на чтение
    with open("./Оценки.txt", "r") as file:
        file_result = file.read()

    # Создание списка строк исходного файла
    result_list = file_result.split("\n")

    # Цикл по каждой строке в списке
    for result in result_list:
        # Разделение по : и назначение переменных
        name, values = result.split(": ")

        # Список значений по разделителю ,
        values_list = values.split(', ')

        # Конвертация значений списка в целочисленный тип
        values_list = [int(x) for x in values_list]

        # Определение нового ключа словаря и значения
        this_dict[name] = values_list

    # Вывод полученного словаря на экран
    print(this_dict)
    # Вызов функции и вывод ее результата
    print(counter(this_dict, 2))


# Complete the isValid function below.
def isValid(s):
    print('input string', s)

    # create a character dictionary that will house all the unique characters in
    # the input string

    # create a for loop that will loop through the input string
        # if current index character is not in character dictionary
            # create a new key with the character and initialize the value to one
        # else iterate the value by one

    # create a second loop that will iterate through the keys to find the minimum and
    # maximum frequency of each character in the string and the number of strings that have maximum frenquency.

    # if maximum frienquency is one less than minmum and only one key has the maxiumum
    # frequency return YES else NO

    char_dict = {}

    for character in s:
        if character not in char_dict:
            char_dict[character] = 1
        else:
            char_dict[character] += 1

    minimum_frequency = float('inf')
    maximum_frequency = 0
    maximum_count = 0
    minimum_count = 0

    for key in char_dict:
        if minimum_frequency > char_dict[key]:
            minimum_frequency = char_dict[key]
            minimum_count = 1
        elif minimum_frequency == char_dict[key]:
            minimum_count += 1

        if maximum_frequency < char_dict[key]:
            maximum_frequency = char_dict[key]
            maximum_count = 1
        elif maximum_frequency == char_dict[key]:
            maximum_count += 1

    if maximum_frequency == minimum_frequency:
        return "YES"
    elif maximum_frequency - 1 == minimum_frequency and maximum_count == 1 or minimum_count == 1 and minimum_frequency == 1:
        return "YES"
    elif maximum_frequency - 1 == minimum_frequency and minimum_count == 1:
        return "YES"
    else:
        return "NO"


# -*- coding: utf-8 -*-
from django.contrib.sites.models import Site
from django.contrib.sites.models import get_current_site
from django.conf import settings

from opps.channels.models import Channel

class URLMiddleware(object):
    def process_request(self, request):
        """
        if the requested site is id 2 it
        will force the ROOT_URLCONF = 'yourproject.urls_2.py'
        """
        self.request = request
        site = get_current_site(request)
        if site.id > 1:
            prefix = "_{0}".format(site.id)
            self.request.urlconf = settings.ROOT_URLCONF + prefix

class TemplateContextMiddleware(object):
    """
    Include aditional items in response context_data
    """
    def process_template_response(self, request, response):
        if hasattr(response, 'context_data'):
            if 'channel' not in response.context_data:
                site = get_current_site(request)
                response.context_data['channel'] = Channel.objects\
                        .get_homepage(site=site or Site.objects.get(pk=1))
        return response


import string
from collections import Counter

with open("input.txt") as f:
    data = (l.strip(string.whitespace) for l in f.readlines())

total = 0

group_answers = ""
group_size = 0

for l in data:
    if l == "":
        c = Counter(group_answers)
        total += sum(1 for v in c.values() if v == group_size)
        group_answers = ""
        group_size = 0
        continue
    group_answers += l
    group_size += 1

if len(group_answers) > 0:
    c = Counter(group_answers)
    total += sum(1 for v in c.values() if v == group_size)

print(f"Total questions answered 'yes' by all group members: {total}")


def main():
    a=float(input("Enter the temperature in degrees Fahrenheit: "))
    b=float (((a-32)*5)/9)
    print (a,"degrees Fahrenheit in degrees Celcius is",b)

    c=str(input("Do you want to do this again: Y or N? "))
    if c == 'y':
        main()
    else:
        print ("Goodbye.")
main()


import csv
from collections import OrderedDict
from lorem_text import lorem
import h3
import logging
import requests
import json
from fred_client import FredClient
import numpy as np
import datetime
from Request import db

class CacheStrategy:
    def update_keygroup(self, new_file_ids:list, old_file_ids:dict) -> dict:
        """Updates the old cache with the new file ids"""
        pass

    def add(self, key, value):
        """Adds a key and value to the cache"""
        pass

class LRU(CacheStrategy):
    def __init__(self, capacity=100):
        self.capacity = capacity
        self.cache = OrderedDict()

    def update_keygroup(self, new_file_ids:list, old_file_ids:dict) -> dict:
        """

        Parameters
        ----------
        new_file_ids: list
            List where each row represents a row of the db table
        old_file_ids: dict
            Files retrieved from the meta data keygroup. Key is the file id and value the req_count

        Returns
        -------
        Updated dict for the meta data keygroup

        """
        if len(old_file_ids) > 0:
            self.cache = OrderedDict(old_file_ids)
        if len(new_file_ids) > 0:
            for row in new_file_ids:
                self.add(row["file_id"], row["req_count"])
        return self.cache

    def add(self, key, value):
        """
        Adds key and value to the keygroup cache.
        Parameters
        ----------
        key
        value

        Returns
        -------

        """
        if key not in self.cache:
            self.cache[key] = value
            self.cache.move_to_end(key)
        else:
            self.cache.move_to_end(key)

        # if cache is full
        if len(self.cache) > self.capacity:
            # remove first
            self.cache.popitem(last=False)

class LFU(CacheStrategy):
    def __init__(self, capacity=100):
        self.capacity = capacity
        self.cache = dict()

    def update_keygroup(self, new_file_ids:list, old_file_ids:dict) -> dict:
        """

        Parameters
        ----------
        new_file_ids: list
            List where each row represents a row of the db table
        old_file_ids: dict
            Files retrieved from the meta data keygroup. Key is the file id and value the req_count

        Returns
        -------
        Updated dict for the meta data keygroup

        """
        if len(old_file_ids) > 0:
            self.cache = old_file_ids
        if len(new_file_ids) > 0:
            for row in new_file_ids:
                self.add(row["file_id"], row["req_count"])

        # divide req_count by two
        # this will reduce the chance that a value that was popular in the beginning still be popular in the end
        # although nobody requested this file anymore
        if len(self.cache) > 0:
            for k, v in self.cache.items():
                self.cache[k] = int(v / 2)
        if len(list(self.cache.keys())) > self.capacity:
            sorted_cache = sorted(self.cache.items(), key=lambda kv: kv[1], reverse=True)
            self.cache = dict(sorted_cache[:-1])
        return self.cache

    def add(self, key, value):
        """
        Adds key and value to the keygroup cache.
        Parameters
        ----------
        key
        value

        Returns
        -------

        """
        if key not in self.cache:
            self.cache[key] = value
        else:
            old_count = self.cache[key]
            # add old and new count
            self.cache[key] = old_count + value

class Personalised(CacheStrategy):
    """
    capacity: how many at max we store in our meta data kg
    expiry_h: file ids that are removed in our meta data kg after this many hours
    treshold: how many request a file_id at least have to have to land in the meta data cache.
    """
    def __init__(self, capacity=0, expiry_h=24, threshold=2):
        self.capacity = capacity
        self.expiry_h = expiry_h
        self.threshold = threshold
        self.cache = OrderedDict()

    def clean_up(self):
        """
        Cleans up the current cache (meta data keygroup) according to the expiry.
        Returns
        -------

        """
        if len(self.cache) == 0:
            return
        current_time = datetime.datetime.utcnow() - datetime.timedelta(hours=self.expiry_h)
        for key in self.cache.keys():
            # remove from meta data if file hasn't been accessed for the setted expiry time
            if self.cache[key]["timestamp"] < datetime.datetime.timestamp(current_time):
                del self.cache[key] # delete key

    def update_keygroup(self, new_file_ids:list, old_file_ids:dict):
        """
        Parameters
        ----------
        new_file_ids: list
            List where each row represents a row of the db table
        old_file_ids: dict
            Files retrieved from the meta data keygroup. Key is the file id and value the req_count

        Returns
        -------
        Updated dict for the meta data keygroup

        """
        if len(old_file_ids) > 0:
            self.cache = OrderedDict(old_file_ids)
        if len(new_file_ids) > 0:
            for row in new_file_ids:
                if row["req_count"] > self.threshold:
                    now = datetime.datetime.utcnow()
                    # transform to timestamp bc datetime is not supported by json dumps
                    self.add(row["file_id"], {"timestamp": datetime.datetime.timestamp(now)})
        self.clean_up()
        return self.cache

    def add(self, key, value):
        """
        Adds key and value to the keygroup cache.
        Parameters
        ----------
        key
        value

        Returns
        -------

        """
        if key not in self.cache:
            self.cache[key] = value
            self.cache.move_to_end(key)
        else:
            self.cache.move_to_end(key)

        if self.capacity > 0 & len(self.cache) > self.capacity:
            # remove first
            self.cache.popitem(last=False)

class Satellite:
    """
    This class holds all the information about a single satellite.
    Kepler Ellipse, offset are needed for our own simulation. For the integration into Celestial these two are not
    needed hence, we do not need to use e.g. update position in Celestial.

    Attributes
    ----------
    name: str
        Name of the satellite as "satellite{id} of node on plane}"
    kepler_ellipse: KeplerEllipse
        The kepler ellipse of this satellite.
    offset: int
        The offset of this satellite
    current_time: int
        The current time of the simulation in seconds.
    x_position: int
        The unrotated x position of the satellite.
    y_position: int
        The unrotated y position of the satellite.
    z_position: int
        The unrotated z position of the satellite.
    keygroup:
        The current keygroup of the satellite.
    host:
        Host of the satellite.
    port:
        Port of the satellite.
    fredComm:
        fred functions class
    """

    def __init__(self,
                 name,
                 fred_client,
                 keygroup_layers,
                 db_get_files,
                 db_rm_all,
                 kepler_ellipse=None,
                 offset=0,
                 strategy: CacheStrategy = Personalised()
                 ):
        logging.basicConfig(filename='/logs/' + name + '_satellite.log',
                            filemode='a',
                            format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
                            datefmt='%H:%M:%S',
                            level=logging.INFO)
        self.logger = logging.getLogger(f'{name}_satellite')
        self.name = name
        self.fred_client = fred_client
        self.keygroup_layers = keygroup_layers
        self.baseurl = "http://172.26.4.1:9001/position/" + name
        self.strategy = strategy
        self.db_get_files = db_get_files
        self.db_rm_all = db_rm_all

    def get_current_position(self):
        """
        Returns the current position of a satellite but without the rotation

        Returns
        -------
        x_position: int
        y_position: int
        z_position: int
        """
        r = requests.get(url=self.baseurl)
        position = json.loads(r.text)
        radius = 6371000
        lon = np.degrees(np.arctan2(position['y'], position['x']))
        lat = np.degrees(np.arcsin(position['z'] / radius))

        return lat, lon

    def join_keygroup(self, keygroup):
        """
        Join the metadata keygroup
        Parameters
        ----------
        keygroup
            Name of metadata keygroup.

        Returns
        -------

        """
        status = 1
        try:
            response = self.fred_client.add_replica_node_to_keygroup(keygroup)
            status = response.status
        except Exception as e:
            status = 1
        if status == 1:
            try:
                response = self.fred_client.create_keygroup(keygroup)
            except:
                return False
        return True

    def check_keygroup(self):
        """
        Checks whether the keygroup is still the same.
        If yes it returns 0. Otherwise, it returns the new keygroup_id.

        Parameters
        ----------
        hex_resolution

        Returns
        -------

        """
        lat, lon = self.get_current_position()
        new_keygroup_names = [h3.geo_to_h3(lat, lon, resolution) for resolution in
                              range(self.keygroup_layers)]  # is the same as h3 are
        self.fred_client.setLowestKeygroup(new_keygroup_names[-1])
        joined_keygroups = self.fred_client.get_keygroups()

        # remove all the keygroups that contain the word metadata
        joined_keygroups = [ x for x in joined_keygroups if "metadata" not in x ]
        # Checks if the new_keygroup_names need to be joined
        needsToJoin = [True for x in range(self.keygroup_layers)]
        for kg in joined_keygroups:
            for x in range(self.keygroup_layers):
                # Checks if the satellite is already inside the keygroup
                if kg == new_keygroup_names[x]:
                    needsToJoin[x] = False
                    break

        for x in range(self.keygroup_layers):
            # If the satellite isn't inside the keygroup yet
            if needsToJoin[x]:
                status = 1
                try:
                    response = self.fred_client.add_replica_node_to_keygroup(new_keygroup_names[x])
                    status = response.status

                    # try to enter the same keygroup but for meta data
                    # if the other keygroup entering failed this should too
                    self.fred_client.add_replica_node_to_keygroup(new_keygroup_names[x]+"metadata")

                except Exception as e:
                    status = 1
                if status == 1:
                    try:
                        response = self.fred_client.create_keygroup(new_keygroup_names[x])
                        # create meta data keygroup
                        response = self.fred_client.create_keygroup(new_keygroup_names[x]+"metadata")
                    except:
                        continue

        # Get all keygroups of the satellite and check if it needs to be removed
        keygroups = self.fred_client.get_keygroups()
        # remove all the keygroups that contain the word metadata
        keygroups = [x for x in keygroups if "metadata" not in x]
        for kg in keygroups:
            remove = False
            for new_kg in new_keygroup_names:
                if kg != new_kg:
                    remove = True
                    break
            if remove:
                try:
                    # get current popular files in the current keygroup
                    current_popular_files = self.fred_client.read_file_from_node(f"{kg}metadata", "popularfiles")
                    if len(current_popular_files) > 0:
                        # json.loads does not work if we get an empty string
                        # that's why we have to catch this case
                        current_popular_files = json.loads(current_popular_files)
                    else:
                        current_popular_files = {}
                    # update all the popular files in the current keygroup

                    db_data = self.db_get_files()
                    all_files = self.strategy.update_keygroup(db_data, current_popular_files)
                    # set popular files of current keygroup
                    # this is just a dictionary with keys = file ids, and values = meta data
                    self.fred_client.set_data(f"{kg}metadata", "popularfiles", json.dumps(all_files))

                    # remove satellite from keygroup
                    self.fred_client.remove_replica_node_from_keygroup(kg)
                    self.fred_client.remove_replica_node_from_keygroup(kg+"metadata")
                    # clear db after leaving kg
                    self.db_rm_all()
                except:
                    continue

        # Prints all keygroups of the satellite in the logger
        keygroups = self.fred_client.get_keygroups()
        self.logger.info(f"The keygroups of {self.name}: " + " ".join(str(x) for x in keygroups))
        self.manage(new_keygroup_names)

    def get_files_to_push_or_remove(self, keygroups:list, files_on_top_layer:list):
        """

        Parameters
        ----------
        keygroups
            list of neighboring keygroups
        files_on_top_layer:
            current file ids in a list that are stored in the upper layer. If this is emtpy it is a string of size 0.

        Returns
        -------

        """
        if len(files_on_top_layer) == 0:
            files_on_top_layer = list()
        all_file_id_occurence = list()
        for kg in keygroups:
            # get all popular files from the neighbors and only save the keys = file ids
            files = self.fred_client.read_file_from_node(f"{kg}metadata", "popularfiles")
            if len(files) > 0:
                files = json.loads(files)
                all_file_id_occurence.append(list(files.keys()))

        list_of_ids_that_should_be_pushed = []
        if len(all_file_id_occurence) > 0:
            # count how many times each file id occurs
            flatten_file_id_occurence = [file_id for sublist in all_file_id_occurence for file_id in sublist]
            counted_common_file_ids = dict()
            # count how many keygroups contain a certain file if
            for id in flatten_file_id_occurence:
                counted_common_file_ids[id] = counted_common_file_ids.get(id, 0) + 1

            # if more than 2 keygroups have the same file id put it in a list of ids that should be on the top layer
            list_of_ids_that_should_be_pushed = [k for k, v in counted_common_file_ids.items() if v >= 2]

        # files that should be on the top layer but aren't
        list_of_ids_to_push_up = list(set(list_of_ids_that_should_be_pushed) - set(files_on_top_layer))
        # files that are in top layer but should not be there
        list_of_ids_to_remove = list(set(files_on_top_layer) - set(list_of_ids_that_should_be_pushed))

        return list_of_ids_to_push_up, list_of_ids_to_remove

    def get_file_content_of_neighbors(self, all_ring_kg, top_layer_kg, file_ids):
        """
        Gets the data from the lower keygroups (center kg and surrounding kg).
        Parameters
        ----------
        all_ring_kg:
            all lower layer kg (center and neighbors)
        top_layer_kg:
            top layer kg
        file_ids:
            ids to push up

        Returns
        -------

        """
        if len(file_ids) == 0:
            return
        for kg in all_ring_kg:
            try:
                response = self.fred_client.add_replica_node_to_keygroup(kg)
                status = response.status
            except Exception as e:
                status = 1
            if status == 0:
                for id in file_ids:
                    data = self.fred_client.read_file(id)
                    if len(data) > 0:
                        self.fred_client.set_data(top_layer_kg, id, data)
                        self.fred_client.remove_data(kg, id)
                self.fred_client.remove_replica_node_from_keygroup(kg)

    def add_data_to_kg(self, file_ids: list, keygroup):
        """
        NOT USED ATM
        Adds the data to a keygroup but generates the data first and doesnt delete from lower kg
        Parameters
        ----------
        file_ids
            List of file ids to be added into the keygroup
        keygroup
            Keygroup to add the data into. Should be the top layer keygroup.

        Returns
        -------

        """
        if len(file_ids) == 0:
            return
        files_csv = open('./files.csv', "r")
        reader = csv.reader(files_csv)
        paragraphs = 5
        for file_id in file_ids:
            for line in reader:
                if line[0] == file_id:
                    paragraphs = int(line[1])
            lorem_text = lorem.paragraphs(paragraphs)
            self.fred_client.set_data(keygroup, file_id, lorem_text)

    def remove_data_from_kg(self, file_ids:list, keygroup):
        if len(file_ids) == 0:
            return
        for file_id in file_ids:
            self.fred_client.remove_data(kg=keygroup, file_id=file_id)

    def manage(self, keygroups):
        """
        Runs the whole managing process

        Parameters
        ----------
        keygroups:
            Current keygroups the satellite is inside of except for metadata keygroups.

        Returns
        -------
        """

        # Gets a list of keygroups that has a managing role
        manager_list = self.isManager(keygroups)

        # if the list isn't empty, the satellite is a manager
        if len(manager_list) > 0:
            for manage_keygroup in manager_list:
                # Get neighbouring keygroups
                keygroups_to_manage = list(h3.k_ring_distances(manage_keygroup, 1)[1])

                # Get responsible satellite for each neighbour
                for neighbour in keygroups_to_manage:
                    # enter all surrounding meta data keygroups
                    success = self.join_keygroup(neighbour+"metadata")
                    # responsible_satellite = self.fred_client.get_keygroup_replica(neighbour)
                    # self.logger.info(f"{responsible_satellite} is responsible for the neighbour: {neighbour}")

                # get all keygroup this satellite has to check the popular files of
                keygroups_to_manage.append(manage_keygroup)

                # get current files in the top layer
                files_currently_on_top_layer = self.fred_client.read_file_from_node(f"{manage_keygroup}metadata", "layer0files")

                # if it is an empty string
                if len(files_currently_on_top_layer) == 0:
                    files_currently_on_top_layer = "[]"
                files_to_push, files_to_remove = self.get_files_to_push_or_remove(keygroups_to_manage, json.loads(files_currently_on_top_layer))
                # push and remove files to layer 0
                # can we do this differently?
                # self.add_data_to_kg(file_ids=files_to_push, keygroup=keygroups[0])
                self.get_file_content_of_neighbors(keygroups_to_manage, keygroups[0], files_to_push)
                self.remove_data_from_kg(files_to_remove, keygroups[0])
                self.fred_client.set_data(kg=manage_keygroup+"metadata", key="layer0files", value=json.dumps(files_to_push) )

    def isManager(self, keygroups):
        """
        Checks whether the satellite is a manager.

        Parameters
        ----------
        Current keygroups the satellite is inside of

        Returns
        -------
        List of keygroups that the satellite manages
        """
        managerList = []

        # get the center keygroup of resolution 0
        for x in range(1, self.keygroup_layers):
            # Get the central keygroup for resolution x > 0, depending on keygroup_layers in config.toml
            lower_layer_center = h3.h3_to_center_child(keygroups[0], x)
            # Check if the satellite is inside one the manager keygroup
            for i in range(self.keygroup_layers):
                if keygroups[i] == lower_layer_center:
                    managerList.append(keygroups[i])
        return managerList


from pathlib import Path

correct_ref_file = False
correct_thickness = False
list_of_files = []
ref_spectrum_name = ''
reference_spectrum = []
fitting = False
spektri = []
current_real_data = []
real_data_history = []
fitted_parameters = [0, 1]
thickness_history = []
current_fitted_data = []
fitted_data_history = []

# real time
desired_thickness = 0
anod_ending_index = 0
anod_starting_index = 0
i = 0
current_file = Path()
emergency_stop = False

zipper_animation = True
filename = ''

integration_time = 0
integration_time_units = ''
spectra_average = 0
anodization_time = 0
last_thickness = 0
uploader_animation = True


__all__ = [
    'default_memnet_embed_fn_hparams',
]

def default_memnet_embed_fn_hparams():
    """Returns a dictionary of hyperparameters with default hparams for
    :func:`~texar.tf.modules.memory.default_embed_fn`

    .. code-block:: python

        {
            "embedding": {
                "dim": 100
            },
            "temporal_embedding": {
                "dim": 100
            },
            "combine_mode": "add"
        }

    Here:

    "embedding": dict, optional
        Hyperparameters for embedding operations. See
        :meth:`~texar.tf.modules.WordEmbedder.default_hparams` of
        :class:`~texar.tf.modules.WordEmbedder` for details. If `None`, the
        default hyperparameters are used.

    "temporal_embedding": dict, optional
        Hyperparameters for temporal embedding operations. See
        :meth:`~texar.tf.modules.PositionEmbedder.default_hparams` of
        :class:`~texar.tf.modules.PositionEmbedder` for details. If `None`, the
        default hyperparameters are used.

    "combine_mode": str
        Either **'add'** or **'concat'**. If 'add', memory
        embedding and temporal embedding are added up. In this case the two
        embedders must have the same dimension. If 'concat', the two
        embeddings are concated.
    """
    return {
        "embedding": {
            "dim": 100
        },
        "temporal_embedding": {
            "dim": 100
        },
        "combine_mode": "add"
    }


from functools import reduce

def find_maxprod(s, n):
    lst = list(map(int, s))
    idx, prod = 0, reduce(lambda x, y: x*y, lst[:n])
    cur_prod = prod
    for i in range(n, len(lst)):
        cur_prod = cur_prod * lst[i] // lst[i-n]
        # print(prod, lst[i], lst[i-n], cur_prod)
        if cur_prod > prod:
            prod = cur_prod
            idx = i-n+1

    return idx, prod

s = input()
n = int(input())
idx, prod = find_maxprod(s, n)
print("{}={}".format("*".join(s[idx:idx+n]), prod))