#
from typing import Optional, Dict, Tuple, Any, Union
import logging
import numpy as np
import gym
import torch
from torch import nn
from torch import Tensor
from tianshou.data import Batch

import lib.networks.encoders as encoders
import lib.networks.decoders as decoders
from lib.networks.encoders import GRAPH_ENCODERS
from lib.networks.aggregator import Aggregator, DummyAggregator
from lib.networks.decoders.iqn import IQN
from lib.networks.formats import Obs, GraphObs, Emb
from lib.utils import count_parameters

logger = logging.getLogger(__name__)

class Model(nn.Module):
    """
    Model wrapper providing unified interface
    for different encoder/decoder architectures.

    Args:
        problem: current problem type
        observation_space: env observation space
        action_space: env action space
        policy_type: used policy type to determine model output format
                    (default 'DQN'; 'IQN' for implicit quantile network)
        decoder_type: type of decoder
        encoder_args: additional arguments for encoder creation
        decoder_args: additional arguments for decoder creation
        aggregator_args: additional arguments for aggregator creation
        embedding_dim: general embedding dimension of model
        device: device of model (CPU or GPU)
        env_modes: mode cfg of the env
    """
    def __init__(self,
                 problem: str,
                 observation_space: gym.spaces.Dict,
                 action_space: Union[gym.spaces.Discrete, gym.spaces.MultiDiscrete],
                 policy_type: str = "DQN",
                 decoder_type: Union[str, nn.Module] = "FFDecoder",
                 encoder_args: Optional[Dict] = None,
                 decoder_args: Optional[Dict] = None,
                 aggregator_args: Optional[Dict] = None,
                 iqn_args: Optional[Dict] = None,
                 embedding_dim: int = 128,
                 device: Union[str, int, torch.device] = "cpu",
                 env_modes: Dict = None,
                 **kwargs):
        super(Model, self).__init__()

        self.problem = problem
        self._observation_space = observation_space
        self._action_space = action_space
        self.decoder_type = decoder_type
        self.encoder_args = encoder_args if encoder_args is not None else {}
        self.decoder_args = decoder_args if decoder_args is not None else {}
        self.aggregator_args = aggregator_args if aggregator_args is not None else {}
        self.iqn_args = iqn_args if iqn_args is not None else {}
        self.embedding_dim = embedding_dim
        self._device = torch.device(device)
        self.policy_type = policy_type.upper()
        #
        self._idx_inc = None
        self._static_nbh_edge_buffer = None
        self._ref_bs = None

        # get dims from obs and act space
        _, f = self._observation_space.spaces['node_features'].shape
        self.node_feature_dim = f
        self.node_max_dim = None
        self.action_output_dim = self._action_space.n

        # initialize encoder model
        self.encoder = Encoder(
            problem=self.problem,
            embedding_dim=embedding_dim,
            node_feature_dim=self.node_feature_dim,
            edge_feature_dim=1,
            **self.encoder_args, **kwargs)

        # initialize aggregator
        if self.aggregator_args:
            self.aggregator = Aggregator(
                observation_space=self._observation_space,
                action_space=self._action_space,
                emb_dim=embedding_dim,
                env_modes=env_modes,
                **self.aggregator_args)
        else:
            self.aggregator = DummyAggregator()

        # initialize decoder network
        decoder_cl = getattr(decoders, decoder_type) if isinstance(decoder_type, str) else decoder_type
        # jit decoder model
        self.decoder = torch.jit.script(decoder_cl(
            input_dim=self.embedding_dim,
            output_dim=self.action_output_dim,
            **self.decoder_args, **kwargs
        ))

        self.iqn = IQN(
            input_dim=self.action_output_dim,
            output_dim=self.action_output_dim,
            **self.iqn_args
        ) if self.policy_type == "IQN" else None

        self.reset_parameters()
        self.to(device=self._device)

    def __repr__(self):
        super_repr = super().__repr__()     # get torch module str repr
        n_enc_p = count_parameters(self.encoder)
        n_agg_p = count_parameters(self.aggregator)
        n_dec_p = count_parameters(self.decoder)
        n_iqn_p = count_parameters(self.iqn) if self.iqn is not None else 0
        add_repr = f"\n-----------------------------------" \
                   f"\nNum Parameters: " \
                   f"\n  (encoder): {n_enc_p} " \
                   f"\n  (aggregator): {n_agg_p} " \
                   f"\n  (decoder): {n_dec_p + n_iqn_p} " \
                   f"\n  total: {n_enc_p+n_agg_p+n_dec_p+n_iqn_p}"
        return super_repr + add_repr

    def reset_parameters(self):
        """Reset model parameters."""
        self.encoder.reset_parameters()
        self.aggregator.reset_parameters()

    def forward(self,
                obs: Batch,
                state: Optional[np.ndarray] = None,
                info: Optional[Dict] = None,
                **kwargs) -> Tuple[Union[Tensor, Tuple], Any]:
        """
        Meta forward pass wrapper doing required data batch collation and conversion.

        Args:
            obs: ts.batch of observations
            state: optional RNN state
            info: additional env info dict

        Returns:
            logits: logits over action space dimension.
                    depending on policy can also be a tuple, e.g.
                    (mu: Tensor, sigma: Tensor) for Gaussian PPO policy or
                    (logits: Tensor, taus: Tensor) for IQN
            state: optional RNN state

        """
        # convert to torch tensors and push to device
        obs.to_torch(device=self._device)
        bs = obs.shape[0]
        recompute = True
        sample_size = kwargs.pop("sample_size", 0)
        self.node_max_dim = obs.node_features.size(1)

        # collate and format batch
        if self.encoder.uses_graph:
            # convert edges into running idx format expected by torch_geometric
            nbh_e = obs.get('nbh_edges')
            nbh_w = obs.get('nbh_weights')

            # during inference we can keep static components (e.g. node neighborhood)
            # fixed and do not need to recompute them every step
            if (
                self.training   # during training
                or len(info.shape) == 0     # on init
                or bs != self._ref_bs       # bs change
                or (len(info.shape) > 0 and np.any(info['step'] == 0))  # start of new episode
            ):
                self._ref_bs = bs
                self._idx_inc = torch.arange(0, self.node_max_dim * bs, self.node_max_dim,
                                             device=self._device)[:, None, None]
                if nbh_e is not None:
                    self._static_nbh_edge_buffer = self._to_edge_batch(nbh_e, self._idx_inc, self.node_max_dim)
            else:
                recompute = False

            cur_sol_e = self._to_edge_batch(obs['current_sol'], self._idx_inc, self.node_max_dim)
            best_sol_e = self._to_edge_batch(obs['best_sol'], self._idx_inc, self.node_max_dim)

            if self.problem.upper() == "JSSP":
                prep_obs = GraphObs(
                    batch_size=bs,
                    batch_idx=None,     # type: ignore
                    node_features=obs['node_features'].view(-1, self.node_feature_dim),
                    current_sol=None,   # type: ignore
                    current_sol_edges=cur_sol_e,  # type: ignore
                    current_sol_weights=obs['current_sol_w'].view(-1),
                    best_sol=None,  # type: ignore
                    best_sol_edges=best_sol_e,  # type: ignore
                    best_sol_weights=obs['best_sol_w'].view(-1),
                    nbh_edges=self._static_nbh_edge_buffer,  # type: ignore
                    nbh_weights=nbh_w.view(-1) if nbh_w is not None else None,
                    current_sol_seqs=obs['current_sol_seq'],
                    best_sol_seqs=obs['best_sol_seq'],
                    meta_features=obs['meta_features'],
                )
            else:
                if not hasattr(obs, "batch_idx"):
                    raise RuntimeError(f"Specified encoder needs observations from RPGraphVecEnv.")
                prep_obs = GraphObs(
                    batch_size=bs,
                    batch_idx=obs['batch_idx'].view(-1).to(torch.long),
                    node_features=obs['node_features'].view(-1, self.node_feature_dim),
                    current_sol=obs['current_sol'],
                    current_sol_edges=cur_sol_e,  # type: ignore
                    current_sol_weights=self._compute_tour_edge_weights(obs['coords'], cur_sol_e),
                    best_sol=obs['best_sol'],
                    best_sol_edges=best_sol_e,  # type: ignore
                    best_sol_weights=self._compute_tour_edge_weights(obs['coords'], best_sol_e),
                    nbh_edges=self._static_nbh_edge_buffer,  # type: ignore
                    nbh_weights=nbh_w.view(-1) if nbh_w is not None else None,
                    current_sol_seqs=obs['current_sol_seq'],
                    best_sol_seqs=obs['best_sol_seq'],
                    meta_features=obs['meta_features'],
                )
        else:
            assert self.problem.upper() != "JSSP"
            prep_obs = Obs(
                node_features=obs['node_features'],
                current_sol=obs['current_sol'],
                best_sol=obs['best_sol'],
                current_sol_seqs=obs['current_sol_seq'],
                best_sol_seqs=obs['best_sol_seq'],
                meta_features=obs['meta_features'],
            )

        logits, state = self._dqn_forward(bs, prep_obs, state, recompute=recompute, **kwargs)
        if self.policy_type == "IQN":
            # obs batch object does not need mask since logits are already masked, i.e. set to -inf where infeasible
            logits = self.iqn(logits, sample_size, **kwargs)    # returns logits tuple!

        return logits, state

    def _dqn_forward(self,
                     bs: int,
                     prep_obs: Union[Obs, GraphObs],
                     state: Optional[np.ndarray] = None,
                     **kwargs) -> Tuple[Union[Tensor, Tuple], Any]:
        """Inner forward calling encoder, aggregator and decoder models."""
        # encode
        emb = self.encoder(prep_obs, **kwargs)
        # aggregate embeddings
        emb = self.aggregator(
            prep_obs, emb, dims=(bs, self.node_max_dim, self.node_feature_dim)
        )
        # decode
        return self.decoder(emb, state)

    @staticmethod
    @torch.jit.script
    def _to_edge_batch(x: Tensor, idx_inc: Tensor, node_max_dim: int) -> Tensor:
        """Convert a batch of single instance edges to a batch of edges with running idx."""
        bs, e, n = x.size()
        assert e == 2 and x.max() < node_max_dim
        return (x + idx_inc).permute(1, 0, 2).reshape(2, -1)

    @staticmethod
    @torch.jit.script
    def _compute_tour_edge_weights(coords: Tensor, tour_edges: Tensor):
        """Calculate edge weights as euclidean distance between coords."""
        # calc edge weights (Euclidean distance)
        idx_coords = coords.view(-1, 2)[tour_edges]
        return torch.norm(idx_coords[0] - idx_coords[1], p=2, dim=-1)

    def get_optimizer(self, lr: float = 1e-3, **kwargs):
        """Return torch optimizer instance for network."""
        return torch.optim.Adam(self.parameters(), lr=lr, **kwargs)

class Encoder(nn.Module):
    """
    Encoder model wrapper to enable different encoding levels
    between nodes, edges, tours and graph.
    """

    def __init__(self,
                 problem: str,
                 embedding_dim: int,
                 node_feature_dim: int,
                 edge_feature_dim: Optional[int] = None,
                 node_encoder_type: Optional[str] = None,
                 node_encoder_cfg: Optional[Dict] = None,
                 sol_encoder_type: Optional[str] = None,
                 sol_encoder_cfg: Optional[Dict] = None,
                 sub_graph_encoder_type: Optional[str] = None,
                 sub_graph_encoder_cfg: Optional[Dict] = None,
                 graph_encoder_type: Optional[str] = None,
                 graph_encoder_cfg: Optional[Dict] = None,
                 ):
        super(Encoder, self).__init__()

        self.problem = problem
        self.embedding_dim = embedding_dim
        self.node_feature_dim = node_feature_dim
        self.edge_feature_dim = edge_feature_dim
        self.node_encoder_type = node_encoder_type
        self.node_encoder_cfg = node_encoder_cfg if node_encoder_cfg is not None else {}
        self.sol_encoder_type = sol_encoder_type
        self.sol_encoder_cfg = sol_encoder_cfg if sol_encoder_cfg is not None else {}
        self.sub_graph_encoder_type = sub_graph_encoder_type
        self.sub_graph_encoder_cfg = sub_graph_encoder_cfg if sub_graph_encoder_cfg is not None else {}
        self.graph_encoder_type = graph_encoder_type
        self.graph_encoder_cfg = graph_encoder_cfg if graph_encoder_cfg is not None else {}

        self.node_encoder = None
        self.sol_encoder = None
        self.sub_graph_encoder = None
        self.graph_encoder = None
        self.uses_graph = False

        if self.node_encoder_type is not None:
            self.node_encoder = self._init_encoder(
                encoder_type=self.node_encoder_type,
                input_dim=node_feature_dim,
                output_dim=embedding_dim,
                edge_feature_dim=edge_feature_dim,
                **self.node_encoder_cfg
            )

        # group pooling layer
        if self.sol_encoder_type is not None:
            self.sol_encoder = self._init_encoder(
                encoder_type=self.sol_encoder_type,
                input_dim=embedding_dim,
                output_dim=embedding_dim,
                problem=self.problem,
                **self.sol_encoder_cfg
            )

        if self.sub_graph_encoder_type is not None:
            self.sub_graph_encoder = self._init_encoder(
                encoder_type=self.sub_graph_encoder_type,
                input_dim=embedding_dim,
                output_dim=embedding_dim,
                **self.sub_graph_encoder_cfg
            )

        if self.graph_encoder_type is not None:
            self.graph_encoder = self._init_encoder(
                encoder_type=self.graph_encoder_type,
                input_dim=embedding_dim,
                output_dim=embedding_dim,
                **self.graph_encoder_cfg
            )

    def _init_encoder(self,
                      encoder_type: str,
                      input_dim: int,
                      output_dim: int,
                      **kwargs) -> nn.Module:
        self.uses_graph = self.uses_graph or (encoder_type in GRAPH_ENCODERS)
        cl = getattr(encoders, encoder_type) if isinstance(encoder_type, str) else encoder_type
        return cl(
            input_dim=input_dim,
            output_dim=output_dim,
            **kwargs
        )

    def reset_parameters(self):
        if self.node_encoder is not None:
            self.node_encoder.reset_parameters()
        if self.sol_encoder is not None:
            self.sol_encoder.reset_parameters()
        if self.sub_graph_encoder is not None:
            self.sub_graph_encoder.reset_parameters()
        if self.graph_encoder is not None:
            self.graph_encoder.reset_parameters()

    def forward(self, obs: Union[Obs, GraphObs], **kwargs) -> Emb:
        """
        Args:
            obs: batched observation tuple

        Returns:
            emb: tuple of created embeddings
        """
        emb = Emb()
        if self.node_encoder is not None:
            emb = self.node_encoder(obs, emb, **kwargs)
        if self.sol_encoder is not None:
            emb = self.sol_encoder(obs, emb, **kwargs)
        if self.sub_graph_encoder is not None:
            emb = self.sub_graph_encoder(obs, emb, **kwargs)
        if self.graph_encoder is not None:
            emb = self.graph_encoder(obs, emb, **kwargs)
        return emb

# ============= #
# ### TEST #### #
# ============= #
def _test(
    problem: str = "TSP",
    bs: int = 3,
    size: int = 10,
    n: int = 20,
    seed: int = 1,
    n_steps: int = 20,
    mode='ACCEPT_LS',
    mode_args={'ls_op': 'TWO_OPT'},
    graph: bool = False,
    **kwargs
):
    import tianshou as ts
    from lib.env import VecEnv, RPGraphVecEnv

    env_kwargs = {
        'num_steps': n_steps,
        'sampling_args': {'sample_size': size, 'graph_size': n},
        'mode': mode,
        'mode_args': mode_args,
        'debug': False,
    }
    if graph:
        env_cl = RPGraphVecEnv
        train_envs = env_cl(num_envs=bs, problem=problem, env_kwargs=env_kwargs, create_nbh_graph=True)
        test_envs = env_cl(num_envs=bs, problem=problem, env_kwargs=env_kwargs, create_nbh_graph=True)
    else:
        env_cl = VecEnv
        train_envs = env_cl(num_envs=bs, problem=problem, env_kwargs=env_kwargs)
        test_envs = env_cl(num_envs=bs, problem=problem, env_kwargs=env_kwargs)

    train_envs.seed(seed)
    test_envs.seed(seed)

    net = Model(observation_space=train_envs.observation_space, action_space=train_envs.action_space)
    print(net)

    optim = net.get_optimizer()
    policy = ts.policy.DQNPolicy(net, optim, discount_factor=0.99, estimation_step=3, target_update_freq=256)

    train_collector = ts.data.Collector(
        policy, train_envs, ts.data.PrioritizedVectorReplayBuffer(20000, bs), exploration_noise=True
    )
    test_collector = ts.data.Collector(
        policy, test_envs, exploration_noise=False
    )

    result = ts.trainer.offpolicy_trainer(
        policy, train_collector, test_collector,
        max_epoch=2,
        step_per_epoch=200,
        step_per_collect=100,
        update_per_step=0.1,
        episode_per_test=100,
        batch_size=64,
        train_fn=lambda epoch, env_step: policy.set_eps(0.1),
        test_fn=lambda epoch, env_step: policy.set_eps(0.05),
    )
    print(result)


import timeit
import random

from timeit import Timer

def anagram_solution4(s1,s2):
    c1 = [0] * 26
    c2 = [0] * 26
    for i in range(len(s1)):
        pos = ord(s1[i]) - ord('a')
        c1[pos] = c1[pos] +1

    for i in range(len(s2)):
        pos = ord(s2[i])-ord('a')
        c2[pos] = c2[pos] +1

    j=0
    still_ok = True
    while j<26 and still_ok:
        if c1[j]==c2[j]:
            j=j+1
        else:
            still_ok =False
    return still_ok

print(anagram_solution4("python","ythonp"))

# 2n + 26 is linear solution because there are two for loops and 26 iterations in the while loop

# two commmon operations are idexing and assigning to an index position
# if it takes the same amount of time no matter how much data, O(1)
# to grow a list, you can append method or concatenate operator, concatenate by O(k) where k is size of list

# def test1 uses concatenation
# def test2 uses append
# def test3 uses list comprehension
# def test4 uses range

# call function you want to test
# t1 = Timer("test1()", "from __main__import test1")
# print("concat ", t1.timeit(number=1000), "milliseconds")

# pop on list end O(1) but on list front or aywhere else is O(n)

for i in range(10000,1000001,20000):
    t = timeit.Timer("random.randrange(%d) in x" % i, "from __main__ import random, x")
    print(t)

# stack is last in first out, the end is the top and beginning is the tail
# stack adt is defined by the following operations
# Stack() - takes no parameters, creates a new stack
# push(item) adds item to the top of the stack
# pop() returns and removes items from stack top
# peek() returns item at stack top but doesn't remove
# is_empty() returns whether stack is empty or not
# size() shows size of stack

class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self,item):
        self.items.append(item)

#   def push(self, item):
#       self.items.append(0,item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[-1]

    def size(self):
        return len(self.items)

s = Stack()

print(s.isEmpty())

s.push(6)
s.push("cat")
print(s.peek())
s.push(True)

print(s.size())
print(s.isEmpty)
s.push(8.4)

# stacks are useful to solve real problems
# processing of language constructs, simple balance paranetheses and balanced symbols
# convert decimal numbers to binary
# convert infix expression to prefix and postfix expressions and
# balances parentheses ask each opening symbol has according xlosing symbols and all parentheses are properly nested
# if symbol is open parenthesis, push it on stack
# if symbol is close, pop stack
# as long as pop and push are equal, equation is balanced
# balacned symbols problem is a more general situation arising in many programming languages
#

def par_checker(symbol_string):
    s=Stack()
    balanced = True
    index =0
    while index < len(symbol_string) and balanced:
        symbol = symbol_string[index]
        if symbol == "(":
            s.push(symbol)
        else:
            if s.isEmpty():
                balanced = False
            else:
                s.pop()
        index = index +1
    if balanced and s.isEmpty():
        return True
    else:
        return False

print(par_checker("()"))


import re
import urllib
import urllib.request

from urllib.parse import urlencode
from starlette.responses import RedirectResponse
from starlette.status import HTTP_303_SEE_OTHER

class SteamSignIn():

	_provider = 'https://steamcommunity.com/openid/login'

	def redirect_user(self, str_post_data):
		return RedirectResponse(
            url="{0}?{1}".format(self._provider, str_post_data),
		    status_code=HTTP_303_SEE_OTHER,
		    headers={'Content-Type': 'application/x-www-form-urlencoded'}
        )

	def construct_url(self, response_url):
		refinedScripts = re.search('(?:http)', response_url)

		if refinedScripts == None or refinedScripts.group(0) == None:
			response_url = "http://{0}".format(response_url)

		authParameters = {
			"openid.ns":"http://specs.openid.net/auth/2.0",
			"openid.mode": "checkid_setup",
			"openid.return_to": response_url,
			"openid.realm": response_url,
			"openid.identity": "http://specs.openid.net/auth/2.0/identifier_select",
			"openid.claimed_id": "http://specs.openid.net/auth/2.0/identifier_select"
		}

		return urlencode(authParameters)

	def validate_results(self, results):
		validationArgs ={
			'openid.assoc_handle': results['openid.assoc_handle'],
			'openid.signed': results['openid.signed'],
			'openid.sig' : results['openid.sig'],
			'openid.ns': results ['openid.ns']
		}

		signedArgs = results['openid.signed'].split(',')

		for item in signedArgs:
			itemArg = 'openid.{0}'.format(item)
			if results[itemArg] not in validationArgs:
				validationArgs[itemArg] = results[itemArg]

		validationArgs['openid.mode'] = 'check_authentication'
		parsedArgs = urlencode(validationArgs).encode("utf-8")

		with urllib.request.urlopen(self._provider, parsedArgs) as requestData:
			responseData = requestData.read().decode('utf-8')

		if re.search('is_valid:true', responseData):
			matched64ID = re.search('https://steamcommunity.com/openid/id/(\d+)', results['openid.claimed_id'])
			if matched64ID != None or matched64ID.group(1) != None:
				return matched64ID.group(1)
			else:
				return False
		else:
			return False


import os
from os.path import basename, dirname, curdir, abspath, isdir, isfile, exists, splitext, join as pjoin
import sys
import logging
import traceback
from subprocess import CalledProcessError

import flo
from flo.computation import Computation
from flo.builder import WorkflowNotReady
from timeutil import TimeInterval, datetime, timedelta
from flo.util import augmented_env

import sipsprod
from glutil import (
    check_call,
    #dawg_catalog,
    delivered_software,
    #support_software,
    runscript,
    prepare_env,
    #nc_gen,
    nc_compress,
    reraise_as,
    #set_official_product_metadata,
    FileNotFound
)
from flo.sw.hirs2nc.delta import DeltaCatalog

# every module should have a LOG object
LOG = logging.getLogger(__name__)

def set_input_sources(input_locations):
    global delta_catalog
    delta_catalog = DeltaCatalog(**input_locations)

class HIRS2NC(Computation):

    parameters = ['granule', 'satellite', 'hirs2nc_delivery_id']
    outputs = ['out']

    def find_contexts(self, time_interval, satellite, hirs2nc_delivery_id):

        global delta_catalog

        LOG.debug('delta_catalog.collection = {}'.format(delta_catalog.collection))
        LOG.debug('delta_catalog.input_data = {}'.format(delta_catalog.input_data))

        files = delta_catalog.files('hirs', satellite, 'HIR1B', time_interval)

        return [{'granule': file.data_interval.left,
                 'satellite': satellite,
                 'hirs2nc_delivery_id': hirs2nc_delivery_id}
                for file in files
                if file.data_interval.left >= time_interval.left]

    def satellite_version(self, satellite, granule):

        # 4 for everything post April 28, 2005
        if granule > datetime(2005, 4, 28):
            return 4
        # 3 for noaa-15,16,17 until April 28, 2005
        elif satellite in ['noaa-15', 'noaa-16', 'noaa-17']:
            return 3
        # 2 for noaa <= 14
        else:
            return 2

    @reraise_as(WorkflowNotReady, FileNotFound, prefix='NSS.HIRX')
    def build_task(self, context, task):
        '''
        Build up a set of inputs for a single context
        '''
        global delta_catalog

        sensor = 'hirs'
        satellite =  context['satellite']
        file_type = 'HIR1B'
        granule = context['granule']

        hirs_file = delta_catalog.file(sensor, satellite, file_type, granule)

        LOG.debug('data_interval = {}'.format(hirs_file.data_interval))

        task.input('HIR1B', hirs_file)
        task.option('data_interval', hirs_file.data_interval)

    @reraise_as(WorkflowNotReady, FileNotFound, prefix='NSS.HIRX')
    def run_task(self, inputs, context):

        LOG.debug("Running run_task()...")

        for key in context.keys():
            LOG.debug("run_task() context['{}'] = {}".format(key, context[key]))

        granule = context['granule']
        satellite = context['satellite']
        hirs2nc_delivery_id = context['hirs2nc_delivery_id']
        hirs_version = self.satellite_version(context['satellite'], context['granule'])

        # Get the location of the binary package
        delivery = delivered_software.lookup('hirs2nc', delivery_id=hirs2nc_delivery_id)
        dist_root = pjoin(delivery.path, 'dist')
        envroot = pjoin(dist_root, 'env')

        # Get the required  environment variables
        env = prepare_env([delivery])
        LOG.debug(env)

        # What is the path of the python interpreter
        py_interp = "{}/bin/python".format(envroot)
        LOG.debug("py_interp = '{}'".format(py_interp))

        # Path of the hirs2nc binary
        hirs2nc_bin = pjoin(envroot, 'bin', 'hirs2nc')

        # Where are we running the package
        work_dir = abspath(curdir)
        LOG.debug("working dir = {}".format(work_dir))

        input_file = inputs['HIR1B']
        output_file = pjoin(work_dir, basename('{}.nc'.format(inputs['HIR1B'])))
        LOG.debug("Input file = {}".format(input_file))
        LOG.debug("Output file = {}".format(output_file))

        # What are our inputs?
        for input in inputs.keys():
            inputs_dir = dirname(inputs[input])
            LOG.debug("inputs['{}'] = {}".format(input,inputs[input]))
        LOG.debug("Inputs dir = {}".format(inputs_dir))

        # Convert the flat HIRS file to NetCDF4
        cmd = '{} {} {} {} {}'.format(
                py_interp,
                hirs2nc_bin,
                hirs_version,
                input_file,
                output_file
                )
        try:
            LOG.debug("cmd = \\\n\t{}".format(cmd.replace(' ',' \\\n\t')))
            rc_hirs2nc = 0
            runscript(cmd, requirements=[], env=env)
        except CalledProcessError as err:
            rc_hirs2nc = err.returncode
            LOG.error("hirs2nc binary {} returned a value of {}".format(hirs2nc_bin, rc_hirs2nc))
            return rc_hirs2nc, []

        # The staging routine assumes that the output file is located in the work directory
        # "tmp******", and that the output path is to be prepended, so return the basename.
        output = basename('{}.nc'.format(inputs['HIR1B']))

        data_interval = context['data_interval']
        extra_attrs = {'begin_time': data_interval.left,
                       'end_time': data_interval.right}

        return {'out': {'file': nc_compress(output), 'extra_attrs': extra_attrs}}


from dataclasses import dataclass
from typing import Optional, Deque, Tuple
from collections import deque

@dataclass
class Instruction:
    command: str
    cycles: int = 1
    value: Optional[int] = None

def build_instruction_queue(input_filename: str) -> Tuple[Deque[Instruction], int]:
    """
    Builds a queue of instructions to execute. Also returns the total
    amount of CPU cycles to execute all of them, under the assumption that:
    - addx <V> takes two cycles to complete
    - noop takes one cycle to complete
    """
    cycle_count = 0
    instructions = deque()
    with open(input_filename, "r") as in_file:
        i = 0
        for line in in_file:
            split_instruction = line.strip().split(" ")
            if split_instruction[0] == "noop":
                instructions.append(Instruction(command="noop"))
                cycle_count += 1
            else:
                instructions.append(
                    Instruction(command=split_instruction[0], cycles=2, value=int(split_instruction[1]))
                )
                cycle_count += 2

    return instructions, cycle_count

instruction_queue, total_cycles = build_instruction_queue("../inputs/day_ten.txt")
x_register = 1
signal_strengths = []

for cycle in range(1, total_cycles+1):
    current_instruction = instruction_queue[0]

    if cycle == 20 or (cycle % 40 == 20):
        # The 20th cycle, or every 40 cycles after that is an "interesting value" to note,
        # and where we want to collect signal strength (cycle # * X register)
        signal_strengths.append(cycle * x_register)

    if current_instruction.command == "addx" and current_instruction.cycles == 1:
        # If we're running an add command and we only have a cycle left, this is the last cycle.
        # Make sure to actually modify the X register:
        x_register += current_instruction.value

    current_instruction.cycles -= 1
    if current_instruction.cycles == 0:
        # If this was our last cycle for this instruction, pop it off so we move on to the next
        # instruction in the queue on the next iteration.
        instruction_queue.popleft()

print(sum(signal_strengths))


from rest_framework import viewsets
from rest_framework import  filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.authentication import SessionAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
from django.core import  exceptions
from django.db.models import Q
from rest_framework.mixins import (CreateModelMixin,
                                   ListModelMixin,
                                   RetrieveModelMixin,
                                   UpdateModelMixin,
                                   )
from apps.warehouse.serializes.basicinfor_serialize import *
from apps.warehouse.filters.basicinfor_filters import *
from apps.commonFunction import StandardResultsSetPagination ,IsOwnerOrReadOnly ,viewMiddleException

class WarehouseAuditRecordView(ListModelMixin,RetrieveModelMixin, viewsets.GenericViewSet):
    """
    当前APP操作记录
    """
    pagination_class = StandardResultsSetPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    filter_class = WarehouseAuditRecordFilters
    search_fields = ["uri", "uri_id"]
    ordering_fields = ["id","update_time"]
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication, IsOwnerOrReadOnly]
    permission_classes = [IsAuthenticated, ]

    # 重载获取序列化类的方法，根据不同的操作返回不同的序列化类
    def get_serializer_class(self):
        if self.action == "list":
            return WarehouseAuditRecordSerialize_List
        elif self.action == "retrieve":
            return WarehouseAuditRecordSerialize_Retrieve
        return WarehouseAuditRecordSerialize_List

    # 重载数据查询的方法，根据不同的操作查询不同的数据范围
    def get_queryset(self):
            if self.request.user.is_superuser:     # 超级用户可以查看所有信息
                return WarehouseAuditRecordModel.objects.all().order_by("-id")
            user = self.request.user.username
            condtions1 = {'user__iexact': user}     # 普通用户只能查看自己的信息
            if self.action == "list":  # 如果是查看列表
                if not self.request.user.has_perm('warehouse.view_warehouseauditrecordmodel'):  # 如果当前用户没有查看权限
                    raise exceptions.PermissionDenied
            if self.action == "retrieve":  # 如果是查看详情
                if not self.request.user.has_perm('warehouse.read_warehouseauditrecordmodel'):  # 如果当前用户没有查看详情权限
                    raise exceptions.PermissionDenied
            return WarehouseAuditRecordModel.objects.filter(Q(**condtions1))

class WarehouseAlterRecordView(CreateModelMixin, viewsets.GenericViewSet):
    """
    当前APP审核记录
    """
    queryset = WarehouseAlterRecordModel.objects.all().order_by("-id")
    serializer_class = WarehouseAlterRecordSerialize_Create
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication, IsOwnerOrReadOnly]
    permission_classes = [IsAuthenticated, ]

class WarehouseImageView(CreateModelMixin,viewsets.GenericViewSet):
    """
     当前APP图片项
    """
    queryset = WarehouseImageModel.objects.all().order_by("-id")
    serializer_class = WarehouseImageSerialize_Create
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication, IsOwnerOrReadOnly]
    permission_classes = [IsAuthenticated, ]

class WarehouseFileView(CreateModelMixin, viewsets.GenericViewSet):
    """
    当前APP文件项
    """
    queryset = WarehouseFileModel.objects.all().order_by("-id")
    serializer_class = WarehouseFileSerialize_Create
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication, IsOwnerOrReadOnly]
    permission_classes = [IsAuthenticated, ]

class WarehouseDefinitionView(CreateModelMixin, ListModelMixin,
                              RetrieveModelMixin, UpdateModelMixin,
                              viewsets.GenericViewSet):
    """
    仓库信息定义
    """
    pagination_class = StandardResultsSetPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter,filters.OrderingFilter)
    filter_class = WarehouseDefinitionFilters
    search_fields = ["name","code","affiliation","location","principal"]
    ordering_fields = ["id","update_time","position_sum"]
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication, IsOwnerOrReadOnly]
    permission_classes = [IsAuthenticated, ]

    #重载获取序列化类的方法，根据不同的操作返回不同的序列化类
    def get_serializer_class(self):
        if self.action == "create":
            return WarehouseDefinitionSerialize_Create
        elif self.action == "list":
            return WarehouseDefinitionSerialize_List
        elif self.action == "retrieve":
            return WarehouseDefinitionSerialize_Retrieve
        elif self.action == "update":
            return  WarehouseDefinitionSerialize_Update
        elif self.action == "partial_update":
            return WarehouseDefinitionSerialize_Partial
        return WarehouseDefinitionSerialize_List

    # 重查询的方法，根据不同的操作查询不同的数据范围载数据
    def get_queryset(self):
        if self.request.user.is_superuser:
            return WarehouseDefinitionModel.objects.all().order_by("-id")   # 超级用户可以查看所有信息
        user = self.request.user.username
        condtions1 = {'create_user__iexact': user,
                      'state__in': ("新建", "审核中", "使用中")  # 信息创建者可以看到 (新建,审核,使用中)的数据,,
                      }
        condtions2 = {'auditor__iexact': user,
                      'state__in': ("审核中", "使用中",)  # 信息审核者可以看到 (审核,使用中)的数据
                      }
        condtions3 = {'state__in': ("使用中",)  # 所有用户 可以看到(使用中)的数据
                      }
        if self.action == "list":   # 如果是查看列表
             if  not self.request.user.has_perm('warehouse.view_warehousedefinitionmodel'):    # 如果当前用户没有查看权限
                 condtions3={}       #如果普通用户不具备查看列表权限权限,则不能查看列表信息
        if self.action == "retrieve":   # 如果是查看列表
             if  not self.request.user.has_perm('warehouse.read_warehousedefinitionmodel'):    # 如果当前用户没有查看详情权限
                 condtions3 = {}  #如果普通用户不具备查看详情权限,则不能查看详情信息
        if self.action == "update":  # 如果是更新列表
            condtions2 = {}
            condtions3 = {}  # 只有创建者可以更新
        if self.action == "partial_update":  # 如果是部分更新列表
            condtions3 = {}  # 只有创建者跟审核者可以部分更新
        return WarehouseDefinitionModel.objects.filter(Q(**condtions1) | Q(**condtions2)|Q(**condtions3))

class WarehouseDefinitionViews(ListModelMixin,viewsets.GenericViewSet):
    """
    仓库层级结构
    """
    serializer_class = WarehouseDefinitionSerialize_First
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]
    def get_queryset(self):
        if (self.request.user.is_superuser or self.request.user.has_perm('warehouse.view_warehousedefinitionmodel')):
            return WarehouseDefinitionModel.objects.filter(classes="一级类别")
        else:
            raise exceptions.PermissionDenied

class PositionDefinitionView(CreateModelMixin, ListModelMixin,
                             RetrieveModelMixin, UpdateModelMixin,
                            viewsets.GenericViewSet):
    """
    仓位信息定义
    """
    pagination_class = StandardResultsSetPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter,filters.OrderingFilter)
    filter_class = PositionDefinitionFilters
    search_fields = ["name","code","place"]
    ordering_fields=["id","update_time","maximum"]
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication,IsOwnerOrReadOnly ]
    permission_classes = [IsAuthenticated, ]

    #重载获取序列化类的方法，根据不同的操作返回不同的序列化类
    def get_serializer_class(self):
        if self.action == "create":
            return PositionDefinitionSerialize_Create
        elif self.action == "list":
            return PositionDefinitionSerialize_List
        elif self.action == "retrieve":
            return PositionDefinitionSerialize_Retrieve
        elif self.action == "update":
            return PositionDefinitionSerialize_Update
        elif self.action == "partial_update":
            return PositionDefinitionSerialize_Partial
        return PositionDefinitionSerialize_List

    # 重载数据查询的方法，根据不同的操作查询不同的数据范围
    def get_queryset(self):
        if self.request.user.is_superuser:
            return PositionDefinitionModel.objects.all().order_by("-id") # 超级用户可以查看所有信息
        user = self.request.user.username
        condtions1 = {'create_user__iexact': user,
                      'state__in': ("新建", "审核中","闲置", "使用中")  # 信息创建者可以看到 (新建,审核,使用中)的数据,,
                      }
        condtions2 = {'auditor__iexact': user,
                      'state__in': ("审核中","闲置", "使用中",)  # 信息审核者可以看到 (审核,使用中)的数据
                      }
        condtions3 = {'state__in': ("使用中","闲置")  # 其他用户 可以看到(使用中)的数据
                      }
        if self.action == "list":  # 如果是查看列表
            if not self.request.user.has_perm('warehouse.view_positiondefinitionmodel'):  # 如果当前用户没有查看权限
                condtions3 = {}  #如果普通用户不具备查看列表权限权限,则不能查看列表信息
        if self.action == "retrieve":  # 如果是查看列表
            if not self.request.user.has_perm('warehouse.read_positiondefinitionmodel'):  # 如果当前用户没有查看详情权限
                condtions3 = {} #如果普通用户不具备查看详情权限,则不能查看详情信息
        if self.action == "update":  # 如果是更新列表
            condtions2 = {}
            condtions3 = {}  # 只有创建者可以更新
        if self.action == "partial_update":  # 如果是部分更新列表
            condtions3 = {}  # 只有创建者跟审核者可以部分更新
        return PositionDefinitionModel.objects.filter(Q(**condtions1) | Q(**condtions2) | Q(**condtions3)).order_by("-id").order_by("-id")

class WarehouseBoardView(CreateModelMixin, ListModelMixin,
                           RetrieveModelMixin, UpdateModelMixin,
                          viewsets.GenericViewSet):
    """
    仓库看板定义
    """
    pagination_class = StandardResultsSetPagination
    filter_backends = (DjangoFilterBackend, filters.SearchFilter,filters.OrderingFilter)
    filter_class =WarehouseBoardFilters
    search_fields = ["name","code"]
    ordering_fields = ["id","update_time"]
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication,]
    permission_classes = [IsAuthenticated, ]

    # 重载获取序列化类的方法，根据不同的操作返回不同的序列化类
    def get_serializer_class(self):
        if self.action == "create":
            return WarehouseBoardSerialize_Create
        elif self.action == "list":
            return WarehouseBoardSerialize_List
        elif self.action == "retrieve":
            return WarehouseBoardSerialize_Retrieve
        elif self.action == "update":
            return WarehouseBoardSerialize_Update
        elif self.action == "partial_update":
            return WarehouseBoardSerialize_Partial
        return WarehouseBoardSerialize_List

    # 重载数据查询的方法，根据不同的操作查询不同的数据范围
    def get_queryset(self):
        if self.request.user.is_superuser:
            return WarehouseBoardModel.objects.all().order_by("-id")  # 超级用户可以查看所有信息
        user = self.request.user.username
        condtions1 = {'create_user__iexact': user,
                      'state__in': ("新建", "审核中", "使用中")  # 信息创建者可以看到 (新建,审核,使用中)的数据,,
                      }
        condtions2 = {'auditor__iexact': user,
                      'state__in': ("审核中", "使用中",)  # 信息审核者可以看到 (审核,使用中)的数据
                      }
        condtions3 = {'state__in': ("使用中",)  # 其他用户 可以看到(使用中)的数据
                      }
        if self.action == "list":  # 如果是查看列表
            if not self.request.user.has_perm('warehouse.view_warehouseboardmodel'):  # 如果当前用户没有查看权限
                condtions3 = {}  #如果普通用户不具备查看列表权限权限,则不能查看列表信息
        if self.action == "retrieve":  # 如果是查看列表
            if not self.request.user.has_perm('warehouse.read_warehouseboardmodel'):  # 如果当前用户没有查看详情权限
                condtions3 = {} #如果普通用户不具备查看详情权限,则不能查看详情信息
        if self.action == "update":  # 如果是更新列表
            condtions2 = {}
            condtions3 = {}  # 只有创建者可以更新
        if self.action == "partial_update":  # 如果是部分更新列表
            condtions3 = {}  # 只有创建者跟审核者可以部分更新
        return WarehouseBoardModel.objects.filter(Q(**condtions1) | Q(**condtions2) | Q(**condtions3)).order_by("-id")


from democli.utils.log_util import create_logger

logger = create_logger(__name__)

# quit on error
def quit_on_error(message=None, exception=None):
    if message:
        logger.error(str(message))
    if exception:
        raise exception
    else:
        logger.debug("Exiting with code 1..")
        exit(1)

def encode_for_display(text):
    """
    Encodes strings so they can display as ASCII in a Windows terminal window.
    This function also encodes strings for processing by xml.etree.ElementTree functions.

    Returns an ASCII-encoded version of the text.
    Unicode characters are converted to ASCII placeholders (for example, "?").
    """
    return text.encode('ascii', errors="backslashreplace").decode('utf-8')


"""
Assorted utilities for working with neural networks in AllenNLP.
"""
from collections import defaultdict
from typing import Dict, List, Optional, Any, Tuple, Callable
import logging
import itertools
import math
import torch
from torch.autograd import Variable

def get_lengths_from_binary_sequence_mask(mask: torch.Tensor):
    """
    Compute sequence lengths for each batch element in a tensor using a
    binary mask.
    Parameters
    ----------
    mask : torch.Tensor, required.
        A 2D binary mask of shape (batch_size, sequence_length) to
        calculate the per-batch sequence lengths from.
    Returns
    -------
    A torch.LongTensor of shape (batch_size,) representing the lengths
    of the sequences in the batch.
    """
    return mask.long().sum(-1)

def sort_batch_by_length(tensor: torch.autograd.Variable,
                         sequence_lengths: torch.autograd.Variable):
    """
    Sort a batch first tensor by some specified lengths.
    Parameters
    ----------
    tensor : Variable(torch.FloatTensor), required.
        A batch first Pytorch tensor.
    sequence_lengths : Variable(torch.LongTensor), required.
        A tensor representing the lengths of some dimension of the tensor which
        we want to sort by.
    Returns
    -------
    sorted_tensor : Variable(torch.FloatTensor)
        The original tensor sorted along the batch dimension with respect to sequence_lengths.
    sorted_sequence_lengths : Variable(torch.LongTensor)
        The original sequence_lengths sorted by decreasing size.
    restoration_indices : Variable(torch.LongTensor)
        Indices into the sorted_tensor such that
        ``sorted_tensor.index_select(0, restoration_indices) == original_tensor``
    permuation_index : Variable(torch.LongTensor)
        The indices used to sort the tensor. This is useful if you want to sort many
        tensors using the same ordering.
    """

    if not isinstance(tensor, Variable) or not isinstance(sequence_lengths, Variable):
        raise Exception("Both the tensor and sequence lengths must be torch.autograd.Variables.")

    sorted_sequence_lengths, permutation_index = sequence_lengths.sort(0, descending=True)
    sorted_tensor = tensor.index_select(0, permutation_index)

    # This is ugly, but required - we are creating a new variable at runtime, so we
    # must ensure it has the correct CUDA vs non-CUDA type. We do this by cloning and
    # refilling one of the inputs to the function.
    index_range = sequence_lengths.data.clone().copy_(torch.arange(0, len(sequence_lengths)))
    # This is the equivalent of zipping with index, sorting by the original
    # sequence lengths and returning the now sorted indices.
    index_range = Variable(index_range.long())
    _, reverse_mapping = permutation_index.sort(0, descending=False)
    restoration_indices = index_range.index_select(0, reverse_mapping)
    return sorted_tensor, sorted_sequence_lengths, restoration_indices, permutation_index

def get_final_encoder_states(encoder_outputs: torch.Tensor,
                             mask: torch.Tensor,
                             bidirectional: bool = False) -> torch.Tensor:
    """
    Given the output from a ``Seq2SeqEncoder``, with shape ``(batch_size, sequence_length,
    encoding_dim)``, this method returns the final hidden state for each element of the batch,
    giving a tensor of shape ``(batch_size, encoding_dim)``.  This is not as simple as
    ``encoder_outputs[:, -1]``, because the sequences could have different lengths.  We use the
    mask (which has shape ``(batch_size, sequence_length)``) to find the final state for each batch
    instance.
    Additionally, if ``bidirectional`` is ``True``, we will split the final dimension of the
    ``encoder_outputs`` into two and assume that the first half is for the forward direction of the
    encoder and the second half is for the backward direction.  We will concatenate the last state
    for each encoder dimension, giving ``encoder_outputs[:, -1, :encoding_dim/2]`` concated with
    ``encoder_outputs[:, 0, encoding_dim/2:]``.
    """
    # These are the indices of the last words in the sequences (i.e. length sans padding - 1).  We
    # are assuming sequences are right padded.
    # Shape: (batch_size,)
    last_word_indices = mask.sum(1).long() - 1
    batch_size, _, encoder_output_dim = encoder_outputs.size()
    expanded_indices = last_word_indices.view(-1, 1, 1).expand(batch_size, 1, encoder_output_dim)
    # Shape: (batch_size, 1, encoder_output_dim)
    final_encoder_output = encoder_outputs.gather(1, expanded_indices)
    final_encoder_output = final_encoder_output.squeeze(1)  # (batch_size, encoder_output_dim)
    if bidirectional:
        final_forward_output = final_encoder_output[:, :(encoder_output_dim // 2)]
        final_backward_output = encoder_outputs[:, 0, (encoder_output_dim // 2):]
        final_encoder_output = torch.cat([final_forward_output, final_backward_output], dim=-1)
    return final_encoder_output

def get_dropout_mask(dropout_probability: float, tensor_for_masking: torch.autograd.Variable):
    """
    Computes and returns an element-wise dropout mask for a given tensor, where
    each element in the mask is dropped out with probability dropout_probability.
    Note that the mask is NOT applied to the tensor - the tensor is passed to retain
    the correct CUDA tensor type for the mask.
    Parameters
    ----------
    dropout_probability : float, required.
        Probability of dropping a dimension of the input.
    tensor_for_masking : torch.Variable, required.
    Returns
    -------
    A torch.FloatTensor consisting of the binary mask scaled by 1/ (1 - dropout_probability).
    This scaling ensures expected values and variances of the output of applying this mask
     and the original tensor are the same.
    """
    binary_mask = tensor_for_masking.clone()
    binary_mask.data.copy_(torch.rand(tensor_for_masking.size()) > dropout_probability)
    # Scale mask by 1/keep_prob to preserve output statistics.
    dropout_mask = binary_mask.float().div(1.0 - dropout_probability)
    return dropout_mask

def block_orthogonal(tensor: torch.Tensor,
                     split_sizes: List[int],
                     gain: float = 1.0) -> None:
        """
        An initializer which allows initializing model parameters in "blocks". This is helpful
        in the case of recurrent models which use multiple gates applied to linear projections,
        which can be computed efficiently if they are concatenated together. However, they are
        separate parameters which should be initialized independently.
        Parameters
        ----------
        tensor : ``torch.Tensor``, required.
            A tensor to initialize.
        split_sizes : List[int], required.
            A list of length ``tensor.ndim()`` specifying the size of the
            blocks along that particular dimension. E.g. ``[10, 20]`` would
            result in the tensor being split into chunks of size 10 along the
            first dimension and 20 along the second.
        gain : float, optional (default = 1.0)
            The gain (scaling) applied to the orthogonal initialization.
        """

        if isinstance(tensor, Variable):
        # in pytorch 4.0, Variable equals Tensor
        #    block_orthogonal(tensor.data, split_sizes, gain)
        #else:
            sizes = list(tensor.size())
            if any([a % b != 0 for a, b in zip(sizes, split_sizes)]):
                raise ConfigurationError("tensor dimensions must be divisible by their respective "
                                         "split_sizes. Found size: {} and split_sizes: {}".format(sizes, split_sizes))
            indexes = [list(range(0, max_size, split))
                       for max_size, split in zip(sizes, split_sizes)]
            # Iterate over all possible blocks within the tensor.
            for block_start_indices in itertools.product(*indexes):
                # A list of tuples containing the index to start at for this block
                # and the appropriate step size (i.e split_size[i] for dimension i).
                index_and_step_tuples = zip(block_start_indices, split_sizes)
                # This is a tuple of slices corresponding to:
                # tensor[index: index + step_size, ...]. This is
                # required because we could have an arbitrary number
                # of dimensions. The actual slices we need are the
                # start_index: start_index + step for each dimension in the tensor.
                block_slice = tuple([slice(start_index, start_index + step)
                                     for start_index, step in index_and_step_tuples])
                tensor[block_slice] = torch.nn.init.orthogonal_(tensor[block_slice].contiguous(), gain=gain)


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

"""
__author__ = "Loic Renversade, CRG-IF BM32 @ ESRF"
__version__ = '$Revision$'

import numpy as np
import scipy.signal as sps

import matplotlib.pylab as mplp

from LaueTools.Daxm.classes.calibration.generic import Calib, CalibError

class CalibFluo(Calib):

    def __init__(self, scan, sample, verbose=True):
        Calib.__init__(self, scan, sample, verbose)

        self.print_msg(" > for fluorescence-based calibration.")

        self.grid_dim = None

        Calib.init(self)

    # Set calibration points from grid
    def set_points_grid(self, dims=None, halfboxsize=None, adjust=True):

        if dims is None:
            dims = [2, 2]

        if halfboxsize is None:
            halfboxsize = [2, 0]

        self.grid_dim = dims

        XYcam = self.gen_wires_points(dims, method="grid", adjust=adjust)

        print('XYcam',XYcam)
        print(halfboxsize)

        self.set_points(XYcam, halfboxsize)

    # Calibration points
    def gen_wires_points(self, dims=None, method='grid', adjust=True):

        if dims is None:
            dims = [2, 2]

        self.print_msg("- Generating calibration points...")

        XYcam = []

        for wid in range(self.scan.wire_qty):
            XYcam.append(self.gen_wire_points(wid, dims, method, adjust))

        return XYcam

    def gen_wire_points(self, wire, dims=None, method='grid', adjust=True):

        if dims is None:
            dims = [2, 2]

        self.print_msg(" > Wire {:d}:", (wire,))

        if method == 'grid':

            XYcam = self.gen_points_grid(wire, dims, adjust)

        else:

            self.print_msg("Unknown method to generate calibration points: '{}'", (method,), "F")

        # depends method
        return XYcam

    def gen_points_grid(self, wire, dims, adjust=False):

        # initial regular grid according to dims
        self.print_msg("   regular {}x{} grid", dims)

        XYcam = gen_grid([0, self.scan.get_img_params(['framedim'])[0]],
                         self.scan.calc_wire_range_scan_int(wire), dims)

        # TODO: optimize calibration grid according to image and delta
        if adjust:
            self.print_msg("   auto-adjusting to avoid peaks.")

            dX = int(1. / 3 * self.scan.get_img_params(['framedim'])[0] / self.grid_dim[0])

            XYcam = adjust_grid(XYcam, self.scan.get_image(0), self.data_hbs, dX)

        return XYcam

    # solver
    def run_init(self):

        self.print_msg("- preparing sample...")
        self.run_init_sample()

        Calib.run_init(self)

    def run_init_sample(self):

        # fluo src
        src_I, self.src_y, src_E, _ = self.model_src.get_source_fluo()

        # for consistency, duplicate for each point
        self.src_I, self.src_E = [], []
        for _ in range(self.data_qty):
            self.src_I.append(src_I)
            self.src_E.append(src_E)

        self.src_I = np.array(self.src_I)
        self.src_E = np.array(self.src_E)

    # plots
    def plot_exp_wire(self, wid):

        fig, axarr = mplp.subplots(self.grid_dim[1], self.grid_dim[0], sharex=True, sharey=True, squeeze=False)

        k = 0

        for i in range(self.grid_dim[1]):

            for j in range(self.grid_dim[0]):

                axarr[i, j].plot(self.data_pw[wid][k], self.data_I[wid][k], 'r-o', linewidth=1.5)

                if j == 0:
                    axarr[i, j].set_ylabel('Intensity', fontsize=14)

                if i == self.grid_dim[1] - 1:
                    axarr[i, j].set_xlabel('Wire motor (mm)', fontsize=14)

                axarr[i, j].annotate(self.data_XYcam[wid][k], xy=(1, 0), xycoords='axes fraction',
                                     xytext=(0.975, 0.025), textcoords='axes fraction',
                                     horizontalalignment='right', verticalalignment='bottom')
                k = k + 1

        fig.suptitle('Experimental profiles of wire #{}'.format(wid + 1), fontsize=16)

    def plot_calib_wire(self, wid, sim_I):

        fig, axarr = mplp.subplots(self.grid_dim[1], self.grid_dim[0], sharex=True, sharey=True, squeeze=False)

        k = 0

        for i in range(self.grid_dim[1]):

            for j in range(self.grid_dim[0]):

                axarr[i, j].plot(self.data_pw[wid][k], self.data_I[wid][k], 'r-o', linewidth=1.5)

                axarr[i, j].plot(self.data_pw[wid][k], sim_I[k], 'k', linewidth=1.5)

                if j == 0:
                    axarr[i, j].set_ylabel('Intensity', fontsize=14)

                if i == self.grid_dim[1] - 1:
                    axarr[i, j].set_xlabel('Wire motor (mm)', fontsize=14)

                axarr[i, j].annotate(self.data_XYcam[wid][k], xy=(1, 0), xycoords='axes fraction',
                                     xytext=(0.975, 0.025), textcoords='axes fraction',
                                     horizontalalignment='right', verticalalignment='bottom')
                k = k + 1

        fig.suptitle('Calibration results: experimental vs simulated profiles of wire #{}'.format(wid + 1), fontsize=16)

# Calibration grids
def gen_grid(x_limits, y_limits, dims):
    x0, xf = [int(x) for x in x_limits]
    y0, yf = [int(y) for y in y_limits]

    # initial regular grid according to dims
    xp = np.linspace(x0, xf, num=dims[0] + 2)
    yp = np.linspace(y0, yf, num=dims[1] + 2)

    xy_grid = [[int(x), int(y)] for y in yp[1:-1] for x in xp[1:-1]]

    return xy_grid

def adjust_grid(xy_grid, img_ref, halfboxsize=None, margin=5):
    if halfboxsize is None:
        halfboxsize = [5, 0]

    meanfilter = np.ones([2 * d + 1 for d in halfboxsize])

    I0m = sps.convolve2d(img_ref, meanfilter, mode='same', boundary="symm")

    res = []

    for x, y in xy_grid:
        kx = np.argmin(I0m[(x - margin):(x + margin + 1), y])

        res.append([x - margin + kx, y])

    return res


import os
import os.path
import sys
import json
import datetime
import time
import logging
import logging.handlers
import urllib.parse
import xmltodict
import requests
import argparse
import multiprocessing

from orderedattrdict import AttrDict

from lib_log import log

# ----- start of configuration ------------------------------------------------

BASE_URL = 'http://192.168.8.1'
COOKIE_URL = '/html/index.html'

# ----- Helper functions -----------------------------------------------------

datetime_str_format = "%Y-%m-%d %H:%M:%S"

def now_dt():
    return datetime.datetime.now().replace(microsecond=0)

def now_str():
    return now_dt().strftime(datetime_str_format)

class Task:
    def __init__(self, action=None):
        self.action = action

class USB_modem:
    """
    Manage the USB modem via hilink

    Starts a background process, which does all communication with the  modem.
    This serializes all communication with the modem
    """

    def __init__(self):
        self.session = requests.Session()

        self.task_queue = multiprocessing.Queue()       # Tasks to worker
        self.result_queue = multiprocessing.Queue()     # Tasks from worker
        self.p = multiprocessing.Process(target=self.background_worker, args=(self.task_queue, self.result_queue))
        self.p.start()

    # ----------------------------------------------------------------------
    # Here is all background process and helper functions
    # ----------------------------------------------------------------------

    def background_worker(self, task_queue, result_queue):
        """
        This method is running as a separate process
        """
        r = self.session.get(BASE_URL + COOKIE_URL)
        # except requests.exceptions.ConnectionError as err:

        while True:
            task = task_queue.get()

            res = Task(action='result')
            if task.action == 'list_received_sms':
                messages = self.b_get_sms_list()
                res.messages = messages
                self.result_queue.put(res)

            elif task.action == 'list_sent_sms':
                messages = self.b_get_sms_list(outbox=True)
                res.messages = messages
                self.result_queue.put(res)

            elif task.action == 'send_sms':

                # delete any lingering SMS in outbox
                while True:
                    messages = self.b_get_sms_list(outbox=True)
                    if len(messages):
                        for message in messages:
                            self.b_delete_sms(message.Index)
                    else:
                        break

                # send SMS
                res.index = -1
                self.b_send_sms(numbers=task.numbers, text=task.text)

                # list SMS in outbox.
                # It takes some time until the sent message is visible
                # in the outbox. Wait for it
                for i in range(0,5):
                    time.sleep(1)
                    messages = self.b_get_sms_list(outbox=True)

                if len(messages):
                    res.index = messages[0].Index
                    if len(messages) > 1:
                        log.warning("After SMS sent, more than one message in outbox")

                    # delete sms in outbox
                    self.b_delete_sms(res.index)
                else:
                    log.error("Sent SMS was not stored in outbox")

                self.result_queue.put(res)

            elif task.action == 'receive_sms':
                self.result_queue.put(res)

            elif task.action == 'delete_sms':
                index = task.index
                r = self.b_delete_sms(index)
                self.result_queue.put(res)

            elif task.action == 'stop':
                print("Ending background process")
                self.result_queue.put(res)
                return  # this quits the background process

            else:
                print("Unknown task: %s" % task.action)

    def b_get_session(self):
        """
        All communication with the USB modem needs a valid session
        """
        session_token = xmltodict.parse(self.session.get(BASE_URL +\
            "/api/webserver/SesTokInfo").text).get('response',None)
        session = session_token.get("SesInfo")  #cookie
        token = session_token.get("TokInfo")    #token
        return session, token

    def b_get_sms_list(self, outbox=False):
        """
        Return a list with up to 10 received SMSes
        """
        session, token = self.b_get_session()
        headers = {
            'Cookie': session,
            '__RequestVerificationToken': token,
            'charset'        : 'UTF-8',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            }

        if outbox:
            boxtype = '2'
        else:
            boxtype = '1'

        api_url = BASE_URL + "/api/sms/sms-list"
        post_data =  b""
        post_data += b'<?xml version="1.0" encoding="UTF-8"?>\n'
        post_data += b"<request>\n"
        post_data += b"  <PageIndex>1</PageIndex>\n"
        post_data += b"  <ReadCount>10</ReadCount>\n"
        post_data += b"  <BoxType>%s</BoxType>" % boxtype.encode()
        post_data += b"  <SortType>0</SortType>"
        post_data += b"  <Ascending>0</Ascending>"
        post_data += b"  <UnreadPreferred>0</UnreadPreferred>"
        post_data += b"</request>\n"

        ret = self.session.post(url=api_url, data=post_data, headers=headers).text
        data = xmltodict.parse(ret)

        ret_messages = []

        if 'Messages' in data['response']:
            messages = data['response']['Messages']
            if messages is not None:
                message_list = messages['Message']

                # If we only have one message, it is not returned as a list
                # so it cannot be iterated over, convert to list.
                if not isinstance(message_list, list):
                    message_list = [ message_list ]

                for message in message_list:
                    if message['SmsType'] == '1':
                        msg = AttrDict()
                        for attr in ['Index', 'Phone', 'SmsType', 'Content']:
                            msg[attr] = message[attr]
                        if msg['Content'] is None:
                            msg['Content'] = ' '
                        msg['Content'] = msg['Content'].encode('latin1').decode('utf8', 'ignore')
                        ret_messages.append(msg)
                        print(msg)

        return ret_messages

    def b_delete_sms(self, index):
        """
        Delete a SMS from the modem.
        """
        log.info("Delete SMS with index %s" % index)
        session, token = self.b_get_session()
        headers = {
            'Cookie': session,
            '__RequestVerificationToken': token,
            }
        api_url = BASE_URL + "/api/sms/delete-sms"
        post_data = b""
        post_data += b'<?xml version="1.0" encoding="UTF-8"?>\n'
        post_data += b"<request>\n"
        post_data += b"  <Index>%s</Index>\n" % str(index).encode()
        post_data += b"</request>\n"
        ret = self.session.post(url=api_url, data=post_data, headers=headers).text
        data = xmltodict.parse(ret)
        return data

    def b_send_sms(self, numbers=None, text=None):
        log.info("Sending SMS, numbers: %s  Text: %s" % ( ",".join(numbers), text))
        session, token = self.b_get_session()
        api_url = BASE_URL + "/api/sms/send-sms"
        length = str(len(text))
        headers = {
            'Cookie': session,
            '__RequestVerificationToken': token,
             "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"
            }

        # Build XML structure
        post_data = b""
        post_data += b'<?xml version="1.0" encoding="UTF-8"?>\n'
        post_data += b"<request>\n"
        post_data += b"  <Index>-1</Index>\n"
        post_data += b"  <Phones>\n"
        for number in numbers:
            post_data += b"    <Phone>%s</Phone>\n" % number.encode()
        post_data += b"  </Phones>\n"
        post_data += b"  <Sca></Sca>\n"
        post_data += b"  <Content>%s</Content>\n" % text.encode()
        post_data += b"  <Length>%s</Length>\n" % length.encode()
        post_data += b"  <Reserved>1</Reserved>\n"
        post_data += b"  <Date>%s</Date>\n" % now_str().encode()
        post_data += b"</request>\n"

        ret = self.session.post(url=api_url, data=post_data, headers=headers).text
        return xmltodict.parse(ret)

    # ----------------------------------------------------------------------
    # End of background process and helper functions
    # ----------------------------------------------------------------------

    def list_received_sms(self):
        m = Task(action='list_received_sms')
        self.task_queue.put(m)
        task = self.result_queue.get()
        return task.messages

    def list_sent_sms(self):
        t = Task(action='list_sent_sms')
        self.task_queue.put(t)
        task = self.result_queue.get()
        return task.messages

    def send_sms(self, numbers, text):
        t = Task(action='send_sms')
        t.numbers = numbers
        t.text = text
        self.task_queue.put(t)
        task = self.result_queue.get()
        return task.index

    def receive_sms(self, index):
        t = Task(action='receive_sms')
        t.index = index
        self.task_queue.put(t)
        task = self.result_queue.get()

    def delete_sms(self, index):
        t = Task(action='delete_sms')
        t.index = index
        self.task_queue.put(t)
        task = self.result_queue.get()
        # return task.status

    def stop(self):
        t = Task(action='stop')
        self.task_queue.put(t)

def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("--cmd",
                        required=True,
                        choices = ['list_received_sms',
                                   'list_sent_sms',
                                   'send_sms',
                                   'receive_sms',
                                   'delete_sms',
                                   ])
    parser.add_argument("--number")
    parser.add_argument("--text")
    parser.add_argument("--index", type=int, default=None)

    args = parser.parse_args()

    usb_modem = USB_modem()

    if args.cmd == 'list_received_sms':
        messages = usb_modem.list_received_sms()
        if len(messages):
            for message in messages:
                print(message)
        else:
            print("No messages received")

    elif args.cmd == 'list_sent_sms':
        messages = usb_modem.list_sent_sms()
        if len(messages):
            for message in messages:
                print(message)
        else:
            print("No messages received")

    elif args.cmd == 'send_sms':
        if not args.number:
            print("Please specify number")
            sys.exit(1)
        if not args.text:
            print("Please specify text to be sent")
            sys.exit(1)

        index = usb_modem.send_sms([args.number], args.text)
        print("index %s" % index)

    elif args.cmd == 'receive_sms':
        pass

    elif args.cmd == 'delete_sms':
        if not args.index:
            print('Please specify index')
            sys.exit(1)
        usb_modem.delete_sms(args.index)

    else:
        print("Error: Unknown command %s" % args.cmd)
        sys.exit(1)

    usb_modem.stop()

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""
Created on Thu Mar 19 12:28:00 2020
ERA-Interim - api request
@author: Michael Tadesse
"""
import os

os.chdir('D:\\data\\era_interim\\era_interm_scripts')

#param: "228.128" == prcp
#param: "34.128" == sst
#param: "151.128" == mean sea level pressure
#date foremat: "1900-01-01/to/1900-01-31"

var_name = {"34.128":'sst'}
years = list(range(1979,2019));

#list of the variable names
var_list = list(var_name.keys())

for ii in range(0, len(var_list)):
    for jj in range(0,len(years)):
        print(var_name[var_list[ii]], years[jj])

        save_name_nc = '_'.join(['era', 'interim', var_name[var_list[ii]], \
                              str(years[jj]), '.nc'])
        save_name_py = '_'.join(['era', 'interim', var_name[var_list[ii]], \
                              str(years[jj]), '.py'])
        os.chdir('D:\\data\\era_interim\\era_interm_scripts')
        f = open('api_req_original_sst.py', 'r')
        filedata = f.read()
        f.close()

        v_date = ''.join([str(years[jj]),'-01-01/to/',str(years[jj]), '-12-31'])
        newdata = filedata.replace("var_date", repr(v_date))
        newdata = newdata.replace("var_param", repr(var_list[ii]))
        newdata = newdata.replace("var_save_name", repr(save_name_nc))

        os.chdir('D:\\data\\era_interim\\era_interm_scripts\\all_apiRequests')
        f = open(save_name_py, 'w')
        f.write(newdata)
        f.close()


import re
import pyglet, math
from pyglet import resource
from pyglet.window import key
from . import physicalobject, resources, util

class Player(physicalobject.PhysicalObject):
    """Physical object that responds to user input"""

    def __init__(self, *args, **kwargs):
        super(Player, self).__init__(img=resources.player_image, *args, **kwargs)

        # Set some easy-to-tweak constants
        self.thrust = 300.0
        self.rotate_speed = 200.0

        self.isFocus = True

        # Let pyglet handle keyboard events for us
        self.key_handler = key.KeyStateHandler()

    def move(self, dt):
        # Do all the normal physics stuff
        x1, y1 = super(Player, self).move(dt)

        if self.key_handler[key.A]:
            self.rotation -= self.rotate_speed * dt
        if self.key_handler[key.D]:
            self.rotation += self.rotate_speed * dt

        if self.key_handler[key.W]:
            angle_radians = -math.radians(self.rotation)
            force_x = math.cos(angle_radians) * self.thrust * dt
            force_y = math.sin(angle_radians) * self.thrust * dt
            self.velocity_x += force_x
            self.velocity_y += force_y

            self.image = resources.player_image_thrust
        else:
            self.image = resources.player_image

        return x1, y1

    def render(self, camera_position, screen_size, zoom):
        if zoom < 0.1:
            self.image = resources.green_circle
            self.scale = 1
        else:
            #self.image = resources.player_image
            self.scale = zoom

        un_zoomed_x = ((self.global_x_position - camera_position[0]) + screen_size[0] / 2)
        un_zoomed_y = (self.global_y_position - camera_position[1]) + screen_size[1] / 2

        self.x = util.apply_zoom(un_zoomed_x, screen_size[0], zoom)
        self.y = util.apply_zoom(un_zoomed_y, screen_size[1], zoom)


#!/usr/bin/python

from __future__ import division
import sys
import Image
import json

archivo, resultado, esp = sys.argv[1:]

esp = int(esp)

im = Image.open(archivo)

pix = im.load()

width, height = im.size

puntos = [[esp*i, esp*j] for j in range(int(height/esp)) for i in range(int(width/esp))]

colores = ['#%02x%02x%02x' % pix[a[0],a[1]] for a in puntos]

tabla = [{"x": punto[0], "y":punto[1], "color":color} for (punto,color) in zip(puntos,colores)]

conclusion = {"espacio": esp, "xdim": width, "ydim": height, "tabla": tabla}

json.dump(conclusion, open(resultado,'w'))


# name = input("What is Your Mobile Number: ")
# print("Your Name is ",name)
# print(type(name))
# Mobile = int(input("Enter Your Mobile Number: "))
# Price = float(input("Total Price: "))
# mobile = complex(input("Enter Complex Number:"))
# print(Mobile)
# print(Price)
# print(mobile)
name="Yuvraj"
age=26
print("My name is", name,"My age is", age)


from datetime import datetime, timedelta
from subscription_handler import SubscriptionHandler
from customer import Customer, NotEnoughCredit, CustomerInDebt
from subscription import Subscription
from display import AlertMessage

class Subject:
    def __init__(self):
        self._observers = {}

    def register(self, observer_key, observer):
        if observer not in self._observers:
            self._observers[observer_key] = observer

    def detach(self, observer_key):
        try:
            del self._observers[observer_key]
        except ValueError:
            pass

    def notify(self, data = None):
        for _, observer in self._observers.items():
            observer.update(data)

class SubscriptionSystem(Subject):
    """General class to manage subscriptions"""
    def __init__(self, subscription_interval=timedelta(minutes=3)):
        Subject.__init__(self)
        self.subscription_interval = subscription_interval
        self.subscriptions = {}
        self._time = datetime.now()
        self.customers = {}

    def run(self):
        while True:
            try:
                command = input()
                self.handle_command(command)
                self.pass_time()

            except NotEnoughCredit as e:
                AlertMessage(e.message())
            except KeyError:
                AlertMessage(f"Key(customer_id/subscription_title) not found")

            # Test:
            print(f"--> System Time: {self._time}")

    def handle_command(self, command):
        if command == "":
            return

        tokens = command.split(" ")
        invalid_command = False

        if tokens[0] == "add":
            if tokens[1] == "sub":
                title, price = tokens[2], int(tokens[3])
                self.add_subscription(title, price)

            elif tokens[1] == "customer":
                customer_id, username , credit = tokens[2], tokens[3], int(tokens[4])
                self.add_customer(customer_id, username, credit)

            elif tokens[1] == "credit":
                customer_id, credit_amount = tokens[2], int(tokens[3])
                self.customers[customer_id].add_credit(credit_amount)

            else:
                invalid_command = True

        elif tokens[0] == "subscribe":
            customer_id, title = tokens[1], tokens[2]
            self.subscribe_customer(customer_id, title)

        elif tokens[0] == "deact":
            customer_id, title = tokens[1], tokens[2]
            self.deactivate_subscription(customer_id, title)

        elif tokens[0] == "react":
            customer_id, title = tokens[1], tokens[2]
            self.activate_subscription(customer_id, title, self._time)

        elif tokens[0] == "pay":
            customer_id = tokens[1]
            self.customers[customer_id].pay_debts()

        elif tokens[0] == "ls":
            customer_id = tokens[2]
            if tokens[1] == "subs":
                self.list_customer_subs(customer_id)
            elif tokens[1] == "invoices":
                self.customers[customer_id].display_invoices()
            else:
                invalid_command = True

        elif tokens[0] == "report":
            customer_id = tokens[1]
            self.customers[customer_id].display_report()

        elif tokens[0] == "help":
            try:
                self.prompt_help(' '.join(tokens[1:]))
                return
            except IndexError:
                self.prompt_help()
                return

        if invalid_command:
            self.prompt_help()

    def add_subscription(self, title, price):
        subscription = Subscription(title, price)
        self.subscriptions[title] = subscription

    def add_customer(self, customer_id, username, credit):
        customer = Customer(int(customer_id), username, credit)
        self.customers[customer_id] = customer

    def subscribe_customer(self, customer_id, title):
        handler_key = customer_id + title
        if handler_key in self._observers.keys():
            AlertMessage("Already subscribed!")
        else:
            try:
                handler = SubscriptionHandler(
                    self.customers[customer_id], self.subscriptions[title],
                    self.subscription_interval, self._time
                )

                Subject.register(self, handler_key, handler)
            except CustomerInDebt as e:
                AlertMessage(e.message())

    def deactivate_subscription(self, customer_id, title):
        handler_key = customer_id + title
        self._observers[handler_key].deactivate()

    def activate_subscription(self, customer_id, title, time):
        handler_key = customer_id + title
        self._observers[handler_key].activate(time)

    def list_customer_subs(self, customer_id):
        for key, sub in self._observers.items():
            if key.startswith(customer_id):
                sub.display()

    def pass_time(self):
        self._time += timedelta(minutes=1)
        self.notify(self._time)

    def prompt_help(self, parent=""):
        commands = ["add", "subscribe", "deact", "react", "pay", "ls", "report"]

        print()
        print("-------------------------------------------------------------------")
        if parent == "add":
            print(f"Usage: {parent} [sub/customer/credit] [ARG...]")
            print()
            print("Add items to the subscription system")
        elif parent == "add sub":
            print(f"Usage: {parent} title price")
            print()
            print("Add subscription to the system")
        elif parent == "add customer":
            print(f"Usage: {parent} id username credit")
            print()
            print("Add customer to the system")
        elif parent == "add credit":
            print(f"Usage: {parent} customer_id amount")
            print()
            print("Add credit to customer")
        elif parent == "subscribe":
            print(f"Usage: {parent} customer_id subscription_title")
            print()
            print("Subscribe customer to a subscription")
        elif parent in ["deact", "react"]:
            print(f"Usage: deact/react customer_id subscription_title")
            print()
            print("Deactivate/activate a subscription")
        elif parent == "pay":
            print(f"Usage: {parent} customer_id")
            print()
            print("Pay user's debts")
        elif parent == "ls":
            print(f"Usage: {parent} [subs/invoices] customer_id")
            print()
            print("List customer's [subscriptions/invoices]")
        elif parent == "report":
            print(f"Usage: {parent} customer_id")
            print()
            print("Generate report of customer's invoices and credit spent in the system")
        else:
            print("Usage: COMMAND customer_id [ARGS...]")
            print("Commands:")
            for  cmd in commands:
                print()
                print("  " + cmd)

        print()
        print("For additional detail on each command try `help COMMAND [SUBCOMMAND]`")
        print("-------------------------------------------------------------------")
        print()


import telebot
from config import token
from parser import get_data

bot = telebot.TeleBot(token)
countries = ('Russia', 'Italy', 'USA')

@bot.message_handler(commands=['start'])
def start_command(message):
    keyboard = telebot.types.ReplyKeyboardMarkup(True)
    keyboard.row(*countries)
    bot.send_message(message.chat.id, "Выбери срану из списка:", reply_markup=keyboard)

@bot.message_handler(content_types=['text'])
def command_country(message):
    if message.text in countries:
        data = get_data(message.text)
        msg = f"Всего случаев: {data['total_cases']}\n" \
              f"Новых случаев: {data['new_cases']}\n" \
              f"Всего смертей: {data['total_deaths']}\n" \
              f"Динамика смертей: {data['new_deaths']}\n" \
              f"Всего вылечившихся: {data['total_recovered']}\n"
        bot.send_message(message.chat.id, msg)
    else:
        bot.send_message(message.chat.id, 'Выберите странну из списка:')

if __name__ == "__main__":
    bot.polling(none_stop=True, timeout=0)


import cv2
import os
import numpy as np

def create_video_from_images(image_folder, output_video_path, fps=24, frame_width=1920, frame_height=1080,
                             video_length=None, codec='none'):
    images = sorted([img for img in os.listdir(image_folder) if img.endswith((".jpg", ".jpeg", ".png", ".JPG"))])

    if video_length is not None:
        fps = len(images) / video_length

    # Získáme rozměry prvního obrázku (předpokládáme, že všechny mají stejné rozměry)
    image_height, image_width = cv2.imread(os.path.join(image_folder, images[0]), 0).shape[:2]

    if output_video_path.lower().endswith(".mp4"):
        if codec == 'none':
            codec = 'H265'
        elif codec not in ('H264', 'X264', 'H265', 'VP90', 'mp4v', 'DIVX', 'XVID', 'FMP4', 'avc1'):
            print("Nepodporovaný codec pro mp4.")
            return
    elif output_video_path.lower().endswith(".avi"):
        if codec == 'none':
            codec = 'DIVX'
        elif codec not in ('DIVX', 'XVID', 'MJPG', 'WMV1', 'WMV2', 'mpg1', 'I420', 'IYUV', 'H264'):
            print("Nepodporovaný codec pro mp4.")
            return
    else:
        print("Nepodporovaný nebo nezadaný formát.")
        return

    # Nastavení kodeku a vytvoření objektu pro video zápis
    #                                   VideoWriter objekt s nekomprimovaným kodekem (VYUY)
    # fourcc = cv2.VideoWriter_fourcc('Y', 'U', 'Y', 'V') # - nefunkční
    fourcc = cv2.VideoWriter_fourcc(*codec)
    out = cv2.VideoWriter(output_video_path, fourcc, fps, (frame_width, frame_height), isColor=True)

    # Výpočet poměru šířky a výšky načteného obrázku
    image_ratio = image_width / image_height

    # Výpočet poměru šířky a výšky požadovaného pole
    desired_ratio = frame_width / frame_height

    # Rozhodnutí o změně velikosti obrázku
    if image_ratio > desired_ratio:
        new_width = frame_width
        new_height = int(frame_width / image_ratio)
    else:
        new_width = int(frame_height * image_ratio)
        new_height = frame_height

    # Umístění obrázku do pole, aby zabíralo maximální plochu
    x_offset = (frame_width - new_width) // 2
    y_offset = (frame_height - new_height) // 2

    for image_name in images:
        image = cv2.imread(os.path.join(image_folder, image_name), 1)

        # Změna velikosti obrázku
        resized_image = cv2.resize(image, (new_width, new_height))

        # Vytvoření prázdného pole
        output_image = np.zeros((frame_height, frame_width, 3), dtype=np.uint8)

        # Umístěte fotografii na střed obrazu
        output_image[y_offset:y_offset + new_height, x_offset:x_offset + new_width] = resized_image
        out.write(output_image)

    # Uzavření objektu pro video zápis
    out.release()

    print("hotovo")

def play_video(video_path):
    cap = cv2.VideoCapture(video_path)
    close = False

    while True:
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break

            cv2.namedWindow('Video', cv2.WINDOW_NORMAL)
            cv2.resizeWindow('Video', 1920 // 2, 1080 // 2)
            cv2.imshow('Video', frame)

            if cv2.waitKey(25) & 0xFF == 27:  # Klávesa "Esc" pro ukončení
                close = True
                break

        # Posuneme časový ukazatel zpět na začátek videa
        cap.set(cv2.CAP_PROP_POS_FRAMES, 0)

        if close:  # Klávesa "Esc" pro ukončení
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    image_path = "photos"
    output_path = "output_video.mp4"

    create_video_from_images(image_path, output_path, video_length=60, codec='mp4v',
                             frame_width=3840, frame_height=2160)

    if os.path.exists(output_path):
        play_video(output_path)
    else:
        create_video_from_images(image_path, output_path)
        play_video(output_path)

    """print("\nChcete video smazat?")
    while True:
        ans = input("\tZadejte Y / N: ")
        if ans == "Y":
            os.remove(output_video_path)
            break
        elif ans == "N":
            break
        else:
            print("Zadejte platnou odpověď.")"""


from dataclasses import dataclass
import inspect as ins
from typing import *
import warnings as W

Term = Any
Quote = Sequence[Term]
Data = List
TYPE = TypeVar("TYPE")

@dataclass
class Reduction:
    quote: Quote
    index: int = 0

    def shift(self) -> Any:
        t = self.quote[self.index]
        self.index += 1
        return t

    def at_end(self) -> bool:
        return self.index == len(self.quote)

ParamCheck = Callable[[Any], bool]

def with_attr(*attrs: str) -> ParamCheck:
    def _check(p: Any) -> bool:
        return all(hasattr(p, a) for a in attrs)
    return _check

is_quote = with_attr("__iter__", "__len__")
is_iterable = with_attr("__iter__")
is_mapping = with_attr("__iter__", "__len__", "items")

def of_type(T: Type) -> ParamCheck:
    return lambda p: isinstance(p, T)

no_check = of_type(object)

@dataclass
class State:
    data: Data
    execution: List[Reduction]

    def consume(self, *checks: ParamCheck) -> Sequence:
        if len(checks) == 0:
            W.warn("Consuming 0 term is no-op.", category=RuntimeWarning)
            return []
        elif len(self.data) < len(checks):
            raise IndexError(
                f"Consuming {len(checks)} data elements is not possible, "
                f"stack depth is {len(self.data)}"
            )

        consumed = []
        num_checks = len(checks)
        for i, check in enumerate(checks):
            p = self.data[i - num_checks]
            if not check(p):
                raise ValueError(f"Parameter {i} fails suitability check")
            consumed.append(p)
        del self.data[-num_checks:]
        return consumed

    def consume_any_n(self, n: int) -> Sequence:
        return self.consume(*([no_check] * n))

    def feed(self, *terms: Term) -> None:
        self.data += list(terms)

    def push(self, quote: Quote) -> None:
        if quote:
            self.execution.append(Reduction(quote))

    def next_term(self) -> Any:
        assert self.execution
        current = self.execution[-1]
        term = current.shift()
        if current.at_end():
            self.execution.pop()
        return term

@dataclass
class internal:
    apply: Callable[[State], None]

    @property
    def __name__(self) -> str:
        return self.apply.__name__

    @__name__.setter
    def __name__(self, name_new: str) -> None:
        self.apply.__name__ = name_new

    def __str__(self) -> str:
        return self.apply.__name__

    def __repr__(self) -> str:
        return str(self)

class SubReference(Protocol):

    def resolve(self, x: Any) -> Any:
        ...

@dataclass
class Attr:
    name: str

    def resolve(self, x: Any) -> Any:
        return getattr(x, self.name)

@dataclass
class Item:
    key: Any

    def resolve(self, x: Any) -> Any:
        return x[self.key]

@dataclass
class Reference:
    key: Union[int, slice]
    subrefs: List[SubReference]

    def __getattr__(self, name: str) -> "Reference":
        return Reference(self.key, self.subrefs + [Attr(name)])

    def __getitem__(self, key: Any) -> "Reference":
        return Reference(self.key, self.subrefs + [Item(key)])

    @property
    def set(self) -> "Setter":
        return Setter(self)

    def resolve(self, stack: Data) -> Tuple[Any, int]:
        x: Any
        if isinstance(self.key, int):
            depth = self.key + 1
            x = stack[-self.key - 1]
        elif isinstance(self.key, slice):
            start = self.key.start or 0
            stop = self.key.stop
            assert stop is not None
            step = self.key.step or 1
            x = stack[-stop - start + (step if start else 0)::step]
            depth = self.key.stop
        else:
            raise RuntimeError(f"Reference key should be int or slice: got {self.key}")

        for subref in self.subrefs:
            x = subref.resolve(x)
        return x, depth

def resolve_references(c: Any, state: State) -> Any:
    depth = 0

    def resolve(x: Any) -> Any:
        nonlocal depth
        if isinstance(x, (list, tuple)):
            return type(x)(resolve(e) for e in x)
        elif isinstance(x, set):
            return {resolve(e) for e in x}
        elif isinstance(x, dict):
            return {k: resolve(v) for k, v in x.items()}
        elif isinstance(x, Reference):
            result, d = x.resolve(state.data)
            depth = max(depth, d)
            return result
        else:
            return x

    resolved = resolve(c)
    if depth > 0:
        state.consume_any_n(depth)
    return resolved

def _set(ref: Reference, how: Callable[[Any, Any], None]) -> internal:
    @internal
    def set_(state: State) -> None:
        target, depth = ref.resolve(state.data)
        if depth != 2:
            raise TypeError(
                "The target of the operation must be stack element at index 1; "
                f"here, target was resolved at index {depth - 1}"
            )
        owner, value = state.consume_any_n(2)
        how(target, value)
        state.feed(owner)

    return set_

@dataclass
class Setter:
    _ref: Reference

    def __getattr__(self, name: str) -> internal:
        def set_attribute(target: Any, value: Any) -> None:
            setattr(target, name, value)
        return _set(self._ref, set_attribute)

    def __getitem__(self, key: Any) -> internal:
        def set_item(target: Any, value: Any) -> None:
            target[key] = value
        return _set(self._ref, set_item)

def reduce(quote: Quote) -> Sequence:
    if not quote:
        return []

    state = State(data=[], execution=[Reduction(quote=quote)])

    while state.execution:
        term_raw = state.next_term()
        term = resolve_references(term_raw, state)

        if isinstance(term, internal):
            cast(internal, term).apply(state)
        elif hasattr(term, "__call__"):
            sig = ins.signature(term)
            num_args = len([
                p
                for p in sig.parameters.values()
                if (
                    p.kind in {
                        ins.Parameter.POSITIONAL_ONLY,
                        ins.Parameter.POSITIONAL_OR_KEYWORD
                    } and p.default is ins.Parameter.empty
                )
            ])
            args: Sequence
            if num_args == 0:
                args = []
            else:
                args = state.consume_any_n(num_args)

            result = term(*args)
            if result is not None:
                state.feed(result)
        else:
            state.feed(term)

    return state.data


import bisect

class Solution:
    # @param A, a list of integers
    # @param target, an integer to be searched
    # @return an integerA

    def bsearch(self, A, target):
        idx = bisect.bisect_left(A, target)
        if 0 <= idx < len(A) and A[idx] == target:
            return idx
        else:
            return -1

    def mplus(self, a, b):
        if a < 0  or b < 0:
            return -1
        return a + b

    def search(self, A, target):
        if len(A) == 0:
            return -1
        if len(A) < 10:
            for i in xrange(len(A)):
                if A[i] == target:
                    return i
            return -1

        mid = len(A) / 2
        if A[mid] == target:
            return mid

        # assume not rotated
        tmp = self.bsearch(A, target)
        if tmp >= 0 and tmp < len(A) and A[tmp] == target:
            return tmp

        # print "mid =", mid, "A =", A
        if A[mid] > A[0]:
            if target >= A[mid]:
                return self.mplus(mid + 1, self.search(A[mid + 1 :], target))
            else: # target < A[mid]
                if target <= A[-1]:
                    return self.mplus(mid + 1, self.search(A[mid + 1 :], target))
                else: # target > A[-]
                    return self.bsearch(A[: mid], target)

        else: # A[mid] < A[0]
            if target <= A[mid]:
                return self.search(A[: mid + 1], target)
            else:
                if target > A[-1]:
                    return self.search(A[: mid], target)
                else:
                    return self.mplus(mid + 1, self.bsearch(A[mid + 1:], target))


import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split, GridSearchCV, KFold, cross_val_score
from sklearn.metrics import mean_squared_error
from sklearn.preprocessing import OneHotEncoder
from sklearn.linear_model import Lasso
from sklearn.ensemble import RandomForestRegressor, StackingRegressor
from xgboost import XGBRegressor
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import MaxAbsScaler

# Load the data
train = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')

# EDA
plt.figure(figsize=(12, 6))
sns.histplot(train['SalePrice'], kde=True)
plt.title('Sale Price Distribution')
plt.show()

plt.figure(figsize=(12, 6))
sns.scatterplot(x=train['GrLivArea'], y=train['SalePrice'])
plt.title('Sale Price vs. GrLivArea')
plt.show()

correlation_matrix = train.corr()
plt.figure(figsize=(12, 12))
sns.heatmap(correlation_matrix, cmap='coolwarm', annot=False)
plt.title('Correlation Matrix')
plt.show()

# Identify categorical and numerical columns
categorical_columns = train.select_dtypes(include=['object']).columns
numerical_columns = train.select_dtypes(exclude=['object']).drop(['Id', 'SalePrice'], axis=1).columns

# Preprocessing
preprocessor = ColumnTransformer(
    transformers=[
        ('num', SimpleImputer(strategy='mean'), numerical_columns),
        ('cat', Pipeline(steps=[
            ('impute', SimpleImputer(strategy='constant', fill_value='missing')),
            ('onehot', OneHotEncoder(handle_unknown='ignore'))]), categorical_columns)])

# Prepare the data
X_train = train.drop(['Id', 'SalePrice'], axis=1)
y_train = train['SalePrice']
X_test = test.drop(['Id'], axis=1)

# Preprocess the data
X_train = preprocessor.fit_transform(X_train)
X_test = preprocessor.transform(X_test)

# Feature scaling
scaler = MaxAbsScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# Define base models for stacking
base_models = [
    ('random_forest', RandomForestRegressor(n_jobs=-1, random_state=42)),
    ('xgb_regressor', XGBRegressor(n_jobs=-1, random_state=42)),
    ('lasso', Lasso(max_iter=10000, random_state=42))
]

# Set up stacking regressor
stacking_regressor = StackingRegressor(estimators=base_models, final_estimator=Lasso(max_iter=10000, random_state=42), n_jobs=-1)

# Perform KFold cross-validation
kf = KFold(n_splits=5, random_state=42, shuffle=True)
rmse_scores = np.sqrt(-cross_val_score(stacking_regressor, X_train, y_train, scoring='neg_mean_squared_error', cv=kf))

# Print mean and standard deviation of RMSE scores
print(f"KFold Cross-Validation RMSE scores: {rmse_scores}")
print(f"Mean RMSE score: {rmse_scores.mean():.2f}")
print(f"Standard deviation of RMSE scores: {rmse_scores.std():.2f}")

# Train the stacking model
stacking_regressor.fit(X_train, y_train)

# Generate predictions
predictions = stacking_regressor.predict(X_test)

# Create the submission file
submission = pd.DataFrame({'Id': test['Id'], 'SalePrice': predictions})
submission.to_csv('submission.csv', index=False)

print("Submission file created.")