# encoding: utf-8
# Created on 2014-5-27
# @author: binge

from hashlib import sha1
from tenjin.helpers import *
from tornado.web import RequestHandler, HTTPError
from utils import settings, conns_helper
from utils.common import TimeHelper
import json
import os
import tenjin
import time
import traceback
import uuid
import service
from tornado import log

tenjin_engine = tenjin.Engine(pp=[ tenjin.TrimPreprocessor() ], layout=os.path.join(os.path.dirname(__file__), "views/_layout.html"))

class BaseHandler(RequestHandler):

    MTHOD_NOT_ALLOWED = 405
    URL_NOT_FOUND = 404
    SERVER_ERROR = 500

    _skip_attrs = ['get', 'post']

    _redis = conns_helper.get_redis_conn(db=settings.SESSION_REDIS_DB)

    def initialize(self, init_context=True):
        self.user_service = service.user_serv
        self.context = self.__init_context(init_context)

    def __init_context(self, init_context):
        context = {}
        if init_context:
            context['now_time'] = TimeHelper.time_2_str()
        return context

    def gene_html(self, template_name_prefix, template_name_suffix='.html', layout=True):
        return tenjin_engine.render(os.path.join(os.path.dirname(__file__), template_name_prefix + template_name_suffix), self.context, layout=layout)

    def render(self, template_name_prefix, template_name_suffix='.html', layout=True):
        self.write(self.gene_html(template_name_prefix, template_name_suffix, layout))
#         self.finish()

    def raise_http_error(self, err_code, err_info=None):
        if not err_info:
            err_info = traceback.format_exc()
        if err_info:
            self.log_err(err_info)
        if 'X-Requested-With' in self.request.headers and 'XMLHttpRequest' == self.request.headers['X-Requested-With']:
            self.set_status(err_code)
            self.finish()
        else:
            self.context['err_code'] = err_code
            self.render('views/err', layout=False)

    def ajax_result(self, result):
        #self.set_header('Content-Type', 'application/json; charset=UTF-8')
        self.write(json.dumps(result, ensure_ascii=False))
#         self.finish()

    def list_parms(self, params, empty_err_code=None):
        if not params:
            if empty_err_code:
                self.raise_http_error(empty_err_code)
            return []
        return params.split('/')

    def __set_session_attr__(self, name, value):
        Session(self).__setattr__(name, value)

    def __get_session_attr__(self, name):
        return Session(self).__getattr__(name)

    def __del_session_attr__(self, name):
        Session(self).__delattr__(name)

    def __destory_session__(self):
        Session(self).__destory__()

    def log_err(self, err):
        log.access_log.error(err)

class Session(object):
    _prefix = "_session:"
    _id = None
    _skip = ['_redis', '_request', '_id']
    def __init__(self, request):
        self._redis = request._redis
        self._request = request
        # init session id
        _id = request.get_secure_cookie('sessionid')
        if _id and self._redis.exists(_id):
            self._id = _id

    def init_session(self):
        """初始化"""
        if not self._id:
            self._id = self.generate_session_id()
            self._request.set_secure_cookie('sessionid', self._id)
        self.__set_expire()

    def generate_session_id(self):
        """Generate a random id for session"""
        secret_key = self._request.settings['cookie_secret']
        ip = self._request.request.remote_ip
        while True:
            rand = os.urandom(16)
            now = time.time()
            sessionid = sha1("%s%s%s%s" % (rand, now, ip, secret_key))
            sessionid = self._prefix + sessionid.hexdigest()
            if not self._redis.exists(sessionid):
                break
        return sessionid

    def __set_expire(self):
        # 延期过期时间
        self._redis.hset(self._id, 'lastActive', time.time())
        self._redis.expire(self._id, settings.SESSION_MAXLIFETIME)

    def __getattr__(self, name):
        if self._id:
            self.__set_expire()
            return self._redis.hget(self._id, name)
        if not name in self._skip:
            return None
        return object.__getattribute__(self, name)

    def __setattr__(self, name, value):
        if not name in self._skip:
            self.init_session()
            self._redis.hset(self._id, name, value)
        object.__setattr__(self, name, value)

    def __delattr__(self, name):
        if not name in self._skip:
            return self._redis.hdel(self._id, name)
        object.__delattr__(self, name)

    def __destory__(self):
        self._redis.delete(self._id)

def auto_login(require_login=True):
    def wrapper(fn):
        def login(request, *args):
            user = request.__get_session_attr__('user')
            if not user:
                user_id = request.get_secure_cookie('user_id')
                save_me = None
#                 save_me = request.get_secure_cookie('save_me')
                if user_id and save_me:
                    user = request.user_service.find_one({'_id' : user_id})
                    if user:
                        request.__set_session_attr__('user', user)
            else:
                user = eval(user)
            if user:
                request.current_user = user
                request.context['curr_user'] = user
            else:
                if require_login:
                    if 'X-Requested-With' in request.request.headers and 'XMLHttpRequest' == request.request.headers['X-Requested-With']:
                        request.set_status(403)
                        request.finish()
                    else:
                        request.redirect("/auth/login")
                    return None
            return fn(request, *args)
        return login
    return wrapper

def logout():
    def wrapper(fn):
        def _do(request, *args):
            request.__destory_session__()
            request.set_secure_cookie('save_me', '', 0)
            request.set_secure_cookie('user_id', '', 0)
            return fn(request, *args)
        return _do
    return wrapper

def except_err():
    def wrapper(fn):
        def _except(request, *args):
            try:
                return fn(request, *args)
            except:
                request.raise_http_error(request.SERVER_ERROR, traceback.format_exc())
            finally:
                pass
        return _except
    return wrapper

class ErrHandler(BaseHandler):

    def get(self, res):
        if res:
            try:
                fns = os.path.dirname(__file__).split(os.sep)[:-1]
                fns.append(res)
                if os.path.exists(os.sep.join(fns)):
                    rf = open(os.sep.join(fns))
                    self.finish(rf.read())
                else:
                    self.write('go fuck yourself!')
            except:
                self.raise_http_error(self.URL_NOT_FOUND)
            finally:
                return
        self.raise_http_error(self.URL_NOT_FOUND)

    def post(self, res):
        self.get()


import cv2
from datetime import datetime

import PCA.PCA_math as PCA
import settings.settings as set_man
import utils.log as log_man
import camera.camera as cam_man
import utils.img as img_man
import settings.settings as set_man

# module config
_color_red = (0, 0, 255)
_color_white = (255, 255, 255)

def training_mode_setup():
    PCA.load_model()

def training_mode_loop():
    # load settings
    avg_mine_dia = set_man.get_settings('avg_mine_dia')
    cam = cam_man.get_cam()
    frame_size = set_man.get_settings('frame_size')

    # read frame from camera
    _, frame = cam.read()
    frame = cv2.resize(frame, dsize=(frame_size, frame_size), interpolation=cv2.INTER_CUBIC)
    grey_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # check if there is object in the middle of the frame
    is_mid = img_man.is_obj_in_middle(grey_frame)

    mid_obj_x = int(frame_size / 2)
    mid_obj_y = int(frame_size / 2)

    # highlight middle object
    if (is_mid):
        frame = cv2.circle(frame, (mid_obj_x, mid_obj_y), 2, _color_red, -1)
        frame = cv2.circle(frame, (mid_obj_x, mid_obj_y),
                           int(avg_mine_dia / 2), _color_red, 2)
    else:
        frame = cv2.circle(frame, (mid_obj_x, mid_obj_y), 2, _color_white, -1)
        frame = cv2.circle(frame, (mid_obj_x, mid_obj_y),
                           int(avg_mine_dia / 2), _color_white, 2)

    # show modified frame
    cv2.imshow('Robot Camera', frame)

    # read key hit
    key = cv2.waitKey(1) & 0xFF

    # process key hit
    if (key == ord('s')):
        # crop central image
        cor_image = grey_frame[int(mid_obj_x - (avg_mine_dia) / 2):int(mid_obj_x + ((avg_mine_dia) / 2)),
                               int(mid_obj_y - (avg_mine_dia) / 2):int(mid_obj_y + ((avg_mine_dia) / 2))]

        # save image to the dataset directory
        cur_img_count: int = set_man.get_settings('next_img_index')
        img_dir = f"./dataset/img{cur_img_count}.jpg"
        set_man.set_settings('next_img_index', cur_img_count + 1)
        cv2.imwrite(img_dir, cor_image)

        log_man.add_log('modes.training_mode_loop',
                        'DEBUG', f"added image {img_dir} to dataset")

    elif (key == ord('t')):
        # crop central image
        cor_image = grey_frame[int(mid_obj_x - (avg_mine_dia) / 2):int(mid_obj_x + ((avg_mine_dia) / 2)),
                               int(mid_obj_y - (avg_mine_dia) / 2):int(mid_obj_y + ((avg_mine_dia) / 2))]

        # test the model
        img_name = PCA.match_image(cor_image)
        print(img_name)
        input()

    elif (key == ord('r')):
        # train the model
        log_man.add_log('modes.training_mode_loop',
                        'INFO', f"fitting PCA model to the dataset")
        PCA.train_model()
        log_man.add_log('modes.training_mode_loop',
                        'INFO', f"done fitting PCA model to the dataset")

        set_man.save_settings()

        return -1

    elif (key == ord('q')):
        set_man.save_settings()
        return -1

    return 0


import pytest
import requests

class TestFirstAPI:
    names = [
        ("John"),
        ("Jane"),
        ("Jack"),
        (""),
    ]

    @pytest.mark.parametrize("name", names)
    def test_first_api(self, name):
        url = 'https://playground.learnqa.ru/api/hello'
        # name = 'Sodikmirzo'
        data = {'name': name}

        response = requests.get(url, params=data)

        assert response.status_code == 200, "Wrong response code"

        response_dick = response.json()
        assert "answer" in response_dick, "There is no field 'answer' in the response"

        if len(name) == 0:
            expected_response_text = "Hello, someone"
        else:
            expected_response_text = f"Hello, {name}"
        actual_response_text = response_dick['answer']
        assert actual_response_text == expected_response_text, "Actual response text is not equal to expected"


class Solution:
    def minCost(self, n: int, cuts: List[int]) -> int:
        # sorting -> to make sure cuts are in ordered when paritioning

        cuts.sort()

        cuts = [0] + cuts
        cuts.append(n)

        length = len(cuts)

        @cache
        def findoptimalcuts(start, end):
            if start == end - 1:
                return 0

            if start >= end:
                return 0

            min_cuts = float('inf')

            for indx in range(start + 1, end):
                cur_cut = cuts[end] - cuts[start]

                # consider cur_cut as mid point
                left_cut = findoptimalcuts(start, indx)
                right_cut = findoptimalcuts(indx, end)

                cur_cut += left_cut + right_cut

                min_cuts = min(min_cuts, cur_cut)

            return min_cuts

        return findoptimalcuts(0, length - 1)


from maya import cmds

import pyblish.api
import colorbleed.api
import colorbleed.maya.action

SUFFIX_NAMING_TABLE = {'mesh': ["_GEO", "_GES", "_GEP", "_OSD"],
                       'nurbsCurve': ["_CRV"],
                       'nurbsSurface': ["_NRB"],
                       None: ['_GRP']}

ALLOW_IF_NOT_IN_SUFFIX_TABLE = True

class ValidateTransformNamingSuffix(pyblish.api.InstancePlugin):
    """Validates transform suffix based on the type of its children shapes.

    Suffices must be:
        - mesh:
            _GEO (regular geometry)
            _GES (geometry to be smoothed at render)
            _GEP (proxy geometry; usually not to be rendered)
            _OSD (open subdiv smooth at rendertime)
        - nurbsCurve: _CRV
        - nurbsSurface: _NRB
        - null/group: _GRP

    .. warning::
        This grabs the first child shape as a reference and doesn't use the
        others in the check.

    """

    order = colorbleed.api.ValidateContentsOrder
    hosts = ['maya']
    families = ['colorbleed.model']
    category = 'cleanup'
    optional = True
    version = (0, 1, 0)
    label = 'Suffix Naming Conventions'
    actions = [colorbleed.maya.action.SelectInvalidAction]

    @staticmethod
    def is_valid_name(node_name, shape_type):
        """Return whether node's name is correct.

        The correctness for a transform's suffix is dependent on what
        `shape_type` it holds. E.g. a transform with a mesh might need and
        `_GEO` suffix.

        When `shape_type` is None the transform doesn't have any direct
        children shapes.

        """
        if shape_type not in SUFFIX_NAMING_TABLE:
            return ALLOW_IF_NOT_IN_SUFFIX_TABLE
        else:
            suffices = SUFFIX_NAMING_TABLE[shape_type]
            for suffix in suffices:
                if node_name.endswith(suffix):
                    return True
            return False

    @classmethod
    def get_invalid(cls, instance):
        transforms = cmds.ls(instance, type='transform', long=True)

        invalid = []
        for transform in transforms:
            shapes = cmds.listRelatives(transform,
                                        shapes=True,
                                        fullPath=True,
                                        noIntermediate=True)

            shape_type = cmds.nodeType(shapes[0]) if shapes else None
            if not cls.is_valid_name(transform, shape_type):
                invalid.append(transform)

        return invalid

    def process(self, instance):
        """Process all the nodes in the instance"""

        invalid = self.get_invalid(instance)
        if invalid:
            raise ValueError("Incorrectly named geometry "
                             "transforms: {0}".format(invalid))


# -*- coding: utf-8 -*-
"""
@version: 3.8.3
@time: 21/4/26 10:52
@author: Yamisora
@file: backtest.py
"""
# import matplotlib.pyplot as plt
# import pandas as pd
import time

from strategy import *

class Backtest:
    def __init__(self, start_cash=300000, fee=0.0003):
        """
        回测
        @start_cash: 初始资金
        @fee: 手续费比例
        """
        # index选择指数组合
        self.index_name = 'hs300'
        self.index_code = 'sh.000300'
        # 存储路径
        self.base_data_path = './data/'
        self.data_path = './data/stocks/'
        # 默认万三手续费
        self.fee = fee
        # 指数组合内股票名称,代码数据
        self.stocks = pd.read_csv('{}{}_stocks.csv'.format(self.base_data_path, self.index_name))
        self.stocks_codes = self.stocks['code']
        # 指数日线数据
        self.index = pd.read_csv('{}{}.csv'.format(self.data_path, self.index_code))
        # 交易日str序列
        self.trading_dates = self.index['date']
        # 今日名称str与序列序号int
        self.today = (self.trading_dates[0], 0)
        # 初始资金
        self.start_cash = start_cash
        # 每日可用资金
        self.cash = pd.DataFrame(self.trading_dates)
        self.cash['cash'] = start_cash
        self.cash = self.cash.set_index('date')
        # 每日持股
        self.position = pd.DataFrame()
        self.position['date'] = self.trading_dates
        for stock_code in self.stocks_codes:
            self.position[stock_code] = 0
        self.position = self.position.set_index('date')

    def stocks_data(self, stock_codes, trading_date: str) -> pd.DataFrame():
        """
        读取指定交易日内，一系列股票日线数据
        """
        # 空输入情况
        if stock_codes.empty:
            return pd.DataFrame(None)
        stocks = pd.DataFrame()
        for stock_code in stock_codes:
            # 读取每只股票数据
            data = pd.read_csv('{}{}.csv'.format(self.data_path, stock_code), index_col='date')
            if trading_date in data.index:
                # 读入指定日期数据
                stocks = stocks.append(data.loc[trading_date], ignore_index=True)
        stocks = stocks.set_index('code')
        return stocks

    def buy(self, stocks_codes) -> bool:
        """
        全仓买入trading date的所有stock codes股票
        """
        trading_date = self.today[0]
        # 读入当前交易日内所有待购买股票日线数据
        stocks = self.stocks_data(stocks_codes, trading_date)
        # 空输入情况
        if stocks.empty:
            return False
        # 预计购买股票数
        n = len(stocks_codes)
        # 每只股票可用购买资金
        single = self.cash.loc[trading_date, 'cash'] // n
        for stock_code in stocks_codes:
            # 每只股票开盘价作为买入价
            open_price = stocks.loc[stock_code, 'open']
            # 计算除去手续费后可购买份额(整百)
            quantity = ((single / (1+self.fee)) / open_price) // 100
            # 买入并修改当日现金余额
            self.position.loc[trading_date, stock_code] += quantity * 100
            self.cash.loc[trading_date, 'cash'] -= open_price * quantity * 100
        del stocks
        return True

    def sell(self, stocks_codes):
        """
        空仓trading date的除去stock codes外股票
        """
        trading_date = self.today[0]
        # 读入当前交易日内所有股票日线数据
        stocks = self.stocks_data(self.stocks_codes, trading_date)
        # 初始化卖出金额
        cash = 0
        # 卖出股票数量
        sell_num = 0
        # 卖出所有不继续持仓的股票并删除欲购买列表中已持仓的股票
        for stock_code in self.stocks_codes:
            position = self.position.loc[trading_date, stock_code]
            if position != 0:
                if stock_code not in stocks_codes:
                    # 卖出
                    cash += position * stocks.loc[stock_code, 'open'] * (1-self.fee)
                    self.position.loc[trading_date, stock_code] = 0
                    sell_num += 1
                else:
                    # 去除已选股票中已持仓股票
                    stocks_codes = stocks_codes.drop(stock_code)
        # 当日现金余额增加卖出金额
        self.cash.loc[trading_date, 'cash'] += cash
        del stocks
        return stocks_codes, sell_num

    def next_day(self) -> str:
        """
        返回下一个交易日str
        延续前一天cash数量
        """
        # 获取当日现金余额、持仓、日期序号
        cash = self.cash.loc[self.today[0], 'cash']
        position = self.position.loc[self.today[0]]
        today = self.today[1]
        if today < len(self.trading_dates) - 1:
            # 更新下一日现金余额、持仓、日期元组
            self.today = (self.trading_dates[today+1], today+1)
            self.cash.loc[self.today[0], 'cash'] = cash
            self.position.loc[self.today[0]] = position
            return self.today[0]

    def calculate(self):
        """
        计算收益折线
        """
        # 总收益百分比
        basic_position = self.start_cash
        position = []
        for i, trading_date in enumerate(self.trading_dates):
            # 每隔5交易日计算持仓
            if i % 5 != 0:
                continue
            print('当前计算交易日: '+trading_date, end='\r')
            # 读入当前交易日内所有股票日线信息
            stock_data = self.stocks_data(self.stocks_codes, trading_date)
            # 初始化当前拥有总金额为现金金额
            daily_position = self.cash.loc[trading_date, 'cash']
            for stock_code in self.stocks_codes:
                # 确认每只股票持股数
                quantity = self.position.loc[trading_date, stock_code]
                if quantity != 0:
                    daily_position += quantity * stock_data.loc[stock_code, 'close']
            position.append(daily_position)
        position = pd.Series(position)
        position /= basic_position
        return position

if __name__ == '__main__':
    start_time = time.time()
    bt1 = Backtest(start_cash=10000000, fee=0.0003)
    bt2 = Backtest(start_cash=10000000, fee=0.0003)
    bt3 = Backtest(start_cash=10000000, fee=0.0003)
    bt4 = Backtest(start_cash=10000000, fee=0.0003)
    bt5 = Backtest(start_cash=10000000, fee=0.0003)
    # bt6 = Backtest(start_cash=10000000, fee=0.0003)
    # bt7 = Backtest(start_cash=10000000, fee=0.0003)
    bt8 = Backtest(start_cash=10000000, fee=0.0003)
    bt9 = Backtest(start_cash=10000000, fee=0.0003)
    bt10 = Backtest(start_cash=10000000, fee=0.0003)
    bt11 = Backtest(start_cash=10000000, fee=0.0003)
    # bt12 = Backtest(start_cash=10000000, fee=0.0003)
    # bt13 = Backtest(start_cash=10000000, fee=0.0003)
    bt14 = Backtest(start_cash=10000000, fee=0.0003)
    bt15 = Backtest(start_cash=10000000, fee=0.0003)
    strategy = Strategy(data_days=10)
    for date_key, date in bt1.trading_dates.items():
        # 每10交易日调仓一次
        if date_key % 10 == 0:
            print('当前交易日: '+date)
            print('因子模型选股中...')
            chosen1 = strategy.choose_by_bm(bt1.today, 90)
            chosen3 = strategy.choose_by_mf(bt3.today, 90)
            chosen4 = strategy.choose_by_tr(bt4.today, 90)
            print('神经网络模型选股中...')
            chosen2 = strategy.choose_by_cnn(bt2.today, 90)
            chosen5 = strategy.choose_by_lstm(bt5.today, 90)
            # chosen6 = strategy.choose_by_gru(bt6.today, 90)
            # chosen7 = strategy.choose_by_rnn_tanh(bt7.today, 90)
            chosen8 = strategy.choose_by_rnn_relu(bt8.today, 90)
            chosen9 = strategy.choose_by_resnet18(bt9.today, 90)
            chosen10 = strategy.choose_by_resnet34(bt10.today, 90)
            chosen11 = strategy.choose_by_resnet50(bt11.today, 90)
            # chosen12 = strategy.choose_by_resnet101(bt12.today, 90)
            # chosen13 = strategy.choose_by_resnet152(bt13.today, 90)
            chosen14 = strategy.choose_by_densenet(bt14.today, 90)
            print('集成学习模型选股中...')
            chosen15 = strategy.choose_by_ensemble(bt15.today)

            to_buy1, sell1 = bt1.sell(chosen1)
            print('价值因子(BM)选股模型卖出', sell1, '只股票')
            to_buy2, sell2 = bt2.sell(chosen2)
            print('CNN选股模型卖出', sell2, '只股票')
            to_buy3, sell3 = bt3.sell(chosen3)
            print('动量因子(MF)选股模型卖出', sell3, '只股票')
            to_buy4, sell4 = bt4.sell(chosen4)
            print('换手率因子(TR)选股模型卖出', sell4, '只股票')
            to_buy5, sell5 = bt5.sell(chosen5)
            print('LSTM选股模型卖出', sell5, '只股票')
            # to_buy6, sell6 = bt6.sell(chosen6)
            # print('GRU选股模型卖出', sell6, '只股票')
            # to_buy7, sell7 = bt7.sell(chosen7)
            # print('RNN_tanh选股模型卖出', sell7, '只股票')
            to_buy8, sell8 = bt8.sell(chosen8)
            print('RNN_relu选股模型卖出', sell8, '只股票')
            to_buy9, sell9 = bt9.sell(chosen9)
            print('ResNet18选股模型卖出', sell9, '只股票')
            to_buy10, sell10 = bt10.sell(chosen10)
            print('ResNet34选股模型卖出', sell10, '只股票')
            to_buy11, sell11 = bt11.sell(chosen11)
            print('ResNet50选股模型卖出', sell11, '只股票')
            # to_buy12, sell12 = bt12.sell(chosen12)
            # print('ResNet101选股模型卖出', sell12, '只股票')
            # to_buy13, sell13 = bt13.sell(chosen13)
            # print('ResNet152选股模型卖出', sell13, '只股票')
            to_buy14, sell14 = bt14.sell(chosen14)
            print('DenseNet选股模型卖出', sell14, '只股票')
            to_buy15, sell15 = bt15.sell(chosen15)
            print('集成学习选股模型卖出', sell15, '只股票')
            bt1.buy(to_buy1)
            print('价值因子(BM)选股模型买入', len(to_buy1), '只股票')
            bt2.buy(to_buy2)
            print('CNN选股模型买入', len(to_buy2), '只股票')
            bt3.buy(to_buy3)
            print('动量因子(MF)选股模型买入', len(to_buy3), '只股票')
            bt4.buy(to_buy4)
            print('换手率因子(TR)选股模型买入', len(to_buy4), '只股票')
            bt5.buy(to_buy5)
            print('LSTM选股模型买入', len(to_buy5), '只股票')
            # bt6.buy(to_buy6)
            # print('GRU选股模型买入', len(to_buy6), '只股票')
            # bt7.buy(to_buy7)
            # print('RNN_tanh选股模型买入', len(to_buy7), '只股票')
            bt8.buy(to_buy8)
            print('RNN_relu选股模型买入', len(to_buy8), '只股票')
            bt9.buy(to_buy9)
            print('ResNet18选股模型买入', len(to_buy9), '只股票')
            bt10.buy(to_buy10)
            print('ResNet34选股模型买入', len(to_buy10), '只股票')
            bt11.buy(to_buy11)
            print('ResNet50选股模型买入', len(to_buy11), '只股票')
            # bt12.buy(to_buy12)
            # print('ResNet101选股模型买入', len(to_buy12), '只股票')
            # bt13.buy(to_buy13)
            # print('ResNet152选股模型买入', len(to_buy13), '只股票')
            bt14.buy(to_buy14)
            print('DenseNet选股模型买入', len(to_buy14), '只股票')
            bt15.buy(to_buy15)
            print('集成学习选股模型买入', len(to_buy15), '只股票')
        bt1.next_day()
        bt2.next_day()
        bt3.next_day()
        bt4.next_day()
        bt5.next_day()
        # bt6.next_day()
        # bt7.next_day()
        bt8.next_day()
        bt9.next_day()
        bt10.next_day()
        bt11.next_day()
        # bt12.next_day()
        # bt13.next_day()
        bt14.next_day()
        bt15.next_day()
    mid_time = time.time()
    span = mid_time - start_time
    print('回测模拟交易用时 {} 分 {} 秒'.format(int(span // 60), span % 60))
    print('\n计算价值因子(BM)选股模型收益中')
    bm_position = bt1.calculate()
    print('\n计算CNN选股模型收益中')
    cnn_position = bt2.calculate()
    print('\n计算动量因子(MF)选股模型收益中')
    mf_position = bt3.calculate()
    print('\n计算换手率因子(TR)选股模型收益中')
    tr_position = bt4.calculate()
    print('\n计算LSTM选股模型收益中')
    lstm_position = bt5.calculate()
    # print('\n计算GRU选股模型收益中')
    # gru_position = bt6.calculate()
    # print('\n计算RNN_tanh选股模型收益中')
    # rnn_tanh_position = bt7.calculate()
    print('\n计算RNN_relu选股模型收益中')
    rnn_relu_position = bt8.calculate()
    print('\n计算ResNet18选股模型收益中')
    resnet18_position = bt9.calculate()
    print('\n计算ResNet34选股模型收益中')
    resnet34_position = bt10.calculate()
    print('\n计算ResNet50选股模型收益中')
    resnet50_position = bt11.calculate()
    # print('\n计算ResNet101选股模型收益中')
    # resnet101_position = bt12.calculate()
    # print('\n计算ResNet152选股模型收益中')
    # resnet152_position = bt13.calculate()
    print('\n计算DenseNet选股模型收益中')
    densenet_position = bt14.calculate()
    print('\n计算集成学习选股模型收益中')
    ensemble_position = bt15.calculate()
    # 指数收益百分比
    basic_index_price = bt1.index['close'][0]
    index_price = bt1.index['close'][::5] / basic_index_price
    x = range(0, len(bt1.trading_dates), 5)
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.figure(figsize=[20, 15], dpi=160)
    plt.subplot(211)
    plt.plot(x, index_price, 'k:', label='沪深300指数收益率')
    plt.plot(x, bm_position, 'r:', label='价值因子(BM)选股模型持仓收益率')
    plt.plot(x, cnn_position, label='CNN选股模型持仓收益率')
    plt.plot(x, mf_position, 'g:', label='动量因子(MF)选股模型持仓收益率')
    plt.plot(x, tr_position, 'b:', label='换手率因子(TR)选股模型持仓收益率')
    plt.plot(x, lstm_position, label='LSTM选股模型持仓收益率')
    # plt.plot(x, gru_position, label='GRU选股模型持仓收益率')
    # plt.plot(x, rnn_tanh_position, label='RNN_tanh选股模型持仓收益率')
    plt.plot(x, rnn_relu_position, label='RNN_relu选股模型持仓收益率')
    plt.plot(x, resnet18_position, label='ResNet18选股模型持仓收益率')
    plt.plot(x, resnet34_position, label='ResNet34选股模型持仓收益率')
    plt.plot(x, resnet50_position, label='ResNet50选股模型持仓收益率')
    # plt.plot(x, resnet101_position, label='ResNet101选股模型持仓收益率')
    # plt.plot(x, resnet152_position, label='ResNet152选股模型持仓收益率')
    plt.plot(x, densenet_position, label='DenseNet选股模型持仓收益率')
    plt.plot(x, ensemble_position, label='集成学习选股模型持仓收益率')
    plt.ylabel('收益率/%')
    x_ticks = list(x[::len(x)//9])
    x_ticks.append(x[-1])
    x_labels = [bt1.trading_dates[i] for i in x_ticks]
    plt.xticks(x_ticks, x_labels)
    plt.legend()
    plt.subplot(212)
    plt.plot(x, [0]*len(x), 'k:', label='基准市场收益率(沪深300)', )
    plt.plot(x, bm_position.values-index_price.values, 'r:', label='价值因子(BM)选股模型持仓超额收益率')
    plt.plot(x, cnn_position.values-index_price.values, label='CNN选股模型持仓超额收益率')
    plt.plot(x, mf_position.values-index_price.values, 'g:', label='动量因子(MF)选股模型持仓超额收益率')
    plt.plot(x, tr_position.values-index_price.values, 'b:', label='换手率因子(TR)选股模型持仓超额收益率')
    plt.plot(x, lstm_position.values-index_price.values, label='LSTM选股模型持仓超额收益率')
    # plt.plot(x, gru_position.values-index_price.values, label='GRU选股模型持仓超额收益率')
    # plt.plot(x, rnn_tanh_position.values-index_price.values, label='RNN_tanh选股模型持仓超额收益率')
    plt.plot(x, rnn_relu_position.values-index_price.values, label='RNN_relu选股模型持仓超额收益率')
    plt.plot(x, resnet18_position.values-index_price.values, label='ResNet18选股模型持仓超额收益率')
    plt.plot(x, resnet34_position.values-index_price.values, label='ResNet34选股模型持仓超额收益率')
    plt.plot(x, resnet50_position.values-index_price.values, label='ResNet50选股模型持仓超额收益率')
    # plt.plot(x, resnet101_position.values-index_price.values, label='ResNet101选股模型持仓超额收益率')
    # plt.plot(x, resnet152_position.values-index_price.values, label='ResNet152选股模型持仓超额收益率')
    plt.plot(x, densenet_position.values-index_price.values, label='DenseNet选股模型持仓超额收益率')
    plt.plot(x, ensemble_position.values-index_price.values, label='集成学习选股模型持仓超额收益率')
    plt.ylabel('超额收益率/%')
    plt.xticks(x_ticks, x_labels)
    plt.legend()
    plt.savefig('result.jpg')
    end_time = time.time()
    span = end_time - mid_time
    print('计算持仓收益用时 {} 分 {} 秒'.format(int(span // 60), span % 60))
    span = end_time - start_time
    print('总计用时 {} 分 {:.2f} 秒'.format(int(span // 60), span % 60))


import gdrive
import os
import shutil
import discord
from pathlib import Path
from discord.ext import commands
from dotenv import load_dotenv
import asyncio

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
# The token key is load from the .env file

FFMPEG_PATH = "/usr/bin/ffmpeg"
PATH = Path("/home/aurnytoraink/Projets/Code/Bot/Diskcord/") # <= Set yout path

# discord.opus.load_opus()
voicechannel = []
bot = commands.Bot(command_prefix='$')

# Loads modules
service = gdrive.login()

# Reset cache music
if os.path.exists(PATH / 'musics'):
    shutil.rmtree(PATH / "musics")
os.makedirs(PATH / "musics")

@bot.event
async def on_ready():
    print(f'{bot.user} has connected to Discord!')

@bot.command(name="join", help="Invite le bot dans un salon vocal")
async def join(ctx):
    user = ctx.message.author
    if user.voice is not None:
        place = len(voicechannel)
        voicechannel.append([await user.voice.channel.connect(timeout=100),[],0])
        voicechannel[place][0].play((discord.FFmpegPCMAudio(PATH / "connected_sound.opus", executable=FFMPEG_PATH)))

#TODO Corriger pour que le titre de la musique s'afficher Ã  chaque fois qu'il passe Ã  la suivante
#TODO Ne laisser passer que les liens Google, Nextcloud
@bot.command(name="play", help="Lien de la (ou les) musique(s) Ã  jouer")
async def play(ctx, *args):
    user = ctx.message.author
    def check_playlist(vc):
        if vc[1] != [] and vc[2] < len(vc[1]) - 1:
            vc[2] += 1
            currentMusic = vc[1][vc[2]][0]
            gdrive.downloadMedia(service, currentMusic, str(id))
            # task = asyncio.ensure_future(ctx.send("**Je chanteðŸŽ¶: **" + currentMusicName + "\n**Queue:** {}/{}".format((vc[2]+1),len(vc[1]))))
            # print(task)
            vc[0].play(discord.FFmpegPCMAudio(PATH / ("musics/"+str(id)+'/'+currentMusic), executable=FFMPEG_PATH), after=lambda e: check_playlist(vc))
            return

    try:
        voicechannel.append([await user.voice.channel.connect(timeout=100),[],0])
    except AttributeError:
        await ctx.send("**Hmmm... Vous n'Ãªtes pas connectÃ© Ã  un salon vocal !**")
    except discord.errors.ClientException:
        pass
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            if len(args) == 0:
                if vc[0].is_paused() or vc[0].is_playing():
                    if vc[0].is_paused():
                        vc[0].resume()
                        return
                    else:
                        await ctx.send("Ã‚llo ? Vous m'entendez ?\nLa musique est dÃ©jÃ  en cours de lecture !")
                        return
                else:
                    await ctx.send("-ã�ˆï¼Ÿ\nJe dois jouer quelle musique ?")
                    return
            elif args[0] == "random":
                queuedlist = gdrive.getMedias(service, args[1], True)
            elif args[0] == "add":
                if args[1] == "random":
                    queuedlist = gdrive.getMedias(service, args[2], True)
                else:
                    queuedlist = gdrive.getMedias(service, args[1])
                if queuedlist is None:
                    await ctx.send("**Aucune musique trouvÃ©e !**")
                    return
                vc[1] += queuedlist
                await ctx.send("**Youpi!** J'ai ajoutÃ© votre dossier Ã  la queue.")
                return
            else:
                queuedlist = gdrive.getMedias(service, args[0])
            if queuedlist is None:
                await ctx.send("Aucune musique trouvÃ©e !")
                return
            if vc[0].is_playing:
                vc[1] = []
                vc[2] = 0
                vc[0].stop()
            await asyncio.sleep(1)
            await ctx.send("**Chargement...**")
            vc[1] = queuedlist
            id = vc[0].channel.id
            currentMusic = vc[1][vc[2]][0]
            currentMusicName = vc[1][vc[2]][1]
            gdrive.downloadMedia(service, currentMusic, str(id))
            await ctx.send("**Je chanteðŸŽ¶: **" + currentMusicName + "\n**Queue:** {}/{}".format((vc[2]+1),len(vc[1])))
            vc[0].play(discord.FFmpegPCMAudio(PATH / ("musics/"+str(id)+'/'+currentMusic), executable=FFMPEG_PATH), after=lambda e: check_playlist(vc))
        else:
            place = len(voicechannel)
            voicechannel.append([await user.voice.channel.connect(timeout=100),[],0])
            voicechannel[place][0].play((discord.FFmpegPCMAudio(PATH / "connected_sound.opus", executable=FFMPEG_PATH)))

@bot.command(name="np", aliases=["display","current"], help="Affiche la musique en cours")
async def np(ctx):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            if vc[0].is_playing():
                await ctx.send("**Je chanteðŸŽ¶: **" + vc[1][vc[2]][1] + "\n**Queue:** {}/{}".format((vc[2]+1),len(vc[1])))
            else:
                await ctx.send("**AÃ¯e AÃ¯e AÃ¯e !** Je joue pas de musique actuellement")

@bot.command(name="add", help="Rajoute la (ou les) musique(s) Ã  la queue actuelle")
async def add(ctx, *args):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            if len(args) == 0:
                await ctx.send("-ã�ˆï¼Ÿ\nJe dois rajouter quelle musique ?")
                return
            elif args[0] == "random":
                queuedlist = gdrive.getMedias(service, args[1], True)
            else:
                queuedlist = gdrive.getMedias(service, args[0])
            if queuedlist is None:
                await ctx.send("**Aucune musique trouvÃ©e !**")
                return
            vc[1] += queuedlist
            await ctx.send("**Youpi!** J'ai ajoutÃ© votre dossier Ã  la queue.")

@bot.command(name="pause", help='Met en pause la musique')
async def pause(ctx):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            if vc[0].is_paused():
                vc[0].resume()
            else:
                vc[0].pause()
        else:
            await ctx.send("Vous n'Ãªtes pas dans un salon vocal !")

@bot.command(name="resume", help='Fonction inverse de $pause') #TODO Prevent user if there is not music playing
async def resume(ctx):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            if vc[0].is_paused():
                vc[0].resume()
            else:
                await ctx.send("Ã‚llo ? Vous m'entendez ?\nLa musique est dÃ©jÃ  en cours de lecture !")
        else:
            await ctx.send("Vous n'Ãªtes pas dans un salon vocal !")

@bot.command(name="stop", help="ArrÃªte la musique et efface la liste d'attente")
async def stop(ctx):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            vc[1] = []
            vc[2] = 0
            vc[0].stop()
        else:
            await ctx.send("Vous n'Ãªtes pas dans un salon vocal !")

@bot.command(name="next", aliases=['skip','s'], help="Passe Ã  la musique suivante\nPS: Vous pouvez passer plusieurs musiques en indiquant le nombre de musique Ã  sauter")
async def next(ctx, *arg):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            if len(arg) != 0:
                if len(vc[1]) > vc[2]+int(arg[0]):
                    vc[2] += int(arg[0]) - 1
                    vc[0].stop()
                    currentMusicName = vc[1][vc[2]+1][1]
                    await ctx.send("**Je chanteðŸŽ¶: **" + currentMusicName + "\n**Queue:** {}/{}".format((vc[2]+2),len(vc[1])))
                else:
                    await ctx.send("**AÃ¯e aÃ¯e aÃ¯e !**\n`Out of Range: Le nombre entrÃ© dÃ©passe la liste`")
            else:
                if len(vc[1]) - 1 != vc[2]:
                    vc[0].stop()
                    currentMusicName = vc[1][vc[2]+1][1]
                    await ctx.send("**Je chanteðŸŽ¶: **" + currentMusicName + "\n**Queue:** {}/{}".format((vc[2]+2),len(vc[1])))
                else:
                    await ctx.send("**Fin de la queue atteinte**")

@bot.command(name="back", aliases=['b'], help="Reviens Ã  la musique prÃ©cÃ©dente\nPS: Vous pouvez revenir plusieurs fois en indiquant le nombre de musique Ã  sauter")
async def back(ctx, *arg):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            if len(arg) != 0:
                if vc[2] - int(arg[0]) >= 0 and vc[2] > 0:
                    vc[2] -= int(arg[0]) + 1
                    vc[0].stop()
                    currentMusicName = vc[1][vc[2]+1][1]
                    await ctx.send("**Je chanteðŸŽ¶: **" + currentMusicName + "\n**Queue:** {}/{}".format((vc[2]+2),len(vc[1])))
                else:
                    await ctx.send("**AÃ¯e aÃ¯e aÃ¯e !**\nQueuedlist: Out of Range > `Le nombre entrÃ© dÃ©passe la liste`")
            else:
                if vc[2] > 0:
                    vc[2] -= 2
                    vc[0].stop()
                    currentMusicName = vc[1][vc[2]+1][1]
                    await ctx.send("**Je chanteðŸŽ¶: **" + currentMusicName + "\n**Queue:** {}/{}".format((vc[2]+2),len(vc[1])))
                else:
                    await ctx.send("**Vous avez atteint le dÃ©but de la liste !**")

@bot.command(name="leave", help="Permet au bot de se dÃ©gourdir les jambes (ou plutÃ´t la bande passante")
async def leave(ctx):
    user=ctx.message.author
    for vc in voicechannel:
        if vc[0].channel == user.voice.channel:
            vc[1] = []
            vc[2] = 0
            vc[0].stop()
            vc[0].play(discord.FFmpegPCMAudio(PATH / "leave_sound.opus", executable=FFMPEG_PATH))
            await asyncio.sleep(1.5)
            await vc[0].disconnect()
            await ctx.send("Bis bald! :wave:")
            voicechannel.remove(vc)
            shutil.rmtree(PATH / ('musics/'+str(vc[0].channel.id)))
        else:
            await ctx.send("Vous n'Ãªtes pas dans un salon vocal !")

bot.run(TOKEN)


from django.contrib import admin
from django.contrib.contenttypes import generic
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from aircraftlogger.models import *
from soaring_club.conf.settings import *

class InstallationInline(admin.TabularInline):
    model = Installation
    extra = 1

class InstallationAdmin(admin.ModelAdmin):
    list_display = ('plane', 'flarm', 'flarmid', 'date_added', 'date_removed')
admin.site.register(Installation, InstallationAdmin)

class OwnershipInline(admin.TabularInline):
    model = Ownership
    extra = 1

class OwnershipAdmin(admin.ModelAdmin):
    list_display = ('plane', 'owner', 'date_purchased', 'date_sold')
admin.site.register(Ownership, OwnershipAdmin)

class MemberTypeInline(generic.GenericTabularInline):
    model = MemberType
    extra = 2
#admin.site.register(MemberType)

class MemberAdmin(admin.ModelAdmin):
    prepopulated_fields = {'sort_name' : ('last_name', 'first_name')}
    list_display = ('last_name', 'first_name', 'user', 'types', 'email', 'notes')
    inlines = [OwnershipInline,MemberTypeInline,]
    search_fields = ('last_name', 'first_name', 'type__type')

admin.site.register(Member, MemberAdmin)

class PlaneAdmin(admin.ModelAdmin):
    list_display = ('type', 'regmark', 'manufacturer', 'model', 'owners_str')
    list_display_links = ('regmark', )
    list_filter = ('type',)
    inlines = [InstallationInline, OwnershipInline]
admin.site.register(Plane, PlaneAdmin)

class FlarmAdmin(admin.ModelAdmin):
    inlines = [InstallationInline,]
    extra = 1
admin.site.register(Flarm, FlarmAdmin)

class FlightBillInline(admin.TabularInline):
    model = FlightBill
    verbose_name = verbose_name_plural = 'Flight bill'
    fk_name = 'flight'
    extra = 1

class GliderFlightInline(admin.TabularInline):
    model = FlightBill
    verbose_name = verbose_name_plural = 'Glider flight'
    fk_name = 'tow_flight'
    extra = 1

class FlightAdminForm(forms.ModelForm):
    takeoff_field = forms.CharField(max_length=20, initial=HOME_AIRPORT, required=False, label=_('Takeoff field'))
    landing_field = forms.CharField(max_length=20, initial=HOME_AIRPORT, required=False, label=_('Landing field'))
    class Meta:
        model = Flight

class FlightAdmin(admin.ModelAdmin):
    list_display = ('id', 'date', 'plane', 'pilot', 'porpouse','takeoff', 'landing', 'landing_field', 'cost' )
    #list_editable = ('date', 'takeoff',  'landing', 'pilot', 'plane',)
    date_hierarchy = 'date'
    list_filter = ( 'porpouse', 'plane', 'pilot' )
    search_fields = ('id', 'pilot__sort_name', 'plane__regmark', 'plane__model', 'plane__type', 'porpouse', )
    inlines = [FlightBillInline, ]
    save_as = True
    save_on_top = True
    form = FlightAdminForm

admin.site.register(Flight, FlightAdmin)

class FlightBillAdmin(admin.ModelAdmin):
    list_display = ('__unicode__', 'flight', 'tow_flight', 'payer', 'cost', 'cost_class',)
    list_filter = ('cost_class', 'payer',)
    search_fields = ('payer__sort_name', 'flight__id')

admin.site.register(FlightBill, FlightBillAdmin)

admin.site.register(MemberCredit)

class ReceiptDetailGenericInline(admin.TabularInline):
    model = ReceiptDetailGeneric
    fields = ('description', 'quantity', 'amount', 'total', 'memo')
    formfield_overrides = {
        models.TextField: {'widget': forms.Textarea(attrs={'class':'note', 'rows':'1', 'cols':'30'})}
    }
    verbose_name  = 'Item'
    verbose_name_plural = 'Items'
    extra = 3
#admin.site.register(ReceiptDetailGeneric)

# class TowDetailInline(admin.TabularInline):
#     model = TowDetail
#     fields = ('cents', 'cent_cost', 'total', 'memo')
#     formfield_overrides = {
#         models.TextField: {'widget': forms.Textarea(attrs={'class':'note', 'rows':'1', 'cols':'30'})}
#     }
#     verbose_name  = 'Tow credit'
#     verbose_name_plural = 'Tow credits'
#     extra = 1
#     max_num = 1
#admin.site.register(TowDetail)

class ReceiptDetailFlightInline(admin.TabularInline):
    model = ReceiptDetailFlight
    fields = ('credit_class', 'credit', 'price_credit', 'total', 'memo')
    formfield_overrides = {
        models.TextField: {'widget': forms.Textarea(attrs={'class':'note', 'rows':'1', 'cols':'30'})}
    }
    verbose_name  = 'Flights credit'
    verbose_name_plural = 'Flights credits'
    extra = 3
    max_num = 3

# class MotorGliderDetailInline(admin.TabularInline):
#     model = MotorGliderDetail
#     formfield_overrides = {
#         models.TextField: {'widget': forms.Textarea(attrs={'class':'note', 'rows':'1', 'cols':'30'})}
#     }
#     fields = ('cents', 'cent_cost', 'total', 'memo')
#     verbose_name  = 'Motor glider credit'
#     verbose_name_plural = 'Motor glider credits'
#     extra = 1
#     max_num = 1
#admin.site.register(MotorGliderDetail)

class ReceiptAdmin(admin.ModelAdmin):
    inlines = [ReceiptDetailGenericInline, ReceiptDetailFlightInline]
    date_hierarchy = 'date'
    list_filter = ('description',)
    search_fields = ('reference', 'payer__sort_name', 'description')
    exclude = ('created','created_by', 'updated', 'updated_by')
    list_display = ('reference', 'date', 'payer', 'tow_cents', 'tmg_cents', 'total', 'description', 'created_by', 'created')
    #list_editable = ('reference', 'payer', 'note')
    formfield_overrides = {
        models.TextField: {'widget': forms.Textarea(attrs={'class':'note', 'rows':'1', 'cols':'50'})}
    }

    def save_model(self, request, obj, form, change):
        if not change:
            obj.created_by = request.user
        else:
            obj.updated_by = request.user
        if form.is_valid():
            description = form.cleaned_data['description']
            if not description:
                if form.data:
                    cents = ugettext('Cents')
                    description = ''
                    for k,v in form.data.iteritems():
                        if 'description' in k and v:
                            description += ', '+v
                        elif 'receiptdetailflight' in k and 'credit_class' in k and v:
                            if v == 'towing':
                                cents = ugettext('Tow cents')
                            elif v == 'tmg':
                                cents = ugettext('TMG cents')
                            elif v == 'tourist':
                                cents = ugettext('Tourist cents')
                            elif v == 'promo':
                                cents = ugettext('Promotional flight')
                            description += ', '+cents
                    if description:
                        description = description[2:]
            obj.description = description
        obj.save()

admin.site.register(Receipt, ReceiptAdmin)

class TowerLogAdmin(admin.ModelAdmin):
    list_display = ('log_file', 'created')
admin.site.register(TowerLog, TowerLogAdmin)


"""Seed file to make sample data for adoption db."""

from models import db, Pet
from app import app

db.drop_all()
db.create_all()

# Add pets

tina = Pet(
    name="Tina",
    species="hedgehog",
    img_url="https://nypost.com/wp-content/uploads/sites/2/2021/05/hedgehog.jpg?quality=75&strip=all&w=1488",
    age=4,
    available=False,
)
yuki = Pet(
    name="Yuki",
    species="dog",
    img_url="https://scontent-iad3-1.xx.fbcdn.net/v/t39.30808-6/306992082_10161853861704392_3834033049827520645_n.jpg?_nc_cat=110&ccb=1-7&_nc_sid=0debeb&_nc_ohc=68moG2AnxSEAX8MrRI8&_nc_ht=scontent-iad3-1.xx&oh=00_AfClJkJnU2S8l_ZS3oQvcNygpYGweCPIG-yusbcIfnd3wg&oe=63857C75",
    age=1,
    available=False,
)
skunky = Pet(name="Skunky", species="cat")

db.session.add(tina)
db.session.add(yuki)
db.session.add(skunky)

db.session.commit()


import data.config
from .. import create_segments
from ..record import Record
from ..segment import Segment, Intersection
import fiona
import os
from .. import util
import shutil
import json
from shapely.geometry import LineString, MultiLineString

TEST_FP = os.path.dirname(os.path.abspath(__file__))

def test_get_intersection_buffers():
    """
    Use small test version of inters.shp to test
    """

    inters = fiona.open(
        TEST_FP + '/data/processed/maps/inters.geojson')
    inters = util.reproject_records([x for x in inters])

    assert len(inters) == 6

    # Two test intersections overlap with the regular buffer
    int_buffers = create_segments.get_intersection_buffers(inters, 20)
    assert len(int_buffers) == 5

    # No intersections overlap with a small buffer
    int_buffers = create_segments.get_intersection_buffers(inters, 5)
    assert len(int_buffers) == 6

def test_find_non_ints():

    roads, inters = util.get_roads_and_inters(os.path.join(
        TEST_FP,
        'data/processed/maps/boston_test_elements.geojson'
    ))

    int_buffers = create_segments.get_intersection_buffers(inters, 20)
    non_int_lines, inter_segments = create_segments.find_non_ints(
        roads, int_buffers)
    assert len(non_int_lines) == 7

    # Test that when a segment falls entirely within an intersection buffer
    # it is not included as a non intersection segment
    roads, inters = util.get_roads_and_inters(os.path.join(
        TEST_FP,
        'data/test_create_segments/no_non_inter.geojson'
    ))

    int_buffers = create_segments.get_intersection_buffers(inters, 20)
    non_int_lines, inter_segments = create_segments.find_non_ints(
        roads, int_buffers)
    assert len(non_int_lines) == 8
    assert len(inter_segments) == 2

def test_create_segments_from_json(tmpdir):
    """
    Just test that this runs, for now
    """
    # Copy test data into temp directory
    orig_path = os.path.dirname(
        os.path.abspath(__file__)) + '/data/'
    path = tmpdir.strpath + '/data/processed/maps/'

    os.makedirs(path)
    shutil.copyfile(
        orig_path + 'missing_segments_test.geojson',
        path + 'osm_elements.geojson'
    )
    non_inters, inters = create_segments.create_segments_from_json(
        path + 'osm_elements.geojson',
        path
    )

    # Now test for the issue where we thought a dead end was an intersection
    # Just make sure that doesn't die
    shutil.copyfile(
        orig_path + 'bad_intersection_test.geojson',
        path + 'osm_elements.geojson'
    )
    create_segments.create_segments_from_json(
        path + 'osm_elements.geojson',
        path
    )

def test_get_intersection_name():
    inter_segments = [{
        'id': 1,
        'name': 'Test Street',
    }, {
        'id': 2,
        'name': 'Test Street',
    }, {
        'id': 3,
        'name': '[Another Street, One More Road]',
    }]
    name = create_segments.get_intersection_name(inter_segments)
    assert name == 'Another Street near One More Road and Test Street'

def test_get_non_intersection_name():
    non_inter_segment = Segment(None, {
        'osmid': 1,
        'name': 'Main Street',
        'from': '100',
        'to': '200'
    })
    inters_by_id = {
    }
    name = create_segments.get_non_intersection_name(
        non_inter_segment, inters_by_id)
    assert name == 'Main Street'

    inters_by_id['100'] = 'From Street'
    name = create_segments.get_non_intersection_name(
        non_inter_segment, inters_by_id)
    assert name == 'Main Street from From Street'

    inters_by_id['100'] = None
    inters_by_id['200'] = 'To Street, Another Street'
    name = create_segments.get_non_intersection_name(
        non_inter_segment, inters_by_id)
    assert name == 'Main Street from To Street/Another Street'

    inters_by_id['100'] = 'From Street'
    name = create_segments.get_non_intersection_name(
        non_inter_segment, inters_by_id)
    assert name == 'Main Street between From Street and To Street/Another Street'

def _create_point_test(tmpdir):
    base_path = os.path.join(
        os.path.dirname(
            os.path.abspath(__file__)),
        'data')
    test_path = os.path.join(
        base_path,
        'test_create_segments'
    )

    with open(os.path.join(test_path, 'points_test.json'), 'r') as f:
        data = json.load(f)

    # All the line strings are roads
    non_inters = [Segment(LineString(
        x['geometry']['coordinates']), x['properties']
    ) for x in data if x['geometry']['type'] == 'LineString']
    # There's only one test intersection
    inter = [x for x in data if x['geometry']['type'] == 'MultiLineString'][0]
    lines = [LineString(x) for x in inter['geometry']['coordinates']]
    inters = [Intersection(
        975,
        lines,
        inter['properties']['data'],
        {'id': inter['properties']['id']}
    )]
    coords = []
    for line in inters[0].lines:
        coords.append(line.coords)
    inters[0].geometry = MultiLineString(
        coords)

    featsfile = os.path.join(test_path, 'points.geojson')
    outputfile = os.path.join(tmpdir.strpath, 'result.json')
    return base_path, non_inters, inters, outputfile, featsfile

def test_update_intersection_properties(tmpdir):
    base_path, non_inters, inters, outputfile, featsfile = _create_point_test(
        tmpdir)
    non_inters, inters = create_segments.add_point_based_features(
        non_inters, inters, outputfile, featsfile)
    config = data.config.Configuration(
        os.path.join(base_path, 'config_features.yml'))
    results = create_segments.update_intersection_properties(
        inters, config)
    print(results[0].properties)
    assert results[0].properties == {
        'id': 975,
        'osm_speed': '25',
        'width': 13,
        'cycleway_type': None,
        'oneway': 1,
        'lanes': 2,
        'signal': 0,
        'crosswalk': 1,
        'jam': None,
        'width_per_lane': 6,
        'jam_percent': None,
        'connected_segments': []
    }

def test_add_point_based_features(tmpdir):

    base_path, non_inters, inters, outputfile, featsfile = _create_point_test(
        tmpdir)
    non_inters, inters = create_segments.add_point_based_features(
        non_inters, inters, outputfile, featsfile)

    # Check whether the segments we expected got the properties
    assert inters[0].data[0]['crosswalk'] == 1
    signalized = [x for x in non_inters if x.properties['signal']]
    assert len(signalized) == 1
    assert signalized[0].properties['id'] == '001556'

    # Run again (to read from file) and make sure everything looks the same
    non_inters, inters = create_segments.add_point_based_features(
        non_inters, inters, outputfile, featsfile)

    assert inters[0].data[0]['crosswalk'] == 1
    signalized = [x for x in non_inters if x.properties['signal']]
    assert len(signalized) == 1
    assert signalized[0].properties['id'] == '001556'

    # Test writing to the file is as expected
    expected = [{
        "feature": "signal",
        "location": {"latitude": 42.383125, "longitude": -71.138121},
        "near_id": "001556"
    }, {
        "feature": "signal",
        "location": {"latitude": 42.386904, "longitude": -71.1161581},
        "near_id": ""
    }, {
        "feature": "crosswalk",
        "location": {"latitude": 42.3834466, "longitude": -71.1377047},
        "near_id": 975
    }]
    with open(outputfile, 'r') as f:
        output = json.load(f)
        assert output == expected

    # Now test with adding additional_features, and use forceupdate
    additional_feats_file = os.path.join(
        base_path, 'test_create_segments', 'additional_points.json')
    non_inters, inters = create_segments.add_point_based_features(
        non_inters, inters, outputfile, featsfile,
        additional_feats_filename=additional_feats_file, forceupdate=True)
    assert non_inters[4].properties['parking_tickets'] == 2
    assert non_inters[4].properties['traffic_volume'] == 200

    expected = expected + [{
        "feature": "parking_tickets",
        "date": "2016-05-17T00:00:00Z",
        "location": {"latitude": 42.38404209999999, "longitude": -71.1370766},
        "category": "NO PARKING",
        "near_id": "001557"
    }, {
        "feature": "parking_tickets",
        "date": "2014-01-04T15:50:00Z",
        "location": {"latitude": 42.38404209999999, "longitude": -71.1370766},
        "category": "METER EXPIRED", "near_id": "001557"
    }, {
        "feature": "traffic_volume",
        "date": "2014-01-04T15:50:00Z",
        "location": {"latitude": 42.38404209999999, "longitude": -71.1370766},
        "feat_agg": "latest", "value": 100, "near_id": "001557"
    }, {
        "feature": "traffic_volume",
        "date": "2015-01-04T15:50:00Z",
        "location": {"latitude": 42.38404209999999, "longitude": -71.1370766},
        "feat_agg": "latest", "value": 200, "near_id": "001557"
    }]

    with open(outputfile, 'r') as f:
        output = json.load(f)
        assert output == expected

def test_get_connections():
    test_path = os.path.join(
        os.path.dirname(
            os.path.abspath(__file__)),
        'data',
        'test_create_segments')

    test_file = os.path.join(test_path, 'test_get_connections1.geojson')

    roads, inters = util.get_roads_and_inters(test_file)

    # Test the segment on the other side of the median
    # getting dropped from the intersection
    connections = create_segments.get_connections(
        [Record(inters[0]['properties'], point=inters[0]['geometry'])], roads)

    # One intersection is found
    assert len(connections) == 1
    # And it only has three components
    assert len(connections[0][0]) == 3
    ids = [int(x.properties['id']) for x in connections[0][0]]
    ids.sort()
    assert ids == [263, 1167, 1168]

    # Test an intersection with two connected points getting merged
    # into one intersection
    test_file = os.path.join(test_path, 'test_get_connections2.geojson')
    roads, inters = util.get_roads_and_inters(test_file)
    # The initial file should have 7 roads and 2 intersections
    assert len(roads) == 7
    assert len(inters) == 2
    connections = create_segments.get_connections(
        [Record(x['properties'], point=x['geometry']) for x in inters], roads)

    assert len(connections) == 1
    assert len(connections[0][0]) == 7

    # Test that the case with two unconnected intersections works
    test_file = os.path.join(test_path, 'unconnected.geojson')
    roads, inters = util.get_roads_and_inters(test_file)
    connections = create_segments.get_connections(
        [Record(x['properties'], point=x['geometry']) for x in inters], roads)
    assert len(connections) == 2
    assert connections[0][0]
    assert connections[1][0]

    test_file = os.path.join(test_path, 'missing_int_segments.geojson')
    roads, inters = util.get_roads_and_inters(test_file)
    connections = create_segments.get_connections(
        [Record(x['properties'], point=x['geometry']) for x in inters], roads)
    assert len(connections) == 1
    assert len(connections[0][0]) == 7

    # Test an edge case where the point is slightly off from the line
    # This happens at least once in the Boston data, although it should
    # never happen in the openstreetmap data
    test_file = os.path.join(test_path, 'empty_set_inter.geojson')

    roads, inters = util.get_roads_and_inters(test_file)

    # Test the segment on the other side of the median
    # getting dropped from the intersection
    connections = create_segments.get_connections(
        [Record(inters[0]['properties'], point=inters[0]['geometry'])], roads)
    assert connections[0][0]

def test_connected_segments():
    """
    Test of the connected components for intersections and non intersections
    """

    roads, inters = util.get_roads_and_inters(os.path.join(
        TEST_FP,
        'data/test_create_segments/test_adjacency.geojson'
    ))

    int_buffers = create_segments.get_intersection_buffers(inters, 20)
    non_int_lines, inter_segments = create_segments.find_non_ints(
        roads, int_buffers)

    # This tests a bugfix where lines that almost but not quite intersect
    # are correctly left out of set of intersection lines
    assert len(inter_segments[1].lines) == 3

    # Test connected segments
    assert set(inter_segments[0].connected_segments) == set([
        '0011', '007', '005', '000'])
    assert set(non_int_lines[8].properties['connected_segments']) == set([
        3, 4])

def test_multilinestring():
    """
    Test that MultiLineStrings get converted into LineStrings
    """
    roads, inters = util.get_roads_and_inters(os.path.join(
        TEST_FP,
        'data/test_create_segments/test_linestring.geojson'
    ))

    for i, road in enumerate(roads):
        road.properties['orig_id'] = int(str(99) + str(i))

    int_buffers = create_segments.get_intersection_buffers(inters, 20)
    non_int_lines, inter_segments = create_segments.find_non_ints(
        roads, int_buffers)
    assert all([x.geometry.type == 'LineString' for x in non_int_lines])


# Combine the two programs from Exercise into one file.
# If the number is already stored, report the favorite number to the user.
# If not, prompt for the user’s favorite number and store it in a file.
# Run the program twice to see that it works.
import json
filename = "faveNumber.json"
try:
    with open(filename, 'r') as f:
        Fave_number = json.load(f)
except FileNotFoundError:
    Fave_number = input("Can you tell me what your favourite is ?: ")
    with open(filename, "w") as f:
        json.dump(Fave_number, f)
else:
    print(f"I know your favorite number! It's {Fave_number}.")


from typing import Tuple
import tensorflow as tf

# The goal is to calculate the top K highest relevant negative samples from very large dataset
# but given scenarios K = 10, the top K might have overlapse ids with the positive sample
# given ids of positive samples on each batch row, remove overlapse ids if exists

# A query embedding will be passed into stream
queries = None

# top 10
k = 10

# Given candidates = movies.batch(128).map(
#       lambda x: (x["movie_id"], movie_model(x["movie_title"]))
# )
# this function will be used as a another mapper to candidate
# notice that output indices will be 2 dimension
def top_scores(candidate_index: tf.Tensor,
                candidate_batch: tf.Tensor) -> Tuple[tf.Tensor, tf.Tensor]:

    scores = tf.linalg.matmul(queries, candidate_batch, transpose_b=True)

    k_ = k

    scores, indices = tf.math.top_k(scores, k=k_, sorted=True)

    return scores, tf.gather(candidate_index, indices)

# top_scores will produce multiple batch of tuple(score, identity)
# this function will be used as reduce, to reduce result to only 1 tuple of top k
def top_k(state: Tuple[tf.Tensor, tf.Tensor],
            x: Tuple[tf.Tensor, tf.Tensor]) -> Tuple[tf.Tensor, tf.Tensor]:

    state_scores, state_indices = state
    x_scores, x_indices = x

    joined_scores = tf.concat([state_scores, x_scores], axis=1)
    joined_indices = tf.concat([state_indices, x_indices], axis=1)

    k_ = k

    scores, indices = tf.math.top_k(joined_scores, k=k_, sorted=True)

    return scores, tf.gather(joined_indices, indices, batch_dims=1)

# You can use this function instead of tf.gather(identifiers, indices, batch_dims=1)
def _take_along_axis(arr: tf.Tensor, indices: tf.Tensor) -> tf.Tensor:
  """Partial TF implementation of numpy.take_along_axis.

  See
  https://numpy.org/doc/stable/reference/generated/numpy.take_along_axis.html
  for details.

  Args:
    arr: 2D matrix of source values.
    indices: 2D matrix of indices.

  Returns:
    2D matrix of values selected from the input.
  """

  row_indices = tf.tile(
      tf.expand_dims(tf.range(tf.shape(indices)[0]), 1),
      [1, tf.shape(indices)[1]])
  gather_indices = tf.concat(
      [tf.reshape(row_indices, (-1, 1)),
       tf.reshape(indices, (-1, 1))], axis=1)

  return tf.reshape(tf.gather_nd(arr, gather_indices), tf.shape(indices))

# 10 + 1 positive samples
# First step would be calculate top 11 scores,
# then reduce the ids if exists and recalculate top 10 scores
adjusted_k = 11

batch_size = 5

# Seed data for testing, ensure data format
scores = tf.reshape(tf.cast(tf.range(50, (adjusted_k * 5) + 50), tf.float32), shape=(batch_size, adjusted_k))
identifiers = tf.reshape(tf.range(adjusted_k * 5), shape=(batch_size, adjusted_k))

def exclude():
    # Seed ids need to be excluded
    exclude = tf.constant([
        [2],
        [15],
        [27],
        [33],
        [47],
    ])

    idents = tf.expand_dims(identifiers, -1)
    exclude = tf.expand_dims(exclude, 1)

    isin = tf.math.reduce_any(tf.math.equal(idents, exclude), -1)

    # Set the scores of the excluded candidates to a very low value.
    adjusted_scores = (scores - tf.cast(isin, tf.float32) * 1.0e5)

    # Make sure k is smaller or equal scores size
    k_ = tf.math.minimum(k, tf.shape(scores)[1])

    _, indices = tf.math.top_k(adjusted_scores, k_)

    # produce the same result
    print(tf.gather(identifiers, indices, batch_dims=1))
    print(_take_along_axis(identifiers, indices))

exclude()


"""
Knoxville Divergence

Definition The Knoxville Divergence indicator suggests that price will reverse in direction, making it a
counter-trend indicator. For example, if price is in an uptrend with the Knoxville Divergence line set above the
price on the chart, the trader will understand that the indicator is suggesting price will potentially reverse and
shift to a downtrend shortly. This indicator is very useful for counter-trend traders and general trend-traders
alike, as it adds perspective for those seeking to enter a trade, while following a long-term trend.

History This indicator is used and admired by Rob Booker, an experienced entrepreneur and currency trader who has
helped bring popularity to the indicator.

Takeaways
When analyzing Knoxville Divergence, it should be known that the indicator is comprised of two main elements.

The Momentum indicator. If price is rising, but the momentum indicator is falling, the Knoxville Divergence indicator
might appear on the chart to signal to the trader that a price reversal may be closing in. This indicator must be
paired with another, however, because it does not tell the trader everything they need to know. This is why it pairs
nicely with our second element.

Relative Strength Index. If there is a simultaneous discrepancy between price and the momentum indicator,
the Relative Strength Index (RSI) will signal as overbought or oversold, and will trigger the Knoxville Divergence
line to appear on the chart.

Script:
First, we need to compute the Momentum indicator. The Momentum of a price is simply the difference in price over

the specified period. In this case, the period is 18.

Next, we will calculate the Relative Strength Index (RSI). The RSI is a bit more complex. It measures the speed and
change of price movements and is often used to identify overbought or oversold conditions in a market. When the RSI
for a security gets above 70, it could indicate that the asset is overbought, and when it gets below 30,
it could indicate the asset is oversold. """

import matplotlib.pyplot as plt
import ta
import yfinance as yf

def get_knoxville_divergence(data, period=21):
    # Calculate Momentum and RSI
    data['momentum'] = ta.momentum.AwesomeOscillatorIndicator(high=data['High'], low=data['Low'], window1=5, window2=period).awesome_oscillator()
    data['rsi'] = ta.momentum.RSIIndicator(close=data['Close'], window=period).rsi()

    # Initialize Knoxville Divergence series with 0
    data['knoxville_divergence'] = 0

    # Identify Bullish/Bearish Divergence
    for i in range(period, len(data)):
        # Bullish Divergence
        if data['Close'].iloc[i] > data['Close'].iloc[i-period] and data['momentum'].iloc[i] < data['momentum'].iloc[i-period] and data['rsi'].iloc[i] < 30:
            data['knoxville_divergence'].iloc[i] = -1
        # Bearish Divergence
        elif data['Close'].iloc[i] < data['Close'].iloc[i-period] and data['momentum'].iloc[i] > data['momentum'].iloc[i-period] and data['rsi'].iloc[i] > 70:
            data['knoxville_divergence'].iloc[i] = 1

    return data

# Fetch data from Yahoo Finance
data = yf.download('PLTR', start='2022-01-01', end='2023-01-01', interval='1d')

# Calculate Knoxville Divergence
data = get_knoxville_divergence(data)

# Plot the Close price and the Knoxville Divergence
fig, ax1 = plt.subplots()

color = 'tab:blue'
ax1.set_xlabel('Date')
ax1.set_ylabel('Close', color=color)
ax1.plot(data.index, data['Close'], color=color)
ax1.tick_params(axis='y', labelcolor=color)

ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis
color = 'tab:red'
ax2.set_ylabel('Knoxville Divergence', color=color)
ax2.plot(data.index, data['knoxville_divergence'], color=color)
ax2.tick_params(axis='y', labelcolor=color)

plt.title('PLTR Close Price and Knoxville Divergence')
fig.tight_layout()  # otherwise the right y-label is slightly clipped
plt.show()


class Solution:
    def findSubstring(self, s, words):
        """
        做不来
        :param s:
        :param words:
        :return:
        """
        if not s or not words:
            return []

        lenth = len(words[0]) * len(words)
        word_len = len(words[0])
        from collections import Counter
        words_hash = Counter(words)
        res = []
        for i in range(0, len(s) - lenth + 1):
            tmp = s[i:i + lenth]
            # print(tmp)
            c_tmp = []
            for j in range(0, lenth, word_len):
                c_tmp.append(tmp[j:j+word_len])
            # print(c_tmp)
            c_tem_hash = Counter(c_tmp)
            if c_tem_hash == words_hash:
                res.append(i)
        return res

if __name__ == "__main__":
    str = "barfoothefoobarman"
    words = ["foo", "bar"]
    s = Solution()
    print(s.findSubstring(str, words))


from typing import Any, Text, Dict, List, Union
from rasa_sdk import Action, Tracker
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.forms import FormAction
from rasa_sdk.events import SlotSet, FollowupAction
from misc_utils.tictactoe import *

# Global Variables for TicTacToe
boards = [' ' for x in range(10)]

class ActionPlayTictactoe(Action):

    def name(self) -> Text:
        return "action_play_tictactoe"

    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
        global boards

        dispatcher.utter_message(text="Alright! Let's get our game faces on!")
        dispatcher.utter_message(text="Here's our board...")
        dispatcher.utter_message(printBoard(boards))
        dispatcher.utter_message(text="You'll have to fill in the board positions with numbers...")
        dispatcher.utter_message(text="Type in a number between 1-9 for the appropriate position")
        return [FollowupAction('tictactoe_input'), SlotSet("TicTacToe", None)]

class TicTacToeInput(FormAction):
    def name(self) -> Text:
        return "tictactoe_input"

    @staticmethod
    def required_slots(tracker: "Tracker") -> List[Text]:
        return ["TicTacToe"]

    def slot_mappings(self) -> Dict[Text, Union[Dict, List[Dict]]]:
        return {
            "TicTacToe": [
                self.from_text(intent=None)
            ]
        }

    def validate_TicTacToe(
            self,
            value: Text,
            dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any],
    ) -> Dict[Text, Any]:
        global boards
        if not isBoardFull(boards):
            if not isWinner(boards, 'O'):
                num = tracker.latest_message.get('text')
                boards, move = playerMove(boards, str(num))
                dispatcher.utter_message(str(move))
                strs = printBoard(boards)
                dispatcher.utter_message(strs)
                if move != 'Oops...This space is already occupied! Try again':
                    if not isBoardFull(boards):
                        if not isWinner(boards, 'X'):
                            boards, num = compMove(boards)
                            boards = insertLetter(boards, 'O', num)
                            dispatcher.utter_message(
                                'I placed an \'O\' at position number {}... Your turn! :'.format(str(num)))
                            dispatcher.utter_message(printBoard(boards))
                            return {"TicTacToe": None}
                        else:
                            dispatcher.utter_message('You won! Good Job!')
                            return {"TicTacToe": tracker.latest_message.get('text')}
                    else:
                        dispatcher.utter_message("Awww dang! It's a tie!")
                        return {"TicTacToe": tracker.latest_message.get('text')}
            else:
                dispatcher.utter_message('Sorry! I won ! Better luck next time, buddy')
                return {"TicTacToe": tracker.latest_message.get('text')}
        else:
            dispatcher.utter_message("Awww dang! It's a tie!")
            return {"TicTacToe": tracker.latest_message.get('text')}

    def submit(self, dispatcher: CollectingDispatcher,
               tracker: Tracker,
               domain: Dict[Text, Any]) -> List[Dict]:
        global boards
        boards = [' ' for x in range(10)]
        return [SlotSet("TicTacToe", None)]


#!/usr/bin/env python
class Solution:
    # @param {integer} x
    # @return {boolean}
    def isPalindrome(self, x):
        if x < 0:
            return False
        numList = list(str(x))
        length = len(numList)
        i, j = 0, length-1
        while i < j:
            if numList[i] != numList[j]:
                return False
            i += 1
            j -= 1
        return True


"""
Support for the DirecTV receivers.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.directv/
"""
import logging
import requests
import voluptuous as vol

from homeassistant.components.media_player import (
    MEDIA_TYPE_MOVIE, MEDIA_TYPE_TVSHOW, PLATFORM_SCHEMA, SUPPORT_NEXT_TRACK,
    SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK,
    SUPPORT_SELECT_SOURCE, SUPPORT_STOP, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,
    MediaPlayerDevice)
from homeassistant.const import (
    CONF_DEVICE, CONF_HOST, CONF_NAME, CONF_PORT, STATE_OFF, STATE_PAUSED,
    STATE_PLAYING)
import homeassistant.helpers.config_validation as cv
import homeassistant.util.dt as dt_util

REQUIREMENTS = ['directpy==0.5']

_LOGGER = logging.getLogger(__name__)

ATTR_MEDIA_CURRENTLY_RECORDING = 'media_currently_recording'
ATTR_MEDIA_RATING = 'media_rating'
ATTR_MEDIA_RECORDED = 'media_recorded'
ATTR_MEDIA_START_TIME = 'media_start_time'

DEFAULT_DEVICE = '0'
DEFAULT_NAME = "DirecTV Receiver"
DEFAULT_PORT = 8080

SUPPORT_DTV = SUPPORT_PAUSE | SUPPORT_TURN_ON | SUPPORT_TURN_OFF | \
    SUPPORT_PLAY_MEDIA | SUPPORT_SELECT_SOURCE | SUPPORT_STOP | \
    SUPPORT_NEXT_TRACK | SUPPORT_PREVIOUS_TRACK | SUPPORT_PLAY

DATA_DIRECTV = 'data_directv'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_HOST): cv.string,
    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
    vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
    vol.Optional(CONF_DEVICE, default=DEFAULT_DEVICE): cv.string,
})

def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the DirecTV platform."""
    known_devices = hass.data.get(DATA_DIRECTV)
    if not known_devices:
        known_devices = []
    hosts = []

    if CONF_HOST in config:
        hosts.append([
            config.get(CONF_NAME), config.get(CONF_HOST),
            config.get(CONF_PORT), config.get(CONF_DEVICE)
        ])

    elif discovery_info:
        host = discovery_info.get('host')
        name = 'DirecTV_{}'.format(discovery_info.get('serial', ''))

        # Attempt to discover additional RVU units
        try:
            resp = requests.get(
                'http://%s:%d/info/getLocations' % (host, DEFAULT_PORT)).json()
            if "locations" in resp:
                for loc in resp["locations"]:
                    if("locationName" in loc and "clientAddr" in loc
                       and loc["clientAddr"] not in known_devices):
                        hosts.append([str.title(loc["locationName"]), host,
                                      DEFAULT_PORT, loc["clientAddr"]])

        except requests.exceptions.RequestException:
            # Bail out and just go forward with uPnP data
            if DEFAULT_DEVICE not in known_devices:
                hosts.append([name, host, DEFAULT_PORT, DEFAULT_DEVICE])

    dtvs = []

    for host in hosts:
        dtvs.append(DirecTvDevice(*host))
        known_devices.append(host[-1])

    add_entities(dtvs)
    hass.data[DATA_DIRECTV] = known_devices

class DirecTvDevice(MediaPlayerDevice):
    """Representation of a DirecTV receiver on the network."""

    def __init__(self, name, host, port, device):
        """Initialize the device."""
        from DirectPy import DIRECTV
        self.dtv = DIRECTV(host, port, device)
        self._name = name
        self._is_standby = True
        self._current = None
        self._last_update = None
        self._paused = None
        self._last_position = None
        self._is_recorded = None
        self._assumed_state = None

        _LOGGER.debug("Created DirecTV device for %s", self._name)

    def update(self):
        """Retrieve latest state."""
        _LOGGER.debug("Updating state for %s", self._name)
        self._is_standby = self.dtv.get_standby()
        if self._is_standby:
            self._current = None
            self._is_recorded = None
            self._paused = None
            self._assumed_state = False
            self._last_position = None
            self._last_update = None
        else:
            self._current = self.dtv.get_tuned()
            self._is_recorded = self._current.get('uniqueId') is not None
            self._paused = self._last_position == self._current['offset']
            self._assumed_state = self._is_recorded
            self._last_position = self._current['offset']
            self._last_update = dt_util.now() if not self._paused or\
                self._last_update is None else self._last_update

    @property
    def device_state_attributes(self):
        """Return device specific state attributes."""
        attributes = {}
        if not self._is_standby:
            attributes[ATTR_MEDIA_CURRENTLY_RECORDING] =\
                self.media_currently_recording
            attributes[ATTR_MEDIA_RATING] = self.media_rating
            attributes[ATTR_MEDIA_RECORDED] = self.media_recorded
            attributes[ATTR_MEDIA_START_TIME] = self.media_start_time

        return attributes

    @property
    def name(self):
        """Return the name of the device."""
        return self._name

    # MediaPlayerDevice properties and methods
    @property
    def state(self):
        """Return the state of the device."""
        if self._is_standby:
            return STATE_OFF

        # For recorded media we can determine if it is paused or not.
        # For live media we're unable to determine and will always return
        # playing instead.
        if self._paused:
            return STATE_PAUSED

        return STATE_PLAYING

    @property
    def assumed_state(self):
        """Return if we assume the state or not."""
        return self._assumed_state

    @property
    def media_content_id(self):
        """Return the content ID of current playing media."""
        if self._is_standby:
            return None

        return self._current['programId']

    @property
    def media_content_type(self):
        """Return the content type of current playing media."""
        if self._is_standby:
            return None

        if 'episodeTitle' in self._current:
            return MEDIA_TYPE_TVSHOW

        return MEDIA_TYPE_MOVIE

    @property
    def media_duration(self):
        """Return the duration of current playing media in seconds."""
        if self._is_standby:
            return None

        return self._current['duration']

    @property
    def media_position(self):
        """Position of current playing media in seconds."""
        if self._is_standby:
            return None

        return self._last_position

    @property
    def media_position_updated_at(self):
        """When was the position of the current playing media valid.

        Returns value from homeassistant.util.dt.utcnow().
        """
        if self._is_standby:
            return None

        return self._last_update

    @property
    def media_title(self):
        """Return the title of current playing media."""
        if self._is_standby:
            return None

        return self._current['title']

    @property
    def media_series_title(self):
        """Return the title of current episode of TV show."""
        if self._is_standby:
            return None

        return self._current.get('episodeTitle')

    @property
    def media_channel(self):
        """Return the channel current playing media."""
        if self._is_standby:
            return None

        return "{} ({})".format(
            self._current['callsign'], self._current['major'])

    @property
    def source(self):
        """Name of the current input source."""
        if self._is_standby:
            return None

        return self._current['major']

    @property
    def supported_features(self):
        """Flag media player features that are supported."""
        return SUPPORT_DTV

    @property
    def media_currently_recording(self):
        """If the media is currently being recorded or not."""
        if self._is_standby:
            return None

        return self._current['isRecording']

    @property
    def media_rating(self):
        """TV Rating of the current playing media."""
        if self._is_standby:
            return None

        return self._current['rating']

    @property
    def media_recorded(self):
        """If the media was recorded or live."""
        if self._is_standby:
            return None

        return self._is_recorded

    @property
    def media_start_time(self):
        """Start time the program aired."""
        if self._is_standby:
            return None

        return dt_util.as_local(
            dt_util.utc_from_timestamp(self._current['startTime']))

    def turn_on(self):
        """Turn on the receiver."""
        _LOGGER.debug("Turn on %s", self._name)
        self.dtv.key_press('poweron')

    def turn_off(self):
        """Turn off the receiver."""
        _LOGGER.debug("Turn off %s", self._name)
        self.dtv.key_press('poweroff')

    def media_play(self):
        """Send play command."""
        _LOGGER.debug("Play on %s", self._name)
        self.dtv.key_press('play')

    def media_pause(self):
        """Send pause command."""
        _LOGGER.debug("Pause on %s", self._name)
        self.dtv.key_press('pause')

    def media_stop(self):
        """Send stop command."""
        _LOGGER.debug("Stop on %s", self._name)
        self.dtv.key_press('stop')

    def media_previous_track(self):
        """Send rewind command."""
        _LOGGER.debug("Rewind on %s", self._name)
        self.dtv.key_press('rew')

    def media_next_track(self):
        """Send fast forward command."""
        _LOGGER.debug("Fast forward on %s", self._name)
        self.dtv.key_press('ffwd')

    def select_source(self, source):
        """Select input source."""
        _LOGGER.debug("Changing channel on %s to %s", self._name, source)
        self.dtv.tune_channel(source)


# # key:value ilişkisi vardır. d[key] = value
# d1 = {}
# d2 = dict()
#
# telefonListesi = {"051454":"Annem","1232351asd":"Babam","13asd13":"Ahmet"}
# print(telefonListesi["1232351asd"])
#
# d3 = {2:"cengiz","Ali": "Mühendis", "Ahmet": "Sekreter", 6: "Sanane", 1.6: True}
#
# # EKLEME
# d3["Ezgi"]="Yazar"
# d3[2]="Işıl" # eğer aynı keyde eleman varsa eskisinin üzerine basar-siler, öyle ekler
# print(d3)
#
# print(d3.keys()) # keyleri verir
# print(d3.values()) # value verir
# print(d3.get("Ezgi1")) # keyin karsılındakı value verir
# # print(d3["asd"]) # yoksa hata verir
# if "Işıl" in d3:
#     print(d3["asd"])
# else:
#     print("Bu eleman yoktur !")
#
# # SİLME
# if "Ezgi" in d3:
#     print(d3.pop("Ezgi")) # siler ve sildiği değeri geri döndürür
#     print(d3.popitem()) # son elemanı siler ve geri döndürür

# d1 = {"Ahmet Fatih":["Tel1","Tel2"]}
#
# d2 = {"Sisli":{"Muhendis":["Ahmet","Serkan"],"TeknikServis":["Mesut","Ezgi"]},
#       "Kadikoy":{"Muhendis":["Ali","Mesut"]}}
# #print(d2["Kadikoy"]["Muhendis"])
#
# for item in d2.keys():
#     print(d2[item])

'''
    tr-ing sözlük:
    bailangıçta kendiniz 3-5 tane key-value ekleyin.
    kullanıcıya sorulur:
    1-Ekleme
    2-Arama
    3-Çıkış

    1->> ingilizcesi eklenecek olan kelime giriniz :
        bunun karşılığı nedir: bu key-value ilişkisi eklenir
    2->> araacak olan tr kelimesi griniz:
        bu kelime varsa karşılığı yazıdlır yoksa yoktur yazılır ve
        bu değeri sozluge eklemek ister msiniz: E ise value istenir ve diziye eklenir,
                                                H ise tamam denilir
    3->> çıkış yapılıyor.

'''

sozluk = {"car": "araba", "white": "beyaz", "black": "siyah"}

while True:
    secim = input("""
1-Ekleme
2-Arama
3-Çıkış
Seçiminiz:""")
    if secim == "1":
        ing = input("ING giriniz :")
        tr = input("TR giriniz :")

        sozluk[ing] = tr
        print("Ekleme gerçekleşti !")
    elif secim == "2":
        ing = input("ING kelime giriniz :")
        if ing in sozluk:
            print("{}->{}".format(ing, sozluk[ing]))
        else:
            yrd = input("bu veri yoktur. yardımcı olmak ister msin:")
            if yrd == "E":
                tr = input("TR girinzi :")
                sozluk[ing] = tr
                print("Teşekkürler")
            else:
                print("Peki yardım etsen nolurdu. !")
    elif secim == "3":
        print("Çıkış yapılyıor ")
        break
    else:
        print("Hatalı giriş yaptınız !")


# -*- coding: utf-8 -*-
# Project  : TensorFlowProjects
# File     : ep2.py
# Author   : guile
# Version  : v1.0
# Email    : lavender.lhy@gmail.com
# Date     : 2020-11-10 15:29
# Remarks  : 使用 tf.data 加载文本数据
# Tensorflow and keras
import tensorflow as tf
import tensorflow_datasets as tfds
import os

# 需要设置gpu的memory，，，否则报错
gpus = tf.config.list_physical_devices('GPU')
print(gpus)
tf.config.experimental.set_memory_growth(gpus[0], True)

DIRECTORY_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/illiad/'
FILE_NAMES = ['cowper.txt', 'derby.txt', 'butler.txt']

for name in FILE_NAMES:
    text_dir = tf.keras.utils.get_file(name, origin=DIRECTORY_URL + name)

parent_dir = "/home/guile/.keras/datasets"

def labeler(example, index):
    return example, tf.cast(index, tf.int64)

labeled_data_sets = []

for i, file_name in enumerate(FILE_NAMES):
    line_dataset = tf.data.TextLineDataset(os.path.join(parent_dir, file_name))
    labeled_dataset = line_dataset.map(lambda ex: labeler(ex, i))
    labeled_data_sets.append(labeled_dataset)

BUFFER_SIZE = 50000
BATCH_SIZE = 65
TAKE_SIZE = 5000

all_labeled_data = labeled_data_sets[0]
for label_set in labeled_data_sets[1:]:
    all_labeled_data = all_labeled_data.concatenate(label_set)

all_labeled_data = all_labeled_data.shuffle(BUFFER_SIZE, reshuffle_each_iteration=False)

tokenizer = tfds.features.text.Tokenizer()

vocabulary_set = set()
for text_tensor, _ in all_labeled_data:
    some_tokens = tokenizer.tokenize(text_tensor.numpy())
    vocabulary_set.update(some_tokens)

vocab_size = len(vocabulary_set)

encoder = tfds.features.text.TokenTextEncoder(vocabulary_set)
example_set = next(iter(all_labeled_data))[0].numpy()

encoded_example = encoder.encode(example_set)

def encode(tt, label):
    encoded_text = encoder.encode(tt.numpy())
    return encoded_text, label

def encode_map_fn(text, label):
    encoded_text, label = tf.py_function(encode, inp=[text, label], Tout=(tf.int64, tf.int64))
    encoded_text.set_shape([None])
    label.set_shape([])
    return encoded_text, label

all_encoded_data = all_labeled_data.map(encode_map_fn)

train_data = all_encoded_data.skip(TAKE_SIZE).shuffle(BUFFER_SIZE)
train_data = train_data.padded_batch(BATCH_SIZE)

test_data = all_encoded_data.take(TAKE_SIZE)
test_data = test_data.padded_batch(BATCH_SIZE)

sample_text, sample_label = next(iter(test_data))
print(sample_text[0])
print()
print(sample_label[0])

vocab_size += 1

model = tf.keras.Sequential()
model.add(tf.keras.layers.Embedding(vocab_size, 64))
model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)))

for units in [64, 64]:
    model.add(tf.keras.layers.Dense(units, activation="relu"))

model.add(tf.keras.layers.Dense(3, activation="softmax"))

model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])

model.fit(train_data, epochs=3, validation_data=test_data)

eval_loss, eval_acc = model.evaluate(test_data)

print()
print("Eval Loss: {}, Eval Acc: {}".format(eval_loss, eval_acc))


import pickle
import re
def determine(ing_list):
	non_ = ['chicken','beef','fish','mutton','meat','turkey','ribs','spareribs','bacon','ham','lamb','eggs','bison','mussels','crabs','oysters','pork','loin','buffalo','rack','clams','crabmeat','bonelespork','salmon','quartchicken','quartturkey','boneleschuck','bone','catfish','filletcatfish','caviar','crab','prawn','prawns','salami','pepperoni','yolk','shrimp','shrimps']
	non_ = set(non_)
	for i in ing_list:
		if i in non_:
			return False
	return True
file = open('ingredientsnew.txt','r')
wfile = open('ingr_parsed.txt','w')
veg = 0
nonveg = 0
cur_veg = True
cur_ingr = []
for i in file:
	print(i,cur_ingr)
	i = re.sub(',',' ',i)
	wfile.write(i+'\n'+str(cur_ingr)+'\n')
	if '[' in i and len(cur_ingr)>0:
		index = i.index('[')
		vn = determine(cur_ingr)
		if vn:
			veg += 1
			#print(cur_ingr)
		else:
			nonveg += 1
		cur_ingr = i[index+1:].split()
	elif ']' in i:
		index = i.index(']')
		temp = i[:index].split()
		for j in temp:
			cur_ingr.append(j)
	else:
		#cur_ingr.append(i)
		temp = i.split()
		for j in temp:
			cur_ingr.append(j)

	#print(temp)
print(veg,nonveg)


import pygame
import math
from pygame.locals import *
import langton

RESOLUTION = (1000, 500)
GAME_GRID = (100, 50)
HOW_FAST = 1
WHITE = (255,255,255)
PURPLE = (135,95,154)
BLACK = (0,0,0)

class Game():

    def __init__(self, x, y):
        self.map = langton.Map(x, y)
        self.block_rect = (RESOLUTION[0]/x, RESOLUTION[1]/y)
        self.iterations = 0

    def setup(self):
        pygame.init()

        ant1 = langton.Ant(self.map.get_num_ants())
        self.map.add_ant(ant1, self.map.x//2 , self.map.y//2)
        self.GAME_END = False
        self.game_display = pygame.display.set_mode(RESOLUTION, RESIZABLE)
        self.clock = pygame.time.Clock()

        pygame.display.set_caption("WOJTEK CIOTA")

    def event_loop(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.GAME_END = True

            if event.type == pygame.MOUSEBUTTONDOWN:
                print(event)
                mouse_x = int(event.pos[0] // self.block_rect[0])
                mouse_y = int(event.pos[1] // self.block_rect[1])
                print(mouse_x, mouse_y)
                self.map.add_ant(langton.Ant(self.map.get_num_ants()), mouse_x, mouse_y)

    def draw_area(self):
        self.block_rect = (RESOLUTION[0] / self.map.x, RESOLUTION[1] / self.map.y)
        for x, row in enumerate(self.map.get_area()):
            for y, col in enumerate(row):
                x_pos = self.block_rect[0] * x
                y_pos = self.block_rect[1] * y
                height = self.block_rect[1] + 1
                width = self.block_rect[0] + 1
                if col[0] == 0:
                    if len(col) > 1:
                        pass
                        pygame.draw.rect(self.game_display, (255,100,200), (x_pos, y_pos, height, width))
                    else:
                        pass
                    pygame.draw.rect(self.game_display, WHITE, (x_pos, y_pos, height, width))
                else:
                    random = (((math.sqrt(col[0]*2))**col[0])* 10)%255
                    random_color = ((random* col[0])%255, (random*20)%255, (random*random)%255)
                    pygame.draw.rect(self.game_display, BLACK, (x_pos, y_pos, height, width))

    def main_loop(self):
        self.event_loop()

        for iter in range(HOW_FAST):
            self.map.update_ants()

        self.game_display.fill(WHITE)

        self.iterations += 1
        self.draw_area()

        self.clock.tick(60)
        self.message(str(self.clock.get_fps()//1),0)
        self.message(str(self.iterations),1)

        pygame.display.update()

    def is_end(self):
        return self.GAME_END

    def quit(self):
        pygame.quit()

    def message(self, text, where):

        default_font = pygame.font.get_default_font()
        font = pygame.font.Font('freesansbold.ttf', 22)
        shifting = font.render('', False, BLACK).get_rect()[3] * where
        text_surface = font.render(text, True, BLACK)

        self.game_display.blit(text_surface, (0, shifting))

if __name__ == '__main__':

    game = Game(GAME_GRID[0],GAME_GRID[1])

    game.setup()
    while 1:
        game.main_loop()

        if game.is_end():
            break
    game.quit()


import sys

a = 10
b = 3

# Adição
soma = a + b

# Subtração
subtracao = a - b

# Multiplicação
multiplicacao = a * b

# Divisão (retorna um número de ponto flutuante)
divisao = a / b

# Divisão inteira
divisao_inteira = a // b

# Resto da divisão
resto_divisao = a % b

# Potência
potencia = a ** b

a = 10
b = 3

# Adição
a += b

# Subtração
a -= b

# Multiplicação
a *= b

# Divisão
a /= b

# Divisão inteira
a //= b

# Resto da divisão
a %= b

# Potência
a **= b

# Fatorial de 30
fatorial_30 = 1
for i in range(1, 31):
    fatorial_30 *= i

print("Fatorial de 30 em Python:", fatorial_30)

maior_valor_int_C_CPP = 2**31 - 1

print("Maior valor inteiro em C/C++ (signed int):", maior_valor_int_C_CPP)

# Atribuição de valor a uma variável
num = 5
novo_num = num + 3

print("Original:", num)
print("Novo:", novo_num)

# Atribuição de valor a uma variável
num = 5
soma = num + 3

print("Original:", num)
print("Soma:", soma)

# Imprime o caractere e seu código numérico
for i in range(10):
    print(f"'{chr(ord('0') + i)}' - {ord('0') + i}")

# Imprime o caractere e seus códigos numéricos em decimal, octal e hexadecimal
for i in range(10):

    char = chr(ord('0') + i)
    decimal_code = ord(char)
    octal_code = oct(decimal_code)
    hexadecimal_code = hex(decimal_code)

    print(f"'{char}' - Decimal: {decimal_code}, Octal: {octal_code}, Hexadecimal: {hexadecimal_code}")

# Solicita e imprime o caractere e seus códigos numéricos em decimal, octal e hexadecimal
caractere = input("Digite um caractere: ")

decimal_code = ord(caractere)
octal_code = oct(decimal_code)
hexadecimal_code = hex(decimal_code)

print(f"'{caractere}' - Decimal: {decimal_code}, Octal: {octal_code}, Hexadecimal: {hexadecimal_code}")

# Em Python, os caracteres especiais, como 'ç' e 'ã', são tratados como caracteres Unicode.
# Python suporta Unicode, o que permite representar uma ampla variedade de caracteres,
# incluindo caracteres acentuados, especiais e de outros idiomas.

# Exercício 4: Manipulação de variáveis de tipo string e explorando os métodos da classe.
nome_completo = "João da Silva"

espaco_separador = nome_completo.find(' ')
nome = nome_completo[:espaco_separador]
sobrenome = nome_completo[espaco_separador + 1:]

ordem_alfabetica = sorted([nome, sobrenome])

tamanho_nome = len(nome)
tamanho_sobrenome = len(sobrenome)

e_palindromo = nome == nome[::-1]

print("Nome Completo:", nome_completo)
print("Nome:", nome)
print("Sobrenome:", sobrenome)
print("Ordem Alfabética:", ordem_alfabetica)
print("Quantidade de Caracteres (Nome):", tamanho_nome)
print("Quantidade de Caracteres (Sobrenome):", tamanho_sobrenome)
print("É Palíndromo:", e_palindromo)

# Operadores Aritméticos
a = 5.0
b = 2.0

soma = a + b       # Soma
subtracao = a - b  # Subtração
multiplicacao = a * b  # Multiplicação
divisao = a / b    # Divisão
resto_divisao = a % b  # Resto da divisão
potencia = a ** b  # Potência

# Operadores Aritméticos Compostos
a += b  # Adição
a -= b  # Subtração
a *= b  # Multiplicação
a /= b  # Divisão
a **= b  # Potência

maior_potencia_de_2 = sys.float_info.max_exp
menor_potencia_de_2 = sys.float_info.min_exp

print("Maior Potência de 2:", maior_potencia_de_2)
print("Menor Potência de 2:", menor_potencia_de_2)

num = 3.14

print("Número Original:", num)
print("Parte Inteira:", num.__int__())
print("Arredondado:", num.__round__(2))
print("Transformado em String:", num.__str__())