from django.test import TestCase
from django.urls import reverse, resolve
from django.apps import apps
from titles.models import Genre, Title
from django.template.defaultfilters import slugify
from django.urls import reverse, resolve
from post.templatetags.urlparams import urlparams
from ..views import TitleList

class BaseTitleListTests(object):
    def setUp(self):
        self.title = Title.objects.create(
            original_name="Tetsugaka Letra",
            russian_name="первый тест",
            english_name="first test",
        )
        self.title2 = Title.objects.create(
            original_name="test", russian_name="первый тест", english_name="first test"
        )
        self.genre1 = Genre.objects.create(name="Romance", slug=slugify("Romance"))
        self.genre2 = Genre.objects.create(name="Action", slug=slugify("Action"))

        self.modeltype = apps.get_model(app_label="titles", model_name=self.model)
        self.item = self.modeltype.objects.create(
            title=self.title,
        )
        self.item.genre.set([self.genre1, self.genre2])
        self.item2 = self.modeltype.objects.create(
            title=self.title2,
        )
        self.item2.genre.set([self.genre1])
        self.url = reverse(f"{self.model}_list")
        self.response = self.client.get(self.url)

    def get_url(self, base_url, params):
        return "{base_url}{querystring}".format(base_url=base_url, querystring=params)

    def test_anime_status_code(self):
        self.assertEqual(self.response.status_code, 200)

    def test_anime_template(self):  # new
        self.assertTemplateUsed(self.response, "titles/list.html")

    def test_homepage_does_not_contain_incorrect_html(self):
        self.assertNotContains(self.response, "Hi there! I should not be on the page.")

    def test_homepage_url_resolves_homepageview(self):
        view = resolve(self.url)
        self.assertEqual(view.func.__name__, TitleList.as_view().__name__)

    def test_list_items(self):
        values = ["id", "title__original_name", "image__thumbnail"]
        self.assertQuerysetEqual(
            self.response.context["list"],
            self.modeltype.objects.all()
            .values(*values)
            .order_by("title__original_name"),
        )

    def test_no_filter_name(self):
        q = ""
        url_filter_name = self.get_url(self.url, urlparams(q=q))
        responce_filter_name = self.client.get(
            url_filter_name, HTTP_ACCEPT="application/json"
        )
        self.assertEqual(responce_filter_name.context["query"], q)
        self.assertEqual(responce_filter_name.context["list"].count(), 2)

        self.assertContains(responce_filter_name, self.title.original_name)

    def test_filter_name(self):
        q = self.title.original_name
        url_filter_name = self.get_url(self.url, urlparams(q=q))
        responce_filter_name = self.client.get(
            url_filter_name, HTTP_ACCEPT="application/json"
        )
        self.assertEqual(responce_filter_name.context["query"], q)
        self.assertEqual(responce_filter_name.context["list"].count(), 1)
        self.assertContains(responce_filter_name, self.title.original_name)

    def test_filter_wrong_name(self):
        q = "I'm not exist"
        url_filter_name = self.get_url(self.url, urlparams(q=q))
        responce_filter_name = self.client.get(
            url_filter_name, HTTP_ACCEPT="application/json"
        )
        self.assertEqual(responce_filter_name.context["query"], q)
        self.assertEqual(responce_filter_name.context["list"].count(), 0)
        self.assertNotContains(responce_filter_name, self.title.original_name)

    def test_filter_attributes(self):

        url_filter_attr = self.get_url(self.url, urlparams(genre=self.genre2))
        responce_filter_attr = self.client.get(
            url_filter_attr, HTTP_ACCEPT="application/json"
        )
        self.assertEqual(responce_filter_attr.context["list"].count(), 1)
        self.assertEqual(self.response.context["list"].count(), 2)

    def test_homepage_contains_correct_html(self):
        self.assertContains(self.response, self.item)

    def test_homepage_contains_correct_modelname(self):
        self.assertEqual(self.response.context["model"], self.model.capitalize())

    def test_homepage_contains_correct_modelname(self):
        self.assertNotEqual(self.response.context["model"], "Wrong Model Name")

class AnimePageTests(BaseTitleListTests, TestCase):
    """
    Tests for animepage
    """

    def setUp(self):
        self.model = "anime"
        super().setUp()

class MangaPageTests(BaseTitleListTests, TestCase):
    """
    Tests for mangapage
    """

    def setUp(self):
        self.model = "manga"
        super().setUp()


from utils import *
from plot_utils import *

google_lat, google_lon = 46.500458, 8.052669

year = 2020
month = 1
day = 1

interval = 30
n_intervals = 0

start_date = datetime.date(year = year, month = month, day = day)
start_date = datetime.datetime.now().date()

td = datetime.timedelta(days = interval)
final_date = start_date + n_intervals * td

metadata_links = {'2m' : '/Users/george-birchenough/Downloads/ch.swisstopo.swissalti3d-fGQ3d2A6.csv' , \
                  '0.5m' : 'https://ogd.swisstopo.admin.ch/resources/ch.swisstopo.swissalti3d-3TuKAiHo.csv' }

transformer = Transformer.from_crs( 'epsg:4326', 'epsg:2056' )
observer_lon, observer_lat = transformer.transform( google_lat, google_lon)

filename = metadata_links['2m']
grid_size = 2
radius = 1
tile_meta_df = get_tile_metadata(filename)
target_tiles = get_targets(observer_lat, observer_lon, tile_meta_df, radius)
plot_tile_corners(target_tiles)

array, blank_array = get_tiles(target_tiles)

observer_pixel, observer_height = get_observer_position(array, blank_array, observer_lat, observer_lon )
peaks_df = get_peaks( array, observer_pixel, observer_height, grid_size)

plot_main(google_lat, google_lon, observer_height, peaks_df, start_date, final_date, td )


from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
from myadmin.models import Types,Goods,Orders,Detail
from django.core.paginator import Paginator
from PIL import Image
import time,json,os
#=========商品类别

#浏览商品
def type_index(request,pIndex=1):
	#执行数据查询,并放置模板中
	list = Types.objects.extra(select = {'_has':'concat(path,id)'}).order_by('_has')
	#遍历查询结果,为每个结果对象追加一个pname属性,目的用于缩进标题
	for ob in list:
		ob.pname = '...'*(ob.path.count(',')-1)
	#context = {'typeslist':list}
	#判断并封装搜索学生信息
	where = []
	if request.GET.get('name','') != '':
		list = list.filter(name__contains=request.GET['name'])
		where.append('name='+request.GET['name'])
	#传入数据和页的大小来创建对象
	p = Paginator(list,10)
	#判断页号没有初始值时初始化1
	if pIndex == '':
		pIndex = '1'
	pIndex = int(pIndex) #类型转换int
	list2 = p.page(pIndex)#获取当前页数据
	plist = p.page_range#获取页码信息
	#封装分页信息
	context = {'stulist':list2,'plist':plist,'pIndex':pIndex,'where':where}
	return render(request,'myadmin/types/index.html',context)
#添加商品
def type_add(request,tid):
	#获取父类别信息,若没有则默认为根类别信息
	if tid == '0':
		context = {'pid':0,'path':'0,','name':'根类别'}
	else:
		ob = Types.objects.get(id=tid)
		context = {'pid':ob.id,'path':ob.path+str(ob.id)+',','name':ob.name}
	return render(request,'myadmin/types/add.html',context)

#执行商品类别信息添加
def type_insert(request):
	try:
		ob = Types()
		ob.name = request.POST['name']
		ob.pid = request.POST['pid']
		ob.path = request.POST['path']
		ob.save()
		print(1)
		context = {'info':'添加成功'}
	except:
		context = {'info':'添加失败'}
	return render(request,'myadmin/info.html',context)

#执行商品类别信息删除
def type_del(request,tid):
	try:
		#获取被删除商品的子类别信息量,若有数据,就禁止删除当前的类别
		row = Types.objects.filter(pid=tid).count()
		if row > 0:
			context = {'info':'删除失败,此类别还有子类别'}
			return render(request,'myadmin/info.html',context)
		else:
			ob = Types.objects.get(id=tid)
			ob.delete()
			context = {'info':'删除成功'}
	except:
		context = {'info':'删除失败!'}
	return render(request,'myadmin/info.html',context)

#商品信息编辑表单
def type_edit(request,tid):
	ob = Types.objects.get(id=tid)
	context = {'type':ob}
	return render(request,'myadmin/types/edit.html',context)
#执行商品信息编辑
def type_update(request,tid):
	try:
		ob = Types.objects.get(id=tid)
		ob.name = request.POST['name']
		ob.save()
		context = {'info':'修改成功'}
	except:
		context = {'info':'修改失败'}
	return render(request,'myadmin/info.html',context)

#==============商品信息管理

#商品信息浏览
def goods_index(request,pIndex=1):
	#执行数据查询,并放置到模板中
	list = Goods.objects.all()
	for ob in list:
		ty = Types.objects.get(id = ob.typeid)
		ob.typename = ty.name
	# context = {'goodslist':list}
	#判断并封装搜索学生信息
	where = []
	if request.GET.get('goods','') != '':
		list = list.filter(goods__contains=request.GET['goods'])
		where.append('name='+request.GET['goods'])
	p = Paginator(list,6)
	#判断页号没有初始值时初始化1
	if pIndex == '':
		pIndex = '1'
	pIndex = int(pIndex) #类型转换int
	list2 = p.page(pIndex)#获取当前页数据
	plist = p.page_range#获取页码信息
	#封装分页信息
	context = {'goodslist':list2,'plist':plist,'pIndex':pIndex,'where':where}
	# return render(request,'myadmin/types/index.html',context)
	return render(request,'myadmin/goods/index.html',context)

#商品信息添加
def goods_add(request):
	#获取商品类别信息
	list = Types.objects.extra(select={'_has':'concat(path,id)'}).order_by('_has')
	context = {'typelist':list}
	return render(request,'myadmin/goods/add.html',context)
#执行商品信息添加
def goods_insert(request):
	# try:
	#判断并执行图片上传
	myfile = request.FILES.get('pic',None)
	if not myfile:
		return HttpResponse('没有上传信息')
	#以时间戳命名一个新的图片名称
	filename = str(time.time())+'.'+myfile.name.split('.').pop()
	# destination = open(os.path.join('./static/goods',filename),'wb+')
	destination = open(os.path.join("./static/myadmin/goods/",filename),'wb+')
	for chunk in myfile.chunks():
		destination.write(chunk)
	destination.close()

	#执行图片缩放
	im = Image.open('./static/myadmin/goods/'+filename)
	#缩放375*375
	im.thumbnail((375,375))
	#把缩放的图像用jpeg格式保存
	im.save('./static/myadmin/goods/'+filename,'jpeg')
	#缩放220*220
	im.thumbnail((220,220))
	#把缩放的图像用jpeg格式保存
	im.save('./static/myadmin/goods/m_'+filename,'jpeg')
	#缩放100*100
	im.thumbnail((100,100))
	#把缩放的图像用jpeg格式保存
	im.save('./static/myadmin/goods/s_'+filename,'jpeg')

	#获取信息并执行添加
	ob = Goods()
	ob.goods = request.POST['goods']
	ob.typeid = request.POST['typeid']
	ob.company = request.POST['company']
	ob.price = request.POST['price']
	ob.store = request.POST['store']
	ob.descr = request.POST['descr']
	ob.picname = filename
	ob.state = 1
	ob.addtime = time.time()
	ob.save()
	context = {'info':'添加成功'}
	# except:
	# 	context = {'info':'添加失败'}
	return render(request,'myadmin/info.html',context)

#删除商品信息
def goods_del(request,gid):
	try:
		ob = Goods.objects.get(id=gid)
		#执行图片删除
		os.remove('./static/myadmin/goods/'+ob.picname)
		os.remove('./static/myadmin/goods/m_'+ob.picname)
		os.remove('./static/myadmin/goods/s_'+ob.picname)
		#执行信息删除
		ob.delete()
		context = {'info':'删除成功!'}
	except:
		context = {'info':'删除失败!'}
	return render(request,'myadmin/info.html',context)

#编辑商品信息表单
def goods_edit(request,gid):
	try:
		#获取要编辑的信息
		ob = Goods.objects.get(id=gid)
		#获取商品信息类别
		list = Types.objects.extra(select={'_has':'concat(path,id)'}).order_by('_has')
		#放置信息加载模板
		context = {'typelist':list,'goods':ob}
		return render(request,'myadmin/goods/edit.html',context)
	except:
		context = {'info':'没有找到要修改的信息'}
	return render(request,'myadmin/info.html',context)

#执行编辑商品信息
def goods_update(request,gid):
	try:
		#判断是否有文件上传
		#执行图片的上传
		myfile = request.FILES.get("pic",None)
		if not myfile:
			ob = Goods.objects.get(id= gid)
			ob.goods = request.POST['goods']
			ob.typeid = request.POST['typeid']
			ob.company = request.POST['company']
			ob.price = request.POST['price']
			ob.store = request.POST['store']
			ob.descr = request.POST['descr']
			ob.state = request.POST['state']
			ob.addtime= time.time()
			ob.save()
		else:
			ob = Goods.objects.get(id= gid)
			os.remove('./static/myadmin/goods/'+ob.picname)
			os.remove('./static/myadmin/goods/m_'+ob.picname)
			os.remove('./static/myadmin/goods/s_'+ob.picname)
			filename = str(time.time())+"."+myfile.name.split('.').pop()
			destination = open("./static/myadmin/goods/"+filename,"wb+")
			for chunk in myfile.chunks():      # 分块写入文件
				destination.write(chunk)
			destination.close()

			#执行图片缩放
			im = Image.open('./static/myadmin/goods/'+filename)
			#缩放375*375
			im.thumbnail((375,375))
			#把缩放的图像用jpeg格式保存
			im.save('./static/myadmin/goods/'+filename,'jpeg')
			#缩放220*220
			im.thumbnail((220,220))
			#把缩放的图像用jpeg格式保存
			im.save('./static/myadmin/goods/m_'+filename,'jpeg')
			#缩放100*100
			im.thumbnail((100,100))
			#把缩放的图像用jpeg格式保存
			im.save('./static/myadmin/goods/s_'+filename,'jpeg')

			ob.goods = request.POST['goods']
			ob.typeid = request.POST['typeid']
			ob.company = request.POST['company']
			ob.price = request.POST['price']
			ob.store = request.POST['store']
			ob.descr = request.POST['descr']
			ob.picname = filename
			ob.state = request.POST['state']
			ob.addtime= time.time()
			ob.save()
		context = {'info':'修改成功！'}
	except:
		context = {'info':'修改失败！'}
	return render(request,"myadmin/info.html",context)

#=======订单信息管理
#订单信息浏览
def orders_index(request,pIndex=1):
	list = Orders.objects.all()
	#判断并封装搜索学生信息
	where = []
	if request.GET.get('linkman','') != '':
		list = list.filter(linkman__contains=request.GET['linkman'])
		where.append('linkman='+request.GET['linkman'])
	#传入数据和页的大小来创建对象
	p = Paginator(list,10)
	#判断页号没有初始值时初始化1
	if pIndex == '':
		pIndex = '1'
	pIndex = int(pIndex) #类型转换int
	list2 = p.page(pIndex)#获取当前页数据
	plist = p.page_range#获取页码信息
	#封装分页信息
	context = {'orderslist':list2,'plist':plist,'pIndex':pIndex,'where':where}
	return render(request,'myadmin/orders/index.html',context)

#订单信息编辑
def orders_edit(request,rid):
	orders = Orders.objects.get(id=rid)
	context = {'orders':orders}
	return render(request,'myadmin/orders/edit.html',context)

#执行订单信息编辑
def orders_update(request,rid):
	try:
		ob = Orders.objects.get(id=rid)
		ob.status = request.POST['status']
		ob.save()
		context = {'info':'修改成功!'}
	except:
		context = {'info':'修改失败！'}
	return render(request,'myadmin/info.html',context)

#订单详情页
def orders_detail(request,rid):
	detail = Detail.objects.filter(orderid=rid)
	for ob in detail:
		dt = Goods.objects.get(id=ob.goodsid)
		ob.picname = dt.picname
	context = {'detaillist':detail}
	return render(request,'myadmin/orders/detail.html',context)


import tkinter
import tkinter.messagebox
import customtkinter

customtkinter.set_appearance_mode("System")  # Other: "Light", "Dark"

class App(tkinter.Tk):

    APP_NAME = "CustomTkinter complex example"
    WIDTH = 700
    HEIGHT = 500

    def __init__(self, *args, **kwargs):
        customtkinter.enable_macos_darkmode()

        tkinter.Tk.__init__(self, *args, **kwargs)

        self.title(App.APP_NAME)
        self.geometry(str(App.WIDTH) + "x" + str(App.HEIGHT))
        self.minsize(App.WIDTH, App.HEIGHT)

        self.protocol("WM_DELETE_WINDOW", self.on_closing)
        self.bind("<Command-q>", self.on_closing)
        self.bind("<Command-w>", self.on_closing)
        self.createcommand('tk::mac::Quit', self.on_closing)

        # ============ create two CTkFrames ============

        self.frame_left = customtkinter.CTkFrame(master=self,
                                                 width=200,
                                                 height=App.HEIGHT-40,
                                                 corner_radius=10)
        self.frame_left.place(relx=0.32, rely=0.5, anchor=tkinter.E)

        self.frame_right = customtkinter.CTkFrame(master=self,
                                                  width=420,
                                                  height=App.HEIGHT-40,
                                                  corner_radius=10)
        self.frame_right.place(relx=0.365, rely=0.5, anchor=tkinter.W)

        # ============ frame_left ============

        self.button_1 = customtkinter.CTkButton(master=self.frame_left,
                                                text="CTkButton",
                                                command=self.button_event,
                                                border_width=0,
                                                corner_radius=8)
        self.button_1.place(relx=0.5, y=50, anchor=tkinter.CENTER)

        self.button_2 = customtkinter.CTkButton(master=self.frame_left,
                                                text="CTkButton",
                                                command=self.button_event,
                                                border_width=0,
                                                corner_radius=8)
        self.button_2.place(relx=0.5, y=100, anchor=tkinter.CENTER)

        self.button_3 = customtkinter.CTkButton(master=self.frame_left,
                                                text="CTkButton",
                                                command=self.button_event,
                                                border_width=0,
                                                corner_radius=8)
        self.button_3.place(relx=0.5, y=150, anchor=tkinter.CENTER)

        # ============ frame_right ============

        self.frame_info = customtkinter.CTkFrame(master=self.frame_right,
                                                 width=380,
                                                 height=200,
                                                 corner_radius=10)
        self.frame_info.place(relx=0.5, y=20, anchor=tkinter.N)

        # ============ frame_right -> frame_info ============

        self.label_info_1 = customtkinter.CTkLabel(master=self.frame_info,
                                                   text="CTkLabel: Lorem ipsum dolor sit,\n" +
                                                        "amet consetetur sadipscing elitr,\n" +
                                                        "sed diam nonumy eirmod tempor\n" +
                                                        "invidunt ut labore",
                                                   width=250,
                                                   height=100,
                                                   corner_radius=8,
                                                   fg_color=("white", "gray38"),  # <- custom tuple-color
                                                   justify=tkinter.LEFT)
        self.label_info_1.place(relx=0.5, rely=0.15, anchor=tkinter.N)

        self.progressbar = customtkinter.CTkProgressBar(master=self.frame_info,
                                                        width=250,
                                                        height=15,
                                                        border_width=0)
        self.progressbar.place(relx=0.5, rely=0.85, anchor=tkinter.S)

        # ============ frame_right <- ============

        self.slider_1 = customtkinter.CTkSlider(master=self.frame_right,
                                               width=160,
                                               height=16,
                                               border_width=5.5,
                                               command=self.progressbar.set)
        self.slider_1.place(x=20, rely=0.6, anchor=tkinter.W)
        self.slider_1.set(0.3)

        self.slider_2 = customtkinter.CTkSlider(master=self.frame_right,
                                               width=160,
                                               height=16,
                                               border_width=5.5,
                                               command=self.progressbar.set)
        self.slider_2.place(x=20, rely=0.7, anchor=tkinter.W)
        self.slider_2.set(0.7)

        self.label_info_2 = customtkinter.CTkLabel(master=self.frame_right,
                                                   text="CTkLabel: Lorem ipsum",
                                                   width=180,
                                                   height=20,
                                                   justify=tkinter.CENTER)
        self.label_info_2.place(x=310, rely=0.6, anchor=tkinter.CENTER)

        self.button_4 = customtkinter.CTkButton(master=self.frame_right,
                                                height=25,
                                                text="CTkButton",
                                                command=self.button_event,
                                                border_width=0,
                                                corner_radius=8)
        self.button_4.place(x=310, rely=0.7, anchor=tkinter.CENTER)

        self.entry = customtkinter.CTkEntry(master=self.frame_right,
                                            width=120,
                                            height=25,
                                            corner_radius=10)
        self.entry.place(relx=0.33, rely=0.92, anchor=tkinter.CENTER)
        self.entry.insert(0, "CTkEntry")

        self.button_5 = customtkinter.CTkButton(master=self.frame_right,
                                                height=25,
                                                text="CTkButton",
                                                command=self.button_event,
                                                border_width=0,
                                                corner_radius=8)
        self.button_5.place(relx=0.66, rely=0.92, anchor=tkinter.CENTER)

        self.progressbar.set(0.65)

    def button_event(self):
        print("Button pressed")

    def on_closing(self, event=0):
        customtkinter.disable_macos_darkmode()
        self.destroy()

    def start(self):
        self.mainloop()

if __name__ == "__main__":
    app = App()
    app.start()


# Header (모듈 Import하는 작업)
import pygame, sys
from pygame.locals import*   # 유용한 상수들을 선언없이 사용하기 위해 필수 ex) quit, exit 등

# Initail 문 (무한반복문 이전 문장들, 전역변수 한번 초기화, 몇몇함수 한번 호출, 주로 색상같은 전역변수들)
white = (255,255,255)       # 색상 변수 선언
red = (255,0,0)             # 색상 변수 선언
green = (0,255,0)           # 색상 변수 선언
pygame.init()               # 나중에 사용할 함수를 위해 가장 앞서서 호출되어야 함
pygame.display.set_caption("Hello World Project")
myScreen = pygame.display.set_mode((640,480))                         # 캔버스 생성 (640 x 480 크기)
myTextFont = pygame.font.Font("HoonWhitecatR.ttf",32)                 # 해당 폰트로 32 크기로 설정
myText = myTextFont.render("Hello World!", True, red, green)          # render함수는 텍스트 내용과 색상을 정할수 있다
myTextArea = myText.get_rect()                                        # get_rect() 함수는 텍스트의 폰트 크기와 텍스트 크기 고려 적절한 직사각형 공간을 반환
myTextArea.center = (320, 240)

# Always 문 (무한반복문, 전역변수 계속 업데이트, 몇몇함수 계속 호출)
while True:
    myScreen.fill(white)                     # fill 함수는 캔버스를 단색으로 채우는 기능
    myScreen.blit(myText, myTextArea)        # blit 함수는 특정 객체를 특정 위치에 그리는 기능, blit이 fill 다음에 수행되어야 함

# Event 문 (모든 이벤트를 체크하는 반복문)
    for event in pygame.event.get():         # pygame.event.get() 함수는 Always문에서 발생한 이벤트들의 배열을 반환, 시간순으로 정렬
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    pygame.display.update()            # 일반적으로 다른 변수/함수의 처리가 끝난 이후에 호출, 처리의 결과물을 스크린에 출력하는 함수
                                       # 이함수가 Always 문 마지막에 실행되지 않으면, 출력되는 화면과 게임 내부 데이터가 서로 일치하지 않음


import time

from adafruit_ble import BLERadio
from adafruit_bluefruit_connect.packet import Packet

class BLE(BLERadio):
    def advertisement_test(self):
        from adafruit_ble.advertising.standard import Advertisement
        advertisement = Advertisement()
        advertisement.short_name = "HELLO"
        advertisement.connectable = True

        while True:
            print(advertisement)
            self.start_advertising(advertisement, scan_response=b"")
            while not self.connected:
                pass
            print("connected")
            while self.connected:
                pass
            print("disconnected")

    def deviceinfo_service(self):
        """
        This example does a generic connectable advertisement and prints out the
        manufacturer and model number of the device(s) that connect to it.
        """
        from adafruit_ble.services.standard.device_info import DeviceInfoService

        a = Advertisement()
        a.connectable = True
        self.start_advertising(a)

        # Info that the other device can read about us.
        my_info = DeviceInfoService(manufacturer="CircuitPython.org", model_number="1234")

        print("advertising")

        while not self.connected:
            pass

        print("connected")

        while self.connected:
            for connection in self.connections:
                if not connection.paired:
                    connection.pair()
                    print("paired")
                print(connection, connection.connected)
            time.sleep(5)

        print("disconnected")

    def uart_service(self):
        from adafruit_ble.services.nordic import UARTService

        SEND_RATE = 10  # how often in seconds to send text

        uart_server = UARTService()
        advertisement = ProvideServicesAdvertisement(uart_server)

        count = 0
        while True:
            print("WAITING...")
            # Advertise when not connected.
            self.start_advertising(advertisement)
            while not self.connected:
                pass

            # Connected
            self.stop_advertising()
            print("CONNECTED")

            # Loop and read packets
            last_send = time.monotonic()
            while self.connected:
                # INCOMING (RX) check for incoming text
                if uart_server.in_waiting:
                    raw_bytes = uart_server.read(uart_server.in_waiting)
                    text = raw_bytes.decode().strip()
                    # print("raw bytes =", raw_bytes)
                    print("RX:", text)
                # OUTGOING (TX) periodically send text
                if time.monotonic() - last_send > SEND_RATE:
                    text = "COUNT = {}\r\n".format(count)
                    print("TX:", text.strip())
                    uart_server.write(text.encode())
                    count += 1
                    last_send = time.monotonic()

            # Disconnected
            print("DISCONNECTED")

    def uart2(self):
        from adafruit_ble.advertising.standard import ProductServicesAdvertisement
        from adafruit_ble.services.nordic import UARTService
        from adafruit_bluefruit_connect.color_packet import ColorPacket

        uart_server = UARTService()
        advertisement = ProvideServicesAdvertisement(uart_server)

        while True:
            # Advertise when not connected.
            self.start_advertising(advertisement)
            while not self.connected:
                pass

            while self.connected:
                packet = Packet.from_stream(uart_server)
                if isinstance(packet, ColorPacket):
                    print(packet.color)

    def scan(self):
        from adafruit_ble.advertising.standard import Advertisement, ProvideServicesAdvertisement

        print("scanning")
        found = set()
        scan_responses = set()
        devices = {}
        for advertisement in self.start_scan(ProvideServicesAdvertisement, Advertisement):
            addr = advertisement.address
            if advertisement.scan_response and addr not in scan_responses:
                scan_responses.add(addr)
            elif not advertisement.scan_response and addr not in found:
                found.add(addr)
            else:
                continue

            if advertisement.connectable:
                print("found connectable device", addr, advertisement)
            else:
                print("found non-connectable device", addr, advertisement)
            print()
        print("scan done")
        return found, scan_responses

def test_ble():
    ble = BLE()
    ble.deviceinfo_service()

if __name__ == "__main__":
    test_ble()


# import urllib.request

# proxy_host = '221.211.62.4'
# proxy_port = 1111
# proxy_handler = urllib.request.ProxyHandler({'socks5': f'{proxy_host}:{proxy_port}'})
# opener = urllib.request.build_opener(proxy_handler)
# response = opener.open('https://ifconfig.me/ip')
# print(response.read().decode())

# # import socket
# # import socks
# # import requests

# # # socks.set_default_proxy(socks.SOCKS5, "85.239.55.203",49572)
# # # socket.socket = socks.socksocket
# # print(requests.get('http://cip.cc').text)

from tqdm import tqdm, trange

from urllib3.contrib.socks import SOCKSProxyManager
import socket
import socks
import urllib3    # 导入urllib3模块
headers={'User-Agent' : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0 "}

#uurl = "https://cip.cc"
uurl = "http://www.httpbin.org/ip"
# uurl = "https://ip.900cha.com/"

# # # def shi(url,port):
    # # # http = urllib3.PoolManager(timeout=urllib3.Timeout(connect=0.5, read=1.0))   # 创建连接池管理对象

    # # # socks.set_default_proxy(socks.SOCKS5 , url , port)
    # # # socket.socket = socks.socksocket

    # # # print(url)
    # # # r = http.request('GET', uurl,headers=headers)    # 发送GET请求
    # # # print(r.status,r.data.decode('utf-8'))

def shi(url,port):
    proxy = SOCKSProxyManager("socks4://"+url+":"+str(port)+"/")
    proxy = SOCKSProxyManager("socks5://"+url+":"+str(port)+"/")
    r = proxy.request('GET', uurl ,headers=headers,timeout=1)

    print(r.status,r.data.decode('utf-8'))

f=open("ipip.txt","r",encoding="utf-8")
ww=f.readlines()
f.close()

f=open("workip.txt","w",encoding="utf-8")
f.close()

for ee in tqdm(ww):
    kk=ee.split(":")
    f=open("workip.txt","a+",encoding="utf-8")

    try:
        print(kk[0],int(kk[1]))
        shi(kk[0],int(kk[1]))
        f.write(kk[0])
        f.write(":")
        f.write(kk[1])
        f.write("\n")

    except BaseException as e:
        a=0
    f.close()

# # #
# # #
# # #


def get_fuel(mass):
    return mass // 3 - 2

def recursive_get_fuel(mass):
    total_fuel = 0
    fuel = get_fuel(mass)
    while fuel > 0:
        total_fuel += fuel
        fuel = get_fuel(fuel)
    return total_fuel

lines = [line.rstrip('\n') for line in open('input.txt').readlines()]
masses = [int(line) for line in lines]

print(sum(map(get_fuel, masses)))
print(sum(map(recursive_get_fuel, masses)))


import numpy as np
import pandas as pd
import h5py
from pylds.models import DefaultPoissonLDS, DefaultLDS
from pickle import dump
from sklearn.model_selection import train_test_split

min_segment = 0.5
lfads_dt = 0.01
bin_size = 50 #time step for lds, in ms
thresh = 0.2 #threshold of summed absolute value of lfads controller outputs
D_latent = 10 #
test_size = 50 #number of holdout segment
random_state = 5
default_std = 100 #default smoothing std, miliseconds
pad_interval = True

def split_segments(counts):
    print("spit function entered")
    train_counts, test_counts = train_test_split(counts, test_size=test_size, random_state=random_state)

    return train_counts, test_counts

def get_forward_prediction(model, test_counts):

    predicted_counts = []
    for segment in test_counts:
        p = np.zeros_like(segment)
        obs_init = segment[0,:]
        state_t, _, _, _ = np.linalg.lstsq(model.C, obs_init)
        p[0,:] = model.C.dot(state_t)
        for t in range(1, p.shape[0]):
            state_t = model.A.dot(state_t)
            p[t,:] = state_t.dot(model.C.T)

        predicted_counts.append(p)

    return predicted_counts

def train_model(df, co, n_steps, filename=None, bin_size=bin_size):

    counts = segment_spike_counts(df, co, bin_size)
    train_counts, test_counts = split_segments(counts)

    n_neurons = df.neural.shape[1]
    model = DefaultPoissonLDS(n_neurons, D_latent)
    for segment in train_counts:
        model.add_data(segment)

    ll = np.zeros(n_steps)
    for i in range(n_steps):
        model.EM_step()
        ll[i] = model.log_likelihood()

    try:
        if filename is not None:
            dump(model, open(filename, 'wb'))
    except:
        pass

    return model, ll

def train_model_gaussian(df, co, n_steps, filename=None, bin_size=bin_size):

    counts = segment_spike_counts(df, co, bin_size)
    train_counts, test_counts = split_segments(counts)

    n_neurons = df.neural.shape[1]
    model = DefaultPoissonLDS(n_neurons, D_latent)
    for segment in train_counts:
        model.add_data(segment)

    ll = np.zeros(n_steps)
    for i in range(n_steps):
        model.EM_step()
        ll[i] = model.log_likelihood()

    try:
        if filename is not None:
            dump(model, open(filename, 'wb'))
    except:
        pass

    return model, ll

def bin_dataframe(df, bin_size, smooth=False, std=default_std):
    '''if smooth, then downsample according to bin_size'''
    if smooth:
        n_stds = 3
        winsize = n_stds * std * 2 #multiple of 2 for n_stds on each side of the window
        if pad_interval:
            min_periods = None
        else:
            min_periods = 1

        return df.rolling(winsize, win_type='gaussian', min_periods=min_periods).sum(std=std).dropna(axis=0).values[::bin_size]
    else:
        return df.rolling(bin_size).sum().values[bin_size-1::bin_size]

def get_trial_segments(signal, thresh, min_segment_idx=None):
    '''Returns two arrays representing the indices of the endpoints of segments where
    signal is less than thresh. If min_segment is given, then only the segments with length
    greater than min_segment are returned'''

    starts = np.where(np.logical_and(signal[:-1] > thresh, signal[1:] <= thresh))[0] + 1
    if signal[0] <= thresh:
        starts = np.insert(starts, 0, 0)

    stops = np.where(np.logical_and(signal[:-1] <= thresh, signal[1:] > thresh))[0] + 1

    if signal[-1] <= thresh:
        stops = np.append(stops, len(signal))

    if min_segment_idx is not None:
        include_idx = stops - starts >= min_segment_idx
        starts = starts[include_idx]
        stops = stops[include_idx]

    return starts, stops

def segment_spike_counts(df, co, bin_size=bin_size, smooth=False, std=default_std):
    '''Gets spike counts for segments with minimum length autonomous'''

    assert df.index[-1][0]+1==co.shape[0]
    abs_co = np.abs(co).sum(axis=2)
    min_segment_idx = int(min_segment/lfads_dt)
    counts = []
    for i in range(co.shape[0]):
        starts, stops = get_trial_segments(abs_co[i,:], thresh, min_segment_idx=min_segment_idx)
        for start, stop in zip(starts, stops):
            if start*lfads_dt <= 6*std/1000:
                continue
            if pad_interval:
                padded_start_t = start*lfads_dt - 6*std/1000
                padded_stop_t = stop*lfads_dt
                if padded_start_t < 0:
                    import pdb;pdb.set_trace()
                segment_spikes = df.loc[i].neural.loc[padded_start_t:padded_stop_t]
                binned = bin_dataframe(segment_spikes, bin_size, smooth, std=std)
                counts.append(binned)
            else:
                segment_spikes = df.loc[i].neural.loc[start*lfads_dt:stop*lfads_dt]
                binned = bin_dataframe(segment_spikes, bin_size, smooth, std=std)
                counts.append(binned)

        print('Trial %d of %d processed'%(i+1, co.shape[0]))

    return counts

def random_intervals(df, n_intervals, interval_len, trial_len, bin_size=bin_size, smooth=False, std=default_std):

    '''
    Parameters
    df: data frame containing experiment data
    n_intervals: number of intervals
    interval_len: length of intervals to sample (in seconds)
    trial_len: length of trial given to lfads
    bin_size: bin_size in number of samples (ms)
    '''
    #making sure interval_len is integer multiple of bin_size
    assert (interval_len/(bin_size/1000))%1 == 0

    #cutting out spikes after end of trial
    df=df.groupby('trial').apply(lambda _df: bin_dataframe(_df.loc[_df.index[0][0]].loc[:trial_len].neural, bin_size, smooth, std=std))
    spikes = np.concatenate(df.values)
    k = 0
    intervals = np.zeros((n_intervals, int(interval_len/(bin_size/1000)), spikes.shape[1]))
    bin_size_s = bin_size/1000 #bin_size in seconds
    while k < n_intervals:
        start_idx = np.random.random_integers(0, spikes.shape[0])
        start_t = start_idx * bin_size_s
        stop_t = start_t + interval_len
        # don't use interval if trial boundary in interval
        if np.floor((stop_t-bin_size_s)/(trial_len-bin_size_s)) > np.floor((start_t-bin_size_s)/(trial_len-bin_size_s)):
            continue

        stop_idx = int(np.round(stop_t/(bin_size/1000)))
        interval = spikes[start_idx:stop_idx,:]
        # don't use interval if it overlaps with already sampled interval
        if np.any(np.isnan(interval)):
            continue

        intervals[k, :, :] = interval

        spikes[start_idx:stop_idx,:] = np.nan
        k += 1

    return intervals

if __name__=='__main__':
    trial_type = 'all'
    data_filename = '../data/intermediate/rockstar.p'
    lfads_filename = "/home/pmalonis/lfads_analysis/data/model_output/rockstar_8QTVEk_%s.h5"%trial_type
    with h5py.File(lfads_filename, 'r') as h5file:
        co = np.array(h5file['controller_outputs'])

    df = pd.read_pickle(data_filename)


import re
import scrapy
from scrapy.loader import ItemLoader
from ..items import BanrepItem
from itemloaders.processors import TakeFirst
import json

pattern = r'(\xa0)?'
base = 'https://admin.banrepcultural.org/api/elasticsearch?type=article_category&page={}'

class BanrepSpider(scrapy.Spider):
	name = 'banrep'
	page = 0
	start_urls = [base.format(page)]

	def parse(self, response):
		data = json.loads(response.text)
		for index in range(len(data['nodes']['article'])):
			title = data['nodes']['article'][index]['title']
			date = data['nodes']['article'][index]['date']
			link = data['nodes']['article'][index]['path']
			yield response.follow(link, self.parse_post, cb_kwargs=dict(date=date, title=title))

		if self.page < data['pagination']['all']['total']:
			self.page += 12
			yield response.follow(base.format(self.page), self.parse)

	def parse_post(self, response, date, title):
		content = response.xpath('//div[@class="news-body"]//text() | //div[@class="body field"]//text()[not (ancestor::em)] | //div[contains(@class,"field field-name")]//text()').getall()
		content = [p.strip() for p in content if p.strip()]
		content = re.sub(pattern, "",' '.join(content))

		item = ItemLoader(item=BanrepItem(), response=response)
		item.default_output_processor = TakeFirst()

		item.add_value('title', title)
		item.add_value('link', response.url)
		item.add_value('content', content)
		item.add_value('date', date)

		yield item.load_item()


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

from datetime import datetime
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError, UserError

class StationSales(models.Model):
    _name = 'station.sales'
    _description = 'Manage sales at a service station'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _rec_name = 'pump'
    _order = 'id desc'

    # This is a development only test function

    # def test(self):
    #     company_id = self.env.user.company_id
    #     print(company_id.partner_id.name)

    #     for line in self.nozzle_record_line:
    #         product = self.env['product.product'].search(
    #             [('id', '=', line.nozzle_id.inherited_id)])

    #         product_stock = self.env['stock.quant'].search(
    #             [('product_id', '=', product.id)])[0]

    #         if self.sales_mode_id == 'metres':
    #             product_stock.sudo().update({
    #                 'quantity': product_stock.quantity - line.ltrs
    #             })
    #         else:
    #             product_stock.sudo().update({
    #                 'quantity': product_stock.quantity - line.litres
    #             })

    @api.model
    def create(self, vals):
        if vals.get('invoice_ref', _('New') == _('New')):
            vals['invoice_ref'] = self.env['ir.sequence'].next_by_code(
                'station.sales.sequence') or _('New')
        result = super().create(vals)
        return result

    def unlink(self):
        for rec in self:
            if (self.state == 'invoiced') and (self.invoice_ids != []):
                raise UserError(
                    _('You can not delete an invoiced sale, consider archiving the record if you must remove it from the view.'))
        return super().unlink()

    def _prepare_invoice(self):
        journal = self.env['account.move'].with_context(
            default_type='out_invoice')._get_default_journal()

        invoice_vals = {
            'type': 'out_invoice',
            'ref': self.invoice_ref,
            'invoice_user_id': self.csa_id.id,
            'journal_id': journal.id,
            'state': 'draft',
            'invoice_date': self.date,
            'invoice_line_ids': []
        }
        return invoice_vals

    def _declare_payment_lines(self):
        return ['visa_line', 'loyalty_cards_line',
                'invoices_line', 'shell_pos_line', 'mpesa_line', 'drop_line']

    def prepare_invoice_lines(self):
        invoice_val_dicts = []
        payment_lines = self._declare_payment_lines()
        company_partner_id = self.env.user.company_id.partner_id

        for record in payment_lines:
            for rec in self[record]:
                if rec.amount > 0:
                    invoice_val_list = self._prepare_invoice()
                    invoice_val_list['partner_id'] = rec.partner_id and rec.partner_id.id or company_partner_id.id,
                    invoice_val_list['invoice_partner_bank_id'] = rec.partner_id and rec.partner_id.bank_ids[:1].id \
                        or company_partner_id.bank_ids[:1].id,
                    invoice_val_list['invoice_line_ids'] = [0, 0, {
                        'name': rec.code,
                        'account_id': 1,
                        'quantity': 1,
                        'price_unit': rec.amount,
                    }]
                    invoice_val_dicts.append(invoice_val_list)
        return invoice_val_dicts

    def generate_sale_invoices(self):
        new_invoice_vals = self.prepare_invoice_lines()

        if len(new_invoice_vals) == 0:
            raise ValidationError(
                "There is no invoicable line or the line amount, oftenly in the Cash Drop is equals to zero!")
        else:
            for record in new_invoice_vals:
                self.env['account.move'].sudo().create(dict(record))

            self.link_short_or_excess_to_csa()
            self.adjust_inventory()

            self.write({'state': 'invoiced'})

    def link_short_or_excess_to_csa(self):
        '''Shorts or excess should be pushed to the csa's account for accountability or rewarding scheme'''

        for rec in self.env['station.csa'].search([]):
            lines = []
            vals = {
                'date': self.date,
                'description': 'short' if self.short_or_excess < 0 else 'excess',
                'amount': self.short_or_excess,
            }
            lines.append((0, 0, vals))
            rec.short_line = lines if self.csa_id.id == rec.id else None

    def get_invoices_count(self):
        invoices = self.env['account.move'].search(
            [('ref', '=', self.invoice_ref)])
        self.invoices_count = len(invoices)
        self.invoice_ids = invoices

    def action_view_invoice(self):
        invoices = self.mapped('invoice_ids')
        action = self.env.ref('account.action_move_out_invoice_type').read()[0]
        if len(invoices) > 1:
            action['domain'] = [('id', 'in', invoices.ids)]
        elif len(invoices) == 1:
            form_view = [(self.env.ref('account.view_move_form').id, 'form')]
            if 'views' in action:
                action['views'] = form_view + \
                    [(state, view)
                     for state, view in action['views'] if view != 'form']
            else:
                action['views'] = form_view
            action['res_id'] = invoices.id
        else:
            action = {'type': 'ir.actions.act_window_close'}

        context = {
            'default_type': 'out_invoice',
        }
        return action

    def reset_to_draft(self):
        self.write({'state': 'draft'})

    @ api.constrains('fuel_sales', 'date')
    def approve_fuel_Sales(self):
        for rec in self:
            if rec.date.strftime('%Y-%m-%d') > fields.Datetime.now().strftime('%Y-%m-%d'):
                raise ValidationError(
                    'You cannot approve sales for a future date')

        for rec in self.nozzle_record_line:
            for record in self.env['station.nozzles'].search([]):
                record.write({'current_reading': rec.eclose}
                             ) if record.id == rec.nozzle_id.id else None

        if (self.fuel_sales == 0):
            raise ValidationError('You cannot approve zero sales!')
        else:
            self.write({'state': 'approved'})

    @ api.depends('nozzle_record_line.amount')
    def _compute_fuel_sales(self):
        for record in self:
            fuel_sales = 0
            for line in record.nozzle_record_line:
                fuel_sales += line.amount
            record.update({'fuel_sales': fuel_sales})
        return fuel_sales

    @api.model
    def adjust_inventory(self):
        for line in self.nozzle_record_line:
            product = self.env['product.product'].search(
                [('id', '=', line.nozzle_id.inherited_id)])

            product_stock = self.env['stock.quant'].search(
                [('product_id', '=', product.id)])[0]

            if self.sales_mode_id == 'metres':
                product_stock.sudo().update({
                    'quantity': product_stock.quantity - line.ltrs
                })
            else:
                product_stock.sudo().update({
                    'quantity': product_stock.quantity - line.litres
                })

    def do_taxes(self):
        total_tax = 0
        for line in self.nozzle_record_line:
            product = self.env['product.product'].search(
                [('id', '=', line.nozzle_id.inherited_id)])

            tax_ids = product.mapped(('taxes_id')).id

            tax_percentage = self.env['account.tax'].search(
                [('id', '=', tax_ids)]).mapped('amount')[0]

            taxable_amount = product.mapped('taxable_amount')[0]

            total_tax += (tax_percentage/100) * (taxable_amount * line.amount)

        return total_tax

    @ api.depends('amount_untaxed', 'amount_tax', 'visa_line.amount', 'shell_pos_line.amount',
                  'loyalty_cards_line.amount', 'mpesa_line.amount', 'drop_line.amount',
                  'invoices_line.amount')
    def _compute_total_amount(self):
        # payment_lines = self._declare_payment_lines()
        # payment_totals = ['visa_total', 'shell_pos_total', 'mpesa_total','loyalty_cards_total','invoices_total','drop_total']

        for record in self:
            visa_total = 0.0
            shell_pos_total = 0.0
            mpesa_total = 0.0
            loyalty_cards_total = 0.0
            invoices_total = 0.0
            drop_total = 0.0
            fuel_sales = record.fuel_sales
            total_credits = 0.0
            cash_required = 0.0
            short_or_excess = 0.0

            # for rec in payment_lines:
            #     for line in record[rec]:

            for line in record.visa_line:
                visa_total += line.amount

            for line in record.shell_pos_line:
                shell_pos_total += line.amount

            for line in record.mpesa_line:
                mpesa_total += line.amount

            for line in record.loyalty_cards_line:
                loyalty_cards_total += line.amount

            for line in record.invoices_line:
                invoices_total += line.amount

            for line in record.drop_line:
                drop_total += line.amount

            total_credits = visa_total + invoices_total + \
                mpesa_total + shell_pos_total + loyalty_cards_total

            cash_required = fuel_sales - total_credits
            short_or_excess = drop_total - cash_required

            amount_untaxed = total_credits + drop_total
            amount_tax = self.do_taxes()

            short_or_excess_display = '{:+}'.format(short_or_excess)

            record.update({
                'visa_total': visa_total,
                'shell_pos_total': shell_pos_total,
                'loyalty_cards_total': loyalty_cards_total,
                'mpesa_total': mpesa_total,
                'invoices_total': invoices_total,
                'drop_total': drop_total,
                'amount_untaxed': amount_untaxed,
                'amount_tax': amount_tax,
                'amount_total': amount_untaxed + amount_tax,
                'total_credits': total_credits,
                'cash_required': cash_required,
                'short_or_excess': short_or_excess,
                'short_or_excess_display': short_or_excess_display,
            })

    @ api.onchange('pump')
    def _onchange_pump_create_nozzles(self):
        for rec in self:
            lines = [(5, 0, 0)]
            for nozzle in self.pump.nozzle_line:
                val = {
                    'nozzle_id': nozzle,
                    'price': nozzle.price,
                    'eopen': nozzle['current_reading']
                }
                lines.append((0, 0, val))
            rec.nozzle_record_line = lines

    @ api.onchange('csa_id')
    def _onchange_csa_id_filter_pump(self):
        for rec in self:
            return {'domain':
                    {'pump': ['&', ('station_id', '=', rec.csa_id.station_id.id), ('is_active', '=', True)]}}

    @ api.onchange('csa_id')
    def _onchange_csa_id_update_dropby(self):
        for rec in self:
            # THIS WILL CLEAR LINES INCASE CSA CHANGES, OTHERWISE IT WILL ADD NEW CSA TO NEXT LINE
            lines = [(5, 0, 0)]
            rec.station_id = self.csa_id.station_id
            rec.sales_mode_id = self.station_id.sales_mode_id
            val = {
                'code': '0000',
                'drop_by': self.csa_id
            }
            lines.append((0, 0, val))
            rec.drop_line = lines

    station_id = fields.Many2one(
        'station.stations', string='Station')
    csa_id = fields.Many2one('station.csa', string='CSA', required=True)
    pump = fields.Many2one('station.pump', string='Pump', required=True)
    date = fields.Date(
        string='Date', default=fields.Datetime.now, required=True)
    amount_untaxed = fields.Monetary(string='Untaxed Amount', readonly=True)
    amount_tax = fields.Monetary(string='Tax Amount', readonly=True)
    currency_id = fields.Many2one('res.currency')
    amount_total = fields.Monetary(
        string='Total Amount', readonly=True)
    fuel_sales = fields.Monetary(string='Fuel Sales', track_visibility='onchange',
                                 compute='_compute_fuel_sales')
    total_credits = fields.Monetary(string='Total Credits', readonly=True)
    cash_required = fields.Monetary(
        string='Cash Required', track_visibility='onchange', readonly=True)
    short_or_excess = fields.Monetary(string='Short/ Excess', readonly=True)
    short_or_excess_display = fields.Char(
        string='Short/ Excess', readonly=True)

    visa_line = fields.One2many('visa.line', 'visa_id', string='Visa Line')
    shell_pos_line = fields.One2many(
        'shell.pos.line', 'shell_pos_id', string='Shell Pos Line')
    loyalty_cards_line = fields.One2many(
        'loyalty.cards.line', 'loyalty_cards_id', string='Loyalty Cards Line')
    mpesa_line = fields.One2many('mpesa.line', 'mpesa_id', string='Mpesa Line')
    invoices_line = fields.One2many(
        'invoices.line', 'invoices_id', string='Invoices Line')
    drop_line = fields.One2many('drop.line', 'drop_id', string='Drop Line')
    nozzle_record_line = fields.One2many(
        'nozzle.record.line', 'nozzle_record_id', string='Nozzle Record Line')
    visa_total = fields.Monetary(string='Visa Total', compute='_compute_total_amount',
                                 track_visibility='onchange', store=True, readonly=True)
    shell_pos_total = fields.Monetary(
        string='Shell Pos Total', compute='_compute_total_amount', readonly=True, store=True)
    loyalty_cards_total = fields.Monetary(
        string='Loyalty Cards Total', compute='_compute_total_amount', readonly=True, store=True)
    mpesa_total = fields.Monetary(
        string='Mpesa Total', compute='_compute_total_amount', readonly=True, store=True)
    invoices_total = fields.Monetary(
        string='Invoices Total', compute='_compute_total_amount', readonly=True, store=True)
    drop_total = fields.Monetary(
        string='Cash Drop Total', compute='_compute_total_amount', readonly=True, store=True)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('approved', 'To Be Invoiced'),
        ('invoiced', 'Invoiced'),
    ], string='Status', readonly=True, index=True, copy=False, default='draft', track_visibility='onchange')
    shift_id = fields.Selection(
        [('morning', 'Morning'), ('night', 'Night')], string='Shift', required=True)
    invoices_count = fields.Integer(
        string='Invoices', compute="get_invoices_count")
    invoice_ref = fields.Char(string='Ref')
    sales_mode_id = fields.Selection(string='Choice', selection=[
        ('metres', 'Metres'), ('litres', 'Litres')])

    invoice_ids = fields.Many2many(
        "account.move", string='Invoices', compute="get_invoices_count", readonly=True, copy=False)


class Solution:
    def missingNumber(self, nums: list[int]) -> int:
        my_dict = {}
        for i, n in enumerate(nums):
            my_dict[n] = 0
        for i in range(len(nums)+1):
            if i not in my_dict:
                return i

nums = [3, 0, 1]
print(Solution(). missingNumber(nums=nums, ))


class Solution(object):
    def twoSum(self, nums, target):
        # l = []
        # for i in range(len(nums)):
        #     for j in range(len(nums)):
        #         if i == j :
        #             continue
        #         if nums[i] + nums[j] == target :
        #             l.append(i)
        #             l.append(j)
        #             return l
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        for i, value in enumerate(nums):
            complement = target - value

            if complement in nums[i+1:]:
                return nums.index(value), nums[i+1:].index(complement)+i+1


# /**
#  * @author [Limm-jk]
#  * @email [201602057@cs-cnu.org]
#  * @create date 2020-03-20 14:57:03
#  * @modify date 2020-03-20 14:57:03
#  * @desc [LCS]
#  */

arr1 = (list(input()))
arr2 = (list(input()))

DParr = [[0]*(len(arr2)+1) for i in range(len(arr1)+1)]

for i in range(1,len(arr1)+1):
    for j in range(1,len(arr2)+1):
        DParr[i][j] = max(DParr[i-1][j],DParr[i][j-1])
        if arr1[i-1] == arr2[j-1]:
            DParr[i][j] = DParr[i-1][j-1] + 1

print(DParr[len(arr1)][len(arr2)])


import mido
import torch
import NeuralNetUtils as nnu
import MusicTheoryUtils as mtu
import random

ticksPerBeat=480

class WeightedNumberPicker:
	def __init__(self,lowerBounds,upperBounds,probabilities):
		self.lowerBounds=lowerBounds
		self.upperBounds=upperBounds
		self.probabilities=probabilities

	def getValue(self):
		currentPercent=0
		choice=random.randint(1,100)
		for i,prob in enumerate(self.probabilities):
			currentPercent+=prob*100
			if choice <= currentPercent:
				return random.randint(self.lowerBounds[i],self.upperBounds[i])

def percentPicker(numOfNotes):
	if numOfNotes == 1 or numOfNotes == 2:
		return 1
	elif numOfNotes == 3:
		return 2/3
	elif numOfNotes == 4 or numOfNotes == 5:
		return (numOfNotes-2+random.randint(0,1))/numOfNotes
	elif numOfNotes == 6:
		return 4/6
	else:
		return 0.70

class InstrumentSection:
	def __init__(self,sectionName):
		self.sectionName=sectionName
		self.numOfBars=0
		self.numOfRepetitions=1
		self.creationLog=[]
		self.bars=[]
		self.beatsInBars=[]
		self.subDivisionsPerBeats=[]
		self.sectionEndTimeDelta=0
		self.formattedBars=[]
		self.msgs=[]
		self.chosenRhythm=[]
		self.chosenMelody=[]
		self.chosenVelocities=[]
		self.chosenDurations=[]

	def formatBars(self,noteOverlapFlag,chromaticFrequencyFactor,chromaticSizeRange,slideFrequencyFactor,slideSizeRange,nextNote):
	#making nextNote negative will mean it is ignored, useful for the end of a piece
		flattenBars=[]
		barBeats=0
		for i,bar in enumerate(self.bars):
			for j, nE in enumerate(bar):
				flattenBars.append([barBeats+bar[j][0],bar[j][1],bar[j][2],bar[j][3]])
			barBeats+=self.beatsInBars[i]
		if nextNote >= 0:
			flattenBars.append([barBeats,nextNote,0,0])

		if not noteOverlapFlag:
			for i,nE in enumerate(flattenBars[:-1]):
				if flattenBars[i][0]+flattenBars[i][3] >= flattenBars[i+1][0]:
					flattenBars[i][3]=flattenBars[i+1][0]-flattenBars[i][0]

		sliding=False
		for i,nE in enumerate(flattenBars[:-1]):
			if sliding:
				sliding=False
			else:
				noteDifference=abs(flattenBars[i+1][1]-flattenBars[i][1])
				travelDirection=1
				if flattenBars[i][1] > flattenBars[i+1][1]:
					travelDirection=-1
				if not noteDifference == 0:
					timeInterval=(flattenBars[i+1][0]-flattenBars[i][0])/noteDifference
				if noteDifference in chromaticSizeRange and chromaticFrequencyFactor.getValue() == 1:
					for j in range(0,noteDifference):
						self.formattedBars.append([0,flattenBars[i][0]+j*timeInterval,flattenBars[i][1]+travelDirection*j,flattenBars[i][2],flattenBars[i][3]/noteDifference])
				elif noteDifference in slideSizeRange and slideFrequencyFactor.getValue() == 1:
					self.formattedBars.append([1,flattenBars[i][0],flattenBars[i][1],flattenBars[i+1][2],travelDirection,noteDifference,timeInterval,flattenBars[i+1][3]])
					sliding=True
				else:
					self.formattedBars.append([0]+flattenBars[i])

		#[NoteOrSlideFlag(=0),BeatsSinceSectionStart,Note,Velocity,Duration]
		#[NoteOrSlideFlag(=1),BeatsSinceSectionStart,StartNote,Velocity,TravelDirection,SlideSize,TimePerSemi,FinishDuration]

	def convertToMidi(self,startTime,channelNum,instrumentSound,ticksPerInstrumentBeat):
		toConvert=[]
		time=startTime
		finalBarStart=0
		roundedTime=0
		for i,note in enumerate(self.formattedBars):
			if note[0] == 0:
				toConvert.append([1,int(ticksPerInstrumentBeat*note[1]),note[2],note[3]])
				toConvert.append([0,int(ticksPerInstrumentBeat*(note[1]+note[4])),note[2],0])
			else:
				toConvert.append([2,int(ticksPerInstrumentBeat*note[1])]+note[2:6]+[int(ticksPerInstrumentBeat*note[6]),int(ticksPerInstrumentBeat*note[7])])
		toConvert.sort(key=lambda x: x[1])

		prevTime=-startTime
		self.msgs=[mido.Message('program_change', program=instrumentSound, channel=channelNum, time=0)]
		for i,event in enumerate(toConvert):
			types=["note_off","note_on"]
			deltaTime=max(0,event[1]-prevTime)
			if event[0] == 2:
				self.msgs.append(mido.Message("note_on",time=deltaTime,channel=channelNum,note=event[2],velocity=event[3]))
				self.msgs.append(mido.Message("control_change",time=0,channel=channelNum,control=101,value=0))
				self.msgs.append(mido.Message("control_change",time=0,channel=channelNum,control=100,value=0))
				self.msgs.append(mido.Message("control_change",time=0,channel=channelNum,control=6,value=event[5]))
				for j in range(1,event[5]+1):
					self.msgs.append(mido.Message("pitchwheel",time=int(event[6]/2),channel=channelNum,pitch=round(event[4]*(j-0.5)*(8191.5/event[5])-0.5)))
					self.msgs.append(mido.Message("pitchwheel",time=int(event[6]/2),channel=channelNum,pitch=round(event[4]*j*(8191.5/event[5])-0.5)))
				self.msgs.append(mido.Message("note_off",time=event[7],channel=channelNum,note=event[2],velocity=0))
				self.msgs.append(mido.Message("pitchwheel",time=0,channel=channelNum,pitch=0))
				prevTime=event[1]+event[5]*event[6]+event[7]
			else:
				self.msgs.append(mido.Message(types[event[0]],time=deltaTime,channel=channelNum,note=event[2],velocity=event[3]))
				prevTime=event[1]
		self.sectionEndTimeDelta=sum(self.beatsInBars)*ticksPerInstrumentBeat-prevTime

class MelodyInstrumentSection(InstrumentSection):

	def __init__(self,sectionName,minNote,maxNote,melodyNet):
		InstrumentSection.__init__(self,sectionName)
		self.melodyNet=melodyNet
		self.minNote=minNote
		self.maxNote=maxNote

	def addProgressionBars(self,chords,scales,beatsInBar,subDivsPerBeat,
	div1Of4Factor,div3Of4Factor,div2Or4Of4Factor,
	div1Of3Factor,div2Of3Factor,div3Of3Factor,
	octaveRangeFactor,directionChangeFactor,
	durationRange,velocityRange):
		numOfBars=len(chords)
		self.beatsInBars.extend([beatsInBar]*numOfBars)
		noteCount=0
		notesPerBar=[]
		chosenRhythm=[]
		chosenMelody=[]
		chosenDurations=[]
		chosenVelocities=[]

		def addNoteToRhythmChance(noteCount,currentTime,factor,subDivs):
			if factor.getValue() == 1:
				chosenRhythm.append(currentTime)
				noteCount+=1
			currentTime+=1/subDivs
			return noteCount, currentTime

		for i in range(numOfBars):
			currentTime=0
			prevBarNoteCount=noteCount
			for j in range(beatsInBar):
				subDivisionRemainingCount=subDivsPerBeat
				if subDivisionRemainingCount == 1:
					noteCount, currentTime =addNoteToRhythmChance(noteCount,currentTime,div1Of4Factor,subDivsPerBeat)
				else:
					smallestChunkSize=2
					if subDivsPerBeat == 3 or subDivsPerBeat == 4:
						smallestChunkSize=subDivsPerBeat
					while subDivisionRemainingCount > 0:
						divChunkSize=random.randint(smallestChunkSize,min(4,subDivisionRemainingCount))
						if subDivisionRemainingCount == divChunkSize+1:
							if subDivisionRemainingCount == 5:
								divChunkSize=random.randint(2,3)
							else:
								divChunkSize=subDivisionRemainingCount
						subDivisionRemainingCount-=divChunkSize
						if divChunkSize == 4:
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div1Of4Factor,subDivsPerBeat)
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div2Or4Of4Factor,subDivsPerBeat)
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div3Of4Factor,subDivsPerBeat)
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div2Or4Of4Factor,subDivsPerBeat)
						elif divChunkSize == 3:
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div1Of3Factor,subDivsPerBeat)
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div2Of3Factor,subDivsPerBeat)
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div3Of3Factor,subDivsPerBeat)
						else:
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div1Of4Factor,subDivsPerBeat)
							noteCount, currentTime = addNoteToRhythmChance(noteCount,currentTime,div3Of4Factor,subDivsPerBeat)
			notesPerBar.append(noteCount-prevBarNoteCount)
		if noteCount > 0:
			scaleNotes=[]
			for i in range(numOfBars):
				scaleNotes.append([(interval+chords[i].rootNote) % 12 for interval in scales[i]])
			blendNoteDepth=0
			potentialIntervals=[]
			for i in range(numOfBars):
				# print("writing bar {}".format(i))
				attemptsPerBlendDepth=25
				suitableNoteChoice=False
				while not suitableNoteChoice:
					# print("notes in current bar {}".format(notesPerBar[i]))
					while len(potentialIntervals) < notesPerBar[i]:
						blendNoteDepth=min(self.melodyNet.numNotesOut,len(potentialIntervals))
						attempts=0
						blendSearching=True
						while blendSearching:
							if blendNoteDepth > 0 and attempts == attemptsPerBlendDepth:
								attempts=0
								blendNoteDepth-=1
							attempts+=1
							genOut=self.melodyNet(torch.randn(1,self.melodyNet.noiseDim))
							generatedNotes=[]
							for oneHotNote in genOut:
								generatedNotes.append(oneHotNote[0].tolist().index(1))
							# print("generatedNotes: {}".format(generatedNotes))
							# print("generatedNotes[:blendNoteDepth] {}".format(generatedNotes[:blendNoteDepth]))
							# print("potentialIntervals {}".format(potentialIntervals))
							# print("potentialIntervals[-blendNoteDepth:] {}".format(potentialIntervals[-blendNoteDepth:]))
							# print("blend note depth {}".format(blendNoteDepth))
							# input()
							blendSearching=not (blendNoteDepth == 0 or generatedNotes[:blendNoteDepth] == potentialIntervals[-blendNoteDepth:])
						potentialIntervals.extend(generatedNotes[blendNoteDepth:])
						# print("potentialIntervals {}".format(potentialIntervals))
					suitableNotes=0
					potentialNotes=[]
					currentNote=chords[0].rootNote
					if chosenMelody:
						currentNote=chosenMelody[-1]
					direction=random.randint(0,1)
					# print(potentialIntervals[:notesPerBar[i]])
					for interval in potentialIntervals[:notesPerBar[i]]:
						if (currentNote+interval) % 12 in scaleNotes[i]:
							suitableNotes+=1
						currentNote+=interval+6*direction*(2*octaveRangeFactor.getValue()+1)-6
						while currentNote < self.minNote:
							currentNote+=12
						while currentNote > self.maxNote:
							currentNote-=12
						# print(currentNote)
						potentialNotes.append(currentNote)
						if directionChangeFactor.getValue() == 1:
							direction=direction-2*direction
					# input()
					# print("suitable notes {}".format(suitableNotes))
					if suitableNotes == 0:
						suitableNoteChoice=(notesPerBar[i] == 0)
					else:
						suitableNoteChoice=(suitableNotes/notesPerBar[i] >= percentPicker(notesPerBar[i]))
					# print("suitableNoteChoice {}".format(suitableNoteChoice))
					if not suitableNoteChoice:
						potentialIntervals=[]
						# print("potentialIntervals {}".format(potentialIntervals))
						# input()
					# if suitableNoteChoice:
						# print("yay")
						# input()
				chosenMelody.extend(potentialNotes[:])
				# print("chosenMelody {}".format(chosenMelody))
				potentialIntervals=potentialIntervals[notesPerBar[i]:]
				# print("remaining potentialIntervals {}".format(potentialIntervals))
				# input()

			for i in range(noteCount):
				chosenVelocities.append(random.randint(*velocityRange))
				chosenDurations.append(random.randint(*durationRange)/subDivsPerBeat)

		prevNoteCount=0
		for nPB in notesPerBar:
			bar=[]
			for i in range(prevNoteCount,prevNoteCount+nPB):
				bar.append([chosenRhythm[i],chosenMelody[i],chosenVelocities[i],chosenDurations[i]])
			prevNoteCount+=nPB
			self.bars.append(bar)

class PercussionInstrumentSection(InstrumentSection):

	def __init__(self,sectionName,melodyNet):
		InstrumentSection.__init__(self,sectionName)
		self.melodyNet=melodyNet
		self.sectionSkeleton=[]

	def getModifiedSkeleton(self,skeleton,removeChance,addChance,addPercussionGroups,melodyChoiceFactor,velocity):
		newSkeleton=skeleton
		numDivs=skeleton[0]*skeleton[1]
		for i in range(numDivs):
			newSkeleton[2][i]=[elem for elem in skeleton[2][i] if random.randint(1,100) > removeChance]
		netInp=[]
		emptyCount=0
		while len(netInp) < self.melodyNet.layerSizes[0] and emptyCount < numDivs:
			emptyCount=0
			for subDiv in newSkeleton[2]:
				if subDiv:
					drumHits=[0]*self.melodyNet.layerSizes[-1]
					for beat in subDiv:
						drumHits[mtu.lookUpDrumType(beat[0])[0]]=1
					netInp.extend(drumHits)
				else:
					emptyCount+=1
		if emptyCount < numDivs:
			netInp=netInp[-self.melodyNet.layerSizes[0]:]
			for i in range(numDivs):
				if random.randint(1,100) <= addChance:
					self.melodyNet.forwardPropagation(netInp,[0]*self.melodyNet.layerSizes[-1])
					possibleGroups=[group for group in nnu.getIndexesOfSortedList(self.melodyNet.outputs[-1])[:melodyChoiceFactor.getValue()] if group in addPercussionGroups]
					addGroup=random.choice(addPercussionGroups)
					if possibleGroups:
						addGroup=random.choice(possibleGroups)
					hitNote=random.choice(mtu.lookUpDrumCategory(addGroup))[1]
					newSkeleton[2][i].append([hitNote,velocity])
				drumHits=[0]*self.melodyNet.layerSizes[-1]
				for beat in newSkeleton[2][i]:
					drumHits[mtu.lookUpDrumType(beat[0])[0]]=1
				netInp=netInp[self.melodyNet.layerSizes[-1]:]
				netInp.extend(drumHits)
		return newSkeleton

	def setSectionSkeleton(self,skeleton,removeChance,addChance,addPercussionGroups,melodyChoiceFactor,velocity):
		self.sectionSkeleton=self.getModifiedSkeleton(skeleton,removeChance,addChance,addPercussionGroups,melodyChoiceFactor,velocity)

	def addBar(self,removeChance,addChance,addPercussionGroups,melodyChoiceFactor,velocity,fillSkeleton=[]):
		self.numOfBars+=1
		newBeats=self.getModifiedSkeleton(self.sectionSkeleton,removeChance,addChance,addPercussionGroups,melodyChoiceFactor,velocity)
		if fillSkeleton:
			newBeats=self.getModifiedSkeleton(fillSkeleton,removeChance,addChance,addPercussionGroups,melodyChoiceFactor,velocity)
		beatsInBar=newBeats[0]
		subDivsPerBeat=newBeats[1]
		self.beatsInBars.append(beatsInBar)
		self.subDivisionsPerBeats.append(subDivsPerBeat)
		subDivTimeDelta=1/subDivsPerBeat
		bar=[]
		for i in range(beatsInBar):
			for j in range(subDivsPerBeat):
				hitStartTime=i+j*subDivTimeDelta
				for beat in newBeats[2][i*subDivsPerBeat+j]:
					bar.append([hitStartTime,*beat,1])
		self.bars.append(bar)

class AccompanyInstrumentSection(InstrumentSection):
	def __init__(self,sectionName):
		InstrumentSection.__init__(self,sectionName)

	def addBar(self,chord,beatsInBar,subDivisionsPerBeat,velocity):
		self.numOfBars+=1
		self.beatsInBars.append(beatsInBar)
		self.subDivisionsPerBeats.append(subDivisionsPerBeat)
		bar=[]
		for note in chord.chordIntervals:
			bar.append([0,note+chord.rootNote,velocity,beatsInBar])
		self.bars.append(bar)

def combineMidi(midiTracks,saveName):
	mid = mido.MidiFile()
	for midiTrack in midiTracks:
		track = mido.MidiTrack()
		mid.tracks.append(track)
		for msg in midiTrack:
			track.append(msg)
	mid.save(saveName)

cuda=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

melodyModel_5304 = nnu.NoteGenerator(5,144,4,8,0.1,cuda)
melodyModel_5304.load_state_dict(torch.load("trained networks/5304.pt",map_location='cpu'))
melodyModel_5304.eval()

melodyModel_5305 = nnu.NoteGenerator(5,144,4,7,0.1,cuda)
melodyModel_5305.load_state_dict(torch.load("trained networks/5305.pt",map_location='cpu'))
melodyModel_5305.eval()

melodyModel_5306 = nnu.NoteGenerator(5,144,4,9,0.1,cuda)
melodyModel_5306.load_state_dict(torch.load("trained networks/5306.pt",map_location='cpu'))
melodyModel_5306.eval()

melodyModel_6276=nnu.NoteGenerator(5,144,1,8,0.1,cuda)
checkpoint = torch.load("trained networks/6276.pt",map_location='cpu')
melodyModel_6276.load_state_dict(checkpoint['model_state_dict'])
melodyModel_6276.eval()

drumsNet=nnu.VanillaNeuralNet([44,44,44,22,11,11])
drumsNet.readFromcsv('trained networks/d3.csv')


from sklearn.preprocessing import StandardScaler
from sklearn.metrics.pairwise import rbf_kernel
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from scipy.stats import randint as sp_randint
import numpy as np
from sklearn.base import BaseEstimator

from typing import Tuple, Optional

from sklearn.utils import gen_batches
from sklearn.metrics import r2_score, mean_absolute_error

def svm_naive(
    X_train, y_train, n_grid: int = 20, class_weight=None, **kwargs
) -> BaseEstimator:
    """ Naive implementation of the Support Vector Machine
      classifcation function in the scikit-learn package. It
      returns all of the necessary things needed to analyze the
      results and possibly reuse the trained SVC model.

      Parameters
      ----------
      X_train : array, (N x D)
            an array of training points

      y_train : array, (N x 1)
            an array of labels for the training points

      n_grid : int, default=100
            the number of grid points to use for the parameter grid

      kwargs : dict
            a dictionary of keyword arguments to use for the gridsearch.
            Please see the sklearn.svm.SVC function for more details
            on the available arguments

      Returns
      -------

      model : class,
            a class of the SVMModel.

      Information
      -----------
      Author: J. Emmanuel Johnson
      Email : jej2744@rit.edu
            : emanjohnson91@gmail.com
      Date  : 11th April, 2017
      """

    # initialize the SVC model with the rbf kernel
    svm_model = SVC(kernel="rbf", random_state=123, class_weight=class_weight)

    # perform cross validation
    # define the parameter space for C and Gamma
    param_grid = {
        "C": np.linspace(0.01, 20, num=n_grid),
        "gamma": np.linspace(0.01, 20, num=n_grid),
    }

    cv_model = GridSearchCV(estimator=svm_model, param_grid=param_grid, **kwargs)

    # run cross validation model
    cv_model.fit(X_train, y_train)

    return cv_model.best_estimator_

def predict_batches(
    model, der_model, X: np.ndarray, y: np.ndarray, batch_size: Optional[int] = 1_000,
) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]:

    # get samples
    n_samples = X.shape[0]

    # initialize lists to store
    predictions = []
    decision_derivatives = []
    objective_derivatives = []
    mask_derivatives = []
    kernel_derivatives = []
    derivatives = []

    for idx in gen_batches(n_samples, batch_size):

        # Make Predictions on batch
        x_batch = X[idx]
        y_batch = y[idx]

        # get relevant stats
        ypred = model.predict(x_batch)

        # decision function
        decision_derivatives.append(der_model.decision_derivative(x_batch))
        objective_derivatives.append(der_model.objective_derivative(x_batch))
        mask_derivatives.append(der_model.mask_derivative(x_batch))
        kernel_derivatives.append(der_model.kernel_derivative(x_batch))
        derivatives.append(der_model(x_batch))
        predictions.append(ypred)

    # concatenate lists to arrays
    predictions = np.concatenate(predictions)
    derivatives = np.concatenate(derivatives)
    decision_derivatives = np.concatenate(decision_derivatives)
    objective_derivatives = np.concatenate(objective_derivatives)
    mask_derivatives = np.concatenate(mask_derivatives)
    kernel_derivatives = np.concatenate(kernel_derivatives)

    return (
        predictions,
        derivatives,
        decision_derivatives,
        objective_derivatives,
        mask_derivatives,
        kernel_derivatives,
    )


"""
:Author: Stefan Feuz; http://www.laboratoridenvol.com
:License: General Public License GNU GPL 3.0
"""
import logging

from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QMdiSubWindow, QWidget, QSizePolicy, QVBoxLayout, \
                            QHeaderView, QHBoxLayout

from gui.GlobalDefinition import Regex, ValidationValues
from gui.elements.TableView import TableView
from gui.elements.WindowBtnBar import WindowBtnBar
from gui.elements.WindowHelpBar import WindowHelpBar
from Singleton.Singleton import Singleton

from data.procModel.WingModel import WingModel

class BasicData(QMdiSubWindow, metaclass=Singleton):
    """
    :class: Window to display and edit the Basic Data
    """

    __className = 'ProcBasicData'
    '''
    :attr: Does help to indicate the source of the log messages
    '''

    def __init__(self):
        """
        :method: Class initialization
        """
        super().__init__()

        self.win = None
        self.window_ly = None
        self.helpBar = None
        self.numbers_t = None
        self.alpha_t = None
        self.type_t = None
        self.btnBar = None

        self.wing_M = WingModel()
        self.wing_M.dataChanged.connect(self.check_num_cells_ribs)

        self.build_window()

    def closeEvent(self, event):  # @UnusedVariable
        """
        :method: Called at the time the user closes the window.
        """
        pass

    def build_window(self):
        """
        :method: Creates the window including all GUI elements.

        Structure::

            window
                window_ly
                     Tables
                    -------------------------
                                | help_bar
                                | btn_bar
        """
        self.setWindowIcon(QIcon('gui/elements/appIcon.ico'))
        self.win = QWidget()
        self.setWidget(self.win)
        self.win.setMinimumSize(400, 300)

        self.window_ly = QVBoxLayout()

        self.helpBar = WindowHelpBar()

        #############################
        # Add window specifics here
        self.setWindowTitle(_("Basic Data"))

        # Brand name
        brand_name_t = TableView()
        brand_name_t.setModel(self.wing_M)

        for i in range(WingModel.WingNameCol,
                       self.wing_M.columnCount()):
            brand_name_t.hideColumn(i)
        brand_name_t.verticalHeader().setVisible(False)
        brand_name_t.horizontalHeader().\
            setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        brand_name_t.setFixedHeight(2
                                    + brand_name_t.horizontalHeader().height()
                                    + brand_name_t.rowHeight(0))

        brand_name_t.set_help_bar(self.helpBar)
        brand_name_t.set_help_text(WingModel.BrandNameCol,
                                   _('Proc-BrandNameDesc'))

        brand_name_t.en_reg_exp_validator(WingModel.BrandNameCol,
                                          WingModel.BrandNameCol,
                                          Regex.BrandNameString)

        self.window_ly.addWidget(brand_name_t)

        # Wing name
        wing_name_t = TableView()
        wing_name_t.setModel(self.wing_M)

        wing_name_t.hideColumn(0)
        for i in range(WingModel.DrawScaleCol,
                       self.wing_M.columnCount()):
            wing_name_t.hideColumn(i)
        wing_name_t.verticalHeader().setVisible(False)
        wing_name_t.horizontalHeader().\
            setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        wing_name_t.setFixedHeight(2
                                   + wing_name_t.horizontalHeader().height()
                                   + wing_name_t.rowHeight(0))

        wing_name_t.set_help_bar(self.helpBar)
        wing_name_t.set_help_text(WingModel.WingNameCol,
                                  _('Proc-WingNameDesc'))

        wing_name_t.en_reg_exp_validator(WingModel.WingNameCol,
                                         WingModel.WingNameCol,
                                         Regex.WingNameString)

        self.window_ly.addWidget(wing_name_t)

        # Scales
        scales_t = TableView()
        scales_t.setModel(self.wing_M)

        for i in range(WingModel.BrandNameCol,
                       WingModel.WingNameCol + 1):
            scales_t.hideColumn(i)
        for i in range(WingModel.NumCellsCol,
                       self.wing_M.columnCount()):
            scales_t.hideColumn(i)
        scales_t.verticalHeader().setVisible(False)
        scales_t.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        scales_t.setFixedHeight(2 + scales_t.horizontalHeader().height()
                                + scales_t.rowHeight(0))

        scales_t.set_help_bar(self.helpBar)
        scales_t.set_help_text(WingModel.DrawScaleCol,
                               _('Proc-DrawScaleDesc'))
        scales_t.set_help_text(WingModel.WingScaleCol,
                               _('Proc-WingScaleDesc'))

        scales_t.en_double_validator(WingModel.DrawScaleCol,
                                     WingModel.WingScaleCol,
                                     ValidationValues.Proc.ScaleMin,
                                     ValidationValues.Proc.ScaleMax,
                                     10)

        self.window_ly.addWidget(scales_t)

        # numbers
        self.numbers_t = TableView()
        self.numbers_t.setModel(self.wing_M)

        for i in range(WingModel.BrandNameCol,
                       WingModel.WingScaleCol + 1):
            self.numbers_t.hideColumn(i)
        for i in range(WingModel.AlphaMaxTipCol,
                       self.wing_M.columnCount()):
            self.numbers_t.hideColumn(i)
        self.numbers_t.verticalHeader().setVisible(False)
        self.numbers_t.horizontalHeader().\
            setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        self.numbers_t.setFixedHeight(
            2
            + self.numbers_t.horizontalHeader().height()
            + self.numbers_t.rowHeight(0))

        self.numbers_t.en_int_validator(WingModel.NumCellsCol,
                                        WingModel.NumRibsCol,
                                        1, ValidationValues.MaxNumCells)

        self.numbers_t.set_help_bar(self.helpBar)
        self.numbers_t.set_help_text(WingModel.NumCellsCol,
                                     _('Proc-NumCellsDesc'))
        self.numbers_t.set_help_text(WingModel.NumRibsCol,
                                     _('Proc-NumRibsDesc'))

        self.window_ly.addWidget(self.numbers_t)

        # alpha max and param
        self.alpha_t = TableView()
        self.alpha_t.setModel(self.wing_M)

        for i in range(WingModel.BrandNameCol,
                       WingModel.NumRibsCol + 1):
            self.alpha_t.hideColumn(i)
        for i in range(WingModel.ParaTypeCol,
                       self.wing_M.columnCount()):
            self.alpha_t.hideColumn(i)
        self.alpha_t.verticalHeader().setVisible(False)
        self.alpha_t.horizontalHeader().\
            setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        self.alpha_t.setFixedHeight(2
                                    + self.alpha_t.horizontalHeader().height()
                                    + self.alpha_t.rowHeight(0))

        self.alpha_t.set_help_bar(self.helpBar)
        self.alpha_t.set_help_text(WingModel.AlphaModeCol,
                                   _('Proc-AlphaModeDesc'))
        self.alpha_t.set_help_text(WingModel.AlphaMaxCentCol,
                                   _('Proc-AlphaMaxCentDesc'))
        self.alpha_t.set_help_text(WingModel.AlphaMaxTipCol,
                                   _('Proc-AlphaMaxTipDesc'))

        self.alpha_t.en_double_validator(WingModel.AlphaMaxTipCol,
                                         WingModel.AlphaMaxTipCol,
                                         ValidationValues.Proc.AlphaMaxTipMin,
                                         ValidationValues.Proc.AlphaMaxTipMax,
                                         1)
        self.alpha_t.en_int_validator(WingModel.AlphaModeCol,
                                      WingModel.ParaParamCol,
                                      0, 2)
        self.alpha_t.en_double_validator(WingModel.AlphaMaxCentCol,
                                         WingModel.AlphaMaxCentCol,
                                         ValidationValues.Proc.AlphaMaxCentMin,
                                         ValidationValues.Proc.AlphaMaxCentMax,
                                         1)

        self.window_ly.addWidget(self.alpha_t)

        # para type and param
        self.type_t = TableView()
        self.type_t.setModel(self.wing_M)

        for i in range(WingModel.BrandNameCol,
                       WingModel.AlphaMaxCentCol + 1):
            self.type_t.hideColumn(i)
        for i in range(WingModel.LinesConcTypeCol,
                       self.wing_M.columnCount()):
            self.type_t.hideColumn(i)
        self.type_t.verticalHeader().setVisible(False)
        self.type_t.horizontalHeader().\
            setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        self.type_t.setFixedHeight(2
                                   + self.type_t.horizontalHeader().height()
                                   + self.type_t.rowHeight(0))

        self.type_t.set_help_bar(self.helpBar)
        self.type_t.set_help_text(WingModel.ParaTypeCol,
                                  _('Proc-ParaTypeDesc'))
        self.type_t.set_help_text(WingModel.ParaParamCol,
                                  _('Proc-ParaParamDesc'))

        self.type_t.en_reg_exp_validator(WingModel.ParaTypeCol,
                                         WingModel.ParaTypeCol,
                                         Regex.ParaTyp)
        self.type_t.en_int_validator(WingModel.ParaParamCol,
                                     WingModel.ParaParamCol,
                                     0, 1)

        self.window_ly.addWidget(self.type_t)

        #############################
        # Commons for all windows
        self.btnBar = WindowBtnBar(0b0101)
        self.btnBar.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Fixed,
                                              QSizePolicy.Policy.Fixed))
        self.btnBar.my_signal.connect(self.btn_press)
        self.btnBar.set_help_page('proc/basicData.html')

        bottom_layout = QHBoxLayout()
        bottom_layout.addStretch()
        bottom_layout.addWidget(self.helpBar)
        bottom_layout.addWidget(self.btnBar)
        self.window_ly.addLayout(bottom_layout)

        self.win.setLayout(self.window_ly)

    def check_num_cells_ribs(self, q):
        """
        :method: The difference between NumCells and NumRibs must be 1, if
                 this is not the case we have a nonsense setup
        """
        if q.column() == self.wing_M.NumRibsCol \
                or q.column() == self.wing_M.NumCellsCol:
            try:
                num_cells = int(self.wing_M.index(
                    0,
                    self.wing_M.NumCellsCol).data())
                num_ribs = int(self.wing_M.index(
                    0,
                    self.wing_M.NumRibsCol).data())
            except:
                return

            cells = isinstance(num_cells, int)
            ribs = isinstance(num_ribs, int)

            if cells and ribs:
                diff = abs(num_cells - num_ribs)
                if diff == 1:
                    self.numbers_t.setStyleSheet(self.styleSheet())
                else:
                    self.numbers_t.setStyleSheet("border: 1px solid red")

    def btn_press(self, q):
        """
        :method: Handling of all pressed buttons.
        """
        if q == 'Apply':
            pass

        elif q == 'Ok':
            self.close()

        elif q == 'Cancel':
            self.close()
        else:
            logging.error(self.__className
                          + '.btn_press unrecognized button press '
                          + q)


"""下载指标数据"""

import re
import json
from json.decoder import JSONDecodeError

import scrapy
import pymysql
from scrapy import signals
from scrapy.spidermiddlewares.httperror import HttpError
from twisted.internet.error import DNSLookupError
from twisted.internet.error import TimeoutError, TCPTimedOutError
from twisted.internet.error import ConnectionRefusedError
from twisted.web._newclient import ResponseNeverReceived

from ..utils.dbman import query_sql
from ..items import IndicatorDataItem

class IndicatorDataSpider(scrapy.Spider):

    name = 'indicators_data'

    data_pat = re.compile(r'(?<=ld\+json">).*?(?=</)', re.DOTALL)

    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(IndicatorDataSpider, cls).from_crawler(
            crawler, *args, **kwargs
        )
        crawler.signals.connect(spider.spider_opened, signals.spider_opened)
        crawler.signals.connect(spider.spider_closed, signals.spider_closed)
        return spider

    def spider_opened(self, spider):
        self.logger.info('Opening spider %s...', spider.name)
        conn = pymysql.connect(**self.settings['DBARGS'])
        with conn.cursor() as cursor:
            self.countries = query_sql(
                cursor, 'select id, code, url from macro_data_country')
        conn.close()

    def spider_closed(self, spider):
        self.logger.info('Closing spider %s...', spider.name)

    def start_requests(self):
        for it in self.countries:
            yield scrapy.Request(
                it['url'],
                callback=self.parse,
                errback=self.errback_scraping,
                meta={'country_id': it['id'], 'country_code': it['code']}
            )

    def parse(self, response):
        """通过'更多'进入指标详情页"""
        indicators = response.xpath("//*[@class='indicator-column']/li")
        for each in indicators:
            name = each.xpath('./h3/text()').extract_first()
            url = each.xpath('./a/@href').extract_first()
            if name and url:
                yield scrapy.Request(
                    url,
                    callback=self.query_indicators_data,
                    errback=self.errback_scraping,
                    meta={
                        'name': name,
                        'country_id': response.meta['country_id'],
                        'country_code': response.meta['country_code']
                    },
                )

    def query_indicators_data(self, response):
        """查询指标数据"""
        entries = response.xpath("//*[@class='two-column']/li")
        for it in entries:
            title = it.xpath('./h3/text()').extract_first()
            if not title:
                continue
            for each in it.xpath('./ul/li'):
                name = each.xpath('./a/text()').extract_first()
                url = each.xpath('./a/@href').extract_first()
                yield scrapy.Request(
                    url,
                    callback=self.parse_indicators_data,
                    errback=self.errback_scraping,
                    meta={
                        'country_code': response.meta['country_code'],
                        'country_id': response.meta['country_id'],
                        'indicators': [3, name.strip(), title.strip()],
                        'url': url
                    }
                )

    def parse_indicators_data(self, response):
        """json-ld数据解析（待研究）"""
        try:
            data = re.search(self.data_pat, response.text).group()
            jdata = json.loads(data)
            entries = jdata[
                '@graph'][0]['mainEntity']['csvw:tableSchema']['csvw:columns']
            result = []
            for each in entries:
                title = each['csvw:name']
                values = [it['csvw:value'] for it in each['csvw:cells']]
                values.insert(0, title)
                for i in range(len(values)):
                    values[i] = values[i].replace(
                        '\xa0', ' ').replace(',', '|#|')
                result.append(values)
            yield IndicatorDataItem(
                country_code=response.meta['country_code'],
                country_id=response.meta['country_id'],
                indicator_id=response.meta['indicators'],
                url=response.meta['url'], data=zip(*result)
            )
        except (AttributeError, JSONDecodeError, KeyError):
            pass

    def errback_scraping(self, failure):
        req_url = failure.request.url
        if failure.check(HttpError):
            response = failure.value.response
            self.logger.error('HttpError %s on %s', response.status, req_url)
        elif failure.check(DNSLookupError):
            self.logger.error('DNSLookupError on %s', req_url)
        elif failure.check(ConnectionRefusedError):
            self.logger.error('ConnectionRefusedError on %s', req_url)
        elif failure.check(TimeoutError, TCPTimedOutError):
            self.logger.error('TimeoutError on %s', req_url)
        elif failure.check(ResponseNeverReceived):
            self.logger.error('ResponseNeverReceived on %s', req_url)
        else:
            self.logger.error('UnpectedError on %s', req_url)
            self.logger.error(repr(failure))


import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd
from sklearn import preprocessing
from sklearn.preprocessing import PolynomialFeatures
df = pd.read_csv("./CSV_ETH_TOP30/0xUniverse.csv")

# Dropping
df = df.drop('Date', 1)
df = df.drop('Unnamed: 0', 1)
df = df.dropna()

# Normalization
x = df.values
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
df = pd.DataFrame(x_scaled, index = None, columns = ['Balance', 'DAU', 'ETH_Vol', 'Exchange Rank', 'Total Rank', 'Txs'])
df = df[(df.T != 0).any()]

poly = PolynomialFeatures(degree = 3)
x_ = poly.fit_transform(df)

print("feature names")
print(poly.get_feature_names())
print(x_)

# predict = [[0.256, 0.578, 0.0276, 0.582]]
# predict_ = poly.fit_transform(predict)
# print(predict_)


from collections import OrderedDict

from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination

class CustomPagination(PageNumberPagination):
    page_size_query_param = 'page_size'

    def get_paginated_response(self, data):
        pages_count = self.page.paginator.num_pages
        return Response(OrderedDict([
            ('count', self.page.paginator.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('results', data),
            ('pages', pages_count),
        ]))


class Solution(object):
    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode

        Input: 1->2->4, 1->3->4

        Output: 1->1->2->3->4->4

        https://leetcode.com/problems/merge-two-sorted-lists/
        """
        curr = dummy = ListNode(-1)

        while l1 and l2:
            if l1.val <= l2.val:
                curr.next = ListNode(l1.val)
                l1 = l1.next
            else:
                curr.next = ListNode(l2.val)
                l2 = l2.next
            curr = curr.next

        while l1:
            curr.next = ListNode(l1.val)
            l1 = l1.next
            curr = curr.next

        while l2:
            curr.next = ListNode(l2.val)
            l2 = l2.next
            curr = curr.next

        return dummy.next


def HD(string1, string2):
  d=0
  for i in range(len(string1)):
    if string1[i]!=string2[i]:
      d+=1
  return d

def DistancePatternStrings(pattern, dna):
  k=len(pattern)
  d=0
  for linija in dna:
    hd=5000
    for i in range(0, len(linija)-k+1):
      pattern2=linija[i:i+k]
      if HD(pattern, pattern2)<hd:
        hd=HD(pattern, pattern2)
    d=d+hd
  return d