import scrapy

from scrapy.selector import Selector
from douban.items import DoubanItem
import logging
import re
from douban.db_util import db_about
import time

class DmozSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["douban.com"]

    start_urls = [
       'https://movie.douban.com/subject/7054604/',
    ]

    t1=time.time()

    # def parse(self, response):
    #     i=0
    #     for href in Selector(response=response).xpath('//div[@class="article"]/div/div/table/tr/td/a/@href'):
    #         url=href.extract()
    #         i+=1
    #         if(i==1):
    #             yield scrapy.Request(url, callback=self.parse_detail_contents)

    def parse(self, response):

        count=0
        for i in range(0,10):
            db_url = db_about.fetch_data('SELECT movie_id FROM douban.movie_name where flag=0 LIMIT 55000;')
            urls = []
            for i in db_url:
                urls.append('https://movie.douban.com/subject/' + str(i['movie_id']) + '/')

            for i in range(len(urls)):
                yield scrapy.Request(urls[i],callback=self.parse_detail_contents)

            count+=1

        print("{} ------------------------------".format(count))
        print(time.time() - self.t1)
        print(response)

        # urls=['https://movie.douban.com/subject/1291583/']
        # for i in urls:
        #     yield scrapy.Request(i,callback=self.parse_detail_contents)

    def parse_detail_contents(self,response:scrapy.http.Response):
        print(response.meta)
        #由整个网页构成的selector
        full_sel=Selector(response=response)
        info_sel = Selector(text=full_sel.xpath("//div[@id='info']").extract()[0])
        # text=response.body
        # text=text.decode('utf-8')
        # text=text.replace('\n\n','')
        # print(text)
        item = DoubanItem()

        #str
        item['movie_name'] = self.parse_single_line_excetpion("movie_name",full_sel,"//div[@id='content']/h1/span/text()",False,logging.WARN)

        item['movie_id']=response.url.split('/')[-2]
        # print(response.body)

        # 获取电影导演
        # directors_html=info_sel.xpath("//div[@id='info']/span[1]/span[@class='attrs']/a").extract()
        # item['directors']={}
        # for i in directors_html:
        #     item['directors'][self.parse_detail_contents_celebrity(Selector(text=i).xpath('//a/@href').extract())[0]]\
        #                 =Selector(text=i).xpath('//a/text()').extract()[0]

        item['directors']=self.parse_list_exception('directors',info_sel,"//div[@id='info']/span[1]/span[@class='attrs']/a[@rel='v:directedBy']")
        # print(info_sel.xpath("//div[@id='info']/span[1]/span[@class='attrs']").extract())
        # for i in item['directors']:
        #     print(i,item['directors'][i])
        #
        # print("---------------")

        # 获取电影编剧
        # writers_html = info_sel.xpath("//div[@id='info']/span[2]/span[@class='attrs']/a").extract()
        # item['writers'] = {}
        # for i in writers_html:
        #     item['writers'][self.parse_detail_contents_celebrity(Selector(text=i).xpath('//a/@href').extract())[0]] \
        #         = Selector(text=i).xpath('//a/text()').extract()[0]
        if(item['directors']=={}):
            try:
                if(info_sel.re('编剧')!=[]):
                    item['writers'] = self.parse_list_exception('directors', info_sel,
                                              "//div[@id='info']/span[1]/span[@class='attrs']/a")
            except:
                logging.log(level=logging.INFO, msg='---Not find 编剧')
        else:
            try:
                if (info_sel.re('编剧') != []):
                    item['writers'] = self.parse_list_exception('directors', info_sel,
                                                            "//div[@id='info']/span[2]/span[@class='attrs']/a")
            except:
                item['writers']={}
                logging.log(level=logging.INFO, msg='---Not find 编剧')

        # 获取电影演员
        # casts_html=info_sel.xpath("//div[@id='info']/span[@class='actor']/span[@class='attrs']/a").extract()
        # item['casts']={}
        # for i in casts_html:
        #     item['casts'][self.parse_detail_contents_celebrity(Selector(text=i).xpath('//a/@href').extract())[0]] \
        #         = Selector(text=i).xpath('//a/text()').extract()[0]

        item['casts'] = self.parse_list_exception('directors', info_sel,
                                                      "//div[@id='info']/span[@class='actor']/span[@class='attrs']/a")
        # for i in item['casts']:
        #     print(i,item['casts'][i])

        #获取电影风格 list[str]
        # genre=info_sel.xpath("//div[@id='info']/span[@property='v:genre']/text()").extract()
        # item['movie_genre']=genre

        genre=self.parse_single_line_excetpion("movie_genre", info_sel, "//div[@id='info']/span[@property='v:genre']/text()", True)
        item['movie_genre']=genre

        # 获取电影时长
        movie_length=self.parse_single_line_excetpion('movie_length',info_sel,'//span[@property="v:runtime"]/@content',False)
        item['movie_length']=movie_length

        # 获取电影上映日期
        try:
            release_date=self.parse_single_line_excetpion('release_date',info_sel,'//span[@property="v:initialReleaseDate"]/text()',True)
            release_date_map={}
            if(release_date!=None):
                for i in release_date:
                    district=re.findall('\((.*)\)',i)
                    if(district==[]):
                        district='Undefined'
                    else:
                        district=district[0]
                    date=re.findall('(\d{4}-\d{2}-\d{2})',i)[0]
                    release_date_map[district]=date
            item['release_date']=release_date_map
        except:
            release_date_map = {}
            item['release_date'] = release_date_map
            logging.log(level=logging.INFO, msg="--Not find release date")

        # 获取电影又名
        movie_aka=self.parse_re_exception("movie_country",info_sel,'又名:(.*)
')
        item['movie_aka'] = movie_aka

        # try:
        #     movie_aka = info_sel.re('又名:(.*)
')[0]
        #     movie_aka=movie_aka.split(' /')
        #     movie_aka_list=[]
        #     for i in movie_aka:
        #         if(i!=" " and i!="" and i!=None and i!='/'):
        #             movie_aka_list.append(i)
        #     item['movie_aka'] = movie_aka_list
        # except:
        #     logging.log(level=logging.INFO,msg="--Not find movie aka")

        # 获取电影国家 list[str]
        movie_country=self.parse_re_exception("movie_country",info_sel,'制片国家/地区:(.*)
')
        item['movie_country']=movie_country
        # try:
        #     movie_country = info_sel.re('制片国家/地区:(.*)
')[0]
        #     movie_country = movie_country.split(' /')
        #     movie_country_list = []
        #     for i in movie_aka:
        #         if (i != " " and i != "" and i != None and i != '/'):
        #             movie_country_list.append(i)
        #     item['movie_country'] = movie_country
        # except:
        #     logging.log(level=logging.INFO, msg="--Not find movie aka")

        movie_language = self.parse_re_exception("movie_country", info_sel, '语言:(.*)
')
        item['movie_language'] = movie_language

        # try:
        #     movie_language = info_sel.re('语言:(.*)
')[0]
        #     movie_language = movie_language.split(' /')
        #     movie_language_list = []
        #     for i in movie_aka:
        #         if (i != " " and i != "" and i != None and i != '/'):
        #             movie_language_list.append(i)
        #     item['movie_language'] = movie_language
        # except:
        #     logging.log(level=logging.INFO, msg="--Not find movie aka")

        #获取电影imdb id
        try:
            imdb= info_sel.re('http://www.imdb.com/title/(.+?)\"')[0]
            item['movie_imdb_id']=imdb
        except:
            item['movie_imdb_id']=None
            logging.log(level=logging.INFO,msg='---Not find imdb id')

        # 获取电影评分 decimal
        # rating=full_sel.xpath('//div[@id="interest_sectl"]/div/div[@class="rating_self clearfix"]/strong/text()').extract()[0]
        # item['movie_rating']=rating
        rating=self.parse_single_line_excetpion("movie_rating", full_sel, '//div[@id="interest_sectl"]/div/div[@class="rating_self clearfix"]/strong/text()', False)
        item['movie_rating']=rating

        # 获取电影评价人数 , int 可能为空
        # rating_people_num=full_sel.xpath('//div[@class="rating_sum"]/a/span/text()').extract()[0]
        # item['movie_rating_people_num']=rating_people_num
        rating_people_num=self.parse_single_line_excetpion("rating_people_num", full_sel, '//div[@class="rating_sum"]/a/span/text()', False)
        item['movie_rating_people_num']=rating_people_num

        #获取电影评价分布 list[decimal] len=5 可能为空
        rating_distribute=[]
        try:
            for i in range(2,11,2):
                # rating_distribute.append(full_sel.xpath('//div[@class="rating_wrap clearbox"]/span[{}]/text()'.format(i)).extract()[0][:-1])
                rating_distribute.append(self.parse_single_line_excetpion(
                    "movie_rating_distribute",full_sel,'//div[@class="rating_wrap clearbox"]/span[{}]/text()'.format(i),False)[:-1])
        except:
            logging.log(level=logging.INFO,msg="---No distribute")
        item['movie_rating_distribute']=rating_distribute

        #获取电影better than
        rating_better_than=self.parse_single_line_excetpion('rating_better_than',full_sel,'//div[@class="rating_betterthan"]/a/text()',True)
        item['rating_better_than']={}

        try:
            rating_better = {}
            for i in rating_better_than:
                tmp=re.findall('(\d+)\% (.+)',i)
                rating_better[tmp[0][1]]=tmp[0][0]
                item['rating_better_than']=rating_better
        except:
            logging.log(level=logging.INFO, msg="--Not find better than")

        #获取电影标签
        # tags=full_sel.xpath('//div[@class="tags-body"]/a/text()').extract()
        # item['movie_tags']=tags
        tags=self.parse_single_line_excetpion('movie_tags', full_sel, '//div[@class="tags-body"]/a/text()', True)
        item['movie_tags'] = tags

        #获取相似电影
        movie_similar_urls=self.parse_single_line_excetpion('movie_similar',full_sel,'//div[@class="recommendations-bd"]/dl/dd/a/@href',True)
        re_pattern=re.compile('subject/(\d+)/')
        movie_similar=[]
        for i in movie_similar_urls:
            res=re.findall(re_pattern,i)
            movie_similar.append(res[0])
        item['movie_similar']=movie_similar

        yield item

    def parse_re_exception(self,info_title:str,selector:Selector,re:str):
        try:
            movie_aka = selector.re(re)[0]
            movie_aka = movie_aka.split(' /')
            movie_aka_list = []
            for i in movie_aka:
                if (i != " " and i != "" and i != None and i != '/'):
                    movie_aka_list.append(i.replace(" ",""))
            return movie_aka_list
        except:
            logging.log(level=logging.INFO, msg="--Not find "+info_title)
            return []

    def parse_list_exception(self,info_title:str,selecotr:Selector,xpath:str):
        res = {}
        try:
            part_html = selecotr.xpath(xpath).extract()

            for i in part_html:
                res[self.parse_detail_contents_celebrity(Selector(text=i).xpath('//a/@href').extract())[0]] \
                    = Selector(text=i).xpath('//a/text()').extract()[0]
            return res
        except:
            logging.log(level=logging.WARN,msg="---Not find {}".format(info_title))
            return res

    def parse_single_line_excetpion(self, info_title:str, selector:Selector, xpath:str, listOrNot:bool,level=logging.INFO):
        """

        :param selector: Selector
        :param xpath: xpath语句
        :param listOrNot boolean  true  返回 list  ,  false 返回 单个值
        :return:
        """

        try:
            if(listOrNot):
                res=selector.xpath(xpath).extract()
            else:
                res=selector.xpath(xpath).extract()[0]
            return res
        except:
            logging.log(level=level,msg="---Not find {}".format(info_title))
            return None

    def parse_detail_contents_celebrity(self,list):
        """
        将['/celebrity/1009555/', '/celebrity/1357971/'] conver to [1009555,1357971]
        :param list:
        :return: list[str]
        """
        res = []
        for i in list:
            res.append(i.split('/')[-2])
        return res

        # for table in Selector(response=response).xpath('//div[@class="article"]/div/div/table'):
        #     table=Selector(text=table.extract())
        #     item = DoubanItem()
        #     item['title'] = table.xpath("//table/tr/td/a[@class='nbg']/@title")
        #     item['movie_url'] = table.xpath("//table/tr/td/a[@class='nbg']/@href")
        #     # print(table.xpath("//table/tr/td/a[@class='nbg']/@href").extract())
        #     print(table.xpath("//table/tr/td/a[@class='nbg']/@href"))
        #     print(table.xpath("//table/tr/td/a[@class='nbg']/@href").extract())
        #     print()
        #     # item['movie_id'] = table.xpath("//table/tr/td/a[@class='nbg']/@href").extract().split('/')[-1]
        #     # i+=1
        #     print(table.xpath("//table/tr/td/a[@class='nbg']/@href"))
        #     # print(item['movie_id'])
        #     yield item
        # for href in Selector(response=response).xpath('//div[@id="cat-list-content-main"]/div[@class="cat-item"]/a/@href'):
        #     print('http://www.dmoz.org'+href.extract())
        #     url='http://www.dmoz.org/'+href.extract()
        #
        #     yield scrapy.Request(url, callback=self.parse_dir_contents)

        # def parse_dir_contents(self, response):
        #     for sel in response.xpath('//div/div'):
        #         item = DmozItem()
        #         item['title'] = sel.xpath('a/text()').extract()
        #         item['link'] = [sel.xpath('a/@href').extract(),"sss"]
        #         # item['desc'] = sel.xpath('text()').extract()
        #         yield item


# -*- coding: utf-8 -*-

from bot.utils.checks import permitted as requires
from discord.ext import commands
from discord.utils import get
import discord
from bot.utils.config_helper import ConfigHelper

class Reactions(commands.Cog):
    """Automatically give a user a role if they react to a message"""

    def __init__(self, bot):
        self.bot = bot
        self.cfg = ConfigHelper("./config/reactions.json")
        self.data = self.cfg.read()
        self.guild, self.role = None, None

    @commands.Cog.listener()
    async def on_ready(self):
        self.guild = self.bot.get_guild(int(self.data["guild_id"]))
        self.role = self.guild.get_role(self.data["role_id"])

    def blacklist(self, uid: int):
        data = self.cfg.read()
        if uid in data["blacklist"]:
            return
        data["blacklist"].append(uid)
        self.cfg.write(data)

    def unblacklist(self, uid: int):
        data = self.cfg.read()
        if not uid in data["blacklist"]:
            return
        data["blacklist"].pop(data["blacklist"].index(uid))
        self.cfg.write(data)

    def is_relevant_reaction(self, emoji_object):
        id_ = None
        if isinstance(emoji_object, discord.PartialEmoji):
            id_ = emoji_object.id
        if isinstance(emoji_object, discord.Reaction):
            id_ = emoji_object.emoji.id
        return id_ == self.data["emoji_id"]

    async def add_role(self, member: discord.Member):
        await member.add_roles(self.role)

    @commands.Cog.listener()
    async def on_raw_reaction_add(self, payload):
        if payload.message_id != self.data["message_id"]:
            return
        if payload.user_id in self.data["blacklist"]:
            return
        if self.is_relevant_reaction(payload.emoji):
            member = get(self.guild.members, id=payload.user_id)
            await self.add_role(member)

    @commands.group(name="pack")
    @requires(50)
    async def pack_group(self, ctx: commands.Context):
        if ctx.invoked_subcommand == None:
            await ctx.channel.send("Usage: `!pack <'mute'|'unmute'> <user_id>`")

    @pack_group.command(name="mute")
    async def pack_mute(self, ctx: commands.Context, member: int):
        self.blacklist(member)
        await ctx.channel.send(f"Pack: muted {member}")

    @pack_group.command(name="unmute")
    async def pack_unmute(self, ctx: commands.Context, member: int):
        self.unblacklist(member)
        await ctx.channel.send(f"Pack: unmuted {member}")

def setup(bot):
    bot.add_cog(Reactions(bot))


from itertools import combinations
import copy

class LabSimulator:
    ds = [(1, 0), (-1, 0), (0, 1), (0, -1)]
    def __init__(self, lab, twos, walls, N, M):
        self.n = N
        self.m = M
        self.lab = lab
        self.twos = twos
        for wall in walls:
            r, c = wall
            self.lab[r][c] = 1

    def simulate(self):
        cnt = 0
        for two in self.twos:
            self.spread(two)
        for r in range(self.n):
            for c in range(self.m):
                cnt += not self.lab[r][c] # if safe
        return cnt

    def spread(self, pos):
        for d in self.ds:
            x, y = pos
            dx, dy = d
            nx, ny = x + dx, y + dy
            if 0 <= nx < self.n and 0 <= ny < self.m and not self.lab[nx][ny]:
                self.lab[nx][ny] = 2
                self.spread((nx, ny))

def solve():
    N, M = tuple(map(int, input().split()))
    lab = []
    for _ in range(N):
        lab.append(list(map(int, input().split())))
    zeros = []
    twos = []
    for r in range(N):
        for c in range(M):
            if lab[r][c] == 0:
                zeros.append((r, c))
            if lab[r][c] == 2:
                twos.append((r, c))
    safe = 0
    for walls in combinations(zeros, 3):
        ls = LabSimulator(copy.deepcopy(lab), twos, walls, N, M)
        safe = max(safe, ls.simulate())
    print(safe)

solve()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Mar 22 09:12:51 2021

@author: dawudabd-alghani
"""

import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as sp

# m = np.arange(-5,7)
# mins = np.array([-6.73,-5.59,-4.25,-3.13,-1.88,-0.56,0.69,1.97,3.49,4.49,5.41,6.56])/10**3
# unc = mins*0.01

# fit,cov = np.polyfit(m, mins, 1, w=1/unc, cov=1)
# linear = np.poly1d(fit)

# plt.grid()
# plt.xlabel('m value')
# plt.ylabel('Shifted minimum location (mm)')
# plt.plot(m, mins, 'x')
# plt.plot(m, linear(m))
# print(linear[1],'±', np.sqrt(cov[1,1]))

# λ = 670/10**9
# unc_λ = 1/10**9
# d = 230/10**6
# unc_d = 20/10**6
# f = 500/10**3
# unc_f = 1/10**3

# grad = λ*f/d
# unc = grad * np.sqrt((unc_λ/λ)**2 + (unc_d/d)**2 + (unc_f/f)**2)
# print(grad, '±', unc)

data = np.loadtxt('Multi Slit/second_Values.csv', skiprows=1, delimiter=',')
x = data[:,0]
y = data[:,1]

plt.plot(x,y,'.')

def sinc(x,a,b,c,d,e):
    x = x - e
    return a * (np.sin(b*x)/(b*x))**2 * (np.cos(c*x))**2 + d

p0 = [130,0.008,0.039,0.01,515]
params, cov = sp.curve_fit(sinc, x, y, p0)
plt.plot(x, sinc(x, *params))
plt.grid()
plt.xlabel('horiizontal pixel value of image')
plt.ylabel('relative brightness')
print(params)

Multi-Slit/Dawud_Investigation of multiple slit interference/Multi slit.py


import pandas as pd
import numpy as np
# 字形CNN
def save_cnn_inputs(address):
    sign_dict = {}
    with open(address + 'sign_dict.txt', 'r', encoding='utf-8')as f:
        datas = f.readlines()
        for data in datas:
            sign_dict[data.split('\t')[1].rstrip('\n')] = data.split('\t')[0]
    num_to_np = {}
    import cv2
    def cv_imread(filePath):
        return cv2.imdecode(np.fromfile(filePath, dtype=np.uint8), -1)

    for key, value in sign_dict.items():
        pic_data = cv_imread(address + str(int(value) + 1) + '.png').tolist()
        list_data = []
        for raw in pic_data:
            for col in raw:
                list_data.append(col)
        num_to_np[key] = list_data
    none_data = cv_imread(address + '0.png').tolist()
    list_data = []
    for raw in none_data:
        for col in raw:
            list_data.append(col)
    num_to_np[' '] = list_data
    np.save(address + 'data_dict.npy', num_to_np)

def get_cnn_inputs(tokens, max_seq_length, num_to_np, ):
    datas = []
    for token in tokens:
        try:
            datas.append(num_to_np[token])
        except KeyError:
            print(num_to_np)
            print("*** picture not found! ***")
            print(token)
            exit()
    while len(datas) < max_seq_length:
        datas.append(num_to_np[' '])
    assert len(datas) == max_seq_length
    datas = np.reshape(np.array(datas), -1)

    return datas.tolist()

# 五笔GRU
def wubi_input(tokens, max_seq_length):
    file = pd.read_excel('wubi.xlsx')
    char_dict = {}
    for i, c in enumerate('abcdefghijklmnopqrstuvwxyz'):
        char_dict[c] = i+1
    char_dict[' '] = 0
    wubi_dict = {}
    for row in file.values:
        assert len(row) == 1
        wubi_dict[row[0][0]] = row[0][1:]
    wubi_dict[' '] = ' '
    wubi_dict['[UNK]'] = '    '
    datas = []
    for i, token in enumerate(tokens):
        try:
            chars = wubi_dict[token]
        except KeyError:
            chars = wubi_dict['[UNK]']
            # print(wubi_dict)
            # print("*** word not found! ***")
            # print(tokens[i-10:i+1])
            # exit()
        char_code = []
        for c in chars:
            char_code.append(char_dict[c])
        while len(char_code) < 4:
            char_code.append(0)
        assert len(char_code) == 4
        datas.append(char_code)
    while len(datas) < max_seq_length:
        datas.append([0, 0, 0, 0])
    assert len(datas) == max_seq_length
    datas = np.reshape(np.array(datas), -1)
    return datas.tolist()
if __name__ == '__main__':
    wubi_input()


"""empty message

Revision ID: 477a4f953b30
Revises: c464a71656d8
Create Date: 2022-03-13 11:41:09.178475

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '477a4f953b30'
down_revision = 'c464a71656d8'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('hostels_photo_gallery')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('hostels_photo_gallery',
    sa.Column('id', sa.INTEGER(), nullable=False),
    sa.Column('image', sa.VARCHAR(length=20), nullable=False),
    sa.Column('description', sa.TEXT(), nullable=False),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('image')
    )
    # ### end Alembic commands ###


from .data import DataIterator
from .loss import MSE, Loss
from .network import NetWork
from .optimizer import SGD, Optimizer
from .tensor import Tensor

def train(
    net: NetWork,
    inputs: Tensor,
    targets: Tensor,
    num_epochs: int = 500,
    iterator: DataIterator = DataIterator(),
    loss: Loss = MSE(),
    optim: Optimizer = SGD(),
) -> None:
    for epoch in range(num_epochs):
        epoch_loss = 0
        for batch in iterator(inputs, targets):
            preds = net.forward(batch.inputs)
            epoch_loss += loss.loss(preds, batch.targets)
            grad = loss.grad(preds, batch.targets)
            net.backward(grad)
            optim.step(net)
        print(epoch, epoch_loss)


#replace a string with another
#replace (string, old, new)

def  replace(string,old,new):
    list = string.split()
    print(list)
    new_string = ''

    for word in list:
        if old in word:
            new_string= new_string + ' ' + word.replace(old,new)

        else:
            new_string = new_string + ' ' + word

    return new_string

string = 'I love spam! Yum, spam sure is great, spam, spam, spam! Yummy!'

print(replace (string,'am','um'))

string = 'Every day I er at the market. But I rer to er again.'

print(replace(string,'er','w'))


import statistics as stats
from collections import defaultdict
from typing import Any, Dict, Iterable, Optional, Union

from fastestimator.summary.summary import Summary, ValWithError
from fastestimator.trace.trace import Trace
from fastestimator.util.data import Data
from fastestimator.util.traceability_util import traceable
from fastestimator.util.util import to_number
from fastestimator.util.base_util import to_set, DefaultKeyDict

@traceable()
class LabelTracker(Trace):
    """A Trace to track metrics grouped by labels, for example per-class loss over time during training.

    Use this in conjunction with ImageViewer or ImageSaver to see the graph at training end. This also automatically
    integrates with Traceability reports.

    Args:
        label: The key of the labels by which to group data.
        metric: The key of the metric by which to score data.
        label_mapping: A mapping of {DisplayName: LabelValue} to use when generating the graph. This can also be used to
            limit which label values are graphed, since any label values not included here will not be graphed. A None
            value will monitor all label values.
        bounds: What error bounds should be graphed around the mean value. Options include None, 'std' for standard
            deviation, and 'range' to plot (min_value, mean, max_value). Multiple values can be specified, ex.
             ['std', 'range'] to generate multiple graphs.
        mode: What mode(s) to execute this Trace in. For example, "train", "eval", "test", or "infer". To execute
            regardless of mode, pass None. To execute in all modes except for a particular one, you can pass an argument
            like "!infer" or "!train".
        ds_id: What dataset id(s) to execute this Trace in. To execute regardless of ds_id, pass None. To execute in all
            ds_ids except for a particular one, you can pass an argument like "!ds1".
        outputs: The name of the output which will be generated by this trace at the end of training. If None then it
            will default to "<metric>_by_<label>".

    Raises:
        ValueError: If `bounds` is not one of the allowed options.
    """
    def __init__(self,
                 label: str,
                 metric: str,
                 label_mapping: Optional[Dict[str, Any]] = None,
                 bounds: Union[None, str, Iterable[Union[str, None]]] = "std",
                 mode: Union[None, str, Iterable[str]] = "eval",
                 ds_id: Union[None, str, Iterable[str]] = None,
                 outputs: Optional[str] = None):
        super().__init__(inputs=[label, metric], outputs=outputs or f"{metric}_by_{label}", mode=mode, ds_id=ds_id)
        self.points = []
        self.label_summaries = DefaultKeyDict(default=lambda x: Summary(name=x))
        self.label_mapping = {val: key for key, val in label_mapping.items()} if label_mapping else None
        bounds = to_set(bounds)
        if not bounds:
            bounds.add(None)
        for option in bounds:
            if option not in (None, "std", "range"):
                raise ValueError(f"'interval' must be either None, 'std', or 'range', but got '{bounds}'.")
        self.bounds = bounds

    @property
    def label_key(self) -> str:
        return self.inputs[0]

    @property
    def metric_key(self) -> str:
        return self.inputs[1]

    def on_batch_end(self, data: Data) -> None:
        self.points.append((to_number(data[self.label_key]), to_number(data[self.metric_key])))

    def on_epoch_end(self, data: Data) -> None:
        label_scores = defaultdict(list)
        for batch in self.points:
            for label, metric in ((batch[0][i], batch[1][i]) for i in range(len(batch[0]))):
                label_scores[label.item()].append(metric.item())
        for label, metric in label_scores.items():
            if self.label_mapping:
                if label in self.label_mapping:
                    label = self.label_mapping[label]
                else:
                    # Skip labels which the user does not want to inspect
                    continue
            if 'std' in self.bounds:
                mean, std = stats.mean(metric), stats.stdev(metric) if len(metric) > 1 else 0.0
                val = ValWithError(mean - std, mean, mean + std)
                key = f"{self.metric_key} ($\\mu \\pm \\sigma$)"
                # {label: {mode: {key: {step: value}}}}
                self.label_summaries[label].history[self.system.mode][key][self.system.global_step] = val
            if 'range' in self.bounds:
                val = ValWithError(min(metric), stats.mean(metric), max(metric))
                key = f"{self.metric_key} ($min, \\mu, max$)"
                self.label_summaries[label].history[self.system.mode][key][self.system.global_step] = val
            if None in self.bounds:
                val = stats.mean(metric)
                key = self.metric_key
                self.label_summaries[label].history[self.system.mode][key][self.system.global_step] = val
        self.points = []

    def on_end(self, data: Data) -> None:
        self.system.add_graph(self.outputs[0], list(self.label_summaries.values()))  # So traceability can draw it
        data.write_without_log(self.outputs[0], list(self.label_summaries.values()))

    def __getstate__(self) -> Dict[str, Any]:
        """Get a representation of the state of this object.

        This method is invoked by pickle.

        Returns:
            The information to be recorded by a pickle summary of this object.
        """
        state = self.__dict__.copy()
        state['label_summaries'] = dict(state['label_summaries'])
        return state

    def __setstate__(self, state: Dict[str, Any]) -> None:
        """Set this objects internal state from a dictionary of variables.

        This method is invoked by pickle.

        Args:
            state: The saved state to be used by this object.
        """
        label_summaries = DefaultKeyDict(default=lambda x: Summary(name=x))
        label_summaries.update(state.get('label_summaries', {}))
        state['label_summaries'] = label_summaries
        self.__dict__.update(state)


import itertools

from yaql.language import contexts
from yaql.language import specs
from yaql.language import utils
from yaql.language import yaqltypes

@specs.parameter('name', yaqltypes.StringConstant())
@specs.name('#get_context_data')
def get_context_data(name, context):
    """:yaql:getContextData

    Returns the context value by its name. This function is system
    and can be overridden to change the way of getting context data.

    :signature: getContextData(name)
    :arg name: value's key name
    :argType name: string
    :returnType: any (value type)
    """
    return context[name]

@specs.parameter('expr', yaqltypes.Lambda(method=True))
@specs.name('#operator_.')
def op_dot(receiver, expr):
    """:yaql:operator .

    Returns expr evaluated on receiver.

    :signature: receiver.expr
    :arg receiver: object to evaluate expression
    :argType receiver: any
    :arg expr: expression
    :argType expr: expression that can be evaluated as a method
    :returnType: expression result type

    .. code::

        yaql> [0, 1].select($+1)
        [1, 2]
    """
    return expr(receiver)

@specs.parameter('expr', yaqltypes.YaqlExpression())
@specs.inject('operator', yaqltypes.Delegate('#operator_.'))
@specs.name('#operator_?.')
def elvis_operator(operator, receiver, expr):
    """:yaql:operator ?.

    Evaluates expr on receiver if receiver isn't null and returns the result.
    If receiver is null returns null.

    :signature: receiver?.expr
    :arg receiver: object to evaluate expression
    :argType receiver: any
    :arg expr: expression
    :argType expr: expression that can be evaluated as a method
    :returnType: expression result or null

    .. code::

        yaql> [0, 1]?.select($+1)
        [1, 2]
        yaql> null?.select($+1)
        null
    """
    if receiver is None:
        return None
    return operator(receiver, expr)

@specs.parameter('sequence', yaqltypes.Iterable())
@specs.parameter('args', yaqltypes.String())
@specs.method
def unpack(sequence, context, *args):
    """:yaql:unpack

    Returns context object with sequence values unpacked to args.
    If args size is equal to sequence size then args get appropriate
    sequence values.
    If args size is 0 then args are 1-based indexes.
    Otherwise ValueError is raised.

    :signature: sequence.unpack([args])
    :receiverArg sequence: iterable of items to be passed as context values
    :argType sequence: iterable
    :arg [args]: keys to be associated with sequence items. If args size is
        equal to sequence size then args get appropriate sequence items. If
        args size is 0 then args are indexed start from 1. Otherwise exception
        will be thrown
    :argType [args]: chain of strings
    :returnType: context object

    .. code::

        yaql> [1, 2].unpack(a, b) -> $a + $b
        3
        yaql> [2, 3].unpack() -> $1 + $2
        5
    """
    lst = tuple(itertools.islice(sequence, len(args) + 1))
    if 0 < len(args) != len(lst):
        raise ValueError('Cannot unpack {0} elements into {1}'.format(
            len(lst), len(args)))
    if len(args) > 0:
        for i in range(len(lst)):
            context[args[i]] = lst[i]
    else:
        for i, t in enumerate(sequence, 1):
            context[str(i)] = t
    return context

def with_(context, *args):
    """:yaql:with

    Returns new context object where args are stored with 1-based indexes.

    :signature: with([args])
    :arg [args]: values to be stored under appropriate numbers $1, $2, ...
    :argType [args]: chain of any values
    :returnType: context object

    .. code::

        yaql> with("ab", "cd") -> $1 + $2
        "abcd"
    """
    for i, t in enumerate(args, 1):
        context[str(i)] = t
    return context

@specs.inject('__context__', yaqltypes.Context())
def let(__context__, *args, **kwargs):
    """:yaql:let

    Returns context object where args are stored with 1-based indexes
    and kwargs values are stored with appropriate keys.

    :signature: let([args], {kwargs})
    :arg [args]: values to be stored under appropriate numbers $1, $2, ...
    :argType [args]: chain of any values
    :arg {kwargs}: values to be stored under appropriate keys
    :argType {kwargs}: chain of mappings
    :returnType: context object

    .. code::

        yaql> let(1, 2, a => 3, b => 4) -> $1 + $a + $2 + $b
        10
    """
    for i, value in enumerate(args, 1):
        __context__[str(i)] = value

    for key, value in kwargs.items():
        __context__[key] = value
    return __context__

@specs.parameter('name', yaqltypes.String())
@specs.parameter('func', yaqltypes.Lambda())
def def_(name, func, context):
    """:yaql:def

    Returns new context object with function name defined.

    :signature: def(name, func)
    :arg name: name of function
    :argType name: string
    :arg func: function to be stored under provided name
    :argType func: lambda
    :returnType: context object

    .. code::

        yaql> def(sq, $*$) -> [1, 2, 3].select(sq($))
        [1, 4, 9]
    """
    @specs.name(name)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)

    context.register_function(wrapper)
    return context

@specs.parameter('left', contexts.ContextBase)
@specs.parameter('right', yaqltypes.Lambda(with_context=True))
@specs.name('#operator_->')
def send_context(left, right):
    """:yaql:operator ->

    Evaluates lambda on provided context and returns the result.

    :signature: left -> right
    :arg left: context to be used for function
    :argType left: context object
    :arg right: function
    :argType right: lambda
    :returnType: any (function return value type)

    .. code::

        yaql> let(a => 1) -> $a
        1
    """
    return right(left)

@specs.method
@specs.parameter('condition', yaqltypes.Lambda())
@specs.parameter('message', yaqltypes.String())
def assert__(engine, obj, condition, message=u'Assertion failed'):
    """:yaql:assert

    Evaluates condition against object. If it evaluates to true returns the
    object, otherwise throws an exception with provided message.

    :signature: obj.assert(condition, message => "Assertion failed")
    :arg obj: object to evaluate condition on
    :argType obj: any
    :arg condition: lambda function to be evaluated on obj. If result of
        function evaluates to false then trows exception message
    :argType condition: lambda
    :arg message: message to trow if condition returns false
    :argType message: string
    :returnType: obj type or message

    .. code::

        yaql> 12.assert($ < 2)
        Execution exception: Assertion failed
        yaql> 12.assert($ < 20)
        12
        yaql> [].assert($, "Failed assertion")
        Execution exception: Failed assertion
    """
    if utils.is_iterator(obj):
        obj = utils.memorize(obj, engine)
    if not condition(obj):
        raise AssertionError(message)
    return obj

@specs.name('#call')
@specs.parameter('callable_', yaqltypes.PythonType(
    object, False, validators=(callable,)))
def call(callable_, *args, **kwargs):
    """:yaql:call

    Evaluates function with specified args and kwargs and returns the
    result.
    This function is used to transform expressions like '$foo(args, kwargs)'
    to '#call($foo, args, kwargs)'.
    Note that to use this functionality 'delegate' mode has to be enabled.

    :signature: call(callable, args, kwargs)
    :arg callable: callable function
    :argType callable: python type
    :arg args: sequence of items to be used for calling
    :argType args: sequence
    :arg kwargs: dictionary with kwargs to be used for calling
    :argType kwargs: mapping
    :returnType: any (callable return type)
    """
    return callable_(*args, **kwargs)

@specs.parameter('func', yaqltypes.Lambda())
def lambda_(func):
    """:yaql:lambda

    Constructs a new anonymous function
    Note that to use this function 'delegate' mode has to be enabled.

    :signature: lambda(func)
    :arg func: function to be returned
    :argType func: lambda
    :returnType: obj type or message

    .. code::

        yaql> let(func => lambda(2 * $)) -> [1, 2, 3].select($func($))
        [2, 4, 6]
        yaql> [1, 2, 3, 4].where(lambda($ > 3)($ + 1))
        [3, 4]
    """
    return func

@specs.name('#operator_.')
@specs.parameter('name', yaqltypes.Keyword())
@specs.inject('func', yaqltypes.Delegate(use_convention=False))
def get_property(func, obj, name):
    """:yaql:operator .

    Returns value of 'name' property.

    :signature: left.right
    :arg left: object
    :argType left: any
    :arg right: object property name
    :argType right: keyword
    :returnType: any

    .. code::

        yaql> now().year
        2016
    """
    func_name = '#property#{0}'.format(name)
    return func(func_name, obj)

@specs.name('call')
@specs.parameter('name', yaqltypes.String())
@specs.parameter('args', yaqltypes.Sequence())
@specs.parameter('kwargs', utils.MappingType)
def call_func(context, engine, name, args, kwargs, receiver=utils.NO_VALUE):
    """:yaql:call

    Evaluates function name with specified args and kwargs and returns the
    result.

    :signature: call(name, args, kwargs)
    :arg name: name of callable
    :argType name: string
    :arg args: sequence of items to be used for calling
    :argType args: sequence
    :arg kwargs: dictionary with kwargs to be used for calling
    :argType kwargs: mapping
    :returnType: any (callable return type)

    .. code::

        yaql> call(let, [1, 2], {a => 3, b => 4}) -> $1 + $a + $2 + $b
        10
    """
    return context(name, engine, receiver)(
        *args, **utils.filter_parameters_dict(kwargs))

def register(context, delegates=False):
    context.register_function(get_context_data)
    context.register_function(op_dot)
    context.register_function(unpack)
    context.register_function(with_)
    context.register_function(send_context)
    context.register_function(let)
    context.register_function(def_)
    context.register_function(elvis_operator)
    context.register_function(assert__)
    context.register_function(call_func)
    if delegates:
        context.register_function(call)
        context.register_function(lambda_)

def register_fallbacks(context):
    context.register_function(get_property)


# 문제 311쪽
n = int(input())

data = list(map(int, input().split()))
# 오름차순으로 정렬
data.sort()

result = 0
count = 0

for i in data:
  count += 1
  # 포함된 명수가 공포도보다 크거나 같으면 result + 1
  if count >= i:
    result += 1
    count = 0

print(result)

[이것이 취업을 위한 코딩테스트다] 정리/3. 알고리즘 유형별 기출문제/11. 그리디 문제/01. 모험가 길드.py


from cachetools import cached, TTLCache
import feedparser
from typing import Dict, List
import numpy as np

class TrendWatcher:

    @classmethod
    @cached(cache=TTLCache(maxsize=2, ttl=1800))
    def get_daily_google_trends(cls) -> List[Dict]:
        trend_feed = "https://trends.google.cz/trends/trendingsearches/daily/rss?geo=CZ"
        trends = feedparser.parse(trend_feed)

        top_trends = []
        for item in trends["entries"]:
            top_trends.append(
                {
                    "value": item["title"],
                    "traffic": item["ht_approx_traffic"],
                    "summary": item["summary"],
                    "published": item["published_parsed"],
                }
            )
        return top_trends


from math import degrees

from manimlib import *

plane = NumberPlane(
    x_range=(-10, 10),
    y_range=(-10, 10),
    background_line_style={"stroke_color": GREY},
    y_axis_config={
        "stroke_color": BLUE_E,
    },
    x_axis_config={
        "stroke_color": YELLOW,
    },
)

class CameraOrientations(ThreeDScene):
    def construct(self):
        frame = self.camera.frame
        colors = [MAROON_D, GREEN_E, PURPLE]
        tracker_texts = ["theta", "phi", "gamma"]

        tracker_groups = VGroup(
            *[
                VGroup(TexText(text + " ="), DecimalNumber(degrees(val)).scale(0.8))
                .arrange(RIGHT)
                .set_color(col)
                for text, val, col in zip(tracker_texts, frame.euler_angles, colors)
            ]
        ).arrange(1.5 * DOWN, aligned_edge=LEFT)
        # tracker_groups.fix_in_frame()

        for axis, label, point in zip(plane.axes, ["x", "y"], [RIGHT, UP]):
            vect = Vector(point)
            vect.add(Tex(label).next_to(vect, UR, buff=0))
            vect.set_color(axis.get_color())
            axis.add(vect)
            axis.vect = vect

        title = TexText("Euler Angles", " :")
        title[0].set_color_by_gradient(*colors)
        title.add(Underline(title[0]))
        title.next_to(tracker_groups, UP, aligned_edge=LEFT)

        group = VGroup(title, tracker_groups).to_corner(UL, 0.25)
        group.add_background_rectangle("#111111", buff=0.2)
        group.fix_in_frame()

        self.add(plane, group, title, Line3D(3 * IN, 3 * OUT, color=WHITE))
        self.wait(2)

        # why doesn't this work in a loop ??
        tracker_groups[0][-1].add_updater(
            lambda d: d.set_value(degrees(frame.euler_angles[0]))
        )
        tracker_groups[1][-1].add_updater(
            lambda d: d.set_value(degrees(frame.euler_angles[1]))
        )
        tracker_groups[2][-1].add_updater(
            lambda d: d.set_value(degrees(frame.euler_angles[2]))
        )

        self.play(frame.set_phi, 70 * DEGREES, run_time=6, rate_func=there_and_back)
        self.wait()
        self.play(frame.set_phi, -70 * DEGREES, run_time=6, rate_func=there_and_back)
        self.wait()
        self.play(frame.set_theta, 70 * DEGREES, run_time=6, rate_func=there_and_back)
        self.wait()
        self.play(frame.set_theta, -70 * DEGREES, run_time=6, rate_func=there_and_back)
        self.wait()
        self.play(frame.shift, 2 * DR, run_time=4, rate_func=there_and_back)
        self.wait()
        self.play(
            frame.set_theta, 45 * DEGREES, frame.set_phi, 45 * DEGREES, run_time=4
        )
        self.wait()
        self.play(frame.set_gamma, 60 * DEGREES, run_time=6, rate_func=there_and_back)
        self.wait()
        self.play(frame.set_gamma, -60 * DEGREES, run_time=6, rate_func=there_and_back)
        self.wait()
        self.play(frame.set_theta, 0, frame.set_phi, 0, run_time=2)
        self.wait()
        self.play(
            frame.set_theta,
            45 * DEGREES,
            frame.set_phi,
            45 * DEGREES,
            frame.set_gamma,
            45 * DEGREES,
            run_time=8,
            rate_func=there_and_back,
        )
        self.wait(4)


import numpy as np
import gym
from gym import spaces

class SparseHopperDisc(gym.Env):
    def __init__(self):
        self.env = gym.make("Hopper-v2")
        lowS = [-0.1, -0.25, -0.4, -0.4, -0.32] + [-7] * 6
        highS = [1.3, 0.02, 0.025, 0.03, 0.7] + [7] * 6
        self.action_space = spaces.Discrete(27)
        self.observation_space = spaces.Box(np.array(lowS), np.array(highS))

    def reset(self):
        return self.env.reset()

    def step(self, a):
        a2 = np.array([(a // 9) - 1, ((a % 9) // 3) - 1, ((a % 9) % 3) - 1])
        step = self.env.step(a2)
        next_obs = step[0]
        posafter, height, ang = self.env.env.sim.data.qpos[0:3]

        if height > 1.3:
            reward = 1
            done = True
        elif abs(ang) > 0.2 or height < 0.7:
            reward = -1
            done = True
        else:
            reward = 0
            done = False

        return next_obs, reward, done, {}


import aiofiles
from aiogram.dispatcher.storage import FSMContext
from aiogram.utils.exceptions import MessageTextIsEmpty, CantParseEntities, PhotoDimensions

from django_admin.bot.models import Page, InfoPage, InnerKeyboard
from filters import CommandBack, OtherWords

from keyboards.inline.buttons import choose_level

from states.state_machine import PositionState
from loader import dp, bot
from utils.debugger import debugger
from aiogram.types import Message

from keyboards.default import enrollee_menu as kb

import logging

from utils import google_sheets
from utils.db_api import db_commands
from utils.bot_commands.commands import commands

from handlers.groups.main_menu_group import group_menu

# * Формирование словаря кнопок первого уровня => кнопка : id
buttons = Page.objects.values("btn_title", "id")
buttons_id: dict = {btn['btn_title']: btn["id"] for btn in buttons}

# * Формирование словаря кнопок второго уровня => кнопка : id
inner_buttons = InnerKeyboard.objects.values("btn_title", "buttons_id")
inner_buttons_id: dict = {btn["btn_title"]: btn["buttons_id"] for btn in inner_buttons}

buttons_title_first = list(buttons_id)
keyboard = {"first": buttons_title_first}

buttons_title_second = list(inner_buttons_id)
keyboard["second"] = buttons_title_second

service_words = [*keyboard["first"], *keyboard["second"], *group_menu, "Назад", *(map(lambda c: f"/{c}", commands))]

# * Обработчик неслужебных слов
@dp.message_handler(OtherWords(service_words))
async def service_words_handler(message: Message):
    """
    Если пользователь ввел сообщение, которое не содержит закрепленные команды или названия кнопок, бот отвечает ему, \
    что не понимает сообщения

    :param message: переменная для манипуляции над сообщениями
    """
    await message.answer("Извините, но я не понимаю вашей команды")

# * Обработчик кнопки Назад
@dp.message_handler(CommandBack())
async def back_to_btn_handler(message: Message):
    """
    Обработчик нажатия кнопки "Назад"

    При нажатии переводит пользователя на уровень ниже

    :param message: переменная для манипуляции над сообщениями
    """
    await message.answer("Вы вернулись назад", reply_markup=await kb.generate_keyboard(
        one_time_keyboard=True
    ))

@dp.message_handler(text="Получить результаты")
async def get_results(message: Message):
    """
    Обработчик нажатия на кнопку "Получить результаты" в разделе "Тест на профориентацию"
    При нажатии обращается к API Google Sheet, для получения результата теста, если таковой имеется
    Если результата нет, бот возвращает пользователю сообщение о его отсутствии

    :param message: переменная для манипуляции над сообщениями
    """
    await message.answer("Ваш запрос обрабатывается. Подождите несколько секунд")

    query: dict = await db_commands.get_bak_directions()
    directions = dict(sorted(query.items(), key=lambda k: k[0]))

    result: str = await google_sheets.proftest_results.get_results(str(message.from_user.id), directions)
    try:
        await message.answer(result)

    except MessageTextIsEmpty:
        await message.answer("Вы еще не прошли профориентационный тест")

# * Обработчик клавиатуры первого уровня
@dp.message_handler(lambda message: message.text in keyboard["first"])
async def menu(message: Message, state: FSMContext):
    pressed_button: str = message.text
    btn_id: int = buttons_id[pressed_button]

    type_content: str = InfoPage.objects.get(id=btn_id).type_content

    try:
        comment: str = InfoPage.objects.get(
            id=btn_id
        ).info

        if type_content == "keyboard":
            await message.answer(
                comment, reply_markup=choose_level
            )
            await state.set_state(PositionState.set_pressed_btn)

            async with state.proxy() as data:
                inline_id: str = Page.objects.get(id=btn_id).inline_tag
                data["page"] = inline_id
            await PositionState.next()

        else:
            if pressed_button == "Тест на профориентацию":
                link = f"https://docs.google.com/forms/d/e/1FAIpQLSeNkbEzcvxl7JsUxuYu13ECBLlZZrxJNyBjC_krgnZbVrUcjQ/viewform?usp=pp_url&entry.834901947={message.from_user.id}"
                comment += f"\nСобственно, сам профориентационный тест"

            if Page.objects.get(btn_title=pressed_button).file.name not in [None, ""]:
                file_path: str = Page.objects.get(btn_title=pressed_button).file.path

                async with aiofiles.open(file_path, "rb") as photograph:
                    await bot.send_photo(
                        chat_id=message.chat.id, photo=photograph,
                        caption=comment,
                        reply_markup=await kb.generate_keyboard(btn_id)
                    )
            else:
                await message.answer(comment, reply_markup=await kb.generate_keyboard(btn_id))

    except MessageTextIsEmpty as error:
        await message.answer(f"Информации нет\n{debugger(error)}", parse_mode='')

    except PhotoDimensions as error:
        await message.answer(f"Ошибка вывода изображения: большое разрешение\n{debugger(error)}", parse_mode='')
        logging.error(error)

    except CantParseEntities as error:
        await message.answer(f"Ошибка! Неправильная разметка информации\n{debugger(error)}", parse_mode='')


import scrapy
import datetime
import pandas as pd

def update(liste):
    if len(liste) == 4:
        d = pd.read_excel("item.xlsx")
        for k,l in d.iterrows():
            if (list(l)[0]==liste[0]):
                d.loc[k,"YeniFiyat"] = liste[1]
                d.loc[k,"YeniDurum"] = liste[2]
                d.loc[k,"GuncellemeTarihi"] = liste[3]
                break
        d.to_excel("item.xlsx",index=False)

def getIlanNo():
    d = pd.read_excel("item.xlsx")
    IlanNo = []
    for i in d['IlanNo']:
        IlanNo.append(i)
    return IlanNo

def getLinks():
    base = "https://www.hurriyetemlak.com/canakkale-merkez/daire/"
    Links = []
    IlanNo = getIlanNo()
    for i in IlanNo:
        Links.append(base + i)
    return Links

def getPriceState():

    d = pd.read_excel("item.xlsx")
    Fiyat = []
    Durum =[]
    IlanNo ={}
    Ilan= getIlanNo()
    for i in d['Fiyat']:
        Fiyat.append(i)
    for j in d['IlanDurumu']:
        Durum.append(j)
    for k,l in enumerate(Ilan):
        IlanNo[l] = [Fiyat[k],Durum[k]]
    return IlanNo

def cmp(f1,f2):
    f1 = f1.replace(" ", "")
    f2 = f2.replace(" ", "")
    if(len(f1)==len(f2)):
        for i,j in enumerate(f1):
            if j == f2[i]:
                continue
            return False
        return True
    else:
        return False

class Spider2(scrapy.Spider):
    name = "Guncelleme"
    try:
        Links = getLinks()
        start_urls = [Links[0]]
        IlanNo = getPriceState()

    except:
        pass
    Count = 0

    def parse(self, response):
        list = []
        x=response.css('.redy ::text').extract()
        list.append(x[0])
        PaS = Spider2.IlanNo.get(list[0])
        price = response.css('div.right p::text').extract()
        price = price[0].replace("\n","")
        Flag1 = cmp(price,PaS[0])

        state = response.css('.short-info-list li ::text')[3].extract()
        Flag2 = cmp(state,PaS[1])

        if (Flag1 == False or Flag2 == False):
            if Flag1 == False:
                list.append(price)
            else:
                list.append("")
            if Flag2 == False:
                list.append(state)
            else:
                list.append("")
            an = datetime.datetime.now()
            list.append(str(an.day) + "." + str(an.month) + "." + str(an.year))
        update(list)
        Spider2.Count +=1

        yield {'item': list}

        yield scrapy.Request(Spider2.Links[Spider2.Count],callback=self.parse)


from flask import Flask, render_template, request, jsonify
from algorithms.classify import classifyBanana

from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
import os

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

app = Flask(__name__)

def getFileExtension(file):
    return file.split('.')[1]

@app.route('/', methods=['GET', 'POST'])
def hello():
    return render_template('main.html')

@app.route('/uploadajax', methods=['GET', 'POST'])
def upldfile():
    if request.method == 'POST':
        files = request.files['file']
        filename = secure_filename(files.filename)
        ext = getFileExtension(filename)
        print(ext)
        name = 'img.jpg' if ext == 'jpg' else 'img.png'
        updir = os.path.join(basedir, 'static/images/')
        files.save(os.path.join(updir, name))
        file_dir = f'static/images/{name}'
        print(file_dir)
        result = classifyBanana(file_dir)
        return jsonify(name=filename, classType = result)


#2.Евгений Пригожин составляет 7-буквенные слова(необязательно осмысленные) из букв Б,О,Е,П,Р,И,П,А,С,Ы.
# Каждую букву можно использовать любое количество раз, либо не использовать вовсе, при этом количество согласных должно быть больше, чем количество гласных.
# Сколько различных слов может составить Евгений Пригожин?

from itertools import product
k=0
for x in product('БОЕПРИПАСЫ', repeat=7):
    s=''.join(x)
    for c in 'БПРС': s=s.replace(c,'0')
    for c in 'ОЕИАЫ': s=s.replace(c,'1')
    if s.count('0')>s.count('1'):
        k+=1
print(k)


import copy

import cv2
import numpy as np
import onnxruntime

class YolopONNX(object):
    def __init__(
        self,
        model_path='yolop-640-640.onnx',
        input_shape=(640, 640),
        score_th=0.3,
        nms_th=0.45,
        providers=['CPUExecutionProvider'],
    ):
        # 入力サイズ
        self.input_shape = input_shape

        # 閾値
        self.class_score_th = score_th
        self.nms_th = nms_th

        # モデル読み込み
        self.onnx_session = onnxruntime.InferenceSession(
            model_path,
            providers=providers,
        )

    def inference(self, image):
        # 前処理
        rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        resize_rgb_image, r, dw, dh, new_unpad_w, new_unpad_h = self._resize_unscale(
            rgb_image,
            self.input_shape,
        )

        input_image = resize_rgb_image.copy().astype(np.float32)
        mean = [0.485, 0.456, 0.406]
        std = [0.229, 0.224, 0.225]
        input_image = (input_image / 255 - mean) / std
        input_image = input_image.transpose(2, 0, 1)
        input_image = np.expand_dims(input_image, axis=0)
        input_image = input_image.astype('float32')

        # 推論
        det_out, drive_area_seg, lane_line_seg = self.onnx_session.run(
            ['det_out', 'drive_area_seg', 'lane_line_seg'],
            input_feed={"images": input_image},
        )

        # NMS
        bboxes = self._nms(
            det_out,
            conf_thres=self.class_score_th,
            iou_thres=self.nms_th,
            agnostic=False,
        )[0]

        # バウンディングボックスの座標を元画像のスケールに変換
        bboxes[:, 0] -= dw
        bboxes[:, 1] -= dh
        bboxes[:, 2] -= dw
        bboxes[:, 3] -= dh
        bboxes[:, :4] /= r

        # 各セグメンテーション領域を選択する
        drive_area_seg = drive_area_seg[:, :, dh:dh + new_unpad_h,
                                        dw:dw + new_unpad_w]
        lane_line_seg = lane_line_seg[:, :, dh:dh + new_unpad_h,
                                      dw:dw + new_unpad_w]

        drive_area_seg_mask = np.argmax(drive_area_seg, axis=1)[0]
        lane_line_seg_mask = np.argmax(lane_line_seg, axis=1)[0]

        return bboxes, drive_area_seg_mask, lane_line_seg_mask

    def draw(
        self,
        image,
        bboxes,
        drive_area_seg_mask,
        lane_line_seg_mask,
    ):
        image_height, image_width, _ = image.shape
        debug_image = copy.deepcopy(image)

        # 道路セグメンテーション
        bg_image = np.zeros(image.shape, dtype=np.uint8)
        bg_image[:] = [0, 255, 0]

        mask = np.stack((drive_area_seg_mask, ) * 3, axis=-1).astype('uint8')
        mask = cv2.resize(
            mask,
            dsize=(image_width, image_height),
            interpolation=cv2.INTER_LINEAR,
        )
        mask = np.where(mask > 0.5, 0, 1)

        mask_image = np.where(mask, debug_image, bg_image)
        debug_image = cv2.addWeighted(debug_image, 0.5, mask_image, 0.5, 1.0)

        # レーンセグメンテーション
        bg_image = np.zeros(image.shape, dtype=np.uint8)
        bg_image[:] = [255, 0, 0]

        mask = np.stack((lane_line_seg_mask, ) * 3, axis=-1).astype('uint8')
        mask = cv2.resize(
            mask,
            dsize=(image_width, image_height),
            interpolation=cv2.INTER_LINEAR,
        )
        mask = np.where(mask > 0.5, 0, 1)

        mask_image = np.where(mask, debug_image, bg_image)
        debug_image = cv2.addWeighted(debug_image, 0.5, mask_image, 0.5, 1.0)

        # 車バウンディングボックス
        for bbox in bboxes:
            x1, y1 = int(bbox[0]), int(bbox[1])
            x2, y2 = int(bbox[2]), int(bbox[3])
            # score = bbox[4]
            # class_id = int(bbox[5])
            cv2.rectangle(debug_image, (x1, y1), (x2, y2), (0, 0, 255), 2, 2)

        return debug_image

    def _xywh2xyxy(self, x):
        y = np.zeros_like(x)
        y[:, 0] = x[:, 0] - x[:, 2] / 2  # top left x
        y[:, 1] = x[:, 1] - x[:, 3] / 2  # top left y
        y[:, 2] = x[:, 0] + x[:, 2] / 2  # bottom right x
        y[:, 3] = x[:, 1] + x[:, 3] / 2  # bottom right y
        return y

    def _box_iou(self, box1, box2):
        def box_area(box):
            # (x2 - x1) * (y2 - y1)
            return (box[2] - box[0]) * (box[3] - box[1])

        area1 = box_area(box1.T)
        area2 = box_area(box2.T)

        # inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)
        inter = (np.min(box1[:, None, 2:], box2[:, 2:]) -
                 np.max(box1[:, None, :2], box2[:, :2])).clamp(0).prod(2)
        # iou = inter / (area1 + area2 - inter)
        return inter / (area1[:, None] + area2 - inter)

    def _nms(
        self,
        prediction,
        conf_thres=0.25,
        iou_thres=0.45,
        agnostic=False,
    ):
        xc = prediction[..., 4] > conf_thres  # candidates

        # Settings
        max_wh = 4096  # (pixels) minimum and maximum box width and height
        max_det = 300  # maximum number of detections per image
        redundant = True  # require redundant detections
        merge = False  # use merge-NMS

        output = [np.zeros((0, 6))] * prediction.shape[0]
        for xi, x in enumerate(prediction):  # image index, image inference
            x = x[xc[xi]]  # confidence

            # If none remain process next image
            if not x.shape[0]:
                continue

            # Compute conf
            x[:, 5:] *= x[:, 4:5]  # conf = obj_conf * cls_conf

            # Box (center x, center y, width, height) to (x1, y1, x2, y2)
            box = self._xywh2xyxy(x[:, :4])

            # Detections matrix nx6 (xyxy, conf, cls)
            conf = copy.deepcopy(x[:, 5:])
            j = np.zeros((x[:, 5:].shape[0], 1))
            x = np.concatenate((box, conf, j), 1)

            # Batched NMS
            c = x[:, 5:6] * (0 if agnostic else max_wh)  # classes
            # boxes (offset by class), scores
            boxes, scores = x[:, :4] + c, x[:, 4]
            i = cv2.dnn.NMSBoxes(
                bboxes=boxes.tolist(),
                scores=scores.tolist(),
                score_threshold=0.3,
                nms_threshold=0.45,
                top_k=5000,
            )
            if len(i) > 0:
                i = i.flatten()
                # limit detections
                if i.shape[0] > max_det:
                    i = i[:max_det]
                # Merge NMS (boxes merged using weighted mean)
                if merge and (1 < n < 3E3):
                    # update boxes as boxes(i,4) = weights(i,n) * boxes(n,4)
                    # iou matrix
                    iou = self._box_iou(boxes[i], boxes) > iou_thres
                    # box weights
                    weights = iou * scores[None]
                    # merged boxes
                    x[i, :4] = np.dot(weights, x[:, :4]).float() / weights.sum(
                        1, keepdim=True)
                    if redundant:
                        # require redundancy
                        i = i[iou.sum(1) > 1]

                output[xi] = x[i]

        return output

    def _resize_unscale(self, img, new_shape=(640, 640), color=114):
        shape = img.shape[:2]  # current shape [height, width]
        if isinstance(new_shape, int):
            new_shape = (new_shape, new_shape)

        resize_rgb_image = np.zeros((new_shape[0], new_shape[1], 3))
        resize_rgb_image.fill(color)
        # Scale ratio (new / old) new_shape(h,w)
        r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])

        # Compute padding
        new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))  # w,h
        new_unpad_w = new_unpad[0]
        new_unpad_h = new_unpad[1]
        pad_w, pad_h = new_shape[1] - new_unpad_w, new_shape[
            0] - new_unpad_h  # wh padding

        dw = pad_w // 2  # divide padding into 2 sides
        dh = pad_h // 2

        if shape[::-1] != new_unpad:  # resize
            img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_AREA)

        resize_rgb_image[dh:dh + new_unpad_h, dw:dw + new_unpad_w, :] = img

        return resize_rgb_image, r, dw, dh, new_unpad_w, new_unpad_h  # (dw,dh)

if __name__ == "__main__":
    yolop = YolopONNX(
        model_path='weights/yolop-640-640.onnx',
        input_shape=(640, 640),
        providers=['CUDAExecutionProvider', 'CPUExecutionProvider'],
    )

    video_capture = cv2.VideoCapture("video/sample.mp4")

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

        bboxes, da_seg_mask, ll_seg_mask = yolop.inference(frame)
        result_image = yolop.draw(
            frame,
            bboxes,
            da_seg_mask,
            ll_seg_mask,
        )

        result_image = cv2.resize(result_image, dsize=None, fx=0.5, fy=0.5)

        cv2.imshow("YOLOP", result_image)
        key = cv2.waitKey(1)
        if key == 27:  # ESC
            break

    video_capture.release()
    cv2.destroyAllWindows()


import datetime
import os

def clear_screen():
    """Clear the screen to prepare it to show the menu."""
    os.system('cls' if os.name == 'nt' else 'clear')

def get_date(initial=None):
    """
    Gets a valid date from user. If no date provided, it returns
    the initial date or None.
    """
    if not initial:
        clear_screen()
    while True:
        print("Date of the task")
        date = input("Please use DD/MM/YYYY: ")
        if date == '' and initial:
            return initial
        try:
            date = datetime.datetime.strptime(date, '%d/%m/%Y')
        except ValueError:
            print("Sorry, you must enter a valid date.\n")
        else:
            return date.date()

def get_date_range():
    """
    Gets a valid date from user. If no date provided, it returns
    the initial date or None.
    """
    clear_screen()
    while True:
        print("Enter the start date")
        start_date = input("Please use DD/MM/YYYY: ")
        try:
            start_date = datetime.datetime.strptime(start_date, '%d/%m/%Y')
        except ValueError:
            print("Sorry, you must enter a valid date.\n")
        else:
            break

    while True:
        print("Enter the end date")
        end_date = input("Please use DD/MM/YYYY: ")
        try:
            end_date = datetime.datetime.strptime(end_date, '%d/%m/%Y')
        except ValueError:
            print("Sorry, you must enter a valid date.\n")
        else:
            return start_date.date(), end_date.date()

def get_title(initial=None):
    """
    Gets a valid title from user. If no title provided, it returns
    the initial title or None.
    """
    if not initial:
        clear_screen()
    while True:
        title = input("Title of the task: ")
        if title != '':
            return title
        if initial:
            return initial
        print("Sorrry, you must provide a task title")

def get_time(initial=None):
    """
    Gets a valid time spent from user. If no time provided, it returns
    the initial time spent or None.
    """
    if not initial:
        clear_screen()
    while True:
        time = input("Time spent (rounded minutes): ")
        if time == '' and initial:
            return initial
        try:
            time = round(int(time))
            if time <= 0:
                raise ValueError
        except ValueError:
            print("Sorry, you must enter a valid numeric time")
        else:
            return str(time)

def get_notes(initial=None):
    """
    Gets notes from user. If no notes provided, it returns the initial
    notes or None.
    """
    if not initial:
        clear_screen()
    notes = input("Notes (Optional, you can leave this empty): ")
    if notes:
        return notes
    return ''


import numpy as np
import warnings

def runValuation(aValuationData, aSimulationData, aMarketEvent, aEventBook, aBaseTickSize, aCorrTickSize, aParameters):
    Info = aValuationData.memoryData
    warnings.simplefilter('ignore', np.RankWarning)
    warnings.filterwarnings('ignore', category=RuntimeWarning)
    Info.UpdateData(10 ** 5, aEventBook, aMarketEvent.askDepth.prices[0:3],
                    aMarketEvent.bidDepth.prices[0:3],
                    aMarketEvent.eventType, aMarketEvent.timestamp,
                    aMarketEvent.askDepth.volumes[0:3], aMarketEvent.bidDepth.volumes[0:3],
                    aSimulationData.simNetPnL, 0.1, 100)

    if Info.counter != 10000:
        if Info.counter > 1:
            Info.counter = 1
        elif Info.counter < -1:
            Info.counter = -1

        if Info.counter != 0 and Info.book_amount != aSimulationData.simNetDelta:
            Info.counter = 0
        elif Info.counter < 1 and Info.counter > -1:
            Info.counter = 0
        elif Info.counter >= 1 and Info.book_amount == 5:
            Info.counter = 0
        elif Info.counter <= -1 and Info.book_amount == -5:
            Info.counter = 0

        if Info.counter1 == 1:
            Info.counter1 = 2
        elif Info.counter1 == -1:
            Info.counter1 = -2

        #if Info.Ind == 1:
        #    Info.Ind = 2
        #elif Info.Ind == -1:
        #    Info.Ind = -2
        #elif Info.Ind == 2 or Info.Ind == -2:
        #    Info.Ind = 0

    Info.UpdateBookAmounts(aSimulationData.simNetDelta, Info.book_amount, aMarketEvent.askDepth.prices[0],
                           aMarketEvent.bidDepth.prices[0])
    Info.cheese_amount = Info.book_amount       #here because there was something weird with the simulation
    Info.book_amount = aSimulationData.simNetDelta

    #Info.TrackBGrad(length1=10, length2=300)
    #Info.TrackDGrad(length1=10, length2=300)
    length = 50

    if aEventBook == 'baseBook' and len(Info.BValList[Info.BValList != 0]) > length and len(Info.DValList[Info.DValList != 0]) > length:
        chris = 0.1
        Baverage = np.mean(Info.BValList[0: length], dtype=np.float64)
        Bstd = max(np.std(Info.BValList[0: length], dtype=np.float64), chris)
        Daverage = np.mean(Info.DValList[0: length], dtype=np.float64)
        Dstd = max(np.std(Info.DValList[0: length], dtype=np.float64), chris)
        n = ((Info.BValList[0] - Baverage) / Bstd)
        m = ((Info.DValList[0] - Daverage) / Dstd)

        Info.prev_n.insert(0, n)
        Info.prev_m.insert(0, m)

        if Info.counter == 10000:
            if abs(m) > 3 and max(Info.prev_n) < 1.5 and min(Info.prev_n) > -1.5:
                Info.counter = 0

        if Info.counter == 0:
            if len(Info.BValList) > length and len(Info.DValList) > length:
                k = 2
                if len(Info.prev_n) >= length:
                    Info.prev_n = Info.prev_n[0:length]

                if len(Info.prev_m) >= length:
                    Info.prev_m = Info.prev_m[0:length]

                if m >= k and len(Info.prev_n) >= length / 2 and len(Info.prev_m) >= length / 2:  #buy
                    if sum(np.array(Info.prev_n) > 2 * m / 3) == 0:
                        Info.counter += 1
                        Info.prev_m = []
                        Info.prev_n = []
                elif m <= -k:    #sell
                    if sum(np.array(Info.prev_n) < 2 * m / 3) == 0:
                        Info.counter -= 1
                        Info.prev_m = []
                        Info.prev_n = []

                elif sum(Info.prev_m) / len(Info.prev_m) > 1: #trending up a lot
                    Info.counter = -1       #seems to revert more often than not
                    Info.counter1 = -1
                    Info.prev_m = []
                    Info.prev_n = []
                elif sum(Info.prev_m) / len(Info.prev_m) < - 1: #trending down a lot
                    Info.counter = 1
                    Info.counter1 = 1
                    Info.prev_m = []
                    Info.prev_n = []

            #if Info.counter == 0 and Info.counter1 == 0:
                #if n >= 5:
                   #Info.counter -= 1
                   # Info.counter1 = 1
                #elif n <= 5:
                   # Info.counter += 1
                    #Info.counter1 = 1

    if Info.counter != 10000:
        Info.DShortTrend(factor = 0.5, width=20)    # 0.08 seconds of data

        # Info.StayClosetoZero(saferange=2, factor = 0.3)

        # if aEventBook == 'baseBook':
        # Info.AppleV1(maxGain = 5, maxLoss = 5, AskPrice = aMarketEvent.askDepth.prices[0], BidPrice = aMarketEvent.bidDepth.prices[0])
        #Info.AppleV2(maxGain = 1000, maxLoss = 300, TimeFrame = 5000)

        #Info.MovingAverage(length = 200, eventbook = aEventBook)

        Info.AppleV4(maxGain = 25, maxLoss = 50, timespan = 5 * 10 ** 4,
                        PnL = aSimulationData.simNetPnL, time = aMarketEvent.timestamp)

        if Info.stopcounter == 0:
            Info.AppleV3(maxGain=250, maxLoss=1000, PnL=aSimulationData.simNetPnL)
        elif Info.stopcounter == 1:
            Info.AppleV3(maxGain = 250, maxLoss = 500, PnL = aSimulationData.simNetPnL)
        elif Info.stopcounter == 2:
            Info.AppleV3(maxGain = 150, maxLoss = 250, PnL = aSimulationData.simNetPnL)
        elif Info.stopcounter >= 3:
            Info.AppleV3(maxGain = 100, maxLoss = 100, PnL = aSimulationData.simNetPnL)

        if aEventBook == 'baseBook':
            if Info.counter < 1 and Info.counter > 0:   #maybe buy
                Info.valuation_ask = aMarketEvent.askDepth.prices[0] + 5
                Info.valuation_bid = aMarketEvent.bidDepth.prices[0] + 0.15 * Info.counter
            elif Info.counter > -1 and Info.counter < 0:    #maybe sell
                Info.valuation_ask = aMarketEvent.askDepth.prices[0] - 0.15 * Info.counter
                Info.valuation_bid = aMarketEvent.bidDepth.prices[0] - 5
            elif Info.counter >= 1:   #buy I st
                Info.valuation_ask = aMarketEvent.askDepth.prices[0] + 5
                Info.valuation_bid = aMarketEvent.bidDepth.prices[0] + 2
            elif Info.counter <= -1:    #sell
                Info.valuation_ask = aMarketEvent.askDepth.prices[0] - 2
                Info.valuation_bid = aMarketEvent.bidDepth.prices[0] - 5
            elif Info.counter == 0: #dont do anything
                Info.valuation_bid = aMarketEvent.bidDepth.prices[0] - 10
                Info.valuation_ask = aMarketEvent.askDepth.prices[0] + 10

    if aEventBook == 'baseBook' and Info.counter == 10000:
        if Info.book_amount > 0:    #sell
            Info.valuation_ask = aMarketEvent.askDepth.prices[0] - 10
            Info.valuation_bid = aMarketEvent.bidDepth.prices[0] - 5
        if Info.book_amount < 0:    #buy
            Info.valuation_ask = aMarketEvent.askDepth.prices[0] + 5
            Info.valuation_bid = aMarketEvent.bidDepth.prices[0] + 10
        if Info.book_amount == 0:   #dont do anything
            Info.valuation_bid = aMarketEvent.bidDepth.prices[0] - 10
            Info.valuation_ask = aMarketEvent.askDepth.prices[0] + 10

    aValuationData.askValuation = Info.valuation_ask
    aValuationData.bidValuation = Info.valuation_bid

    if aEventBook == 'corrBook':
        if len(Info.prev_m) > 10:
            aValuationData.memoryData.testParam = sum(Info.prev_n) / len(Info.prev_n)

    return aValuationData


def parse_scene(hue, scene_id, scene):
    # print('parseScene:', scene)
    name = scene['name']

    group = None
    if 'group' in scene:
        group = scene['group']

    lights = scene['lights']
    lightstates = None
    if 'lightstates' in scene:
        lightstates = scene['lightstates']

    return Scene(hue, scene_id, name, group, lights, lightstates)

class Scene:
    def __init__(self, hue, scene_id, name, group, lights, lightstates):
        self.hue = hue
        self.scene_id = str(scene_id)
        self.name = str(name)
        self.group = str(group)
        self.lights = lights
        self.lightstates = lightstates

    def __repr__(self):
        return 'Scene(id={}, name={}, group={}, lights={}, lightstates={})'.format(self.scene_id, self.name, self.group,
                                                                                self.lights,
                                                                                self.lightstates)


"""
name: count_page.py
create_time: 2023-03-01
author: Ethan White

Description:
"""

page_dic = {f'{i}': 0 for i in range(10)}

def counter_num(page_str):
    """统计数据出现次数，page为页码（字符串）"""
    for item in page_str:
        page_dic[item] += 1

with open('../0_files/123.txt', 'r', encoding='utf-8') as f:
    pages = f.readlines()
    for page in pages:
        counter_num(page)

print(page_dic)


# IMP FOR AI
import numpy as np
import tensorflow as tf
from keras.models import Sequential
from keras.layers import LSTM,Conv1D,MaxPooling1D
from keras.layers import Dense, Dropout
import pandas as pd
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay
from matplotlib import pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import seaborn as sns
from pmdarima import auto_arima

import os, threading, queue
from flask import Flask, request, jsonify, render_template, current_app
from werkzeug.local import LocalProxy
from flask_cors import CORS

app = Flask(__name__)
CORS(app, origins="*")

# current_app = LocalProxy(lambda: app._get_current_object())

seed = 42

def build_model(input_shape, trainY):
    tf.random.set_seed(seed)
    cnn_lstm_model = Sequential()

    cnn_lstm_model.add(Conv1D(filters=128, kernel_size=2, strides=1, padding='valid', input_shape=input_shape))
    cnn_lstm_model.add(MaxPooling1D(pool_size=2, strides=2))

    cnn_lstm_model.add(Conv1D(filters=64, kernel_size=2, strides=1, padding='valid'))
    cnn_lstm_model.add(MaxPooling1D(pool_size=1, strides=2))

    cnn_lstm_model.add(tf.keras.layers.Bidirectional(LSTM(256, return_sequences=True)))
    cnn_lstm_model.add(Dropout(0.2))
    cnn_lstm_model.add(tf.keras.layers.Bidirectional(LSTM(256, return_sequences=True)))
    cnn_lstm_model.add(Dropout(0.2))

    cnn_lstm_model.add(Dense(32, activation='relu'))
    cnn_lstm_model.add(Dense(trainY.shape[2], activation='relu'))

    cnn_lstm_model.compile(optimizer='adam', loss='mse')
    cnn_lstm_model.summary()
    return cnn_lstm_model

def plot_predictions_with_dates(type,twitter,dates,y_actual_lstm,y_pred_lstm):
    predicted_features=['Open','Adj Close']
    for i,predicted_feature in enumerate(predicted_features):
        plt.figure(figsize=(15,6))
        if twitter :
            plt.title(f'LSTM {type} prediction of {predicted_feature} feature After adding twitter sentiment analysis')
        else:
            plt.title(f'LSTM {type} prediction of {predicted_feature} feature without twitter sentiment analysis')
        sns.lineplot(x=dates, y=y_actual_lstm[:,i],label='Actual')
        sns.lineplot(x=dates, y=y_pred_lstm[:, i], label='Predicted')
        # plt.show()

        image_name = f'./static/graphs/graph_{type}_{predicted_feature}.png'
        plt.savefig(image_name)

        error=mean_squared_error(y_actual_lstm[:,i], y_pred_lstm[:, i])

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

def generateGraph(dataset):
    BASE_URL = './static/graphs/{}'

    fig = plt.gcf()
    fig.set_size_inches(16, 9)  # Set the width and height in inches
    fig.set_dpi(300)  # Set the DPI resolution

    df = pd.read_csv(f'./data/{dataset}.csv')
    df['date'] = pd.to_datetime(df['date'])

    sns.lineplot(x=df["date"], y=df["Adj Close"])
    df['sentiment_analysis'] = df['P_mean']
    df['sentiment_analysis'] = df['sentiment_analysis'].apply(lambda x: 'pos' if x > 0 else 'nue' if x == 0 else 'neg')
    sns.scatterplot(x=df["date"], y=df['Adj Close'], hue=df['sentiment_analysis'], palette=['y', 'r', 'g'])
    plt.xticks(rotation=45)
    plt.title("Sentiments of Stock ", fontsize=16)

    name = 'fig1.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    df=df.drop(list(range(14)),axis=0,inplace=False)
    train_dates = pd.to_datetime(df['date'])

    #Variables for training
    cols = [
        'Open',
        'High', 'Low',
        'Close',
        'Volume',
        'Adj Close',
        'P_mean',
    ]

    #New dataframe with only training data - 5 columns
    df_for_training = df[cols].astype(float)
    df_for_training.index=df['date']

    # print(df_for_training.shape)

    # Data scaling for LSTM because uses sigmoid and tanh that are sensitive to magnitude
    scaler = MinMaxScaler()
    scaler = scaler.fit(df_for_training)
    df_for_training_scaled = scaler.transform(df_for_training)

    scaler_for_inference = MinMaxScaler()
    scaler_for_inference.fit_transform(df_for_training.loc[:,['Open','Adj Close']])

    #Empty lists to be populated using formatted training data
    trainX = []
    trainY = []

    n_future = 1   # Number of days we want to look into the future based on the past days.
    n_past = 5  # Number of past days we want to use to predict the future.

    #Reformat input data into a shape: (n_samples x timesteps x n_features)
    #In my example, my df_for_training_scaled has a shape (12823, 5)
    #12823 refers to the number of data points and 5 refers to the columns (multi-variables).
    for i in range(n_past, len(df_for_training_scaled) - n_future +1):
        trainX.append(df_for_training_scaled[i - n_past:i, 0:df_for_training.shape[1]])
        trainY.append(df_for_training_scaled[i + n_future - 1:i + n_future,[0,-2]])

    trainX, trainY = np.array(trainX), np.array(trainY)
    X_train_lstm_without_twitter, X_test_lstm_without_twitter, y_train_lstm_without_twitter, y_test_lstm_without_twitter = train_test_split(trainX[:,:,:-1], trainY, test_size=0.2, shuffle=False)
    X_train_lstm_twitter, X_test_lstm_twitter, y_train_lstm_twitter, y_test_lstm_twitter = train_test_split(trainX, trainY, test_size=0.2, shuffle=False)

    # Train validation split for LSTM
    X_train_lstm_without_twitter, X_val_lstm_without_twitter, y_train_lstm_without_twitter, y_val_lstm_without_twitter = train_test_split(X_train_lstm_without_twitter, y_train_lstm_without_twitter, test_size=0.1, shuffle=False)
    X_train_lstm_twitter, X_val_lstm_twitter, y_train_lstm_twitter, y_val_lstm_twitter = train_test_split(X_train_lstm_twitter, y_train_lstm_twitter, test_size=0.1, shuffle=False)

    cnn_lstm_model_without_twitter = build_model((X_train_lstm_without_twitter.shape[1],X_train_lstm_without_twitter.shape[2]), trainY)
    cnn_lstm_model_twitter = build_model((X_train_lstm_twitter.shape[1],X_train_lstm_twitter.shape[2]), trainY)
    history_without_twitter = cnn_lstm_model_without_twitter.fit(X_train_lstm_without_twitter, y_train_lstm_without_twitter, epochs=50, batch_size=64, validation_data=(X_val_lstm_without_twitter, y_val_lstm_without_twitter), verbose=1)
    history_twitter = cnn_lstm_model_twitter.fit(X_train_lstm_twitter, y_train_lstm_twitter, epochs=50, batch_size=64, validation_data=(X_val_lstm_twitter, y_val_lstm_twitter), verbose=1)

    plt.figure(figsize=(20,5))
    plt.plot(history_without_twitter.history['loss'], label='Training loss')
    plt.plot(history_without_twitter.history['val_loss'], label='Validation loss')
    plt.title('Training loss Vs. Validation loss without twitter sentiment analysis')
    plt.legend()
    name = 'fig2.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    plt.figure(figsize=(20,5))
    plt.plot(history_twitter.history['loss'], label='Training loss')
    plt.plot(history_twitter.history['val_loss'], label='Validation loss')
    plt.title('Training loss Vs. Validation loss including twitter sentiment analysis')
    plt.legend()
    name = 'fig3.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    training_dates= df_for_training.index[:X_train_lstm_without_twitter.shape[0]]
    #Make prediction
    training_prediction_without_twitter = cnn_lstm_model_without_twitter.predict(X_train_lstm_without_twitter)
    training_prediction_twitter = cnn_lstm_model_twitter.predict(X_train_lstm_twitter)
    training_prediction_without_twitter=training_prediction_without_twitter.reshape(training_prediction_without_twitter.shape[0], training_prediction_without_twitter.shape[2])
    training_prediction_twitter=training_prediction_twitter.reshape(training_prediction_twitter.shape[0], training_prediction_twitter.shape[2])
    y_train_pred_lstm_without_twitter = scaler_for_inference.inverse_transform(training_prediction_without_twitter)
    y_train_pred_lstm_twitter = scaler_for_inference.inverse_transform(training_prediction_twitter)
    y_train_lstm_reshaped_without_twitter=y_train_lstm_without_twitter.reshape(y_train_lstm_without_twitter.shape[0], y_train_lstm_without_twitter.shape[2])
    y_train_actual_lstm = scaler_for_inference.inverse_transform(y_train_lstm_reshaped_without_twitter)

    # PRINTING TRAINING KE 4 GRAPHS
    plot_predictions_with_dates('Training',False,training_dates,y_train_actual_lstm,y_train_pred_lstm_without_twitter)
    plot_predictions_with_dates('Training',True,training_dates,y_train_actual_lstm,y_train_pred_lstm_twitter)

    validation_dates= df_for_training.index[X_train_lstm_without_twitter.shape[0]:X_train_lstm_without_twitter.shape[0] + X_val_lstm_without_twitter.shape[0]]
    #Make prediction
    validation_prediction_without_twitter = cnn_lstm_model_without_twitter.predict(X_val_lstm_without_twitter)
    validation_prediction_twitter = cnn_lstm_model_twitter.predict(X_val_lstm_twitter)
    validation_prediction_without_twitter=validation_prediction_without_twitter.reshape(validation_prediction_without_twitter.shape[0], validation_prediction_without_twitter.shape[2])
    validation_prediction_twitter=validation_prediction_twitter.reshape(validation_prediction_twitter.shape[0], validation_prediction_twitter.shape[2])
    y_val_pred_lstm_without_twitter = scaler_for_inference.inverse_transform(validation_prediction_without_twitter)
    y_val_pred_lstm_twitter = scaler_for_inference.inverse_transform(validation_prediction_twitter)
    y_val_actual_lstm_reshaped_without_twitter=y_val_lstm_without_twitter.reshape(y_val_lstm_without_twitter.shape[0], y_val_lstm_without_twitter.shape[2])
    y_val_actual_lstm = scaler_for_inference.inverse_transform(y_val_actual_lstm_reshaped_without_twitter)

    # PRINTING VALIDATION KE 4 GRAPHS
    plot_predictions_with_dates('Validation',False,validation_dates,y_val_actual_lstm,y_val_pred_lstm_without_twitter)
    plot_predictions_with_dates('Validation',True,validation_dates,y_val_actual_lstm,y_val_pred_lstm_twitter)

    testing_dates= df_for_training.index[-X_test_lstm_without_twitter.shape[0]:]
    #Make prediction
    testing_prediction_without_twitter = cnn_lstm_model_without_twitter.predict(X_test_lstm_without_twitter)
    testing_prediction_twitter = cnn_lstm_model_twitter.predict(X_test_lstm_twitter)
    testing_prediction_without_twitter=testing_prediction_without_twitter.reshape(testing_prediction_without_twitter.shape[0], testing_prediction_without_twitter.shape[2])
    testing_prediction_twitter=testing_prediction_twitter.reshape(testing_prediction_twitter.shape[0], testing_prediction_twitter.shape[2])
    y_test_pred_lstm_without_twitter = scaler_for_inference.inverse_transform(testing_prediction_without_twitter)
    y_test_pred_lstm_twitter = scaler_for_inference.inverse_transform(testing_prediction_twitter)
    y_test_actual_lstm_reshaped_without_twitter=y_test_lstm_without_twitter.reshape(y_test_lstm_without_twitter.shape[0], y_test_lstm_without_twitter.shape[2])
    y_test_actual_lstm = scaler_for_inference.inverse_transform(y_test_actual_lstm_reshaped_without_twitter)

    # PRINTING TESTING KE 4 GRAPHS
    plot_predictions_with_dates('Testing',False,testing_dates,y_test_actual_lstm,y_test_pred_lstm_without_twitter)
    plot_predictions_with_dates('Testing',True,testing_dates,y_test_actual_lstm,y_test_pred_lstm_twitter)

    df_arima=df_for_training.copy()
    n_past_for_arima=1
    adj_close_feature=df_arima['Adj Close']
    open_feature=df_arima['Open']
    df_arima['Adj Close']=df_arima['Adj Close'].shift(-n_past_for_arima)
    df_arima['Open']=df_arima['Open'].shift(-n_past_for_arima)
    df_arima.dropna(inplace=True)
    df_arima['Adj Close_feature']=adj_close_feature.iloc[:-1]
    df_arima['open_feature_feature']=open_feature.iloc[:-1]
    # df_arima=df_arima.reindex(columns=['open_lag','High', 'Low', 'Close', 'adj_close_lag','P_mean','Adj Close','Open',])
    X_arima=df_arima.drop(['Adj Close','Open'],axis=1)
    y_arima=df_arima[['Open','Adj Close']]
    X_train_arima_twitter, X_test_arima_twitter, y_train_arima, y_test_arima=train_test_split(X_arima, y_arima, test_size=0.2, shuffle=False)

    X_train_arima_without_twitter, X_test_arima_without_twitter= X_train_arima_twitter.drop('P_mean', axis=1), X_test_arima_twitter.drop('P_mean', axis=1)

    arima_model_for_open_without_twitter = auto_arima(y_train_arima['Open'], exogenous=X_train_arima_without_twitter,
                                                    start_p=2, d=None, start_q=3, max_p=5, max_d=3, max_q=5, D=None, start_Q=1, max_P=2, max_D=1, max_Q=2, max_order=5,
                                                    seasonal=True,
                                                    error_action='ignore',
                                                    suppress_warnings=True,
                                                    stepwise=True
                                                    )

    arima_model_for_open_twitter = auto_arima(y_train_arima['Open'], exogenous=X_train_arima_twitter,
                                            start_p=2, d=None, start_q=3, max_p=5, max_d=3, max_q=5, D=None, start_Q=1, max_P=2, max_D=1, max_Q=2, max_order=5,
                                            seasonal=True,
                                            error_action='ignore',
                                            suppress_warnings=True,
                                            stepwise=True
                                            )
    arima_model_for_open_without_twitter.summary()
    arima_model_for_open_twitter.summary()

    train_prediction_without_twitter= arima_model_for_open_without_twitter.predict(n_periods=len(X_train_arima_without_twitter), exogenous=X_train_arima_without_twitter)
    train_prediction_twitter= arima_model_for_open_twitter.predict(n_periods=len(X_train_arima_twitter), exogenous=X_train_arima_twitter)
    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_train_arima['Open'].index, y=y_train_arima['Open'], label='Actual')
    sns.lineplot(x=y_train_arima['Open'].index, y=train_prediction_without_twitter, label='Prediction')
    plt.title('Arima training Accuracy for Open without twitter sentiment analysis')
    name = 'arima_training_open_wo_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_train_arima['Open'].index, y=y_train_arima['Open'], label='Actual')
    sns.lineplot(x=y_train_arima['Open'].index, y=train_prediction_twitter, label='Prediction')
    plt.title('Arima training Accuracy for Open after adding twitter sentiment analysis')
    name = 'arima_training_open_w_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    test_prediction_without_twitter= arima_model_for_open_without_twitter.predict(n_periods=len(X_test_arima_without_twitter), exogenous=X_test_arima_without_twitter)
    test_prediction_twitter= arima_model_for_open_twitter.predict(n_periods=len(X_test_arima_twitter), exogenous=X_test_arima_twitter)
    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_test_arima['Open'].index, y=y_test_arima['Open'], label='Actual')
    sns.lineplot(x=y_test_arima['Open'].index, y=test_prediction_without_twitter, label='Prediction')
    plt.title('Arima testing Accuracy for open without twitter sentiment analysis')
    name = 'arima_testing_open_wo_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_test_arima['Open'].index, y=y_test_arima['Open'], label='Actual')
    sns.lineplot(x=y_test_arima['Open'].index, y=test_prediction_twitter, label='Prediction')
    plt.title('Arima testing Accuracy for open after adding twitter sentiment analysis')
    name = 'arima_testing_open_w_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    arima_model_for_Adj_Close_without_twitter = auto_arima(y_train_arima['Adj Close'], exogenous=X_train_arima_without_twitter,
                                            start_p=2, d=None, start_q=3, max_p=5, max_d=3, max_q=5, D=None, start_Q=1, max_P=2, max_D=1, max_Q=2, max_order=5,
                                            seasonal=True,
                                            error_action='ignore',
                                            suppress_warnings=True,
                                            stepwise=True
                                            )

    arima_model_for_Adj_Close_twitter = auto_arima(y_train_arima['Adj Close'], exogenous=X_train_arima_twitter,
                                            start_p=2, d=None, start_q=3, max_p=5, max_d=3, max_q=5, D=None, start_Q=1, max_P=2, max_D=1, max_Q=2, max_order=5,
                                            seasonal=True,
                                            error_action='ignore',
                                            suppress_warnings=True,
                                            stepwise=True
                                            )
    arima_model_for_Adj_Close_without_twitter.summary()
    arima_model_for_Adj_Close_twitter.summary()

    train_prediction_without_twitter= arima_model_for_Adj_Close_without_twitter.predict(n_periods=len(X_train_arima_without_twitter), exogenous=X_train_arima_without_twitter)
    train_prediction_twitter= arima_model_for_Adj_Close_twitter.predict(n_periods=len(X_train_arima_twitter), exogenous=X_train_arima_twitter)
    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_train_arima['Adj Close'].index, y=y_train_arima['Adj Close'], label='Actual')
    sns.lineplot(x=y_train_arima['Adj Close'].index, y=train_prediction_without_twitter, label='Prediction')
    plt.title('Arima training Accuracy for Adj Close without twitter sentiment analysis')
    name = 'arima_training_close_wo_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_train_arima['Adj Close'].index, y=y_train_arima['Adj Close'], label='Actual')
    sns.lineplot(x=y_train_arima['Adj Close'].index, y=train_prediction_twitter, label='Prediction')
    plt.title('Arima training Accuracy for Adj Close after adding twitter sentiment analysis')
    name = 'arima_training_close_w_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    test_prediction_without_twitter= arima_model_for_Adj_Close_without_twitter.predict(n_periods=len(X_test_arima_without_twitter), exogenous=X_test_arima_without_twitter)
    test_prediction_twitter= arima_model_for_Adj_Close_twitter.predict(n_periods=len(X_test_arima_twitter), exogenous=X_test_arima_twitter)
    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_test_arima['Adj Close'].index, y=y_test_arima['Adj Close'], label='Actual')
    sns.lineplot(x=y_test_arima['Adj Close'].index, y=test_prediction_without_twitter, label='Prediction')
    plt.title('Arima testing Accuracy for Adj Close without twitter sentiment analysis')
    name = 'arima_testing_close_wo_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    plt.figure(figsize=(15,6))
    sns.lineplot(x=y_test_arima['Adj Close'].index, y=y_test_arima['Adj Close'], label='Actual')
    sns.lineplot(x=y_test_arima['Adj Close'].index, y=test_prediction_twitter, label='Prediction')
    plt.title('Arima testing Accuracy for Adj Close after adding twitter sentiment analysis')
    name = 'arima_testing_close_w_twitter.png'
    plt.savefig(BASE_URL.format(name), dpi=fig.get_dpi())

    us_bd = CustomBusinessDay(calendar=USFederalHolidayCalendar())
    n_past_dates = 5
    n_days_for_prediction = 5

    predict_period_dates = pd.date_range(list(df_for_training.index)[-n_past_dates], periods=n_days_for_prediction,
                                        freq=us_bd).tolist()

    features= ['Open','High', 'Low','Close','Volume','Adj Close','P_mean']
    df_for_training.iloc[-n_past:,:].to_numpy().reshape(1,n_past,len(features)).shape

    x_forcast=df_for_training.iloc[-n_past-1:-1,:]
    x_forcast=scaler.transform(x_forcast).reshape(1,n_past,len(features))
    prediction = cnn_lstm_model_twitter.predict(x_forcast) #shape = (n, 1) where n is the n_days_for_prediction
    prediction=prediction.reshape(prediction.shape[0],prediction.shape[2])
    #Perform inverse transformation to rescale back to original range
    prediction=scaler_for_inference.inverse_transform(prediction)

    # Convert timestamp to date
    forecast_dates = []
    for time_i in predict_period_dates:
        forecast_dates.append(time_i.date())

    print(f'Date = {forecast_dates[-2]}, Prediction open {prediction[0][0]}')
    print(f'Date = {forecast_dates[-2]}, Prediction Adjusted close {prediction[0][1]}')

    folder_path = './static/graphs'
    file_names = os.listdir(folder_path)
    png_file_names = [file for file in file_names if file.endswith('.png')]
    sorted_png_file_names = sorted(png_file_names, key=lambda x: os.path.getctime(os.path.join(folder_path, x)))

    return jsonify({"success": True, "graphs": sorted_png_file_names, "prices": {
        "date": forecast_dates[-2],
        "open":  float(prediction[0][0]),
        "adj_close": float(prediction[0][1])
    }})

def executeMLInBG(modelName, result_queue):
    with app.app_context():
        result = generateGraph(modelName)

        result_queue.put(result)

@app.route('/upload', methods=['GET'])
def upload_csv():
    modelName = request.args.get('modelName')

    # Create a queue to pass the result from generateGraph
    result_queue = queue.Queue()

    # Create a thread to execute the generateGraph function
    thread = threading.Thread(target=executeMLInBG, args=(modelName, result_queue,))
    thread.start()
    thread.join()  # Wait for the thread to complete

    # Retrieve the result from the queue
    result = result_queue.get()

    # Return the data obtained from generateGraph
    with current_app.app_context():
        return result

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


# Say you have an array for which the ith element is the price of a given stock on day i.
#
# If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
#
# Note that you cannot sell a stock before you buy one.

# Example 1:
# Input: [7,1,5,3,6,4]
# Output: 5
# Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
#              Not 7-1 = 6, as selling price needs to be larger than buying price.

# Example 2:
# Input: [7,6,4,3,1]
# Output: 0
# Explanation: In this case, no transaction is done, i.e. max profit = 0.

# 给定一个数组，它的第 i 个元素是一支给定股票第 i 天的价格。
#
# 如果你最多只允许完成一笔交易（即买入和卖出一支股票），设计一个算法来计算你所能获取的最大利润。
#
# 注意你不能在买入股票前卖出股票。
#
# 示例 1:
# 输入: [7,1,5,3,6,4]
# 输出: 5
# 解释: 在第 2 天（股票价格 = 1）的时候买入，在第 5 天（股票价格 = 6）的时候卖出，最大利润 = 6-1 = 5 。
#      注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
#
# 示例 2:
# 输入: [7,6,4,3,1]
# 输出: 0
# 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

# 解析：如果输入的数组长度小于等于1，则无法完成买入卖出操作，故返回0
#      先令第一个数为最小价格，然后从第二个数开始遍历，不断更新最小价格的值，同时不断更新后面各个数值与最低价格的差值，即最大利润；

class Solution:
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        # profit = [0]
        # for i in range(len(prices)):
        #     for j in range(i+1, len(prices)):
        #         if prices[j] > prices[i]:
        #             profit.append(prices[j] - prices[i])
        #         else:
        #             pass
        #     profit = [max(profit)]
        # return profit[0]

        if len(prices) <= 1:
            return 0
        min_price = prices[0]
        max_profit = 0
        for i in range(1,len(prices)):
            min_price = min(min_price, prices[i])
            max_profit = max(max_profit, prices[i]-min_price)
        return max_profit