from __future__ import annotations

import json
from typing import Any, Callable

import numpy as np
import tensorflow as tf
from tensorflow import Tensor

from wheelly.tdlayers import TDNetwork, flat_type_spec

def flat_states(states: Any) -> dict[str, Tensor]:
    """Returns the flatten states

    Arguments:
    states_spec -- the state specification
    states -- the state"""
    result = dict()

    def flat(prefix: str, value: Any):
        if isinstance(value, dict):
            for key, sub_values in value.items():
                flat(prefix=prefix+"." + key,
                     value=sub_values)
        else:
            result[prefix] = tf.constant([value], dtype=tf.float32)

    flat(prefix="input", value=states)
    return result

def choose_actions(flatten_pis: dict[str, Tensor],
                   random: tf.random.Generator) -> dict[str, int]:
    """Returns the actions selecting random by probabilities

    Arguments:
    flatten_pis -- the flatten probabilities
    random -- the random generator"""
    def choose(prob: Tensor) -> int:
        cum = tf.cumsum(x=prob, axis=1)
        sel = random.uniform(shape=(1,))
        action = int(tf.math.count_nonzero(sel >= cum))
        return action

    result = {key: choose(pis) for key, pis in flatten_pis.items()}
    return result

def unflat_actions(actions_spec: dict[str, Any],
                   flatten: dict[str, int]) -> dict[str, Any] | int | float:
    """Returns the unflatten actions

    Arguments:
    actions_spec -- the actions specification
    flatten -- the flatten actions"""
    def unflat(prefix: str,
               spec: dict[str, Any]) -> dict[str, Any] | int | float:

        if "type" in spec:
            assert spec["type"] == "int"
            return flatten[prefix]
        else:
            result = {key: unflat(prefix=f"{prefix}.{key}",
                                  spec=sub_spec)
                      for key, sub_spec in spec.items()}
            return result

    return unflat(prefix="output", spec=actions_spec)

def log_pi(pi: dict[str, Tensor],
           action: dict[str, Any] | int | float,
           actions_spec: dict[str, Any]) -> dict[str, Tensor]:
    """Returns the gradient of log pi for a given pi and action

    Arguments:
    pi -- the probabilities of each action
    action -- the action applied
    actions_spec -- the action specification"""

    def log_pi1(values: dict[str, Tensor],
                prefix: str,
                action: dict[str, Any] | int | float,
                spec: dict[str, Any]) -> dict[str, Tensor]:

        if "type" in spec:
            assert spec["type"] == "int"
            pi_a = pi[prefix]
            x = np.zeros(shape=pi_a.shape)
            x[0, action] = 1
            dl = (1 / pi_a) * x
            values[prefix] = dl
            return values
        else:
            for key, sub_spec in spec.items():
                log_pi1(values=values,
                        prefix=f"{prefix}.{key}",
                        action=action[key],
                        spec=sub_spec)
            return values

    return log_pi1(values={}, prefix="output", action=action, spec=actions_spec)

class TDAgent(tf.train.Checkpoint):
    @staticmethod
    def create(spec: dict[str, Any], random=tf.random.Generator) -> TDAgent:
        policy = TDNetwork.create(spec=spec["policy"], random=random)
        critic = TDNetwork.create(spec=spec["critic"], random=random)
        return TDAgent(states_spec=spec["state_spec"],
                       actions_spec=spec["actions_spec"],
                       reward_alpha=spec["reward_alpha"],
                       policy=policy,
                       critic=critic,
                       random=random)

    @ staticmethod
    def load(path: str) -> TDAgent:
        with open(path + "/agent.json") as json_file:
            spec = json.load(json_file)
        agent = TDAgent.create(
            spec=spec, random=tf.random.get_global_generator())
        file = tf.train.latest_checkpoint(checkpoint_dir=path)
        agent.restore(file)
        return agent

    def __init__(self,
                 states_spec: dict[str, Any],
                 actions_spec: dict[str, Any],
                 reward_alpha: float,
                 policy: TDNetwork,
                 critic: TDNetwork,
                 random: tf.random.Generator):
        super().__init__()

        assert isinstance(states_spec, dict)
        assert isinstance(actions_spec, dict)
        assert isinstance(reward_alpha, float)
        assert isinstance(policy, TDNetwork)
        assert isinstance(critic, TDNetwork)

        self.states_spec = states_spec
        self.actions_spec = actions_spec
        self.flatten_states_spec = flat_type_spec(
            spec=states_spec, prefix="input")
        self.flatten_actions_spec = flat_type_spec(
            spec=actions_spec, prefix="output")
        self.policy = policy
        self.random = random
        self.critic = critic
        self.reward_alpha = reward_alpha
        self.avg_reward = tf.Variable(initial_value=[0],
                                      dtype=tf.float32,
                                      trainable=False)
        self.prev_inputs = None
        self.kpi_listeners: list[Callable[[dict[str, Any]], None]] = []

    def act(self, states: Any) -> dict[str, Any] | int | float:
        """Returns the action for a states based on current policy

        Argument:
        states -- the states"""
        policy_status, inputs = self._policy_status(states=states)
        pis = {key: value for key,
               value in policy_status.items() if key in self.flatten_actions_spec}
        flatten_action = choose_actions(flatten_pis=pis, random=self.random)
        actions = unflat_actions(
            flatten=flatten_action, actions_spec=self.actions_spec,)
        self.last_actions = actions
        self.last_inputs = inputs
        self.last_policy = policy_status
        return actions

    def observe(self, reward: float = 0.0, terminal: bool = False):
        """Observe the result of environment interaction and train the agent

        Arguments:
        reward -- reward
        terminal -- true if terminal state"""
        if self.prev_inputs is not None:
            self._train(s0=self.prev_inputs,
                        actions=self.prev_actions,
                        reward=self.prev_reward,
                        terminal=self.prev_terminal,
                        s1=self.last_inputs)
        if terminal:
            self.prev_inputs = None
            self.prev_actions = None
            self.prev_reward = None
            self.prev_terminal = None
            self.prev_policy = None
        else:
            self.prev_inputs = self.last_inputs
            self.prev_actions = self.last_actions
            self.prev_reward = reward
            self.prev_terminal = terminal
            self.prev_policy = self.last_policy

    def close(self):
        pass

    def _policy_status(self, states: Any):
        """Returns the status of policy network and the states inputs

        Argument:
        states -- the states"""
        inputs = flat_states(states)
        policy_status = self.policy.forward(inputs)
        return policy_status, inputs

    def _train(self, s0: dict[str, Tensor],
               actions: dict[str, Any] | int | float,
               reward: float,
               terminal: bool,
               s1: dict[str, Tensor]):

        c0 = self.critic.forward(s0)
        c1 = self.critic.forward(s1)
        v0 = c0["output"]
        v1 = c1["output"]
        delta = reward - self.avg_reward + v1 - v0
        pi = self.prev_policy
        dc = dict(output=tf.ones(shape=(1, 1)))
        dp = log_pi(pi=pi, action=actions, actions_spec=self.actions_spec)

        avg_reward = tf.constant(self.avg_reward)
        self.avg_reward.assign_add(delta=delta[0] * self.reward_alpha)
        grad_c = self.critic.train(outputs=c0,
                                   grad_outputs=dc,
                                   delta=delta)
        grad_pi = self.policy.train(outputs=pi,
                                    grad_outputs=dp,
                                    delta=delta)

        if len(self.kpi_listeners) > 0:
            trained_c0 = self.critic.forward(s0)
            trained_c1 = self.critic.forward(s1)
            trained_pi = self.policy.forward(s0)

            kpis = dict(
                s0=s0,
                reward=reward,
                terminal=terminal,
                actions=actions,
                s1=s1,
                avg_reward=avg_reward,
                trained_avg_reward=tf.constant(self.avg_reward),
                c0=c0,
                c1=c1,
                delta=delta,
                pi=pi,
                dc=grad_c,
                dp=grad_pi,
                trained_c0=trained_c0,
                trained_c1=trained_c1,
                trained_pi=trained_pi
            )
            self._notify_kpi(kpis)

    def _notify_kpi(self, kpis: dict[str, Any]):
        for listener in self.kpi_listeners:
            listener(kpis)

    def add_kpi_listener(self, callback: Callable[[dict[str, Any]], None]):
        """Adds a kpi listener

        Arguments:
        callback -- the call back listener"""
        self.kpi_listeners.append(callback)

    def save_model(self, path: str):
        tf.train.CheckpointManager(
            checkpoint=self, directory=path, max_to_keep=3).save()
        with open(path + "/agent.json", "w", encoding="utf-8") as f:
            agent_spec = self.spec()
            json.dump(agent_spec, f, ensure_ascii=False)

    def spec(self) -> dict[str, Any]:
        spec = dict(
            state_spec=self.states_spec,
            actions_spec=self.actions_spec,
            reward_alpha=self.reward_alpha,
            policy=self.policy.spec(),
            critic=self.critic.spec()
        )
        return spec


from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.views.generic import ListView

from product_brand.forms import BrandForm
from product_brand.models import Brand
from product_brand.utils import create_brand_from_brandform, create_brand_from_brandeditform

def create_brand(request):

    if request.method == 'GET':
        context = {
            'brand_form': BrandForm()
        }
        return render(request, 'brand/create_brand.html', context)

    if request.method == 'POST':
        brand_from = BrandForm(request.POST)

        if brand_from.is_valid():
            new_brand = create_brand_from_brandform(brand_from, commit=True)

            messages.success(request, 'Salvo Com Sucesso!')

        return HttpResponseRedirect(reverse('home'))

class ListBrand(ListView):
    model = Brand
    template_name = 'brand/list_brand.html'
    paginate_by = 15
    extra_context = dict()
    context_object_name = 'brands'

    def __init__(self, *args, **kwargs):
        super(ListBrand, self).__init__(*args, **kwargs)
        self.codigo = self.nome = None

    def get(self, request, *args, **kwargs):
        self.codigo = self.request.GET.get('codigo', None)
        self.nome = self.request.GET.get('nome', None)

        return super().get(request, *args, **kwargs)

    def get_queryset(self):
        query = """
            SELECT PC.* FROM product_brand PC
        """

        if self.codigo is not None:
            query = query + " WHERE C.id = %s" % str(self.codigo)

        elif self.nome is not None:
            query = query + " WHERE PC.name = %s" % str(self.nome)

        query = query + " order by id"

        qs = Brand.objects.raw(query)

        return qs

def edit_brand(request, pk):

    if request.method == 'GET':

        brand = Brand.objects.filter(id=pk).first()

        if brand is None:
            raise ValueError('Marca não existe!')

        initial = {
            'name': brand.name,
            'initials': brand.initials,
        }

        context = {
            'brand_form': BrandForm(initial=initial)
        }

        return render(request, 'brand/create_brand.html', context)

    if request.method == 'POST':
        brand_edit_from = BrandForm(request.POST)

        if brand_edit_from.is_valid():
            new_brand = create_brand_from_brandeditform(brand_edit_from, pk, commit=True)

            messages.success(request, 'Editado Com Sucesso!')

        return HttpResponseRedirect(reverse('list-brand'))


# Source: langchain.SQLDatabaseChain
"""Chain for interacting with SQL Database."""
from typing import Dict, List, Any

from pydantic import BaseModel, Extra, Field

import json

from langchain.chains.base import Chain
from langchain.chains.llm import LLMChain
from langchain.input import print_text
from langchain.llms.base import LLM

from backend.modules.database.prompt import PROMPT
from backend.modules.database.sql_database import SQLDatabase
from backend.modules.database.encoder import UUIDEncoder

class SQLDatabaseChain(Chain, BaseModel):
    """Chain for interacting with SQL Database.

    Example:
        .. code-block:: python

            from langchain import SQLDatabaseChain, OpenAI, SQLDatabase
            db = SQLDatabase(...)
            db_chain = SelfAskWithSearchChain(llm=OpenAI(), database=db)
    """

    llm: LLM
    """LLM wrapper to use."""
    database: Any  # SQLDatabase
    """SQL Database to connect to."""
    input_key: str = "query"  #: :meta private:
    output_key: str = "result"  #: :meta private:
    debug: bool = False  # even more verbose
    custom_memory: dict = {}

    class Config:
        """Configuration for this pydantic object."""

        extra = Extra.forbid
        arbitrary_types_allowed = True

    @property
    def input_keys(self) -> List[str]:
        """Return the singular input key.

        :meta private:
        """
        return [self.input_key]

    @property
    def output_keys(self) -> List[str]:
        """Return the singular output key.

        :meta private:
        """
        return [self.output_key]

    def _call(self, inputs: Dict[str, str]) -> Dict[str, str]:
        llm_chain = LLMChain(llm=self.llm, prompt=PROMPT, verbose=self.debug)
        input_text = f"{inputs[self.input_key]} \nSQLQuery:"
        llm_inputs = {
            "input": input_text,
            "dialect": self.database.dialect,
            "table_info": self.database.table_info,
            "stop": ["\nSQLResult:"],
        }
        sql_cmd = llm_chain.predict(**llm_inputs)
        if self.verbose:
            print_text(input_text)
            print_text(sql_cmd, color="green")
        error, result = self.database.run(sql_cmd)
        lang_output = ""
        if error:
            lang_output = "Error: " + error
        else:
            lang_output = f"{len(result)} rows returned:"
            if len(result) <= 3:
                lang_output += "\n" + "\n".join(map(str, result))
            else:
                lang_output += f"\n[{result[0]}, ...]"
                lang_output += f"\nAll results are stored in query_result.json"
                with open("query_result.json", "w") as f:
                    json.dump(result, f, cls=UUIDEncoder, default=str)

        if self.verbose:
            print_text("\nSQLResult: ")
            print_text(lang_output, color="yellow")
            print_text("\nAnswer:")
        input_text += f"{sql_cmd}\nSQLResult: {lang_output}\nAnswer:"
        llm_inputs["input"] = input_text
        final_result = llm_chain.predict(**llm_inputs)
        if self.verbose:
            print_text(final_result, color="green")
        self.custom_memory = {
            "query_result": result,
            "sql_cmd": sql_cmd,
            "query_result_summary": {
                "outline": f"{len(result)} rows",
                "source": sql_cmd,
                "text": lang_output,
            }
        }
        if len(result) > 3:
            self.custom_memory["query_result_summary"] = {
                **self.custom_memory["query_result_summary"],
                "type": "json file",
                "name": "query_result.json",
                "example": f"[{result[0]}, ...]",
            }

        return {self.output_key: final_result}


"""
因子数据处理时常用的一些函数
1. 上市时间过滤，剔除新股，默认剔除上市时间 200 天以内的股票, 暂时采用聚宽接口
2. 极值处理, 支持 MAD, STD, Quantile 方式
3. 标准化处理，暂时支持 std
4. 获取行业数据，暂时采用聚宽接口，支持 "sw_l1", "sw_l2", "sw_l3", "jq_l1", "jq_l2", "zjw"
5. 获取市值数据，使用本地接口，支持 'avg', 'mktcap', 'sqrt_mktcap', 'ln_mktcap',
    'cmktcap', 'sqrt_cmktcap', 'ln_cmktcap'
6. 行业中性化与市值中性化
"""
from functools import partial
from typing import List, Tuple, Union

try:
    import jqdatasdk
except:
    print("jqdatasdk not installed")
import numpy as np
import pandas as pd

import statsmodels.api as sm
from QUANTAXIS.QAAnalysis.QAAnalysis_block import QAAnalysis_block
from QUANTAXIS.QAFactor.utils import QA_fmt_code_list
from QUANTAXIS.QAFactor.fetcher import (QA_fetch_stock_basic, QA_fetch_industry_adv)

def QA_fmt_factor(factor: Union[pd.Series, pd.DataFrame]):
    """
    将 factor 格式化
    """
    # 索引设置
    if isinstance(factor, pd.DataFrame):
        factor = factor.stack(dropna=False)
    level_0 = 'datetime'
    try:
        pd.Timestamp(factor.index.levels[0][0])
    except:
        try:
            level_0 = 'code'
            pd.Timestamp(factor.index.levels[1][0])
        except:
            raise ValueError("错误，索引格式不正确")
    if level_0 == 'code':
        factor = factor.swaplevel()
    factor.index.names = ["datetime", "code"]
    factor.index = factor.index.map(lambda x: (pd.Timestamp(x[0]), x[1]))
    return factor.sort_index()

def QA_winsorize_factor(
        factor: Union[pd.Series,
                      pd.DataFrame],
        grouper: list = ["datetime"],
        extreme_scale: float = 1.4826,
        extreme_method: str = "mad",
        extreme_inclusive: bool = False,
        quant: list = None,
        inf2nan: bool = True,
        nan2mean: bool = True,
) -> pd.Series:
    """
    对输入的 Series 进行极值处理
    :param factor: 因子数据, ['日期' '资产'] 的 MultiIndex 或者 ['日期'] 为索引，['资产'] 为列索引的透视表
    :param grouper: 分组数据
    :param extreme_scale: 极值处理对应的 scale
    :param extreme_method: 极值处理方式
    :param extreme_inclusive: 是否保留边界外极值为边界值，默认不保留
    :param inf2nan: 是否将 np.inf -np.inf 转换为 np.nan
    :param quant: 0 ~ 1 之间的范围
    :param nan2mean: 是否将 np.nan 替换为行业平均值
    """

    def _mad_cut(x, scale, inclusive, nan2mean):
        diff = (x - x.median()).apply(abs)
        mad = diff.median()
        upper_limit = x.median() + scale * mad
        lower_limit = x.median() - scale * mad
        if inclusive:
            x.loc[x < lower_limit] = lower_limit
            x.loc[x > upper_limit] = upper_limit
            x.clip(lower_limit, upper_limit, inplace=True)
        else:
            x = x.loc[(x >= lower_limit) & (x <= upper_limit)]
        if nan2mean:
            return x.fillna(np.nanmean(x))
        return x

    def _std_cut(x, scale, inclusive, nan2mean):
        std = x.std()
        upper_limit = x.mean() + scale * std
        lower_limit = x.mean() - scale * std
        if inclusive:
            x.loc[x < lower_limit] = lower_limit
            x.loc[x > upper_limit] = upper_limit
            factor.clip(lower_limit, upper_limit, inplace=True)
        else:
            x = x.loc[(x > lower_limit) & (x < upper_limit)]
        if nan2mean:
            return x.fillna(np.nanmean(x))
        else:
            return x

    def _quant_cut(x, quant, inclusive, nan2mean):
        if inclusive:
            x.loc[x < quant[0]] = quant[0]
            x.loc[x > quant[1]] = quant[1]
            x = np.quantile(x, quant, interpolation="nearest")
        else:
            x = np.quantile(x, quant, interpolation="nearest")
        if nan2mean:
            return x.fillna(np.nanmean(x))
        else:
            return x

    if extreme_method not in ["mad", "std", "quant"]:
        raise ValueError("参数为 mad/std/quant, 仅支持这极值处理方式")
    # 对因子进行格式化
    factor = QA_fmt_factor(factor)
    # inf2nan
    if inf2nan:
        factor.replace([np.inf, -np.inf], np.nan, inplace=True)
    # 极值处理
    if extreme_method == "mad":
        factor = (
            factor.groupby(grouper).apply(
                lambda x:
                _mad_cut(x,
                         extreme_scale,
                         extreme_inclusive,
                         nan2mean)
            ).droplevel(level=1)
        )
        return factor
    elif extreme_method == "std":
        factor = (
            factor.groupby(grouper).apply(
                lambda x:
                _std_cut(x,
                         extreme_scale,
                         extreme_inclusive,
                         nan2mean)
            ).droplevel(level=1)
        )
        return factor
    elif extreme_method == "quant":
        if quant is None:
            raise ValueError("")
        factor = (
            factor.groupby(grouper)
            .apply(lambda x: _quant_cut(x,
                                        quant,
                                        extreme_inclusive,
                                        nan2mean)).droplevel(level=1)
        )
        return factor

def QA_standardize_factor(
        factor: pd.Series,
        standard_method: str = "normal",
        inf2nan: bool = True
) -> pd.Series:
    """
    对输入的因子值进行标准化处理，默认为 Z-score 处理, 其他处理方式待实现
    :param data: 输入的 DataFrame, 索引为股票代码
    :param standard_method: 标准化处理方法，目前接受 "normal"/"weighted"/"john"
    :param inf2nan: 是否将 np.inf 转换为 np.nan
    """
    factor = QA_fmt_factor(factor)
    if standard_method not in ["normal", "weighted", "john"]:
        raise ValueError("仅接受 normal/weighted/john 参数")
    if standard_method == "normal":
        std = factor.std()
        mean = factor.mean()
        factor = (factor - mean) / std
    elif standard_method == "weighted":
        # TODO: 市值加权标准化方法待实现
        raise ValueError("市值加权标准化方法待实现")
    else:
        # TODO: Johnson 变化法
        raise ValueError("John 变化法待实现")
    return factor

def QA_fetch_get_factor_groupby(
        factor: pd.Series,
        industry_cls: str = "sw_l1",
        detailed: bool = False
) -> pd.DataFrame:
    """
    获取因子的行业暴露, 注意，返回的值是 pd.DataFrame 格式，包含原因子值，附加一列
    因子对应的行业信息 (需先自行导入聚宽本地 sdk 并登陆)

    参数
    ---
    :param factor: 因子值，索引为 ['日期' '资产']
    :param industry_cls: 行业分类，默认为申万 1 级行业
    :param detailed: 是否使用详细模式，默认为 False, 即取因子日期最后一日的行业信息

    返回值
    ---
    :return: 因子数据, 包括因子值，因子对应行业
    """
    warnings.warn("请先自行导入聚宽本地 sdk 并登陆", UserWarning)
    # 因子格式化
    factor = QA_fmt_factor(factor)
    merged_data = pd.DataFrame(factor.copy().rename("factor"))
    # 股票代码格式化
    stock_list = QA_fmt_code_list(
        factor.index.get_level_values("code").drop_duplicates(),
    )
    # 非详细模式， 行业数据采用当前日期
    ss = pd.Series()
    if detailed:
        # start_time = str(min(factor.index.get_level_values("datetime")))[:10]
        # end_time = str(max(factor.index.get_level_values("datetime")))[:10]
        # date_range = list(
        #     map(pd.Timestamp, QA_util_get_trade_range(start_time, end_time))
        # )
        date_range = (
            factor.index.get_level_values(
                "datetime").drop_duplicates().tolist()
        )

        industry = pd.DataFrame()
        for cursor_date in date_range:
            df_tmp = QA_fetch_industry_adv(code = stock_list, cursor_date = cursor_date)[["code", "industry_name"]]
            df_tmp["date"] = cursor_date
            industry = industry.append(df_tmp)
        ss = industry.set_index(["date", "code"])["industry_name"]
        # industries = map(
        #     partial(jqdatasdk.get_industry,
        #             stock_list),
        #     date_range
        # )
        # industries = {
        #     d: {
        #         s: ind.get(s).get(industry_cls,
        #                           dict()).get("industry_name",
        #                                       "NA")
        #         for s in stock_list
        #     }
        #     for d,
        #     ind in zip(date_range,
        #                industries)
        # }
    else:
        end_time = str(max(factor.index.get_level_values("datetime")))[:10]
        date_range = [pd.Timestamp(end_time)]
        # industries = jqdatasdk.get_industry(stock_list, end_time)
        ss = QA_fetch_industry_adv(stock_list, end_time)[["code", "industry_name"]].set_index(["date", "code"])["industry_name"]
        # industries = {
        #     d: {
        #         s: industries.get(s).get(industry_cls,
        #                                  dict()).get("industry_name",
        #                                              "NA")
        #         for s in stock_list
        #     }
        #     for d in date_range
        # }
    # 可能历史上股票没有行业信息，用之后的行业信息往前填充
    merged_data["date"] = merged_data.index.get_level_values("datetime").map(
        lambda x: x.date()
    )
    merged_data = (
        merged_data.reset_index().set_index(
            ["date",
             "code"]
        ).assign(group=ss).reset_index().set_index(["datetime",
                                                          "code"]
                                                         ).drop("date",
                                                                axis=1)
    )
    group = merged_data["group"].unstack().bfill().stack()
    merged_data["group"] = group
    return merged_data

def QA_fetch_factor_weight(
        factor: pd.Series,
        weight_cls: str = "mktcap",
        detailed: bool = True
) -> pd.DataFrame:
    """
    获取因子的市值暴露, 注意，返回的值是 pd.DataFrame 格式，包含原因子值，附加一列
    因子对应的加权信息

    参数
    ---
    :param factor: 因子值，索引为 ['日期' '资产']
    :param weight_cls: 权重信息，默认加权方式为总市值加权
    :param detailed: 默认为 True, 如果为 False, 取因子最后一日的加权信息

    返回值
    ---
    :return: 因子数据, 包括因子值，因子对应行业
    """
    # 因子格式化
    factor = QA_fmt_factor(factor)
    merged_data = pd.DataFrame(factor.copy().rename("factor"))

    # 股票代码格式化
    code_list = factor.index.get_level_values(
        "code").drop_duplicates().tolist()
    # 非详细模式， 加权数据采用当前日期
    if detailed:
        # start_time = str(min(factor.index.get_level_values("datetime")))[:10]
        end_time = str(max(factor.index.get_level_values("datetime")))[:10]
        # date_range = list(
        #     map(pd.Timestamp, QA_util_get_trade_range(start_time, end_time))
        # )
        date_range = (
            factor.index.get_level_values(
                "datetime").drop_duplicates().tolist()
        )

    else:
        date_range = [pd.Timestamp(end_time)]

    if weight_cls == "avg":
        merged_data["weight"] = 1.0
        return merged_data

    df_local = QAAnalysis_block(
        code=code_list,
        start=date_range[0],
        end=date_range[-1]
    ).market_value
    if weight_cls == "mktcap":
        df_local = df_local.reset_index().pivot(
            index="date",
            columns="code",
            values="mv"
        )
    elif weight_cls == "sqrt_mktcap":
        df_local = (
            df_local.reset_index().pivot(
                index="date",
                columns="code",
                values="mv"
            ).transform("sqrt")
        )
    elif weight_cls == "ln_mktcap":
        df_local = (
            df_local.reset_index().pivot(
                index="date",
                columns="code",
                values="mv"
            ).transform("ln")
        )
    elif weight_cls == "cmktcap":
        df_local = df_local.reset_index().pivot(
            index="date",
            columns="code",
            values="liquidity_mv"
        )
    elif weight_cls == "sqrt_cmktcap":
        df_local = (
            df_local.reset_index().pivot(
                index="date",
                columns="code",
                values="liquidity_mv"
            ).transform("sqrt")
        )
    elif weight_cls == "ln_cmktcap":
        df_local = (
            df_local.reset_index().pivot(
                index="date",
                columns="code",
                values="liquidity_mv"
            ).transform("ln")
        )
    else:
        raise ValueError(f"{weight_cls} 加权方式未实现")
    merged_data["date"] = merged_data.index.get_level_values("datetime").map(
        lambda x: x.date()
    )
    merged_data = (
        merged_data.reset_index().set_index(
            ["date",
             "code"]
        ).assign(weight=df_local.stack()
                 ).reset_index().set_index(["datetime",
                                            "code"]).drop("date",
                                                          axis=1)
    )

    weight = merged_data["weight"].unstack().bfill().stack()
    merged_data["weight"] = weight
    return merged_data

def QA_fetch_get_factor_start_date(factor: pd.Series) -> pd.DataFrame:
    """
    获取因子池上市时间, 注意，请自行登陆聚宽本地 sdk

    参数
    ---
    :param factor: 因子值，索引为 ['日期' '资产']

    返回值
    ---
    :return: 因子数据
    """
    # 因子格式化
    factor = QA_fmt_factor(factor.copy())
    merged_data = pd.DataFrame(factor.rename("factor"))
    # 股票代码格式化
    stock_list = QA_fmt_code_list(
        factor.index.get_level_values("code").drop_duplicates(),
        style="jq"
    )
    # 上市时间获取
    df_local = jqdatasdk.get_all_securities(types="stock")
    intersection = df_local.index.intersection(stock_list)
    ss = df_local.loc[intersection]["start_date"]
    ss.index = ss.index.map(lambda x: x[:6])
    # 拼接上市时间
    merged_data = merged_data.loc[(slice(None), list(ss.index)), :]
    merged_data["start_date"] = merged_data.index.map(lambda x: ss.loc[x[1]]
                                                      ).tolist()
    return merged_data

def QA_fetch_factor_start_date(factor: pd.Series) -> pd.DataFrame:
    """
    获取因子池上市时间，本地获取接口，使用前先保存股票基本信息
    """
    factor = QA_fmt_factor(factor.copy())
    merged_data = pd.DataFrame(factor.rename("factor"))
    # 股票代码格式化
    stock_list = QA_fmt_code_list(
        factor.index.get_level_values("code").drop_duplicates()
    )
    # 上市时间获取
    df_local = QA_fetch_stock_basic(status=None).set_index("code")
    intersection = df_local.index.intersection(stock_list)
    ss = df_local.loc[intersection]["list_date"]
    # 拼接上市时间
    merged_data = merged_data.loc[(slice(None), list(ss.index)), :]
    merged_data["start_date"] = merged_data.index.map(lambda x: ss.loc[x[1]]
                                                      ).tolist()
    return merged_data

def QA_neutralize_factor(
        factor: pd.Series,
        weight_cls: str = "avg",
        industry: str = "sw_l1"
) -> pd.DataFrame:
    """
    行业中性处理

    参数
    ---
    :param factor: 因子值
    :param weight_cls: 加权方式
    :param industry_cls: 行业分类方式

    返回值
    ---
    :return: 中性化处理后的因子数据
    """
    if type(mkt_cap) == pd.Series:
        LnMktCap = mkt_cap.apply(lambda x: math.log(x))
        if industry:  # 行业、市值
            dummy_industry = get_industry_exposure(factor, date=date)
            x = pd.concat([LnMktCap, dummy_industry.T], axis=1)
        else:        # 仅市值
            x = LnMktCap
    elif industry:
        dummy_industry = get_industry_exposure(factor, date=date)
        x = dummy_industry.T
    return (sm.OLS(factor[factor], x.astype(float)).fit().resid.rename(factor),)


from watchdog.observers import Observer
from libs.models.spotify_pipelinerunner import SpotifyPipelineRunner
from libs.models.observer import PipelineHandler
import time

DB_PATH = r'./database/spotify.db'
INGEST_PATH = r'./data/ingest'
INVALIDE_DATA_PATH = r'./data/invalide'
FINISHED_DATA_PATH = r'./data/loaded'
CREATE_DB_TABLE_STATEMENT = r'./Task1/db/spotify_db_schema.sql'

def main():
    pipeline_runner = SpotifyPipelineRunner(    db_path=DB_PATH,
                                                invalide_data_path=INVALIDE_DATA_PATH,
                                                loaded_data_path= FINISHED_DATA_PATH,
                                                db_schema_path=CREATE_DB_TABLE_STATEMENT)
    event_handler = PipelineHandler(pipeline_runner)
    observer = Observer()
    observer.schedule(event_handler, path=INGEST_PATH, recursive=False)
    observer.start()

    try:
        while True:
            # Set the thread sleep time
            time.sleep(1)
    except KeyboardInterrupt:
        print('Stop')
        observer.stop()
    observer.join()

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
import datetime
import unittest
from bs4 import BeautifulSoup
from OperationForecast import OperationForecastDY
from webscraping import Scraper

class WebscrapingTest(unittest.TestCase):
    """[summary]
    Scraperクラスのユニットテストクラス
    """

    def test_scraping(self):
        """[summary]
        staticmethod(scraping)のテストメソッド
        """
        url = "https://xn--eckit8d4bznvdd3177e33ybsr0e.jp/time-table/202006"
        soup = Scraper.scraping(url)
        self.assertEqual(type(soup), BeautifulSoup)
        self.assertIsNotNone(soup)

class OperationForecastDYTest(unittest.TestCase):
    """[summary]
    OperationForecastDYクラスのユニットテストクラス
    """

    instance = None
    date_array = ("10月12日（日）", "1月1日（月）")

    # ここから独自メソッド
    def createinstance(self, urlparam : str =None):
        """[summary]
        コンストラクタ
            OperationForecastDYのインスタンスを生成する
        argument:
            urlparam    URLパラメータ
        """
        url = "https://xn--eckit8d4bznvdd3177e33ybsr0e.jp/time-table/"
        self.instance = OperationForecastDY(url, urlparam)

    # ここからテストメソッド
    def setUp(self):
        """[summary]
        ユニットテスト実行前処理を行うメソッド
        createinstanceを実行して、テスト対象クラスのインスタンスを生成する
        """
        self.createinstance()

    def test_constructor(self):
        """[summary]
        コンストラクタのテストメソッド
        """

        # urlparamなし
        self.assertIsNotNone(self.instance.url_)
        self.assertIsNotNone(self.instance.soup_)
        expect_tag = datetime.datetime.now().strftime('%Y%m')
        self.assertEqual(self.instance.tag_, expect_tag)

        # urlparamあり
        urlparam = "202006"
        self.createinstance(urlparam)
        self.assertIsNotNone(self.instance.url_)
        self.assertIsNotNone(self.instance.soup_)
        expect_tag = urlparam
        self.assertEqual(self.instance.tag_, expect_tag)

    def test_convertdate(self):
        """[summary]
        convertdateのテストメソッド
        """
        expect_array = ('2020/10/12', '2020/01/01')
        expect_index = 0
        for dateval in self.date_array:
            self.assertEqual(self.instance.convertdate(dateval), expect_array[expect_index])
            expect_index += 1

    def test_convertweek(self):
        """[summary]
        convertweekのテストメソッド
        """
        expect_array = ('日', '月')
        expect_index = 0
        for dateval in self.date_array:
            self.assertEqual(self.instance.convertweek(dateval), expect_array[expect_index])
            expect_index += 1

    def test_extractData(self):
        """[summary]
        extractDataのテストメソッド
        """
        data = self.instance.extractData()
        self.assertIsNotNone(data)

if __name__ == "__main__":
    unittest.main()


#!/usr/bin/env python3
"""
Read file into texts and calls.
It's ok if you don't understand how to read files
"""
import csv
with open('texts.csv', 'r') as f:
    reader = csv.reader(f)
    texts = list(reader)

with open('calls.csv', 'r') as f:
    reader = csv.reader(f)
    calls = list(reader)

"""
TASK 2: Which telephone number spent the longest time on the phone
during the period? Don't forget that time spent answering a call is
also time spent on the phone.
Print a message:
"<telephone number> spent the longest time, <total time> seconds, on the phone during
September 2016.".
"""
import operator

def get_longest_time(calls):

    phones_times = {}
    #First record
    max_key_value = ( "", 0 )

    # count = 0
    for rec in calls:

        caller = rec[0]
        receiver = rec[1]
        seconds = int(rec[3])

        if phones_times.get(caller):
            phones_times[caller] += seconds
        else:
            phones_times[caller] = seconds

        if phones_times.get(receiver):
            phones_times[receiver] += seconds
        else:
            phones_times[receiver] = seconds

        #Compare and add maximum value to max_key_value
        if phones_times[caller] >= max_key_value[1]:
            max_key_value = ( caller, phones_times[caller] )
        if phones_times[receiver] >= max_key_value[1]:
            max_key_value = ( receiver, phones_times[receiver] )

    return {
        "number": max_key_value[0],
        "time": max_key_value[1]
        }

longest_time = get_longest_time(calls)

print(
f"{longest_time['number']} spent the longest time, {longest_time['time']} seconds, \
on the phone during September 2016."
)


#!/usr/bin/env python

import sys
import os
import re
import logging
import argparse
import pandas as pd
import gzip
import urllib.request as ul
from Bio import Entrez
from Bio.SeqIO.FastaIO import SimpleFastaParser

__author__ = "Fong Yoke"
__license__ = "MIT"
__email__ = "bldmyoke@gmail.com"

def search_assembly_db(user_email, search_term, max_retrieval="1000"):
        """Download assembly db from  NCBI
        """

        Entrez.email = user_email
        handle = Entrez.esearch(db = "assembly", term = search_term, retmax = max_retrieval)
        record = Entrez.read(handle)
        return record

def get_assembly_summary(user_email, search_term, logger):
        """Download assembly summary for the search_term taxa
        Return dict
        """
        logger.info(f"Getting metadata from NCBI using account: {user_email} ")

        uid_list = search_assembly_db(user_email, search_term)["IdList"]
        str_uid_list = ",".join(uid_list)
        handle = Entrez.esummary(db = "assembly", id = str_uid_list)
        record = Entrez.read(handle)
        summary = record["DocumentSummarySet"]["DocumentSummary"]

        return summary

def download_summary(summary, outdir):
    """ Summary to df format, prior to download
    """
    final_df = []
    for uid, item in enumerate(summary):
        assembly_entry = []

        name = item["AssemblyName"]
        name = re.sub(" ", "_", name)
        assembly_entry.append(name)

        url = item["FtpPath_GenBank"]
        label = os.path.basename(url)
        link = os.path.join(url, label + "_genomic.fna.gz")
        assembly_entry.append(link)

        final_df.append(assembly_entry)

    final_df = pd.DataFrame(final_df)
    final_df.columns = ["assembly name", "link"]

    # check assembly names are unique
    dupls = final_df["assembly name"].value_counts() > 1
    dupls = dupls[dupls].index.tolist()

    for dupl in dupls:
        for idx, ind  in enumerate(final_df.loc[final_df["assembly name"] == dupl, :].index.tolist()):
            suffix = str.lower(chr(65 + idx))
            final_df.loc[ind, "assembly name"]  = final_df.loc[ind, "assembly name"] + suffix

    return final_df

def download_assemblies(processed_df, outdir, logger):
    """Download assemblies
    """
    failed_files = []
    for uid, item in enumerate(processed_df.to_dict(orient = "records")):
        # sys.stderr.write(item)
        name = item["assembly name"]
        name = re.sub(" ", "_", name)

        url = item["link"]
        # label = os.path.basename(url)
        # link = os.path.join(url, label + "_genomic.fna.gz")

        filename = os.path.join(outdir, f"{name}.fasta")

        try:
            if os.path.exists(filename) and os.path.getsize(filename) > 0:
                logger.info(f"Assembly file {outdir}/{name}.fasta already exists")
            else:
                logger.info(f"Downloading assembly {name} to {outdir}/{name}.fasta from {url}")
                zip_file = ul.urlopen(url)

                with open(filename, "w") as f:
               	    f.write(gzip.decompress(zip_file.read()).decode("UTF8"))
        except:
            failed_files.append(url)
            os.remove(filename)

    # Trace failed files
    if len(failed_files) > 0:
        print(f"Number of failed downloads: {len(failed_files)}")
        for failed in failed_files:
            print(failed)

def get_assembly_features(assembly_file):
    """Get assembly size and number of contigs
    """
    assembly_size = 0
    number_of_contigs = 0

    with open(assembly_file, "r") as f:
        for title, seq in SimpleFastaParser(f):
            number_of_contigs += 1
            assembly_size += len(seq)

    return assembly_size, number_of_contigs

def give_summary(summary, outdir):
    """ Create assembly metadata
    The metadata are:
    - assembly accession
    - assembly name
    - species name
    - isolate ID
    - assembly release date
    - submitter
    - scaffold N50
    """
    final_df = []
    for uid, item in enumerate(summary):
        assembly_entry = []
        assembly_entry.append(item["AssemblyAccession"])

        name = item["AssemblyName"]
        name = re.sub(" ", "_", name)
        assembly_entry.append(name)

        final_df.append(assembly_entry)

    final_df = pd.DataFrame(final_df)
    final_df.columns = ["assembly accession", "assembly name"]

    # check assembly names are unique
    dupls = final_df["assembly name"].value_counts() > 1
    dupls = dupls[dupls].index.tolist()

    for dupl in dupls:
        for idx, ind  in enumerate(final_df.loc[final_df["assembly name"] == dupl, :].index.tolist()):
            suffix = str.lower(chr(65 + idx))
            final_df.loc[ind, "assembly name"] = final_df.loc[ind, "assembly name"] + suffix

    final_df["species name"] = [item["SpeciesName"] for item in summary]
    final_df["isolate ID "] = [item["Biosource"]["Isolate"] for item in summary]
    final_df["assembly release date"] = [item["AsmReleaseDate_GenBank"] for item in summary]
    final_df["submitter"] = [item["SubmitterOrganization"] for item in summary]
    final_df["scaffold N50"] = [item["ScaffoldN50"] for item in summary]

    col_assem_size = []
    col_n_contigs = []

    for name in final_df["assembly name"].tolist():
        assembly_file = os.path.join(outdir, f"{name}.fasta")
        print(assembly_file)
        assembly_size, number_of_contigs = get_assembly_features(assembly_file)
        col_assem_size.append(assembly_size)
        col_n_contigs.append(number_of_contigs)

    final_df["assembly_size"] = col_assem_size
    final_df["number_of_contigs"] = col_n_contigs

    return final_df

def parse_args(args):
    """Argument parsers
    """
    parser = argparse.ArgumentParser(description = "Download genomes using NCBI entrez and get assembly summary")
    parser.add_argument("-e", "--email_address",
        required = True,
        dest = "email_address",
        help = "Email address (required)")

    parser.add_argument("-t", "--taxa_name",
        required = True,
        dest = "taxa_name",
        help = "Taxa name, E.g. \"Rokubacteria\"")

    parser.add_argument("-o", "--outdir",
        required = True,
        dest = "outdir",
        help = "Output directory")
    if not args:
        parser.print_help(sys.stderr)
        sys.exit()
    return parser.parse_args(args)

def main():
    """Main function
    """
    args = sys.argv[1:]
    args = parse_args(args)

    logger = logging.getLogger("download genomes")
    logger.setLevel(logging.INFO)
    sh = logging.StreamHandler()
    sh.setFormatter(logging.Formatter("%(asctime)s - %(message)s"))
    logger.addHandler(sh)

    os.makedirs(args.outdir, exist_ok = True)

    summary = get_assembly_summary(args.email_address, args.taxa_name, logger)
    processed_summary = download_summary(summary, args.outdir)
    download_assemblies(processed_summary, args.outdir, logger)

    df = give_summary(summary, args.outdir)
    df.to_csv(os.path.join(args.outdir, "assembly_summary.csv"), sep = "\t", index = False)

if __name__ == "__main__":
    main()


""" Chris Milson April 2020
Problem 20

n! means n * (n - 1) * ... * 3 * 2 * 1.

For example, 10! = 10 * 9 * ... * 2 * 1 = 3628800,
and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.

Find the sum of the digits in the number 100!

Answer : 648
"""

def factorialDigits(n):
  """
  Returns a number with the same digits as n! but with the zeros clipped off.
  """
  assert(n >= 0)
  dp = 1
  for i in range(1, n + 1):
    dp *= i
    while not dp % 10: dp //= 10
  return dp

def digitSum(n):
  result = 0
  while n > 0:
    result += n % 10
    n //= 10
  return result

print(digitSum(factorialDigits(100)))


import numpy as np
import torch
from torch.utils.data import DataLoader
from util.loaders import *
import pickle

def buildlibrary(jpgklass, jpg2words, Network, model, enc, savepath, path = "nv_txt/", elements = 2):
    complete_dataset = Triplet_loaderbh_Textvlad(jpgklass, jpg2words, elements, path,
                                                 '/media/presage3/Windows-SSD/images/jpeg_patch/', Network, enc)
    complete_dataset.testing = True
    train_loader = DataLoader(complete_dataset, batch_size=32, shuffle=False)

    dict = {"names": [], "embeds": np.array([])}
    for ids, data in enumerate(train_loader):
        textual, nv, klass, indices = data
        embeds = model.get_embedding(textual.reshape([-1, 1280]), nv.reshape([-1, 4096])).cpu().detach().numpy()
        nv = nv.detach().cpu().numpy()
        if ids == 0:
            dict['embeds'] = embeds
            dict['netvlad'] = nv
        else:
            dict['embeds'] = np.concatenate([dict['embeds'], embeds], axis=0)
            dict['netvlad'] = np.concatenate([dict['netvlad'], nv], axis=0)

        for itera, u in enumerate(klass):
            dict["names"].append(jpgklass[u.item()][indices[itera][0].item()])
            dict["names"].append(jpgklass[u.item()][indices[itera][1].item()])

        if (ids + 1) % 1 == 0:
            print("Building Library: {} / {} ".format(ids + 1, train_loader.__len__()))

    with open(savepath, "wb") as q:
        pickle.dump(dict, q)

    return dict


def listaraluno ():
    id = int(input("informe o id do aluno: "))

    arquivo = open("sempescoco.csv", "r")

    conteudo = arquivo.readlines()
    exist = False
    for i in range(2,len(conteudo)):
        perereca = conteudo[i].split(";")
        if (int(perereca[0]) == id):
            exist = True
            print( "id:"+ perereca[0])
            print( "nome:"  + perereca[1])
            print("matricula:"+perereca[2])
            print( "idade:"+ perereca[3])
            print("nota:"+perereca[4])

    if not exist:
        print("alumo nao existe")

    arquivo.close()

listaraluno()


import copy
import random
import math
import matplotlib.pyplot as plt

N = 10
P = 2

worst_individuals = []
average = []

class Individual:
    def __init__(self):
        self.gene = [0]*N
        self.fitness = 0

def initialise_population():
    pop = []

    for x in range(0, P):
        temp_gene = []
        for n in range(0, N):
            r = random.uniform(1, 10)
            r = int(r)
            temp_gene.append(r)     # Create a gene of the float values

        new_ind = Individual()
        new_ind.gene = temp_gene.copy()
        pop.append(new_ind)

    return pop

population = initialise_population()

for obj in population:
    print(obj.gene)

def fitness_value_st(pop):

    for ind in pop:
        gene = copy.deepcopy(ind.gene)
        fitness = 0            # Give fitness value to a chosen population

        for i in range(0, N):
            x = gene[i]
            sigma = x * x * x * x
            multiply = x * x
            multiply *= 16
            sigma -= multiply
            multiply = 5 * x
            sigma += multiply

            fitness += sigma

        fitness /= 2
        ind.fitness = fitness

fitness_value_st(population)
for obj in population:
    print(obj.gene, obj.fitness)


# -*- coding: utf-8 -*-
from django.shortcuts import *
from django.http import *

from contest.forms import *
from contest.models import *
from contest.crawler import *
from contest.email_reply import *

import json

def feedback(request, contest_id):
    feedbackform = FeedbackForm(
        request.POST,
        instance=Feedback(cid=contest_id))
    if feedbackform.is_valid():
        feedbackform.save()
        return render(
            request,
            'form.html',
            {'form': FeedbackForm(), 'message': '您已成功傳送訊息'})
    else:
        return render(request, 'form.html', {'form': feedbackform})

def signup(request, contest_id):
    contest_data = Contest.objects.filter(cid=contest_id).first()
    signupform = SignUpForm(request.POST, instance=SignUp(cid=contest_id))
    if signupform.is_valid():
        signupform.save()
        signup_reply(contest_data, request)
        return render(
            request,
            'form.html',
            {'form': SignUpForm(), 'message': '您已成功傳送訊息'})
    else:
        return render(request, 'form.html', {'form': signupform})

def clarification(request, contest_id):
    contest_data = Contest.objects.filter(cid=contest_id).first()
    clarificationform = ClarificationForm(
        request.POST,
        instance=Clarification(
            asker='',
            cid=contest_id,
            reply='No reply yet.'))
    if clarificationform.is_valid() and contest_data:
        clar = clarificationform.save(commit=False)
        clar.asker = 'Anonymous' if clar.asker == '' else clar.asker
        clar.save()
        clarification_reply(contest_data, request)
        return render(
            request,
            'form.html',
            {'form': ClarificationForm(), 'message': '您已成功傳送訊息'})
    else:
        return render(request, 'form.html', {'form': clarificationform})

def contest(request, contest_id):
    contest_data = get_object_or_404(Contest, cid=contest_id)
    render_data = {}

    if contest_data:
        if request.is_ajax():
            data = {
                'scoreboard_table': str(get_scoreboard(contest_data)),
                'clarification_table': str(get_clarification(contest_data))
            }
            return HttpResponse(json.dumps(data))

        render_data['signup_form'] = SignUpForm()
        render_data['feedback_form'] = FeedbackForm()
        render_data['clarification_form'] = ClarificationForm()

        render_data['problem_table'] = get_problem(contest_data)
        render_data['contest_data'] = contest_data

    return render(request, 'contest.html', render_data)

def rank(request, contest_id):
    contest_data = get_object_or_404(Contest, cid=contest_id)
    render_data = {}

    if contest_data:
        signups = SignUp.objects.filter(cid=contest_id)
        table = get_scoreboard(contest_data)
        soup = BeautifulSoup(table)

        oj_ids = [str(x.nthu_oj_id.lower()) for x in signups]
        rank_list = []

        for tr in soup.find_all('tr'):
            tds = tr.find_all('td')
            if tds:
                oj_id = tds[0].string
                rank_list += [str(oj_id)]

        prizes = []
        place = 1
        for x in rank_list:
            if x.lower() in oj_ids:
                user = signups.filter(nthu_oj_id__iexact=x).first()
                prizes += [{'place': place,
                            'ojid': user.nthu_oj_id,
                            'email': user.email,
                            'name': user.name}]
                place += 1

        render_data['prizes'] = prizes
        render_data['scoreboard_table'] = table
    return render(request, 'rank.html', render_data)

def competitor(request, contest_id):
    contest_data = get_object_or_404(Contest, cid=contest_id)
    render_data = {}

    return render(request, 'competitor.html', render_data)


from flask import Flask, url_for, render_template, redirect, request
from flask.ext.sqlalchemy import SQLAlchemy
import os
from sqlalchemy import  create_engine

# engine = create_engine('postgresql+psycopg2://MasterControl@localhost:5000/SSItesting')

# from SSItesting.ssitesting import db_session

# login_manager = LoginManager()

app = Flask(__name__)

app.config.from_object(os.environ['APP_SETTINGS'])
db = SQLAlchemy(app)

from models import Result

# login_manager.init_app(app)

# @login_manager.user_loader
# def load_user(user_id):
#     return User.get(user_id)

# @app.route('/signup')
# def signup():
#     return render_template("signup.html")

# @app.route('/login', methods=['GET', 'POST'])
# def login():
#     error = None
#     if request.method == 'POST':
#         if request.form['username'] != 'admin' or request.form['password'] != 'admin':
#             error = 'Invalid credentials.  Please Try Again.'
#         else:
#           return redirect(url_for('home.html'))
#     return render_template("login.html", error=error)

@app.route('/')
def home():
    return render_template("home.html")

@app.route('/<name>')
def hello_name(name):
    return "Hello {}!".format(name)

# @app.route('/login')
# def login():
#     return render_template("login.html")

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()

if __name__ == '__main__':
     app.debug = True
     app.run()


from __future__ import annotations

import os
from pathlib import Path

from setuptools import find_packages, setup

here = Path(__file__).parent.resolve()

def get_version():
    if os.getenv("GITHUB_REF_TYPE", "branch") == "tag":
        return os.environ["GITHUB_REF_NAME"]

    version_file = here / "onetl" / "VERSION"
    version = version_file.read_text().strip()

    build_num = os.getenv("GITHUB_RUN_ID", "0")
    branch_name = os.getenv("GITHUB_REF_NAME", "")

    if not branch_name:
        return version

    return f"{version}.dev{build_num}"

def parse_requirements(file: Path) -> list[str]:
    lines = file.read_text().splitlines()
    return [line.rstrip() for line in lines if line and not line.startswith("#")]

requirements_core = parse_requirements(here / "requirements" / "core.txt")

requirements_ftp = parse_requirements(here / "requirements" / "ftp.txt")
requirements_sftp = parse_requirements(here / "requirements" / "sftp.txt")
requirements_samba = parse_requirements(here / "requirements" / "samba.txt")
requirements_hdfs = parse_requirements(here / "requirements" / "hdfs.txt")
requirements_s3 = parse_requirements(here / "requirements" / "s3.txt")
requirements_webdav = parse_requirements(here / "requirements" / "webdav.txt")
requirements_files = [*requirements_ftp, *requirements_sftp, *requirements_hdfs, *requirements_s3, *requirements_webdav]

requirements_kerberos = parse_requirements(here / "requirements" / "kerberos.txt")
requirements_spark = parse_requirements(here / "requirements" / "spark.txt")
requirements_all = [*requirements_files, *requirements_kerberos, *requirements_spark]

long_description = (here / "README.rst").read_text()

setup(
    name="onetl",
    version=get_version(),
    author="DataOps.ETL",
    author_email="onetools@mts.ru",
    description="One ETL tool to rule them all",
    long_description=long_description,
    long_description_content_type="text/x-rst",
    license="Apache License 2.0",
    license_files=("LICENSE.txt",),
    url="https://github.com/MobileTeleSystems/onetl",
    classifiers=[
        "Development Status :: 3 - Alpha",
        "Framework :: Pydantic",
        "Framework :: Pydantic :: 1",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: Apache Software License",
        "Operating System :: OS Independent",
        "Programming Language :: Python :: 3 :: Only",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Topic :: Software Development :: Libraries",
        "Topic :: Software Development :: Libraries :: Java Libraries",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Topic :: System :: Distributed Computing",
        "Typing :: Typed",
    ],
    project_urls={
        "Documentation": "https://onetl.readthedocs.io/",
        "Source": "https://github.com/MobileTeleSystems/onetl",
        "CI/CD": "https://github.com/MobileTeleSystems/onetl/actions",
        "Tracker": "https://github.com/MobileTeleSystems/onetl/issues",
    },
    keywords=["Spark", "ETL", "JDBC", "HWM"],
    packages=find_packages(exclude=["docs", "docs.*", "tests", "tests.*"]),
    entry_points={"tricoder_package_spy.register": ["onetl=onetl"]},
    python_requires=">=3.7",
    install_requires=requirements_core,
    extras_require={
        "spark": requirements_spark,
        "ftp": requirements_ftp,
        "ftps": requirements_ftp,
        "sftp": requirements_sftp,
        "samba": requirements_samba,
        "hdfs": requirements_hdfs,
        "s3": requirements_s3,
        "webdav": requirements_webdav,
        "files": requirements_files,
        "kerberos": requirements_kerberos,
        "all": requirements_all,
    },
    include_package_data=True,
    zip_safe=False,
)


import random
import string
print(" <<welcome to my haangman>>")
x=int(input(" enter the length of the word :"))
letters=string.ascii_lowercase
word=''.join(random.choice(letters) for i in range(x))
print("-"*x)
chance=5 # total no of chnces left by the user
while chance!=0:
    guess=input(" enter the character :")
    c=0
    for i in word:
        if guess == i:
            c+=1
    print('the charcter is present in the word', c, " times")
    chance-=1
y=input(" ENTER YOUR WORD")
if y== word:
    print(" you won the game")
else:
    print(' the word was', word)
    print(" you lose")


import pandas as pd

# Take user input for balance sheet items
assets = float(input("Enter total assets: "))
liabilities = float(input("Enter total liabilities: "))
equity = float(input("Enter total equity: "))

# Create balance sheet table
data = {'Category': ['Assets', 'Liabilities', 'Equity'],
        'Amount': [assets, liabilities, equity]}
balance_sheet = pd.DataFrame(data)

# Take user input for projected income statement items
revenue = float(input("Enter projected revenue: "))
expenses = float(input("Enter projected expenses: "))
net_income = revenue - expenses

# Create projected income statement table
data = {'Category': ['Revenue', 'Expenses', 'Net Income'],
        'Amount': [revenue, expenses, net_income]}
projected_income_statement = pd.DataFrame(data)

# Take user input for ratio analysis items
current_assets = float(input("Enter current assets: "))
current_liabilities = float(input("Enter current liabilities: "))
current_ratio = current_assets / current_liabilities

# Create ratio analysis table
data = {'Ratio': ['Current Ratio'],
        'Value': [current_ratio]}
ratio_analysis = pd.DataFrame(data)

# Take user input for projected cash flow statement items
operating_cash_flow = float(input("Enter operating cash flow: "))
investing_cash_flow = float(input("Enter investing cash flow: "))
financing_cash_flow = float(input("Enter financing cash flow: "))
net_cash_flow = operating_cash_flow + investing_cash_flow + financing_cash_flow

# Create projected cash flow statement table
data = {'Category': ['Operating Cash Flow', 'Investing Cash Flow', 'Financing Cash Flow', 'Net Cash Flow'],
        'Amount': [operating_cash_flow, investing_cash_flow, financing_cash_flow, net_cash_flow]}
projected_cash_flow_statement = pd.DataFrame(data)

# Take user input for fixed assets calculation items
fixed_assets_cost = float(input("Enter fixed assets cost: "))
accumulated_depreciation = float(input("Enter accumulated depreciation: "))
net_fixed_assets = fixed_assets_cost - accumulated_depreciation

# Create fixed assets calculation table
data = {'Category': ['Fixed Assets Cost', 'Accumulated Depreciation', 'Net Fixed Assets'],
        'Amount': [fixed_assets_cost, accumulated_depreciation, net_fixed_assets]}
fixed_assets_calculation = pd.DataFrame(data)

# Display all tables
print("Balance Sheet")
print(balance_sheet)
print("\nProjected Income Statement")
print(projected_income_statement)
print("\nRatio Analysis")
print(ratio_analysis)
print("\nProjected Cash Flow Statement")
print(projected_cash_flow_statement)
print("\nFixed Assets Calculation")
print(fixed_assets_calculation)


import os
import numpy as np
from keras.applications.resnet50 import preprocess_input
from keras.preprocessing import image
from keras.utils.np_utils import to_categorical
import argparse
import utils
import glob
import pickle
from dataset import Dataset

dataset = Dataset(dataset='viper')
N_CLUSTER = 3

def generate_labels_for_gan():
    image_labels = {}
    f = open('/home/paul/datasets/viper/train.list', 'r')
    old_lbl = -1
    # Get a dictionnary of current ids in train set
    for line in f:
        line = line.strip()
        img, lbl = line.split()
        lbl = int(lbl)
        if lbl != old_lbl:
            splt = img.split('_')
            image_labels[splt[0]] = int(lbl)
            old_lbl = lbl
    f.close()
    for n_cluster in range(N_CLUSTER):
        cluster_path = os.path.join(dataset.cluster_path(), 'cluster_%s' % n_cluster)
        cluster_labels = {}
        cluster_imgs = glob.glob(os.path.join(cluster_path, '*.jpg'))
        cluster_imgs = sorted(cluster_imgs)
        for img in cluster_imgs:
            img = os.path.basename(img)
            splt = img.split('_')
            try:
                cluster_labels[splt[0]] += 1
            except KeyError:
                cluster_labels[splt[0]] = 1
        # build the idx
        f = open(os.path.join(dataset.cluster_path(), 'gan%s.list' % n_cluster), 'w')
        for i in cluster_labels:
            print(i)
            #if cluster_labels[i] > 4:
            f.write("%s\n" % image_labels[i])
        f.close()
        print(image_labels[i])
        # build the idx

def load_gan(gan_path, n_gan_images):
    return get_gan_data(n_gan_images)

def get_gan_data(n_gan_images):
    images = dict()
    labels = []
    # Get the labels for each gan set and save in array labels
    for i in range(N_CLUSTER):
        f = open(os.path.join(dataset.cluster_path(), 'gan%s.list' % i), 'r')
        tmp_labels = np.zeros(shape=dataset.n_classe(), dtype=np.int32)
        for line in f:
            lbl = line.strip()
            tmp_labels[int(lbl)] = 1
        f.close()
        labels.append(tmp_labels)
    labels = np.array(labels)
    n_gan = int(np.floor(n_gan_images / N_CLUSTER + 1))
    data_list = None
    for i in range(N_CLUSTER):
        gan_list = glob.glob(os.path.join(dataset.gan_path(), 'gan_%s*.jpg' % i))
        gan_list = gan_list[:n_gan]
        if data_list is None:
            data_list = gan_list
        else:
            data_list = np.concatenate((data_list, gan_list), axis=0)

    data_list = np.unique(data_list)
    np.random.shuffle(data_list)
    data_list = data_list[:n_gan_images]
    assert len(data_list) == n_gan_images

    for i, filename in enumerate(data_list):
        img_name = os.path.basename(filename)
        lbl = int(img_name.split('_')[1])
        try:
            images[str(lbl)].append(img_name)
        except KeyError:
            images[str(lbl)] = list()
            images[str(lbl)].append(img_name)

    labels = np.array(labels)

    assert np.sum([len(images[i]) for i in images]) == n_gan_images
    print(images)
    assert len(images) == labels.shape[0]
    assert labels.shape[1] == dataset.n_classe()
    return images, labels

if __name__ == '__main__':
    generate_labels_for_gan()
    #images, labels = get_gan_data(2000)
    #pickle.dump((images, labels), open('/home/fstu1/datasets/gan_data', 'wb'), protocol=2)
    print()
    print('Generated GAN data saved')


#exercício 3.10
salario = float(input("Digite seu salário: "))
porcentagem = float(input("Digite a porcentagem do aumento: "))

aumento = salario * porcentagem / 100
novo_salario = salario + aumento

print("O aumento foi de R$%.1f." %aumento)
print("O novo salário é R$%.2f." %novo_salario)

Python/Introdução à programação com Python - Nilo Ney/Capítulo 3/exercício 3.10.py


from __future__ import absolute_import

import laia.common.logging as log
import numpy as np
from scipy.spatial.distance import pdist

from laia.meters import Meter
from laia.utils.accumulate import accumulate

_logger = log.get_logger(__name__)

class PairwiseAveragePrecisionMeter(Meter):
    r"""Compute Average Precision over pairs of objects using some metric.

    When a set of examples are added, its feature vectors and labels are
    given and stored in the ``PairwiseAveragePrecisionMeter`` object.
    The actual computation of the Average Precision will be done once the
    ``value`` property of the object is accessed.

    Then, the specified ``metric`` is used to measure all pairs of objects
    and these pairs are sorted in increasing order to compute both the
    Global and Mean Average Precision.

    *Important*: Self-pairs are ignored to compute the Average Precision.

    Args:
      metric (function, str): metric used to sort the pairs of objects
          (in increasing order). You can use the same metrics accepted by
          SciPy's ``pdist``.
      ignore_singleton (boolean, default: True): if true, ignore objects
          whose label is not shared with any other object.
    """

    def __init__(
        self,
        metric="euclidean",
        ignore_singleton=True,
        exceptions_threshold=5,
        exclude_labels=None,
    ):
        super(PairwiseAveragePrecisionMeter, self).__init__(exceptions_threshold)
        self._metric = metric
        self._features = []
        self._labels = []
        self._label_count = {}
        self._ignore_singleton = ignore_singleton
        self._gap, self._map = None, None
        self._exclude_labels = exclude_labels
        # This is only to detect whether the metric is valid or not.
        _ = pdist([[1, 1], [1, 1]], metric)

    @property
    def logger(self):
        return _logger

    def reset(self):
        self._features = []
        self._labels = []
        self._label_count = {}
        self._gap, self._map = None, None
        return self

    def add(self, features, labels):
        r"""Add objects to the set used to compute the AP."""
        # If anything was computed, reset
        self._gap, self._map = None, None

        features = np.asarray(features)
        assert isinstance(labels, (list, tuple))

        self._features.append(features)
        self._labels.extend(labels)
        for c in labels:
            cnt = self._label_count.get(c, 0)
            self._label_count[c] = cnt + 1
        return self

    def _compute(self):
        # Concatenate all feature tensors (batches).
        all_features = np.concatenate(self._features)
        if self._ignore_singleton:
            mask = [i for i, c in enumerate(self._labels) if self._label_count[c] > 1]
            all_features = all_features[mask]
            all_labels = [c for c in self._labels if self._label_count[c] > 1]
        else:
            all_labels = self._labels
        if self._exclude_labels:
            mask = [
                i for i, c in enumerate(all_labels) if c not in self._exclude_labels
            ]
            all_features = all_features[mask]
            all_labels = [c for c in all_labels if c not in self._exclude_labels]

        n = all_features.shape[0]  # number of objects
        self.logger.debug("Compute Average Precision over {} samples", n)
        distances = pdist(all_features, self._metric)
        # Sort pairs of examples in increasing order
        inds = [(i, j) for i in range(n) for j in range(i + 1, n)]
        inds = [inds[k] for k in np.argsort(distances)]

        events = []
        events_i = [[] for _ in range(n)]
        for (i, j) in inds:
            if all_labels[i] == all_labels[j]:
                events.append(1.0)
                events_i[i].append(1.0)
                events_i[j].append(1.0)
            else:
                events.append(0.0)
                events_i[i].append(0.0)
                events_i[j].append(0.0)

        if events:
            # Compute Global and Mean Average Precision
            g_ap = self._compute_ap_ranked_events(events)
            aps = [self._compute_ap_ranked_events(e) for e in events_i if len(e) > 0]
            m_ap = sum(aps) / len(aps)
            return g_ap, m_ap
        return 0.0, 0.0

    @classmethod
    def _compute_ap_ranked_events(cls, events):
        r"""Compute the average precision of a ranked list of events.

        Each event should be 1.0 if it is relevant or 0.0 if it is not
        relevant.
        """
        # Compute accumulated hits at each position in the ranking
        hits = list(accumulate(events))
        # Compute precision at each position in the ranking
        prec = [h / k for k, h in enumerate(hits, 1)]

        num = sum(p * r for p, r in zip(prec, events))
        den = hits[-1]
        if den > 0:
            return num / den
        # Handle the case where there aren't relevant events.
        return 0.0

    @property
    def value(self):
        r"""Return the Global and Mean Average Precision."""
        if self._gap is None or self._map is None:
            self._gap, self._map = self._compute()
        return self._gap, self._map


arr = [3,9,2,7,10,6,5,8,1]

def partition(arr,left,right):
    pivot = arr[left]
    i, j = left,right

    while i<j:
        while pivot < arr[j]:
            j-=1

        while i<j and pivot >= arr[i]:
            i+=1
        arr[i], arr[j] = arr[j], arr[i]

    arr[left] = arr[i]
    arr[i] = pivot
    return i

def quick_sort(arr,left,right):
    if left >= right:
        return

    pivot = partition(arr,left,right)
    quick_sort(arr,left,pivot-1)
    quick_sort(arr,pivot+1,right)

quick_sort(arr,0,len(arr)-1)
print(arr)


from rest_framework import routers

from investment.views import PortfolioViewSet, AccountViewSet, TransactionViewSet, CurrencyViewSet, InstrumentViewSet

router = routers.DefaultRouter()
router.register("portfolio", PortfolioViewSet, basename="portfolio")
router.register("account", AccountViewSet, basename="account")
router.register("transaction", TransactionViewSet, basename="transaction")
router.register("currency", CurrencyViewSet, basename="currency")
router.register("instrument", InstrumentViewSet, basename="instrument")

urlpatterns = router.urls


n = int(input())
ans = 0
for a in range(1, n+1):
    if a*a*a > n:
        break
    for b in range(a, n+1):
        if a*b*b > n:
            break
        ab = a*b
        cmi = b
        cma = n//ab
        ans += cma - cmi + 1
print(ans)


import json

from flask import jsonify, make_response

def handle(req):
    print('MetaController-FAAS')
    req_json = json.loads(req)
    parent = req_json['parent']
    children = req_json['children']
    # Compute status based on observed state.
    desired_status = {
        "pods": len(children["Pod.v1"])
    }

    print("len(children[Pod.v1] = " + str(len(children["Pod.v1"])))
    print("parent[metadata][name] = " + parent["metadata"]["name"])

    # Generate the desired child object(s).
    who = parent.get("spec", {}).get("who", "World")
    print("who = " + who)
    desired_pods = [
        {
            "apiVersion": "v1",
            "kind": "Pod",
            "metadata": {
                "name": parent["metadata"]["name"]
            },
            "spec": {
                "restartPolicy": "OnFailure",
                "containers": [
                    {
                        "name": "hello",
                        "image": "busybox",
                        "command": ["echo", "Hello, %s!" % who]
                    }
                ]
            }
        }
    ]

    output = {"status": desired_status, "children": desired_pods}

    print(output)

    return make_response(jsonify(output), 200, {'Content-Type': 'application/json'})


try:
	def main():
		l = True
		while l == True:
			a 	  = int(input("a = "))#9
			x = int(input("x = "))#45

			ress = x/a
			result = ress**3

			print(f"\nx = {result}\n======")
	main()
except KeyboardInterrupt:
	print("\nGoodBye!")


# RL-based Dogfight Simulator
# Developed by, Batuhan ATASOY, Ph.D. Mechatronics Engineering

import pygame
import random as rn
import math
import matplotlib.pyplot as plt
import numpy as np

from collections import deque
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam

fps=60

#%% Environment Class
class Env:
    def __init__(self,dimensions):
        # Initializing Colors
        self.white=(255,255,255)
        self.black=(0,0,0)
        self.red=(255,0,0)
        self.green=(0,255,0)
        self.blue=(0,0,100)

        # World Generation
        self.height=dimensions[0]
        self.width=dimensions[1]
        self.trail_set=[]

        # World Settings
        pygame.display.set_caption('RL-based Dogfight Simulator')
        self.map=pygame.display.set_mode((self.height,self.width))

    def trail(self,pos):
        for i in range(0,len(self.trail_set)-1):
            pygame.draw.line(self.map,self.yel,(self.trail_set[i][0],self.trail_set[i][1]),(self.trail_set[i+1][0],self.trail_set[i+1][1]))
            if self.trail_set.__sizeof__()>30000:
                self.trail_set.pop(0)
            self.trail_set.append(pos)

#%% Agent Class
class Player:
    def __init__(self,startpos,robotimg,width):

        # Initialization
        #self.m2p=3779.52
        self.m2p=500
        self.k=0
        self.act='Forward'

        # Player Positions
        self.w=width/100
        self.x=startpos[0]
        self.y=startpos[1]
        self.theta=0
        self.vl=0.01*self.m2p
        self.vr=0.01*self.m2p
        self.minspeed=0.02*self.m2p
        self.maxspeed=0.02*self.m2p

        self.img=pygame.image.load(robotimg)
        self.rotated=self.img
        self.rect=self.rotated.get_rect(center=(self.x,self.y))

    def draw(self,map):
        map.blit(self.rotated,self.rect)

    def update(self,event=None):

        event=pygame.key.get_pressed()

        if event[pygame.K_UP] or action==1:
            self.vl+=0.001*self.m2p
            self.vr+=0.001*self.m2p
            self.k=0
            self.act='Forward'

        elif event[pygame.K_DOWN] or action==2:
            self.vl-=0.001*self.m2p
            self.vr-=0.001*self.m2p
            self.k=0
            self.act='Backward'

        elif event[pygame.K_LEFT] or action==3:
            self.vl+=0.001*self.m2p
            self.vr-=0.001*self.m2p
            self.k+=0.001*math.pi/180
            self.act='Left'

        elif event[pygame.K_RIGHT] or action==4:
            self.vl-=0.001*self.m2p
            self.vr+=0.001*self.m2p
            self.k+=-0.001*math.pi/180
            self.act='Right'

        self.x+=((self.vl+self.vr)*0.5)*math.cos(self.theta)*dt
        self.y-=((self.vl+self.vr)*0.5)*math.sin(self.theta)*dt
        #self.theta+=(self.vr-self.vl)/self.w*dt
        self.theta+=self.k

        self.rotated=pygame.transform.rotozoom(self.img,math.degrees(self.theta)%360,1)
        self.rect=self.rotated.get_rect(center=(self.x,self.y))

        #print('Player=> x={:.2f},y={:.2f},angle={:.2f},action={}'.format(self.x,self.y,math.degrees(self.theta)%360,self.act))

    # Obtaining Coordinate Informations
    def get_player_coordinates(self):
        return (self.x,self.y,math.degrees(self.theta)%360)

#%% Agent Class
class Enemy:
    def __init__(self,startpos,robotimg,width):

        # Initialization
        #self.m2p=3779.52
        self.m2p=500
        self.k=0

        # Player Positions
        self.w=width/100
        self.x=startpos[0]
        self.y=startpos[1]
        self.theta=0
        self.vl=0.01*self.m2p
        self.vr=0.01*self.m2p
        self.minspeed=0.02*self.m2p
        self.maxspeed=0.02*self.m2p

        self.img=pygame.image.load(robotimg)
        self.rotated=self.img
        self.rect=self.rotated.get_rect(center=(self.x,self.y))
        self.act=rn.randint(1,4)

    def draw(self,map):
        map.blit(self.rotated,self.rect)

    def update(self):

        self.act=rn.randint(1,4)

        if self.act==1:
            self.vl+=0.001*self.m2p
            self.vr+=0.001*self.m2p
            self.k=0
        elif self.act==2:
            self.vl-=0.001*self.m2p
            self.vr-=0.001*self.m2p
            self.k=0
        elif self.act==3:
            self.vl+=0.001*self.m2p
            self.vr-=0.001*self.m2p
            self.k+=0.001*math.pi/180
        elif self.act==4:
            self.vl-=0.001*self.m2p
            self.vr+=0.001*self.m2p
            self.k+=-0.001*math.pi/180

        self.x+=((self.vl+self.vr)*0.5)*math.cos(self.theta)*dt
        self.y-=((self.vl+self.vr)*0.5)*math.sin(self.theta)*dt
        #self.theta+=(self.vr-self.vl)/self.w*dt
        self.theta+=self.k

        self.action_dict={1:'Accelerate',2:'Decelerate',3:'Left',4:'Right'}

        self.rotated=pygame.transform.rotozoom(self.img,math.degrees(self.theta)%360,1)
        self.rect=self.rotated.get_rect(center=(self.x,self.y))

        #print('Enemy=> x={:.2f},y={:.2f},angle={:.2f},action={}'.format(self.x,self.y,math.degrees(self.theta)%360,self.action_dict[self.act]))

    # Obtaining Coordinate Informations
    def get_enemy_coordinates(self):
        return (self.x,self.y,math.degrees(self.theta)%360)

#%% DQL Agent Design
class DQLAgent:
    def __init__(self):
        #Parameter Initializations

        self.state_size=3 # Position-x, position-y, heading angle
        self.action_size=4 # Accelerate, Decelerate, Left, Rgiht

        self.gamma=0.95
        self.learning_rate=0.001

        self.epsilon=1
        self.epsilon_decay=0.001
        self.epsilon_min=0.01

        self.memory=deque(maxlen=1000)

        self.model=self.build_model()

    def build_model(self):
        model=Sequential()
        model.add(Dense(32,input_dim=self.state_size,activation='relu'))
        model.add(Dense(32,input_dim=32,activation='relu'))
        model.add(Dense(16,input_dim=32,activation='relu'))
        model.add(Dense(16,input_dim=16,activation='relu'))
        model.add(Dense(8,input_dim=16,activation='relu'))
        model.add(Dense(self.action_size,input_dim=8,activation='linear'))
        model.compile(loss='mse',optimizer=Adam(lr=self.learning_rate))

        return model

    def remember(self,state,action,reward,next_state,done):
        #Storage
        self.memory.append((state,action,reward,next_state,done))

    def act(self,state):
        state=np.array(state)

        if np.random.rand()<=self.epsilon:
            return rn.randrange(self.action_size) #env.action_space.sample()

        act_values=self.model.predict(state)
        return np.argmax(act_values[0])

    def replay(self,batch_size):

        if len(self.memory)<batch_size:
            return

        minibatch=rn.sample(self.memory,batch_size)
        for state,action,reward,next_state,done in minibatch:
            state=np.array(state)
            next_state=np.array(next_state)
            if done:
                target=reward
            else:
                target=reward+self.gamma*np.amax(self.model.predict(next_state)[0])

            train_target=self.model.predict(state)
            train_target[0][action]=target
            self.model.fit(state,train_target,verbose=0)

    def adaptiveEGreedy(self):
        if self.epsilon>self.epsilon_min:
            self.epsilon*=self.epsilon_decay

#%% Environment Design
# class Env:
#     def __init__(self,dimensions):
#         # Initializing Colors
#         self.white=(255,255,255)
#         self.black=(0,0,0)
#         self.red=(255,0,0)
#         self.green=(0,255,0)
#         self.blue=(0,0,100)

#         # World Generation
#         self.height=dimensions[0]
#         self.width=dimensions[1]
#         self.trail_set=[]

#         self.reward=0
#         self.done=False
#         self.total_reward=0
#         self.start1=(rn.randint(300,600),rn.randint(300,600))
#         self.start2=(rn.randint(300,600),rn.randint(300,600))
#         self.player_img='player.png'
#         self.enemy_img='enemy.png'

#         # Agent and Enemy
#         self.player=Player(self.start1, self.player_img, 100*rn.random())
#         self.enemy=Enemy(self.start2, self.enemy_img, 100*rn.random()-200)
#         self.agent=DQLAgent()

#         # World Settings
#         pygame.display.set_caption('RL-based Dogfight Simulator')
#         self.map=pygame.display.set_mode((self.height,self.width))

#     # def trail(self,pos):
#     #     for i in range(0,len(self.trail_set)-1):
#     #         pygame.draw.line(self.map,self.yel,(self.trail_set[i][0],self.trail_set[i][1]),(self.trail_set[i+1][0],self.trail_set[i+1][1]))
#     #         if self.trail_set.__sizeof__()>30000:
#     #             self.trail_set.pop(0)
#     #         self.trail_set.append(pos)

#     def find_distance(self,a,b):
#         return a-b

#     def step(self,action):
#         state_list=[]

#         #Update
#         self.player.update(action)
#         self.enemy.update()

#         # Get Coordinates
#         next_player_state=self.player.get_player_coordinates()
#         next_enemy_state=self.enemy.get_enemy_coordinates()

#         # Finding the Distance between Them
#         state_list.append(self.find_distance(next_player_state[0],next_enemy_state[0]))
#         state_list.append(self.find_distance(next_player_state[1],next_enemy_state[1]))
#         state_list.append(self.find_distance(next_player_state[2],next_enemy_state[2]))

#         return [state_list]

#     def initialStates(self):

#         self.start1=(rn.randint(300,600),rn.randint(300,600))
#         self.start2=(rn.randint(300,600),rn.randint(300,600))

#         self.player=Player(self.start1,'player.png', 100*rn.random())
#         self.enemy=Enemy(self.start2,'enemy.png', 100*rn.random()-200)

#         self.reward=0
#         self.done=False
#         self.total_reward=0

#         state_list=[]

#         # Get Coordinates
#         player_state=self.player.get_player_coordinates()
#         enemy_state=self.enemy.get_enemy_coordinates()

#         # Finding the Distance between Them
#         state_list.append(self.find_distance(player_state[0],enemy_state[0]))
#         state_list.append(self.find_distance(player_state[1],enemy_state[1]))
#         state_list.append(self.find_distance(player_state[2],enemy_state[2]))

#         return [state_list]

#     def run(self):
#         running=True
#         batch_size=16

#         state=self.initialStates()

#         distance=[0]

#         while running:
#             # keep loop running at the right speed
#             clock.tick(fps)

#             player_state=self.player.get_player_coordinates()
#             enemy_state=self.enemy.get_enemy_coordinates()

#             metric_distance=((player_state[0]-enemy_state[0])**2+(player_state[1]-enemy_state[1])**2)**0.5

#             self.reward=float('{:.0f}'.format(-metric_distance))
#             distance.append(metric_distance)

#             # process input
#             # for event in pygame.event.get():
#             #     if event.type==pygame.QUIT:
#             #         running=False

#             # Update
#             action=self.agent.act(state)
#             next_state=self.step(action)
#             self.total_reward+=self.reward

#             self.lasttime=pygame.time.get_ticks()
#             self.time=(pygame.time.get_ticks()-self.lasttime)/1000

#             # Hit Check
#             if metric_distance==0:
#                 self.reward=-150
#                 self.total_reward+=self.reward
#                 self.done=True
#                 running=False
#                 print('Episode ended because of collision.')
#                 print('Total Reward=> {}'.format(self.total_reward))

#             if distance[-2]>distance[-1]:
#                 self.reward=1
#                 self.total_reward+=self.reward
#                 self.done=False
#                 running=False

#             if metric_distance>100:
#                 self.reward=-150
#                 self.total_reward+=self.reward
#                 self.done=False
#                 running=False
#                 print('Episode ended because the agent is too far away.')
#                 print('Total Reward=> {}'.format(self.total_reward))

#             if player_state[1]-enemy_state[1]<10:
#                 self.reward=300
#                 self.total_reward+=self.reward
#                 self.done=True
#                 running=False
#                 print('Episode ended succesfully.')
#                 print('Total Reward=> {}'.format(self.total_reward))

#             self.agent.remember(state,action,self.reward,next_state,self.done)

#             # Update State
#             state=next_state

#             # Training Agent
#             self.agent.replay(batch_size)

#             # Epsilon-greedy
#             self.agent.adaptiveEGreedy()

#             # draw/show
#             # screen.fill(white)
#             # self.player.draw(screen)
#             # self.enemy.draw(screen)

#             # after drawing, flip display
#             # pygame.display.flip()

#             #pygame.display.update()
#             #env.map.fill(env.white)
#             #self.player.draw(env.map)
#             #self.enemy.draw(env.map)
#             # env.trail((player.x,player.y))

#             #print('Distance={:.3f},Reward={:.1f}'.format(distance[-1],self.total_reward))

#     pygame.quit()

#%% Main Program

if __name__=='__main__':
    tot_reward=[]
    tot_reward_100=[]
    t=0

    # Robot Initialization
    pygame.init()

    # Start Position
    horizontal=1000
    vertical=600

    # Time Interval
    dt=0
    lasttime=pygame.time.get_ticks()

    start1=(rn.randint(300,600),rn.randint(300,600))
    start2=(rn.randint(300,600),rn.randint(300,600))

    dims=(horizontal,vertical)

    # Simulation Process => Default: True
    running=True

    # Hiring environment class
    env=Env(dims)

    # Hiring Player Class
    player=Player(start1,'player.png', 0.01*1000)
    enemy=Enemy(start2,'enemy.png', 0.01*1000)

    # Main Loop
    while running:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                running=False

        action=rn.randint(1,4)
        player.update(event)
        enemy.update()

        dt=(pygame.time.get_ticks()-lasttime)/1000
        lasttime=pygame.time.get_ticks()
        pygame.display.update()
        env.map.fill(env.white)
        player.draw(env.map)
        enemy.draw(env.map)
        env.trail((player.x,player.y))

    pygame.quit()

# if __name__=='__main__':
#     horizontal=400
#     vertical=400
#     dims=(horizontal,vertical)
#     env=Env(dims)
#     tot_reward=[]
#     tot_reward_100=[]
#     t=0

#     while True:
#         t+=1
#         print('Episode=>',t)
#         tot_reward.append(env.total_reward)
#         if t%10==0:
#             tot_reward_100.append(env.total_reward)

#         lasttime=pygame.time.get_ticks()
#         dt=(pygame.time.get_ticks()-lasttime)/1000

#         #pygame.display.update()
#         #env.map.fill(env.white)
#         #player.draw(env.map)
#         #enemy.draw(env.map)
#         # env.trail((player.x,player.y))

#         clock=pygame.time.Clock()

#         env.run()


import re

from colors import *

# how many characters are reserved for an element name when dumping
DUMP_SPACING = 24

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    reverse = {value: key for key, value in enums.items()}
    enumsl = {key.lower():value for key, value in enums.items()}
    def cast(self, x):
        if isinstance(x, str):
            v = enumsl.get(x.lower())
            if v:
                return v
            else:
                raise KeyError(x + ' is not a valid enum value')
        else:
            return x

    enums['reverse_mapping'] = reverse
    enums['__new__'] = cast
    return type('Enum', (), enums)

def guid_bracket(val, strict=False):
    if (not strict) or isguid(val):
        if val.startswith('{'):
            return val
        else:
            return '{' + val + '}'
    else:
        raise ValueError('"%s" is not a valid guid' % val)

def guid_unbracket(val, strict=True):
    if (not strict) or isguid(val):
        if val.startswith('{'):
            return val[1:-1]
        else:
            return val
    else:
        raise ValueError('"%s" is not a valid guid' % val)

def isguid(val):
    val = str(val)
    if (val.count('{') ^ val.count('}')) or val.count('{') > 1:
        return False
    exp = r'^\{?[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}\}?$'
    return bool(re.match(exp, val))

def isint(val):
    try:
        int(val)
        return True
    except ValueError:
        return False

def cacheresult(func):
    name = '_' + func.__name__
    def load(self):
        if hasattr(self, name):
            return getattr(self, name)
        else:
            val = func(self)
            setattr(self, name, val)
            return val
    return load

class callbacklist(list):
	'A list that calls a function when changed'
	callback = None
	def _call(self):
		if callable(self.callback):
			self.callback()
	def __init__(self, *args, **kwargs):
		list.__init__(self, *args, **kwargs)
		for i in ('append', 'clear', 'extend',
			  'insert', 'pop', 'remove',
			  'reverse', 'sort'):
			def repl(func):
				def newfunc(*args, **kwargs):
					v = func(*args, **kwargs)
					self._call()
					return v
				return newfunc
			setattr(self, i, repl(getattr(self, i)))

identity = lambda x:x

# END OF LINE


import numpy as np

def read_nodes(path):
    """
    Read data example and save it

    >>> read_nodes("examples/nodes1.csv")
    array([1, 2, 3, 1, 2, 3, 1, 2])
    """
    arr = np.genfromtxt(path, delimiter = "'", dtype = np.int32)
#    arr = arr.reshape(shape)
    return arr

def gen_edges3d(shape):
    """
    Generate edges
    """
    assert len(shape) == 3
    this_id = 0
    edges = []
    edge_id = np.array(range(np.prod(shape))).reshape(shape)
    for k in range(shape[2]):
        for j in range(shape[1]):
            for i in range(shape[0]):
                new_edges = [(i + 1, j, k), (i - 1, j, k), (i, j + 1, k), (i, j - 1, k), (i, j, k - 1), (i, j, k + 1)]
                new_edges = [(x, y, z) for x, y, z in new_edges if x >= 0 and y >= 0 and z >= 0]
                new_edges = [(x, y, z) for x, y, z in new_edges if x < shape[0] and y < shape[1] and z < shape[2]]
                for x, y, z in new_edges:
                    edges.append([this_id, edge_id[x, y, z]])
                this_id += 1
    return np.array(edges, np.int32)

def validate_grid3d_input(nodes):
    """
    Validate grid3d input
    """
    assert isinstance(nodes, np.ndarray), "nodes should be a numpy array"
    assert nodes.ndim == 1, "nodes must have dimension 1"

class grid3d:
    """
    A class to contain grids

    >>> grid = grid3d(np.arange(24), (2, 3, 4)) # compatible shape
    >>> grid = grid3d(np.arange(24), (2, 3, 5))
    Traceback (most recent call last):
        ...
    AssertionError: incompatible shape
    """

    """
    Initializer
    """
    def __init__(self, nodes, shape):
        validate_grid3d_input(nodes)
        assert np.prod(shape) == len(nodes), "incompatible shape"
        self.nodes = nodes
        self.edges = gen_edges3d(shape)

if __name__ == "__main__":
    import doctest
    doctest.testmod()