import requests
import re
import json
import urllib
import time
import timeit
import math
import sys
from datetime import datetime
from dateutil import tz
import os
import dateutil.parser

osenviron={}
djj_djj_cookie=''
Card_telegram=''
Card_num=0
github=1#判断是否在远程运行

#618入口https://carnivalcity.m.jd.com/#/home
#通知telegram格式,机器人id@自己的id

userNameList = []
cookiesList = []
pinNameList = []
shareIdlist=[]#互助码

#=============
questionTask={}
meetingTask= []
shopTask= []
skuTask= []
brandList=[]

shareId=''
result=''
bean=0
jifen=0
ispartin=False
result_all=''

def getUserInfo(ck, pinName):
    url = 'https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?orgFlag=JD_PinGou_New&callSource=mainorder&channel=4&isHomewhite=0&sceneval=2&sceneval=2&callback=GetJDUserInfoUnion'
    headers = {
        'Cookie': ck,
        'Accept': '*/*',
        'Connection': 'close',
        'Referer': 'https://home.m.jd.com/myJd/home.action',
        'Accept-Encoding': 'gzip, deflate, br',
        'Host': 'me-api.jd.com',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Mobile/15E148 Safari/604.1',
        'Accept-Language': 'zh-cn'
    }
    try:
        resp = requests.get(url=url, headers=headers, timeout=60).text
        r = re.compile(r'GetJDUserInfoUnion.*?\((.*?)\)')
        result = r.findall(resp)
        userInfo = json.loads(result[0])
        nickname = userInfo['data']['userInfo']['baseInfo']['nickname']
        return ck, nickname
    except Exception:
        pushmsg(f"用户【{pinName}】Cookie 已失效！",'请重新获取。')

        return ck, False

def iscookie():

    cookies = djj_djj_cookie

    if 'pt_key=' in cookies and 'pt_pin=' in cookies:
        r = re.compile(r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I)
        result = r.findall(cookies)
        if len(result) >= 1:
            print("您已配置{}个账号".format(len(result)))
            for i in result:
                r = re.compile(r"pt_pin=(.*?);")
                pinName = r.findall(i)
                pinName = urllib.parse.unquote(pinName[0])

                # 获取用户名
                ck, nickname = getUserInfo(i, pinName)
                if nickname != False:
                    cookiesList.append(ck)
                    userNameList.append(nickname)
                    pinNameList.append(pinName)
                else:
                    continue

            if len(cookiesList) > 0 and len(userNameList) > 0:
                return cookiesList, userNameList, pinNameList
            else:
                print("没有可用Cookie，已退出")
                exit()
        else:
            print("cookie 格式错误！...本次操作已退出")
            exit()
    else:
        print("cookie 格式错误！...本次操作已退出")
        exit()

def task_mult(count):
     #skuTask,shopTask,meetingTask,questionTask,brandList

   for k in range(len(brandList)):
     brandId=brandList[k]['brandId']
     print(f"\n【{k+1}】【{brandId}品牌任务开始】\n")
     brandTaskInfo(count,brandId)
     browseId=''
     if len(skuTask)==0:
        print('账号黑了')
        break
     print('任务1═══════════════════════════════════')

     for i in range(len(skuTask)):
       print(f"开始浏览任务【{i+1}】-{skuTask[i]['name']}")
       body='brandId='+brandId+'&id='+skuTask[i]['id']+'&taskMark=brand&type=presell&logMark=browseSku'
       browseId=task_doBrowse(count,skuTask[i]['id'],body)
       time.sleep(5)
       print(f"任务【{i+1}】-{skuTask[i]['name']}奖励")
       task_getBrowsePrize(count,browseId,brandId)

     print('任务2═══════════════════════════════════')
     for i in range(len(meetingTask)):
       print(f"开始浏览任务任务【{i+1}】-{meetingTask[i]['name']}")
       body='brandId='+brandId+'&id='+meetingTask[i]['id']+'&taskMark=brand&type=meeting&logMark=browseVenue'
       browseId=task_doBrowse(count,meetingTask[i]['id'],body)
       time.sleep(5)
       print(f"任务【{i+1}】-{meetingTask[i]['name']}奖励")
       task_getBrowsePrize(count,browseId,brandId)
       time.sleep(1)
       print(f"【{brandId}品牌任务结束】")

def brandTaskInfo(count,brandId):
    global result,meetingTask,shopTask,skuTask,questionTask
    result=''
    url = 'https://carnivalcity.m.jd.com/khc/index/brandTaskInfo?brandId='+brandId+'&t=1621815248440'
    headers = {"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Accept-Language": "zh-cn","Connection": "keep-alive","Cookie":count,"Host": "carnivalcity.m.jd.com","Referer": "https://carnivalcity.m.jd.com/","User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}

    resp = requests.get(url=url,headers=headers,timeout=60).json()
    #print(resp)
    if resp['code']==200:
       skuTask=resp['data']['skuTask']
       shopTask=resp['data']['shopTask']
       meetingTask=resp['data']['meetingTask']
       questionTask=resp['data']['questionTask']
       return skuTask,shopTask,meetingTask,questionTask
    else:
        result='🍵'+resp['msg']

    #result=f"现有积分{resp['data']['integralCount']}排名{resp['data']['rank']}"
    #print(result)
def task_doBrowse(count,id,body):
    global result
    url = 'https://carnivalcity.m.jd.com/khc/task/doBrowse'
    headers = {"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Accept-Language": "zh-cn","Connection": "keep-alive",'Content-Type': 'application/x-www-form-urlencoded',"Cookie":count,"Host": "carnivalcity.m.jd.com","Referer": "https://carnivalcity.m.jd.com/","User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}

    resp = requests.post(url=url,headers=headers,data=body,timeout=60).json()
    if resp['code']==200:
      browseId=resp['data']['browseId']
      return browseId
    else:
      result='任务'+resp['msg']
      print(result)

def task_getBrowsePrize(count,browseId,brandId):
    result=''
    global bean,jifen
    url = 'https://carnivalcity.m.jd.com/khc/task/getBrowsePrize'
    headers = {"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Accept-Language": "zh-cn","Connection": "keep-alive",'Content-Type': 'application/x-www-form-urlencoded',"Cookie":count,"Host": "carnivalcity.m.jd.com","Referer": "https://carnivalcity.m.jd.com/","User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}
    body='brandId='+brandId+'&browseId='+browseId
    resp = requests.post(url=url,headers=headers,data=body,timeout=60).json()
    #print(resp)
    if resp['code']==200:
      result=f"任务:{resp['data']['jingBean']}京东豆-{resp['data']['integral']}积分"
      bean+=resp['data']['jingBean']
      jifen+=resp['data']['integral']
    else:
      result='任务'+resp['msg']
    print(result)

#积分排名
def carnivalcity(count):
    global result,brandList
    result=''
    url = 'https://carnivalcity.m.jd.com/khc/index/indexInfo?t=1621812633262'
    headers = {"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Accept-Language": "zh-cn","Connection": "keep-alive","Cookie":count,"Host": "carnivalcity.m.jd.com","Referer": "https://carnivalcity.m.jd.com/","User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}

    resp = requests.get(url=url,headers=headers,timeout=60).json()
    #print(resp)
    result=f"现有积分{resp['data']['integralCount']}排名{resp['data']['rank']}"
    #print(result)

    brandList=resp['data']['brandList']
    return brandList,result

def getBean(count):
    print('\n京东豆记录')
    url = 'https://carnivalcity.m.jd.com/khc/record/jingBeanRecord?pageNum=1'
    headers = {"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Accept-Language": "zh-cn","Connection": "keep-alive","Cookie":count,"Host": "carnivalcity.m.jd.com","Referer": "https://carnivalcity.m.jd.com/","User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}
    jingBeanNum=0
    resp = requests.get(url=url,headers=headers,timeout=60).json()
    #print(resp)
    if resp['code']==200:
      jingBeanNum=resp['data']['jingBeanNum']
    else:
      result='获取京豆记录失败:'+resp['msg']
      print(result)
    return jingBeanNum

#邀请码
def getshareId(count):
    global ispartin,shareId
    ispartin=False
    shareId=''
    url = 'https://carnivalcity.m.jd.com/khc/task/getSupport'
    headers = {"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Accept-Language": "zh-cn","Connection": "keep-alive","Cookie":count,"Host": "carnivalcity.m.jd.com","Referer": "https://carnivalcity.m.jd.com/","User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}

    resp = requests.get(url=url,headers=headers,timeout=60).json()
    if resp['code']==200:
      shareId=resp['data']['shareId']
      ispartin=True
    #else:
     # print('获取邀请码失败:'+resp['msg'])
      #ispartin=False
#助力
def doSupport(count,shareId):
    print('\n助力结果')
    global ispartin
    url = 'https://carnivalcity.m.jd.com/khc/task/doSupport'
    headers = {"Accept": "application/json, text/plain, */*","Accept-Encoding": "gzip, deflate, br","Accept-Language": "zh-cn","Connection": "keep-alive",'Content-Type': 'application/x-www-form-urlencoded',"Cookie":count,"Host": "carnivalcity.m.jd.com","Referer": "https://carnivalcity.m.jd.com/?","User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"}
    body="shareId="+shareId
    resp = requests.post(url=url,headers=headers,data=body,timeout=60).json()
    print(resp)
    if resp['code']==200:
      if resp['data']['status']==3:
         print('你已经助力过了，不要重复助力')
      elif resp['data']['status']==6:
         print('助力成功')
      ispartin=True
    else:
      result='助力失败:'+resp['msg']
      ispartin=False
      print(result)

def Start_Support(count):
   print('\n开始助力')
   if len(shareIdlist)>0:
     for code in shareIdlist:
       if code!=shareId:
         doSupport(count,code)
         time.sleep(2)
       else:
           print('跳过自己的朱丽娜')
   else:
     print('本地朱丽娜为空，本次不助力')

def Get_shareIdlist():
   try:
     for ck in range(len(cookiesList)):
        getshareId(cookiesList[ck])
        if github==0:
            print(f"【{ck+1}】用户名:{pinNameList[ck]},邀请码:{shareId}\n")
        else:
            print(f"【{ck+1}】邀请码:{shareId}\n")
        if not shareId:
          continue
        if not ck in shareIdlist:
          shareIdlist.append(shareId)
        time.sleep(1)
   except Exception as e:
      print(str(e))
   print(f"本地邀请码共计{len(shareIdlist)}个:\n{shareIdlist}\n")
def pushmsg(title,txt):
   txt=urllib.parse.quote(txt)
   title=urllib.parse.quote(title)
   try:
     if Card_telegram.strip():
         print("\n【Telegram消息】")
         id=Card_telegram[Card_telegram.find('@')+1:len(Card_telegram)]
         botid=Card_telegram[0:Card_telegram.find('@')]

         turl=f'''https://api.telegram.org/bot{botid}/sendMessage?chat_id={id}&text={title}\n{txt}'''

         response = requests.get(turl,timeout=5)
   except Exception as e:
      print(str(e))

#def logtxt(user,tm):
  #if os.path.exists(f"/log/入会{user}_{tm}.txt"):
	#1000331552

def Readint():
   global Card_telegram,djj_djj_cookie

   if "Card_telegram" in os.environ:
      Card_telegram = os.environ["Card_telegram"]
   if "Card_telegram" in osenviron:
      Card_telegram = osenviron["Card_telegram"]
   if not Card_telegram:
       print(f'''【通知参数】 is empty,DTask is over.''')
   if "JD_COOKIE" in os.environ:
      djj_djj_cookie = os.environ["JD_COOKIE"]
   if "JD_COOKIE" in osenviron:
      djj_djj_cookie = osenviron["JD_COOKIE"]
   if not djj_djj_cookie:
       print(f'''【djj_djj_cookie】 is empty,DTask is over.''')
       exit()

def count_int():
   global bean,jifen,ispartin,shareId
   bean=0
   jifen=0
   questionTask={}
   meetingTask= []
   shopTask= []
   skuTask= []
   brandList=[]
   shareId=""

def show_result(i,count,username):
   print('\n任务统计')
   global result_all
   jingBeanNum=getBean(count)
   brandList,jinfen_rank=carnivalcity(count)
   result_all+=f"【{i+1}】-【{username}】,本次任务获得{bean}个京东豆,{jifen}积分,活动总京豆{jingBeanNum}个,{jinfen_rank}\n"
   if github==0:
     print(f"【{i+1}】-【{username}】,本次任务获得{bean}个京东豆,{jifen}积分,活动总京豆{jingBeanNum}个,{jinfen_rank}\n")
   else:
      print(f"【{i+1}】本次任务获得{bean}个京东豆,{jifen}积分,活动总京豆{jingBeanNum}个,{jinfen_rank}\n")
def start():
       scriptHeader = """
════════════════════════════════════════
║                                      ║
║     京东618 活动-助力助力助力           ║
║                                      ║
════════════════════════════════════════
"""
       print(scriptHeader)
       Readint()
       iscookie()
       Get_shareIdlist()
       for ck in range(len(cookiesList)):
         if github==0:
         	print(f"【{ck+1}】-【用户名:{pinNameList[ck]}】-任务开始\n")
         else:
            print(f"【{ck+1}】-任务开始\n")
         #if ck==0:
             #continue
         count_int()
         Start_Support(cookiesList[ck])
         #continue
         if not ispartin:
            print('号码黑了，无法参加活动')
            show_result(ck,cookiesList[ck],pinNameList[ck])
            continue
         carnivalcity(cookiesList[ck])
         task_mult(cookiesList[ck])
         show_result(ck,cookiesList[ck],pinNameList[ck])
       if github==0:
         print(result_all)
       pushmsg('京东618活动',result_all)
if __name__ == '__main__':
    print('Localtime', datetime.now(tz=tz.gettz('Asia/Shanghai')).strftime("%Y-%m-%d %H:%M:%S", ))
    start()


CURRENT_FOLDER = '.'

MAIN_MENU_INDEX = 0

# Images
PATH_IMAGE_BACK_NEDDLE = 'images/neddle_back.png'
PATH_IMAGE_RELOAD = 'images/reload.png'

# Game
PATH_TO_FIGURES_DATA = 'config_data/figure_shapes.json'
PATH_TO_DEFAULT_DATA = 'config_data/default_figure_shapes.json'
COLOR = 'color'
COORDS = 'coords'


import random

class RGBpixel(object):
    def __init__(self, x, y, rgb_array, dimmer = 1):
        self.x = x
        self.y = y
        self.rgb = [0, 0, 0]

        for i in range(len(self.rgb)):
            self.rgb[i] = rgb_array[i] * dimmer

class Animation(object):
    def __init__(self, x, y):
        self.starting_x = x
        self.starting_y = y
        self.lightning_counter = 0

    def drawWeather(self, weather, sunset_dimmer, isDay):
        pixel_array = []
        rain_height = 6

        if weather == "Clear":
            if isDay:
                pixel_array = self.drawSun(sunset_dimmer)
            else:
                pixel_array= self.drawMoon()

        if weather == "Clouds" or weather == "Rain" or weather == "Thunderstorm":
            pixel_array.extend(self.drawClouds(isDay, sunset_dimmer))
        if weather == "Rain" or weather == "Thunderstorm":
            pixel_array.extend(self.drawRain(isDay, sunset_dimmer, rain_height))
        if weather == "Thunderstorm":
            if self.lightning_counter == 2:
                pixel_array.extend(drawLightning(isDay))
            if self.lightning_counter >= 2:
                self.lightning_counter = 0
            else:
                self.lightning_counter = self.lightning_counter + 1

        return pixel_array

    def drawSun(self, dimmer):
        ## Draw a sun for the LED Matrix
        pixel_array = []
        rgb = [0, 0, 0]

        starting_x = self.starting_x
        starting_y = self.starting_y

        sun_size = 4
        inner_sun_size = 2
        space_between_rays = 2 + 1

        ## Draw a 4 x 4 box for the sun itself
        for ix in range(sun_size):
            for iy in range(sun_size):
                ## For the inner 2 x 2 box, change the color slightly
                if 0 < ix <= inner_sun_size and 0 < iy <= inner_sun_size:
                    rgb = [255 * dimmer, 255 * dimmer, 0]
                else:
                    rgb = [255 * dimmer, 160 * dimmer, 0]

                ## Create a RGB pixel and add it to our list
                p = RGBpixel(ix + starting_x + 3, iy + starting_y + 3, rgb)
                pixel_array.append(p)

        ## This code will add the "rays" to the sun
        for ix in range(0, 4):
            x = 3 * ix
            for iy in range(1,3):
                rgb = [255 * dimmer, random.randrange(125, 255) * dimmer, 0]

                ## Only draw the pixels that correspond to the corners of the sun
                y = 3 * iy
                if y == 12:
                    y = 0
                elif x == 3 and y == 3:
                    y = 0
                elif x == 6 and y == 3:
                    y = 0
                elif x == 3 and y == 6:
                    y = 9
                elif x == 6 and y == 6:
                    y = 9

                p = RGBpixel(x + starting_x, y + starting_y, rgb)
                pixel_array.append(p)

        return pixel_array

    def drawMoon(self):
        pixel_array = []
        moon_rgb = [5, 5, 5]

        starting_x = self.starting_x + 4
        starting_y = self.starting_y + 3

        ## To draw the moon, draw a black circle in a white circle and then add a star
        pixel_array.extend(self.drawCircle(moon_rgb, 5, starting_x, starting_y))
        pixel_array_clear = self.drawCircle([0, 0, 0], 4, starting_x + 2, starting_y - 2)
##        for pixel_to_remove in pixel_array_clear:
##            for pixel in pixel_array:
##                if pixel_to_remove.rgb == pixel.rgb:
##                    pixel_array.remove(pixel)
        pixel_array.extend(self.drawStar(2, starting_x, starting_y))

        return pixel_array

    def drawCircle(self, rgb, circle_radius, starting_x, starting_y):
        pixel_array = []
        for dcx in range(-circle_radius, circle_radius + 1):
            for dcy in range(-circle_radius, circle_radius + 1):
                if (dcx * dcx) + (dcy * dcy) < (circle_radius+.5) * (circle_radius+.5):
                    p = RGBpixel(dcx + starting_x, dcy + starting_y, rgb)
                    pixel_array.append(p)

        return pixel_array

    def drawStar(self, star_radius, starting_x, starting_y):
        pixel_array = []
        random_white_rgb = [0, 0, 0]
        for sx in range(-star_radius, star_radius + 1):
            for sy in range(-star_radius, star_radius + 1):
                if abs(sx) + abs(sy) < star_radius:
                    w = random.randrange(2, 5)
                    for i in range(len(random_white_rgb)):
                        random_white_rgb[i] = w
                    p = RGBpixel(sx + starting_x + 2 * star_radius, sy + starting_y - star_radius, random_white_rgb)
                    pixel_array.append(p)

        w = random.randrange(2, 5)
        p = RGBpixel(starting_x + star_radius, starting_y - 2 * star_radius, [w, w, w])
        pixel_array.append(p)

        return pixel_array

    def drawClouds(self, isDay, sunset_dimmer):
        pixel_array = []
        rgb = [0, 0, 0]

        starting_x = self.starting_x
        starting_y = self.starting_y

        ## Draw a 5 x 10 box that will be the base of our cloud
        for ix in range(0, 11):
            for iy in range(0, 6):
                ## See if the pixel is in the middle of the could.  If it is, give it a random bright white
                if 1<ix<4 and 0<iy<5:
                    if isDay:
                        w = random.randrange(185, 255) * sunset_dimmer
                    else:
                        w = random.randrange(2, 5)
                    rgb = [w, w, w]
                elif 4<=ix<=6 and 3<iy<5:
                    if isDay:
                        w = random.randrange(185, 255) * sunset_dimmer
                    else:
                        w = random.randrange(2, 5)
                    rgb = [w, w, w]
                elif 6<ix<9 and 1<iy<5:
                    if isDay:
                        w = random.randrange(185, 255) * sunset_dimmer
                    else:
                        w = random.randrange(2, 5)
                    rgb = [w, w, w]
                else:
                    ## If the pixel is around the edge of our cloud, give it a dull gray color
                    if isDay:
                        gray = 128 * sunset_dimmer
                    else:
                        gray = 2
                    rgb = [gray, gray, gray]

                ## Chisel out the parts we don't need
                if ix == 0:
                    if iy == 0 or iy == 1 or iy ==2:
                        rgb = [0, 0, 0]
                elif ix == 1:
                    if iy == 0:
                        rgb = [0, 0, 0]
                elif ix == 4:
                    if iy == 0:
                        rgb = [0, 0, 0]
                elif ix == 5:
                    if iy == 0 or iy == 1:
                        rgb = [0, 0, 0]
                elif ix == 6:
                    if iy == 0:
                        rgb = [0, 0, 0]
                elif ix == 7:
                    if iy == 0:
                        rgb = [0, 0, 0]
                elif ix == 8:
                    if iy == 0:
                        rgb = [0, 0, 0]
                elif ix == 9:
                    if iy == 0 or iy == 1:
                        rgb = [0, 0, 0]
                elif ix == 10:
                    if iy == 0 or iy == 1 or iy == 2 or iy == 3:
                        rgb = [0, 0, 0]

                p = RGBpixel(ix + self.starting_x, iy + self.starting_y, rgb)
                pixel_array.append(p)

        return pixel_array

    def drawRain(self, isDay, sunset_dimmer, rain_height):
        pixel_array = []
        rain_height = 6

        starting_x = self.starting_x
        starting_y = self.starting_y

        for ix in range(1, 10):
#            upper_y = ssy+6
#            lower_y = ssy+11
#            first_rain_x = 0 + random.randrange(0, 2)
#            second_rain_x = 3 + random.randrange(0, 2)
#            third_rain_x = 6 + random.randrange(0, 2)
#            first_rain_y = ssy+7
#            second_rain_y = ssy+7
#            third_rain_y = ssy+7
#            rain_x_array = [first_rain_x, second_rain_x, third_rain_x]
#            rain_y_array = [first_rain_y, second_rain_y, third_rain_y]

            for iy in range(0, 4):
                rgb = [0, 0, 0]
                if isDay:
                    rgb[2] = random.randrange(135, 255) * sunset_dimmer
                else:
                    rgb[2] = random.randrange(2, 5)

                if ix % 2 != 0:
                    p = RGBpixel(ix + starting_x, iy + starting_y + rain_height, rgb)
                    pixel_array.append(p)
        return pixel_array

    def drawLightning(self, isDay, rain_height, lightning_counter):
        pixel_array = []

        starting_x = self.starting_x
        starting_y = self.starting_y
        lightning_x_offset = 4

        if isDay:
            rgb = [255, 215, 0]
        else:
            rgb = [4, 3, 0]

        for iy in range(0, 4):
            tix = 0
            for ix in range(0, 2):
                if iy != 3 or ix != 1:
                    if iy > 1:
                        tix = -1
                    p = RGBpixel(ix + starting_x + lightning_x_offset + iy + tix, iy + starting_y + rain_height, rgb)
                    pixel_array.append(p)

        return pixel_array


from ultralytics import *
from sort import *
from backsubstraction import *
import cv2
import matplotlib.path as mplPath
import cvzone
import math

type = "web"

def Processor(filename, modelt, aoi):

    if modelt == "YOLOv8n":
        model = YOLO('../Yolo-Weights/bestn.pt')
        print("hello")
    elif modelt == "YOLOv8l":
        model = YOLO('../Yolo-Weights/best.pt')
    elif modelt == "Image Processing":
        objectdetector = cv2.createBackgroundSubtractorMOG2(history=400, varThreshold=200)

    yoloclassNames = ["bus", "car", "motorbike", "truck"]

    tracker = Sort(max_age=20, min_hits=3, iou_threshold=0.3)
    totalCount = []

    if(type == "web"):
        video = cv2.VideoCapture(f'uploads/{filename}')
        length = int(video.get(cv2.CAP_PROP_FRAME_COUNT))

    else:
        video = cv2.VideoCapture(0)
    fid = 0
    frame_width = int(video.get(3))
    frame_height = int(video.get(4))
    size = (frame_width, frame_height)

    mask = np.zeros((frame_width, frame_height, 3))

    pointlst = []
    for coord in aoi:
        x = coord['x']
        y = coord['y']
        rti = frame_height / 450
        yt = int(y) * rti
        diff = (800 * rti - frame_width) / 2
        xt = int(x) * rti - diff
        pointlst.append([int(xt), int(yt)])

    pointsnp = np.array(pointlst)
    poly_path = mplPath.Path(pointsnp)

    fresult = cv2.VideoWriter('output.avi',
                              cv2.VideoWriter_fourcc(*'MJPG'),
                              10, size)
    while True:

        ret, frame = video.read()
        cv2.polylines(frame, pts=[pointsnp], isClosed=True, color=(0, 255, 0), thickness=2)
        fid += 1

        if ret == True:
            if modelt == "YOLOv8n" or modelt == "YOLOv8l":
                pred = model(frame, stream=True)
                print("running")
                detections = np.empty((0, 5))
                for r in pred:
                    boxes = r.boxes
                    for box in boxes:
                        x1, y1, x2, y2 = box.xyxy[0]
                        x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
                        cx = (x1 + x2) / 2
                        cy = (y1 + y2) / 2
                        w = x2 - x1
                        h = y2 - y1

                        conf = math.ceil((box.conf[0] * 100)) / 100
                        cls = int(box.cls[0])
                        currentClass = yoloclassNames[cls]

                        if currentClass in ["car", "truck", "bus", "motorbike"] and conf > 0.2:
                            if poly_path.contains_point((cx, cy)):
                                currentArray = np.array([x1, y1, x2, y2, conf])
                                detections = np.vstack((detections, currentArray))

                resultsTracker = tracker.update(detections)

                for result in resultsTracker:
                    x1, y1, x2, y2, id = result
                    x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
                    w = x2 - x1
                    h = y2 - y1
                    cvzone.cornerRect(frame, (x1, y1, w, h), l=9, rt=2, colorR=(255, 0, 255))
                    cvzone.putTextRect(frame, f' {int(id)}', (max(0, x1), max(35, y1)),
                                       scale=2, thickness=3, offset=10)
                    if id not in totalCount:
                        totalCount.append(id)

            elif (modelt == "Image Processing" and fid>1):
                detections = np.empty((0, 5))
                #mask = objectdetector.apply(frame)
                mask = objdet(frame,grayprev,frame_height,frame_width)
                contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
                for cnt in contours:
                    area = cv2.contourArea(cnt)
                    x1, y1, w, h = cv2.boundingRect(cnt)
                    x2 = x1 + w
                    y2 = y1 + h
                    cx = x1 + (w / 2 )
                    cy = y1 + (h / 2)
                    if area > 100 and area < 20000: #w > 50 and h > 50 and w < 300 and h < 300:
                        if poly_path.contains_point((cx, cy)):
                                currentArray = np.array([x1, y1, x2, y2, 0.8])
                                detections = np.vstack((detections, currentArray))

                resultsTracker = tracker.update(detections)

                for result in resultsTracker:
                    x1, y1, x2, y2, id = result
                    x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
                    w = x2 - x1
                    h = y2 - y1
                    cvzone.cornerRect(frame, (x1, y1, w, h), l=9, rt=2, colorR=(255, 0, 255))
                    cvzone.putTextRect(frame, f' {int(id)}', (max(0, x1), max(35, y1)),
                                       scale=2, thickness=3, offset=10)
                    if id not in totalCount:
                        totalCount.append(id)
            if(type=="web"):
                progress = (fid / length) * 100
            cv2.putText(frame, str(len(totalCount)), (255, 100), cv2.FONT_HERSHEY_PLAIN, 5, (50, 50, 255), 8)
            fresult.write(frame)
            grayprev = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        else:
            return len(totalCount)

    video.release()
    fresult.release()
    return -1


import logging
import os
from flask import Flask

from app.blueprints import application, analysis, results

def create_app(test_config=None):
    logging.basicConfig(level=logging.DEBUG)
    app = Flask(__name__, instance_relative_config=True, template_folder='../templates', static_folder='../static')
    app.config.from_mapping(
        SECRET_KEY='dev',
    )

    if test_config is None:
        # load the instance config, if it exists, when not testing
        app.config.from_pyfile('config.py', silent=True)
    else:
        # load the test config if passed in
        app.config.from_mapping(test_config)

    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    app.register_blueprint(application.blueprint)
    app.register_blueprint(analysis.analysis_bp)
    app.register_blueprint(results.results_bp)

    return app


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('catalog', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='Order',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)),
                ('created_at', models.DateTimeField(verbose_name='Opened at', auto_now_add=True)),
                ('closed_at', models.DateTimeField(blank=True, verbose_name='Closed at', null=True)),
                ('is_closed', models.BooleanField(default=False, verbose_name='Is closed')),
                ('is_processed', models.BooleanField(default=False, verbose_name='Is processed')),
                ('phone', models.CharField(max_length=32, null=True)),
                ('address', models.CharField(max_length=256, null=True)),
                ('name', models.CharField(verbose_name='Contact name', max_length=64, null=True)),
            ],
            options={
                'verbose_name_plural': 'Orders',
                'verbose_name': 'Order',
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='OrderPosition',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)),
                ('count', models.PositiveIntegerField(default=0)),
                ('order', models.ForeignKey(related_name='positions', to='cart.Order')),
                ('product', models.ForeignKey(to='catalog.Product')),
            ],
            options={
                'verbose_name_plural': 'Order positions',
                'verbose_name': 'Order position',
                'ordering': ['-count'],
            },
            bases=(models.Model,),
        ),
    ]


import os, csv, datetime, copy
import pandas as pd

ACTION_MAP2 = {
    'BASE': ['AIR', 'CROUCH', 'STAND'],
    'MOVE': ['BACK_JUMP', 'BACK_STEP', 'DASH', 'FOR_JUMP', 'FORWARD_WALK', 'JUMP'],
    'GUARD': ['AIR_GUARD', 'CROUCH_GUARD', 'STAND_GUARD'],
    'RECOV': ['AIR_GUARD_RECOV', 'AIR_RECOV', 'CHANGE_DOWN', 'CROUCH_GUARD_RECOV', 'CROUCH_RECOV', 'DOWN', 'LANDING',
              'RISE', 'STAND_GUARD_RECOV', 'STAND_RECOV', 'THROW_HIT', 'THROW_SUFFER'],
    'SKILL': ['AIR_A', 'AIR_B', 'AIR_DA', 'AIR_DB', 'AIR_FA', 'AIR_D_DB_BA', 'AIR_D_DB_BB', 'AIR_D_DF_FA', 'AIR_D_DF_FB',
              'AIR_FA', 'AIR_FB', 'AIR_F_D_DFA', 'AIR_F_D_DFB', 'AIR_UA', 'AIR_UB', 'CROUCH_A', 'CROUCH_B', 'CROUCH_FA',
              'CROUCH_FB', 'STAND_A', 'STAND_B', 'STAND_FA', 'STAND_FB', 'STAND_D_DB_BA', 'STAND_D_DB_BB', 'STAND_D_DF_FA',
              'STAND_D_DF_FB', 'STAND_D_DF_FC', 'STAND_F_D_DFA', 'STAND_F_D_DFB', 'THROW_A', 'THROW_B'],
    'ALL': []
}

ACTION_MAP2 = {
    'BASE': ['AIR', 'CROUCH', 'STAND'],
    'MOVE': ['BACK_JUMP', 'BACK_STEP', 'DASH', 'FOR_JUMP', 'FORWARD_WALK', 'JUMP'],
    'GUARD': ['AIR_GUARD', 'CROUCH_GUARD', 'STAND_GUARD'],
    'RECOV': ['AIR_GUARD_RECOV', 'AIR_RECOV', 'CHANGE_DOWN', 'CROUCH_GUARD_RECOV', 'CROUCH_RECOV', 'DOWN', 'LANDING',
              'RISE', 'STAND_GUARD_RECOV', 'STAND_RECOV', 'THROW_HIT', 'THROW_SUFFER'],
    'SKILL': ['AIR_A', 'AIR_B', 'AIR_DA', 'AIR_DB', 'AIR_FA', 'AIR_D_DB_BA', 'AIR_D_DB_BB', 'AIR_D_DF_FA', 'AIR_D_DF_FB',
              'AIR_FA', 'AIR_FB', 'AIR_F_D_DFA', 'AIR_F_D_DFB', 'AIR_UA', 'AIR_UB', 'CROUCH_A', 'CROUCH_B', 'CROUCH_FA',
              'CROUCH_FB', 'STAND_A', 'STAND_B', 'STAND_FA', 'STAND_FB', 'STAND_D_DB_BA', 'STAND_D_DB_BB', 'STAND_D_DF_FA',
              'STAND_D_DF_FB', 'STAND_D_DF_FC', 'STAND_F_D_DFA', 'STAND_F_D_DFB', 'THROW_A', 'THROW_B'],
    'ALL': []
}

class Table(pd.DataFrame):
    def __init__(self, data, columns):
        pd.DataFrame.__init__(self, data=data)
        # Remove last column
        del self[len(self.columns)-1]
        self.columns = columns

class GameData:
    def __init__(self, columns):
        self.rounds = []
        self.columns = columns

    def add_round(self, frames):
        self.rounds.append(frames)

    def get_column(self, column_name):
        col_index = self.columns.index(column_name)
        # Control null check
        frames = []
        for round in self.rounds:
            frames.extend([item[col_index] for item in round])
        return frames

    def filter(self, f):
        len_before = len(self)
        for i, round_data in enumerate(self.rounds):
            self.rounds[i] = f(self.columns, round_data)
        return len_before - len(self)

    # if count 3, x-3, x-2 .. x .. x+2, x+3 will be added
    def add_distortion(self, count, action_type):
        len_before = len(self)
        for i, round_data in enumerate(self.rounds):
            self.rounds[i] = self.distortion(self.columns, round_data, count, action_type)
        return len_before - len(self)

    def distortion(self, columns, round_data,count,action_type):
        prepared_frames = []
        for current_frame in round_data:
            if current_frame[columns.index("P2-action")] in ACTION_MAP2[action_type] or action_type == "ALL":
                for i in range(-count, count+1,1):
                    tmp = current_frame.copy()
                    tmp[columns.index("P1-x")] += i
                    tmp[columns.index("P2-x")] += i
                    prepared_frames.append(tmp)
            else:
                prepared_frames.append(current_frame)
        return prepared_frames

    def table(self):
         return [Table(data=item, columns=self.columns) for item in self.rounds]

    def append(self, to_append):
        self.rounds.extend(to_append.rounds)

    def export_csv(self, file_name="game_data_export", columns=None):
        def extract_cols(frame, columns):
            extracted = []
            for column in columns:
                extracted.append(frame[column])
            return extracted;

        def create_file_name():
            # Control existance of out folder
            out_folder = "out/"
            if not os.path.exists(out_folder):
                os.makedirs(out_folder)

            time = datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S')
            return out_folder + file_name + "_" + time + ".csv"

        file_name = create_file_name()
        writer = csv.writer(open(file_name, "w"), delimiter=',')

        # Write columns names
        writer.writerow(["Index"] + (columns if columns else self.columns))

        for i, frame in enumerate(self):
            row = extract_cols(frame, columns) if columns else frame
            writer.writerow([i] + row)

    def clone(self):
        return copy.deepcopy(self)

    def statistics(self):
        def get_statistics_of_round(rounds):
            p1_actions = []
            p2_actions = []
            for round in rounds:
                p1_actions = p1_actions + [frame[self.columns.index('P1-action')] for frame in round]
                p2_actions = p2_actions + [frame[self.columns.index('P2-action')] for frame in round]
            return Statistic(p1_actions), Statistic(p2_actions)

        return get_statistics_of_round(self.rounds)

    def __iter__(self):
        self.iterator_count = 0
        return self

    def __next__(self):
        def round_index():
            cumulative_sum = 0
            for i, r in enumerate(self.rounds):
                cumulative_sum += len(r)
                if self.iterator_count < cumulative_sum:
                    return i

        def frame_index(round_index):
            prev_round_len = 0 if round_index == 0 else sum([len(r) for i, r in enumerate(self.rounds) if i < round_index])
            return self.iterator_count - prev_round_len

        if self.iterator_count < len(self):
            r_index = round_index()
            f_index = frame_index(r_index)
            self.iterator_count += 1
            return dict(zip(self.columns, self.rounds[r_index][f_index]))
        else:
            raise StopIteration

    def __len__(self):
        return sum([len(round) for round in self.rounds])

    def __str__(self):
        return "There are {} rounds and {} frames.".format(len(self.rounds), len(self))

class Statistic:
    def __init__(self, actions):
        self.actions = actions
        self.distributions = dict()

        for action in actions:
            self.distributions[action] = self.distributions.get(action, 0) + 1

    def get_count_of_action(self, action):
        count = self.distributions.get(action, None)
        if count:
            return count
        raise ValueError('This action not exists {}'.format(action))

    def get_distribution_of_action(self, action):
        count = self.get_count_of_action(action)
        return float(count) / float(len(self.actions)) * 100

    def __str__(self):
        msg = ''
        for action, count in self.distributions.items():
            msg += '{},{},{}%\n'.format(
                action,
                count,
                self.get_distribution_of_action(action)
                )
        return msg


# -*- coding:utf-8 -*-
# Author: luoxiaobo
# TIME: 2021/12/9 19:17

import re
from time import sleep

from selenium.webdriver.common.by import By

from GGR import GGR
from base.common import *
from utils.log import logger

class SpeedPicker:

    def __init__(self):
        self.driver = self.init_driver()
        # sleep(10)  # 做一个长等待，没办法。加载慢。
        self.view = (By.XPATH, '//android.view.View')
        self.image = (By.XPATH, '//android.widget.ImageView')

    def device_num(self):
        num = int(__file__.split('\\')[-1].split('.')[0].split('ker')[-1]) - 1  # 序号从0开始
        devices_ls = get_devices()
        try:
            return devices_ls[num], 4725 + num * 5  # 每个设备之间，间隔5个以上
        except:
            logger.warning("There is an error in getting the UDID of the device. Please check it.")

    def init_driver(self):
        device = self.device_num()[0]  # 10.111.150.202 这种格式.
        appium_port = self.device_num()[1]
        browser = GGR().browser(devices=device, platformversion='8', port=appium_port)
        logger.info(f"Script connect Pad UDID:{device},Appium port:{appium_port}")
        return browser

    def robot_batery(self):
        tmp_text = self.driver.app_elements_content_desc()
        for i in tmp_text:
            if i.endswith('%'):
                return i
        else:
            return 'The battery level of the robot is not obtained'

    def open_sp(self):
        # 先判断是否有异常.
        if self.err_notify():  # 异常函数会自己报异常.
            exit(-404)  # 走不动了,直接停吧.
        # 抓取界面的小程序.
        desc = self.driver.app_elements_content_desc(self.view)  # if find element faile,will except,restart script
        if 'SkillSpace' not in ''.join(desc):
            logger.warning(
                "Currently not in Jrvis Launcher.")
            return
        else:
            image = self.driver.find_elements(self.image)
            soft_index = self.driver.app_elements_content_desc(self.view)
            for i in soft_index:
                if 'SpeedPicker' in i:
                    x = i.split('\n')[::-1]
                    sp_index = x.index('SpeedPicker') + 1  # 因为反过来了.从0开始.
                    self.driver.click_one(image[-sp_index])
                    logger.info("SpeedPicker not start,Auto click on SpeedPicker.")
                    sleep(2)
                    tmp_text = self.get_text()
                    for item in tmp_text:
                        if 'version:' in item:
                            logger.info(f"SpeedPicker Version:{item.split(':')[-1]}")
                            self.wait_moment(item, i=False, without="退出")
                            new_text = self.get_text()
                            if item in new_text and '退出' in new_text:
                                logger.warning(f"SpeedPicker can't start.Please check error.{new_text}")
                                exit(-404)
                    # self.wait_moment("version:") 这是部分文本.  # 'version:1.5.730'
                    break
            else:
                logger.warning(
                    f"Note: SpeedPicker is not installed on this device {self.device_num()[0]}, please install it first.")

    def err_notify(self):
        try:
            notify = self.driver.app_elements_content_desc(self.image, wait=1)  # 不用抓太久.
            if notify:
                for i in notify:
                    # The number of notifications in the upper right corner is also the image class So do a screening
                    if len(i) > 3 and '机器人' in i:
                        logger.info(
                            f"This robot [{i}] has some exceptions, please fix them first.")
                        return 1
            else:
                return 0  # Jump out of the loop and do nothing
        except:
            return 0  # Exception notification is not available at any time. Exceptions will be reported

    def inputcode(self, code='199103181516'):  # The universal code is entered by default。
        """For entering bar codes"""
        try:
            # The premise of entering numbers is to click the input button,and pop up the input box.
            # self.driver.click_element((By.XPATH, '//android.widget.EditText'))
            self.driver.input_text(locator=(By.XPATH, '//android.widget.EditText'), text=str(code))
            logger.info(f"Barcode [{code}] entered successfully.")
            self.driver.click_element((By.XPATH, '//android.widget.EditText'))  # need click input bar again
            self.driver.press_keyboard()
        except:
            pass

    def islosepos(self):
        """Determine whether the robot has lost its positioning."""
        try:
            self.driver.find_elements(
                locator=(By.XPATH, '//android.widget.ImageView[contains(@content-desc,"机器人定位丢失")]'),
                wait=1, raise_except=True)
            return 1  # return True
        except:
            sleep(0.1)

    def random_trigger(self, n=30):  # Probability value
        # Random number result, used to trigger an operation.
        if n == 0:  # Set to 0 to disable the random function.
            return 0
        elif n == 1:  # Set to 1 to keep this function on.
            return 1
        elif n >= 2:
            num = random.randint(2, n + 2)  # Start with 2 and pick a number at random
            if num == n:  # Draw this number and turn on this function
                # logger.info(A random event occurred。")
                return 1  # return True
        else:
            return 0

    def pause_move(self, time_out=25):  # 不宜过长,省得脚本卡时间,恢复按钮没了.
        """Pause movement, timeout max. 30s"""
        view_text = self.driver.app_elements_text((By.XPATH, '//android.view.View'))
        wait_time = random.randint(1, time_out)
        if '暂停' in view_text:
            self.driver.click_element((By.XPATH, '//android.view.View[@text="暂停"]'))
            logger.info(f"Click the pause button to pause the mobile robot for [{wait_time}] seconds。")
            sleep(wait_time)
            try:
                self.driver.click_element((By.XPATH, '//android.view.View[@text="恢复"]'))
                logger.info(f"The pause movement is over, and the movement will resume soon。")
                return
            except:
                logger.info("The resume button disappears. It may have been clicked manually, Exit pause move")
                return

    def press_ok(self, num=1):
        # 点击确定按钮
        count = num
        while count > 0:
            try:
                self.driver.click_element((By.XPATH, '//*[contains(@text,"确定")]'), wait=0.1)  # Not too long。
                break
            except:
                count -= 1

    def input_error(self, code):
        # Used to verify the input error barcode. The premise of execution is that the input box pops up.
        err_num = str(random.randint(0, 1000))
        self.inputcode(code=str(code) + err_num)  # Add a random number to form an error barcode.
        logger.info("A random event is triggered, and an [Error barcode] is entered.")

    def get_text(self, wait=3, raise_except=False):  # 3s左右合理,有些流程跳转时,会转圈一会儿.
        count = 20  # 有个限制.
        while count > 0:
            count -= 1  # 避免死循环
            view_ls = self.driver.app_elements_text(self.view, wait)  # 拿到异常类型的文本。文本也是view.View类型的。
            try:
                view_ls = [i for i in view_ls if i != '']  # 去重。会抓到空文本。
                if view_ls:  # 抓到才出去.在sp里,必定是会有文本页面的.
                    return view_ls
                else:
                    if count % 10 == 0:  # 偶尔刷新一次.
                        # 判断是不是在Jarvis主界面.
                        try:
                            tmp_desc = self.driver.app_elements_content_desc()
                            if 'SkillSpace' in ''.join(tmp_desc):
                                self.open_sp()
                        except:
                            pass  # The function needs to be improved
                        logger.info(
                            "The current interface does not contain documentation, if this log keeps refreshing, please check the robot.")
            except TypeError:
                if self.random_trigger(n=60):
                    logger.debug(
                        f"Random logs, don't worry, I'm continuously scraping the docs, but getting the wrong ones, see what I got:->{view_ls}<-")
                    sleep(2)
                if raise_except:
                    raise just_err
                sleep(2)
            except Exception as e:
                logger.info(f"Catch the text flow get some other exceptions:{e}")
        if count == 0:
            logger.info(f"This robot:{self.device_num()[0]}can't get text information for a long time.")
            # raise just_err  # 这个异常,并不能重启脚本.

    def get_text2(self, wait=2):
        view_ls = self.driver.app_elements_text(self.view, wait)
        if view_ls:  # 抓到才出去.在sp里,必定是会有文本页面的.
            return view_ls
        else:
            return []

    def report_err(self):
        view_ls = self.get_text()
        if view_ls[0] == '异常上报':
            logger.info("Currently, it is in the exception reporting interface.")
            self.do_err()
        else:
            try:
                self.driver.click_element((By.XPATH, '//*[@text="异常上报"]'), wait=3, raise_except=True)
                # self.click_view_text("异常上报")  # 不能这么做,点进去了,异常上报还是在文本中.
                self.do_err()
            except:
                logger.warning("The exception reporting function does not click the exception reporting button")
                return

    def do_err(self):
        # 上报异常的冗余函数.
        tmp_text = self.get_text()
        if tmp_text[0] != '异常上报':
            logger.warning(
                "Currently, it is not in the exception reporting interface, and enters the exception process by mistake")
            return
        view_ls = tmp_text[1:]
        err_type = random.choice(view_ls)
        logger.info(f"The randomly selected report type is:{err_type}")
        self.driver.click_one(self.driver.find_element((By.XPATH, '//android.view.View[@text="%s"]' % err_type)))
        count = 3
        while count > 0:
            try:
                view_ls2 = self.get_text()
                err_type2 = re.findall("确定(.*?)吗", ''.join(view_ls2))[0]
                logger.info(f"Are you sure you want to report {err_type2} exception?")
                if err_type2 == err_type or err_type == '其他':  # 确定弹窗起来了. 选择其他异常,询问框不一致.
                    self.driver.click_one(self.driver.find_elements(self.view)[-1])  # 最后一个view元素是'确定'按钮.
                    logger.info(f"Click OK to report the exception:{err_type} successfuly.")
                    if '确定' not in self.get_text():  # 跳转流程了.
                        sleep(6)  # 点完确定,会有个长等待.
                        # self.wait_moment(err_type)  # 用这个方法应该可以,需要验证一下.
                        break
                    else:
                        logger.warning("There seems to be something wrong with the exception reporting interface.")
                sleep(1)  # 暂停一下.
                count -= 1
            except:
                count -= 1
                sleep(1)
        if err_type == '载具不符':
            count = 20
            while count > 0:
                try:
                    self.click_view_text('完成', wait=3)
                    break
                except:
                    count -= 1

    def report_full(self):
        # 上报载物箱已满,前提是:Total_Picking.在拣货界面.
        view_ls = self.get_text()
        if '载物箱已满?' in view_ls:
            if self.random_trigger(n=1500):
                self.click_view_text("载物箱已满?")
                self.driver.click_one(self.driver.find_elements(self.view)[-1])
        else:
            logger.info('No cargo box is full')

    def wait_moment(self, text, timeout=1, i=True, without=None):
        # 持续去抓某个文本，直到这个文本不再这个页面了。说明流程变了。
        # 这里可能是影响效率的地方，想办法怎么优化一下。
        logger.info(f"Continuously check whether the text  [{text}] is in the current interface.")
        count = 0
        err = 10
        while err > 0:
            try:
                view_ls = self.get_text(wait=2, raise_except=True)  # 不用太频繁.
                if view_ls:  # 居然还有空的情况，干。
                    if text in view_ls:
                        if self.random_trigger(n=60):
                            if i:
                                logger.debug(f"Still check:{text},just debug log .....")
                        elif without:
                            # if without text display,break loop
                            if self.driver.element_display((By.XPATH, f'//*[@text="{without}"]')):
                                logger.debug(f"Check without text {without} display. Stop check {text}.")
                                break
                        sleep(1)  # 等待时间不能太长。
                        count += timeout  # 持续计时,看看卡界面多久了.
                        minutes = count // 60
                        if minutes >= 5:  # 每5分钟上报一次.
                            logger.warning(
                                f"The page has not changed for more than {minutes} minutes, please go to check the robot.")
                            self.err_notify()
                            break  # 出问题了，也跳出流程，等着回来吧。

                    else:
                        break  # 抓不到重复的文本了。跳出循环。
                else:
                    if self.random_trigger(n=1):
                        logger.info(f"Get None text,what's happend")
                    err -= 1  # 这种情况,也给他跳出循环.
                    sleep(timeout)
            except TypeError:
                pass  # 类型错误,前提是已经抓到元素,那么就是空文本问题,这种情况,不要跳出去.继续抓.
            except Exception as e:
                logger.warning(f"Some exceptions occurred in the process of getting text:{e}")  # 暂时先保留,现场这里问题是真的多.
                err -= 1
                sleep(1)

    def click_view_text(self, text, wait=1):
        # 强点击,保证点到.
        # logger.info(f"Ready to click：[{text}]")
        count = 3
        while count > 0:
            self.driver.click_element((By.XPATH, f'//*[@text="{text}"]'), wait=wait)
            tmp_text = self.get_text(wait=1)
            if text not in tmp_text:
                logger.info(f"Click text : [{text}] successful.")
                break
            else:
                count -= 1

    def click_input(self):
        # 用来强制点击输入的,免得有点不到的情况.
        # 不能受干扰,要是人为把这个过去了.可能就凉了.  先试试
        count = 5
        while count > 0:
            # # self.press_ok()  # 可能有弹窗干扰.
            text = self.get_text(wait=3)
            if "输入" in text:
                try:
                    self.driver.click_element((By.XPATH, '//*[@text="输入"]'))
                    if "输入" not in text:
                        logger.info("Click the enter button successfully.")
                        break
                except Exception as e:
                    count -= 1  # 不要卡流程,也给个计数限制,目前观察,最多点个两三次,肯定能点到.
                    logger.warning(f"Click input button raise exception:{e}.")
                    sleep(1)
            else:
                break  # 没有输入按钮,就不要卡流程.

    def get_total(self, view_ls):
        # 获取拣货最大数量.
        l = ''.join(view_ls)
        if '输入' in view_ls:
            for i in l.split('/'):
                if i.endswith("拣货数量"):
                    return i.split("拣货数量")[0]
        elif len({'完成', '拣货中'} & set(view_ls)) == 2:
            for i in l.split('/'):
                if "完成" in i:
                    return i.split("完成")[0]

    def find_goods(self):
        find_time = random.randint(1, 3)  # 模拟找货的时间。本身性能也一般,就不要给那么长的等待时间了.
        for i in range(find_time):
            try:
                self.driver.context  # 抓个数据，避免连接挂掉了。
            except:
                pass
            sleep(1)
        logger.info(f"wait a few seconds：{find_time}s,start picking。")

    def picking(self):
        # self.press_ok()
        view_ls = self.get_text()
        logger.info(f"The robot is currently picking goods:{view_ls}")  # 需要记录一下进入拣货流程.
        # 情况1.
        if '输入' in view_ls:  # 1.还没扫码，有输入按钮。
            # self.find_goods()  # 延时等待。不需要了.
            logger.info("Case 1, the product code has not been scanned, and the input button is about to be clicked.")
            if self.random_trigger(n=15):  # 1/15 概率，上报异常。
                self.report_err()
                return  # 结束拣货流程.
            self.click_view_text("输入")  # 点击输入按钮
            total = view_ls[-4]  # 单独的最大拣货数量。  从输入开始走,可以这么拿.
            if self.random_trigger(n=30):  # 随机触发,先去掉，100%触发。
                self.input_error(random.randint(1, 564313112131))  # 随机取一个,取对了,就可以买彩票了。

            good_code = view_ls[view_ls.index("请拣取正确货品并扫码") + 2]
            self.inputcode(code=good_code)  # 输入了商品码。
            # count = 2
            # while count < 5:
            #     # self.press_ok()  # 出现协助弹窗遮挡导致不能顺利输入问题.在载物箱流程比较严重.这里不太可能.
            #     good_code = view_ls[view_ls.index("请拣取正确货品并扫码") + count]
            #     self.inputcode(code=good_code)  # 输入了商品码。
            #     if self.driver.element_display((By.XPATH, '//android.widget.EditText')):
            #         count += 1
            #     else:
            #         # logger.info(f"确定成功输入了商品码.")
            #         break
            if total == "1":
                self.go_to()  # 一个商品,也要检查一下推荐点位.
                return  # 只捡一个，扫码完成就齐活。
            elif total != '1' and total.isdigit():
                logger.debug(f"Get max picking num:{total}")
                self.input_max(total)  # 走这个流程,到这也结束了.不需要单独的return
            else:
                logger.error(f"Get total number error,get text is {total}")  # UI变了,或者人为操作,会到这.
        # 还没扫码,但是点了输入按钮.
        elif '请拣取正确货品并扫码' in view_ls and view_ls[view_ls.index('请拣取正确货品并扫码') + 3] == '0':
            logger.info(f"Case 2, the input box pops up, but the product code is not entered.")
            tmp_text = self.get_text()
            self.inputcode(code=tmp_text[tmp_text.index('请拣取正确货品并扫码') + 2])
            self.input_total()

        elif '拣货数量' in view_ls:  # 弹出了输入商品数字的框。
            logger.info("Case 3, the product code is scanned, but the picking is not completed.")
            try:
                self.driver.find_element((By.XPATH, '//android.widget.EditText')).clear()  # 尝试一下清空.
            except:
                pass
            finally:
                # self.inputcode('9999999999')
                new_text = self.get_text()
                try:
                    num = re.findall(r'~(.*?)之间的有效数值', ''.join(new_text))[0]
                    self.inputcode(num)
                except IndexError:
                    logger.debug(f"list index out of range? {new_text}.")
                    pass  # 抓不到.退出去重来一下试试.
        else:
            # ['载物箱已满?', '拣货中', '6923450659861', '第5个商品', '1/3', '完成', '异常上报']
            logger.info("Case 4, the picking is not completed.")
            tmp_text = self.get_text()
            if '前往' in tmp_text:
                return
            logger.info(f"Scaned text:{tmp_text}")
            total = self.get_total(view_ls)  # 已经扫码的情 况下,最大值,这样处理一下.好点.
            if total == None:
                logger.info(f"Case 4,Get total number error.")
                return  # 有抓不到的情况
            logger.info(f"Scaned goods and need picking {total} goods.")
            self.input_max(total)

    def input_total(self):
        try:
            self.driver.click_element((By.XPATH, '//*[contains(@text,"/")]'), raise_except=True)  # 点击了数字框。默认点到第一个。
            tmp_text = self.get_text()
            logger.info(f"Click goods number，now page text:{tmp_text}")
            total = re.findall('1~(.*?)之间', ''.join(tmp_text))[0]
            self.inputcode(total)
            # self.press_ok()
        except:
            logger.warning("Click '/' fail,please check.")

    def input_max(self, num):
        logger.info("More than 1 product needs to be picked, click the number and enter the maximum value.")
        if self.random_trigger(n=30):  # 上报异常。
            self.report_err()
            return
        try:
            self.driver.click_element((By.XPATH, '//*[contains(@text,"/")]'), raise_except=True)  # 点击了数字框。默认点到第一个。
            logger.info(f"Click goods number，now page text:{self.get_text()}")
        except:
            logger.warning("Click '/' fail,please check.")
        self.inputcode(num)  # 输入最大数量。
        self.click_view_text("确定")  # 强行点确定.
        logger.info(f"Enter the maximum value [{num}] successfully.")
        self.go_to()

    def go_to(self):
        # 重构。
        logger.info("Picking of the current item is complete.Check where you can go.")
        count = 4
        while count > 0:
            try:
                before = self.get_text(wait=1, raise_except=True)  # 先抓一次前文本.
            except:
                continue
            if "请到此处附近" in before:
                try:
                    logger.info(f"Get a recommended target point --- {before[before.index('请到此处附近') + 1]}")
                    break
                except:
                    logger.warning(f"Out of index,why? {before}")
                    break  # 不知道为何,这里会超出索引,奇了怪.
            elif '打包绑定区' in before:
                logger.info("No items to pick, go to the packing area.")
                break
            elif '拣货中' in before and '请拣取正确货品并扫码' in before:
                logger.info("There are other items at the current location that need to be picked.")
                break
            else:
                count -= 1
                # sleep(0.5)

    def bind_carrier(self):
        # 绑定载物箱。
        logger.info("Please bind the container.")
        # self.press_ok()  # 可能超时了，先点击一下。
        if self.random_trigger(n=100):  # 上报异常，就不用做了。
            self.report_err()
            return  # 确保流程跳出去。
        if '输入' in self.get_text():
            self.click_input()
        while True:
            # self.press_ok()
            tmp_text = ''.join(self.get_text()).replace(' ', '')
            if '绑定载物箱' in tmp_text:
                self.inputcode(code=str(random.randint(1, 9999999999999)))
                sleep(1)  # 绑定单个的时候,抓太快了,会重复输一下,此时页面换了,就没有输入框了.给个延时.
                try:
                    self.click_view_text("完成")
                    break  # 绑定完成了
                except:
                    pass
            elif not self.driver.element_display((By.XPATH, '//android.widget.EditText')):
                break  # 输入框消失了,也算完活.不要一直卡着.
            else:
                break

    def other_situation(self):
        # 开另一个线程来检测是否发生异常.持续检测的线程,就不要经常刷新日志了.
        view_text = self.get_text()  # 可能会空.
        view_content = self.driver.app_elements_content_desc(self.view)
        if len({'紧急停止', '若需恢复工作', '请解除急停状态'} & set(view_text)) >= 3:
            # 急停的情况.
            logger.info("Robot is emergence stop,exit script.")
            exit(-104)
        elif '配置' in ''.join(view_content[:3]):  # 拉取配置界面,完成一定是靠前的
            # 获取配置的情况.
            logger.info(f"Webportal or GoGoInsight change some config.Wait a while to get it.")
            count = 5
            while count > 0:
                try:
                    # 考虑网速差,拉取的配置较大的情况.多给点时间.不过拉不完也会重新进来的,问题不大.
                    self.driver.click_element(locator=(By.XPATH, '//android.widget.Button[@content-desc="完成"]'), wait=5)
                    logger.info("Get config success,continue picking")
                    break
                except:
                    count -= 1
                    sleep(1)

        elif '日志' in ''.join(view_content[:3]):
            # 收集日志的情况
            logger.info("Robot is stopped,uploading log.")
            exit(-404)
        elif self.driver.element_display(
                locator=(By.XPATH, '//android.widget.CheckBox[contains(@text,"/sdcard/log")]')):
            logger.info("SpeedPicker is exit,Robot is uploading log")
            exit(-404)
        elif self.driver.element_display(locator=(By.XPATH, '//*[@content-desc="设置"]')):
            logger.info("GGR in setting page.")
            exit(-404)
        else:
            tmp_text = self.get_text(wait=10)
            if {'等待任务中', '绑定载物箱', '前往', '请扫描载物箱码或任意格口码', '已取下', '拣货异常', '拣货中', '异常上报', '输入', '暂停', '恢复'} & set(
                    tmp_text):
                # logger.info("Robot is Picking,don't worry")
                return
            else:
                logger.info("Raising some except,please check by yourself.")
                exit(-500)

    def debug_check(self):
        # 调试脚本效率的,与SP无关.
        while True:
            sleep(1)
            # try:
            print(f"{get_time()} view文本:{self.driver.app_elements_text(self.view)}")
            # except:
            #     print("?????")
            print(f"view_content:{self.driver.app_elements_content_desc(self.view)}")
            print(f"image_content:{self.driver.app_elements_content_desc(self.image)}")
            image_ico = self.driver.find_elements(self.image)
            for i in self.driver.app_elements_content_desc(self.view):
                if "SkillSpace" in i:
                    ico_name = i.split('\n')
                    self.driver.click_one(image_ico[-(len(ico_name) - ico_name.index('SpeedPicker'))])
                    print(f"{get_time()} 点击SpeedPicker")
            try:
                self.click_view_text("退出", wait=60)
                sleep(1)  #
            except:
                pass

    def main(self):
        """主业务流程，通过不断的抓取页面信息。去确定当前SpeedPicker运行状态"""
        self.open_sp()
        while True:
            self.press_ok()  # 应对随时弹出来的需要协助，提示框。
            try:
                view_ls = self.get_text(wait=15)  # 当前页面文本信息。
            except:
                continue
            ls = ''.join(view_ls)  # 这个是长文本。用来做一些特殊判断。
            use_text = {'等待任务中', '绑定载物箱', '载物箱已满?', '前往', '请扫描载物箱码或任意格口码', '已取下', '拣货异常', '拣货中', '异常上报', '输入', '暂停',
                        '恢复', '请取下载物箱 或 卸载载具上的货物', '打包'}
            if self.random_trigger(n=30):
                logger.debug(f"Randomly print log：{view_ls}")  # 调试打印的，后面不用了
            elif len(use_text & set(view_ls)) == 0:
                logger.warning(
                    f"Interface get need text fail，please check is exit SpeedPicker。\nNow Get text list:{view_ls}")
                sleep(5)
                if ['紧急停止', '若需恢复工作', '请解除急停状态'] in view_ls:
                    break
                elif self.random_trigger(3):  # 有时候只是卡一下界面,并不需要一直检查是不是发生了异常.
                    self.other_situation()
            elif '等待任务中' in view_ls:
                logger.info("Robot is waiting for task,please send orders。\n")  # 整两个空行来区分一下任务。
                self.wait_moment("等待任务中")
            elif '前往' in view_ls:
                locate = view_ls[view_ls.index('前往') + 1]  # 前往的后一个，就是目标地点。
                logger.info(f"The robot is going：{locate},please wait。")
                if self.random_trigger(n=30):  # 触发随机。
                    self.pause_move()  # 暂停移动。
                self.wait_moment("前往")
            elif '绑定载物箱' in ''.join(view_ls).replace(' ', ''):
                self.bind_carrier()
            elif len({'拣货中', '请拣取正确货品并扫码', '完成', '异常上报', '拣货数量/需拣数量', '拣货数量'} & set(view_ls)) > 2:
                # 拿到这个，说明在拣货页面。需要根据几种情况去进行处理操作。
                self.picking()  # 封装成函数，单独处理。
            elif '已取下' in ls:
                self.press_ok()  # 确定波次.
                # 异常处理区,或者订单异常终止,都是这个流程,无需重复点.
                self.click_view_text("已取下")  # 强点.
                logger.info("Finished one task,good job!")
                logger.info('~*' * 25 + '\n')
                self.wait_moment('已取下')
            elif '拣货异常' in ls:  # 异常处理区.
                logger.info("Robot in Error area，error goods list：")
                err_info = self.get_text()
                if "已取下" not in err_info:
                    for item in err_info:
                        if item != '':
                            logger.info(f"Error goods list:{item}")
            elif view_ls[0] == "异常上报":  # 异常上报界面.
                logger.info("Now in the report error interface。")
                self.do_err()
            elif self.islosepos():
                logger.error("Device lose pose。")
                break  # 跑不动了。
            else:
                pass

if __name__ == '__main__':
    while True:
        try:
            sp = SpeedPicker()
            sp.main()
            # sp.debug_check()
        except KeyboardInterrupt:
            logger.info("Stop script manual.")
            reset_keyboard(SpeedPicker().device_num()[0])  # reset keyboard
            break
        except Exception as e:
            timeout = 10
            logger.error(
                f"Other except raising,{timeout}s will restart script，Except device："
                f"{SpeedPicker().device_num()[0]},{SpeedPicker().device_num()[1]}:"
                f"\n1.Check Appium server.\n2.Check appium port.\n3.Check device udid(Pad IP).\n4.Check your devices is online")
            logger.warning(f"Raising except is:{e}")
            logger.info(f"Error line:{traceback.format_exc()}")
            sleep(timeout)


from django.contrib import admin
from .models import Course, Module, Topic, Content

class ModuleInline(admin.TabularInline):
    model = Module
    extra = 1  # Number of empty forms to display

class TopicInline(admin.TabularInline):
    model = Topic
    extra = 1  # Number of empty forms to display

class ContentInline(admin.TabularInline):
    model = Content
    extra = 1  # Number of empty forms to display

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    inlines = [ModuleInline, TopicInline, ContentInline]

# @admin.register(Module)
# class ModuleAdmin(admin.ModelAdmin):
#     pass

# @admin.register(Topic)
# class TopicAdmin(admin.ModelAdmin):
#     pass

# @admin.register(Content)
# class ContentAdmin(admin.ModelAdmin):
#     pass


from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm
from .forms import CustomUserCreationForm, CustomUserChangeForm, CustomAuthenticationForm
from django.http import JsonResponse

# 로그인 view
def login(request):
    if request.user.is_authenticated:
        return redirect('posts:index')

    if request.method == 'POST':
        form = CustomAuthenticationForm(request, request.POST)
        if form.is_valid():
            auth_login(request, form.get_user())
            return JsonResponse({'valid': True})
    else:
        form = CustomAuthenticationForm()

    error = form.errors
    context = {
        # 'form': form,
        'valid': False,
        'error': error,
    }
    return JsonResponse(context)

# 로그아웃 view
def logout(request):
    if request.user.is_authenticated:
        auth_logout(request)
    return redirect('posts:index')

# 회원가입 view
def signup(request):
    if request.user.is_authenticated:
        return redirect('posts:index')

    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            auth_login(request, user)
            return JsonResponse({'valid': True})
            return redirect('posts:index')
    else:
        form = CustomUserCreationForm()

    error = form.errors
    print(list(error.keys()))
    context = {
        # 'form': form,
        'valid': False,
        'error_field': list(error.keys())[0],
        'error': error,
    }
    return JsonResponse(context)
    context = {
        'form': form,
    }
    return render(request, 'accounts/signup.html', context)

# 프로필 view
def profile(request, username):
    User = get_user_model()
    person = User.objects.get(username=username)
    context = {
        'person': person,
    }
    return render(request, 'accounts/profile.html', context)

# 프로필 수정 view
@login_required
def update(request):
    if request.method == 'POST':
        form = CustomUserChangeForm(request.POST, instance=request.user)
        if form.is_valid():
            form.save()
        return redirect('posts:index')
    else:
        form = CustomUserChangeForm(instance=request.user)
    context = {
        'form': form,
    }
    return render(request, 'accounts/update.html', context)

# 팔로잉 view
@login_required
def follow(request, user_pk):
    User = get_user_model()
    person = User.objects.get(pk=user_pk)

    if person != request.user:
        if request.user in person.followers.all():
            person.followers.remove(request.user)
            is_followed = False
        else:
            person.followers.add(request.user)
            is_followed = True

        context = {
            'is_followed': is_followed,
            'following_count': person.followings.count(),
            'follower_count': person.followers.count(),
        }
        return JsonResponse(context)

    return redirect('accounts:profile', person.get_username)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 19 17:06:48 2022

@author: michaellee
"""

def findSubstringIterative(needle, haystack):
    i = 0
    while i < len(haystack):
        if haystack[i:i + len(needle)] == needle:
            return i
        i += 1
    return -1

def findSubstringRecursive(needle, haystack, i=0):
    if i >= len(haystack):
        return -1
    if haystack[i:i + len(needle)] == needle:
        return i
    else:
        return findSubstringRecursive(needle, haystack, i + 1)

print(findSubstringIterative('cat', 'My cat Zophie'))
print(findSubstringRecursive('cat', 'My cat Zophie'))


#!/usr/bin/env python
#
# Author: Oscar Benjamin
# Date: Feb 2021
# Description:
#   Command line script to find integer roots of polynomials with
#   integer coefficients.

#-------------------------------------------------------------------#
#                                                                   #
#                   Command-line interface                          #
#                                                                   #
#-------------------------------------------------------------------#

PROGRAM_EXPLANATION = """
Usage:
$ python roots.py COEFF1 COEFF2 ...

Find integer roots of a polynomial with integer coefficients.

Example:

Find the roots of x^4 - 3x^3 - 75x^2 + 475x - 750.

$ python roots.py 1 -3 -75 475 -750
-10
3
5
"""

def main(*arguments):
    """Main entry point for the program"""
    if not arguments:
        print(PROGRAM_EXPLANATION)
        return

    poly = parse_coefficients(arguments)
    roots = integer_roots(poly)
    print_roots(roots)

def parse_coefficients(arguments):
    """Convert string arguments to integer

    >>> parse_coefficients(["2", "3"])
    [2, 3]
    """
    return [int(arg) for arg in arguments]

def print_roots(roots):
    """Print the roots one per line if there are any

    >>> print_roots([2, 3])
    2
    3
    """
    if roots:
        roots_str = [str(r) for r in roots]
        print('\n'.join(roots_str))

#-------------------------------------------------------------------#
#                                                                   #
#                      Polynomial functions                         #
#                                                                   #
#-------------------------------------------------------------------#

class BadPolynomialError(Exception):
    """Raised by polynomial routines when the polynomial is invalid.

    A valid polynomial is a list of coefficients like [1, 2, 1]

    The first (leading) coefficient must *not* be zero in a valid polynomial.
    """
    pass

def find_factors(x):
    factors = []
    # in the ascending order of absolute values
    if x > 0:
        for i in range(1, x + 1):
            if x % i == 0:
                factors.append(i)
    elif x < 0:
        for i in range(x, 0):
            if x % i == 0:
                factors.insert(0, i)
    else:
        factors.append(0)
    return factors

def integer_roots(poly):
    num_coef = len(poly)
    # add exceptions
    if (num_coef>0 and (poly[0]==0 or not isinstance(poly[0], int) ) ) \
        or not isinstance(poly, list):
        raise BadPolynomialError("Invalid coefficients")

    print(poly)
    if num_coef == 0:
        return []
    # find integer factors of a_0 and a_n
    ps = find_factors(poly[-1])
    qs = find_factors(poly[0])
    # find rational roots
    int_roots = []
    for p in ps:
        for q in qs:
            # only keep integer roots
            if p % q == 0:
                tmp = p/q
                # use append for positive, insert for negative
                if tmp < 0: tmp = -1*tmp
                if is_root(poly, tmp):
                    int_roots.append(tmp)
                if is_root(poly, -1*tmp):
                    int_roots.insert(0, -1*tmp)
    return int_roots

def evaluate_polynomial(poly, xval):
    num_coef = len(poly)
    # add exceptions
    if (num_coef>0 and (poly[0]==0 or not isinstance(poly[0], int) ) ) \
        or not isinstance(poly, list):
        raise BadPolynomialError("Invalid coefficients")
    # no coefficients given
    if num_coef == 0:
        return 0
    # evaluating
    val = 0
    for i in range(num_coef):
        power = num_coef-i-1
        val = val + poly[i] * (xval**power)
    return val

def is_root(poly, xval):
    num_coef = len(poly)
    # add exceptions
    if (num_coef>0 and (poly[0]==0 or not isinstance(poly[0], int) ) ) \
        or not isinstance(poly, list):
        raise BadPolynomialError("Invalid coefficients")
    # test root
    val = 0
    for i in range(num_coef):
        power = num_coef-i-1
        val = val + poly[i] * (xval**power)
    if val == 0:
        return True
    else:
        return False

#-------------------------------------------------------------------#
#                                                                   #
#                           Unit tests                              #
#                                                                   #
#-------------------------------------------------------------------#

#
# Run these tests with pytest:
#
#    $ pytest roots.py
#

def test_evaluate_polynomial():
    assert evaluate_polynomial([], 1) == 0
    assert evaluate_polynomial([1], 2) == 1
    assert evaluate_polynomial([1, 2], 3) == 5
    assert evaluate_polynomial([1, 2, 1], 4) == 25

    # Invalid inputs should raise BadPolynomialError
    from pytest import raises
    raises(BadPolynomialError, lambda: evaluate_polynomial([0], 1))
    raises(BadPolynomialError, lambda: evaluate_polynomial({}, 1))
    raises(BadPolynomialError, lambda: evaluate_polynomial([[1]], 1))

def test_is_root():
    assert is_root([], 1) is True
    assert is_root([1], 1) is False
    assert is_root([1, 1], 1) is False
    assert is_root([1, 1], -1) is True
    assert is_root([1, -1], 1) is True
    assert is_root([1, -1], -1) is False
    assert is_root([1, -5, 6], 2) is True
    assert is_root([1, -5, 6], 3) is True
    assert is_root([1, -5, 6], 4) is False

    # Invalid inputs should raise BadPolynomialError
    from pytest import raises
    raises(BadPolynomialError, lambda: is_root([0], 1))
    raises(BadPolynomialError, lambda: is_root({}, 1))
    raises(BadPolynomialError, lambda: is_root([[1]], 1))

def test_integer_roots():
    # In the case of the zero polynomial every value is a root but we return
    # the empty list because we can't list every possible value!
    assert integer_roots([]) == []
    assert integer_roots([1]) == []
    assert integer_roots([1, 1]) == [-1]
    assert integer_roots([2, 1]) == []
    assert integer_roots([1, -5, 6]) == [2, 3]
    assert integer_roots([1, 5, 6]) == [-3, -2]
    assert integer_roots([1, 2, 1]) == [-1]
    assert integer_roots([1, -2, 1]) == [1]
    assert integer_roots([1, -2, 1]) == [1]
    assert integer_roots([1, -3, -75, 475, -750]) == [-10, 3, 5]

    # Invalid inputs should raise BadPolynomialError
    from pytest import raises
    raises(BadPolynomialError, lambda: integer_roots([0]))
    raises(BadPolynomialError, lambda: integer_roots({}))
    raises(BadPolynomialError, lambda: integer_roots([[1]]))

if __name__ == "__main__":
    import sys
    arguments = sys.argv[1:]
    main(*arguments)


import numpy as np
import random
from timeit import default_timer as timer

def create_rand_array(size, low_bound=0, upp_bound=100):
    r = []
    start = timer()
    for i in range(size):
        r.append(random.randint(low_bound, upp_bound))
    end = timer()
    print("Temp creazione array (random):", (end-start), "secondi")
    return r

def create_ordered_array(size):
    o = []
    start = timer()
    for j in range(size):
        o.append(int(j))
    end = timer()
    print("Temp creazione array (ordinato):", (end-start))
    return o

def create_inverted_array(size):
    u = []
    start = timer()
    for i in range(size):
        u.append(int(-i))
    end = timer()
    print("Temp creazione array (invertito):", (end-start))
    return u


class Queue:

    def __init__(self):
        self.q = []
        self.count = 0

    def enqueue(self, item):
        self.q.append(item)
        self.count += 1

    def dequeue(self):
        removed_element = self.q[0]
        self.q.pop(0)
        self.count -= 1
        return removed_element

    def size(self):
        return(self.count)

    def isEmpty(self):
        return self.count == 0

q = Queue()
q.enqueue(5)
q.enqueue(6)
print(q.size())
print(q.isEmpty())
print("Removing: {}".format(q.dequeue()))
print(q.size())
print(q.isEmpty())
print("Removing: {}".format(q.dequeue()))
print(q.size())
print(q.isEmpty())


from django.shortcuts import render
from .models import Book
from django.http import JsonResponse
from .serializers import BookSerializer
from rest_framework import generics
from django.views.decorators.csrf import csrf_exempt
import json

def index(request):
    return render(request, 'index.html')

# get all books
def get_books(request):
    if request.method == 'GET':
        books = Book.objects.all()
        return JsonResponse(list(books.values()), safe=False)
    return JsonResponse({'message': 'Invalid request'}, status=400)

# get book by id
def get_books_by_id(request, pk):
    try:
        books = Book.objects.get(pk=pk)
        data = {
            'id': books.id,
            'title': books.title,
            'author': books.author,
            'desc': books.desc,
        }
        return JsonResponse(data)
    except Book.DoesNotExist:
        return JsonResponse({'message': 'Book does not exist'}, status=404)

# create book with serializers class
class BookCreateView(generics.CreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# update book by id
@csrf_exempt
def update_book(request, pk):
    try:
        book = Book.objects.get(pk=pk)
        if request.method == 'PUT':
            data = json.loads(request.body)
            book.title = data['title']
            book.author = data['author']
            book.desc = data['desc']
            book.save()
            return JsonResponse({'message': 'Book updated successfully'})
        return JsonResponse({'message': 'Invalid request'}, status=400)
    except Book.DoesNotExist:
        return JsonResponse({'message': 'Book does not exist'}, status=404)

# delete book by id
@csrf_exempt
def delete_book(request, pk):
    try:
        book = Book.objects.get(pk=pk)
        book.delete()
        return JsonResponse({'message': 'Book deleted successfully'})
    except Book.DoesNotExist:
        return JsonResponse({'message': 'Book does not exist'}, status=404)


import tkinter

import main

from algorithms.image_operations import save_image
from user_interface.algorithm_buttons import create_algorithm_buttons
from user_interface.image_selector import create_image_selector_frame

def start_user_interface():
    try:
        mainWindow = tkinter.Tk()
        mainWindow.title("ict-app")
        mainWindow.geometry("800x800")
        mainWindow.resizable(width=False, height=False)

        imageSelectionFrame = tkinter.LabelFrame(mainWindow, height=400, labelanchor=tkinter.NW, text="Image")
        create_image_selector_frame(imageSelectionFrame)
        imageSelectionFrame.pack(side=tkinter.TOP, pady=32)

        selectionFrame = tkinter.Frame(mainWindow, height=400)
        create_algorithm_buttons(selectionFrame)
        selectionFrame.pack(side=tkinter.TOP, pady=32)

        performButton = tkinter.Button(mainWindow,
                                       width=18,
                                       text="Perform Compression",
                                       command=save_image)
        performButton.pack(side=tkinter.BOTTOM, pady=32)

        mainWindow.mainloop()

    except KeyboardInterrupt:
        print("Program stopped by keyboard")


import pathlib
import blockwriter

geni_hash = "114bd151f8fb0c58642d2170da4ae7d7c57977260ac2cc8905306cab6b2acabc"

def check_if_file_is():
    print("WARNING: Creating haslist.txt")
    file = pathlib.Path('hashlist.txt')
    if not file.exists():
        file.touch()
        f = open(file, "w")
        f.write(geni_hash+"\n")
        f.close()
    blockwriter.check_if_file_is()


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

import os
from dotenv import load_dotenv

load_dotenv()

BOTUSERNAME = os.getenv("BOTUSERNAME")
TOKEN = os.getenv("TOKEN")
CREATOR = os.getenv("CREATOR")
MAIN_ADMIN = os.getenv("MAIN_ADMIN")

ADMINS = os.getenv("ADMINS").split(':')
ADMINS = [int(user_id) for user_id in ADMINS]

MS_CENTERS = "https://telegra.ph/Spisok-RS-Centrov-03-05"


from setuptools import setup, find_packages
import pathlib, os

pkg_vars = {}
with open(f'src{os.sep}vqgan_clip{os.sep}_version.py') as fp:
    exec(fp.read(), pkg_vars)

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

long_description = (here / 'README.md').read_text(encoding='utf-8')
setup(
    name='vqgan-clip-generator',
    version=pkg_vars['__version__'],
    description='Implements VQGAN+CLIP for image and video generation, and style transfers, based on text and image prompts. Emphasis on ease-of-use, documentation, and smooth video creation.',
    long_description=long_description,
    long_description_content_type='text/markdown',
    url='https://github.com/rkhamilton/vqgan-clip-generator',
    author='Ryan Hamilton',
    author_email='ryan.hamilton@gmail.com',
    classifiers=[
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Build Tools',
        'Environment :: GPU :: NVIDIA CUDA',
        'Natural Language :: English',
        'Topic :: Scientific/Engineering :: Artificial Intelligence',
        'Topic :: Scientific/Engineering :: Image Processing',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.7',
        'Programming Language :: Python :: 3.8',
        'Programming Language :: Python :: 3.9',
        'Programming Language :: Python :: 3 :: Only',
    ],
    keywords='VQGAN, VQGAN+CLIP, deep dream, neural network, pytorch',  # Optional
    package_dir={'': 'src'},  # Optional
    packages=find_packages(where='src'),  # Required
    python_requires='>=3.6, <4',
    install_requires=[
        'piexif==1.1.3',
        'ftfy==6.0.3',
        'regex==2021.9.30',
        'tqdm==4.62.3',
        'pytorch-lightning==1.4.9',
        'kornia==0.5.11',
        'imageio==2.9.0',
        'omegaconf==2.1.1',
        'taming-transformers==0.0.1',
        'torch-optimizer==0.1.0'],
    extras_require={
        'dev' : ['pytest','setuptools'],
        'test': ['pytest'],
    },
    project_urls={  # Optional
        'Bug Reports': 'https://github.com/rkhamilton/vqgan-clip-generator/issues',
        'Source': 'https://github.com/rkhamilton/vqgan-clip-generator',
    },
)


import pvml

def transfer_learning(mlpPath, cnnPath='../models/pvmlnet.npz'):
    cnn = pvml.CNN.load(cnnPath)
    mlp = pvml.MLP.load(mlpPath)

    cnn.weights[-1] = mlp.weights[0][None, None, :, :]
    cnn.biases[-1] = mlp.biases[0]

    cnn.save("../models/cakes-cnn_transferred.npz")
    return cnn


def bubble_sort(tset):
    tlist = tset.copy()
    langd = len(tlist)
    bytplats = False

    for i in range(langd-1):

        for j in range(0, langd-1):

            if( tlist[j] > tlist[j+1]):
                bytplats = True
                tlist[j], tlist[j + 1] =  tlist[j + 1], tlist[j]

        if not bytplats:
            return

    return tlist

def print_list_numbers(t_list):
    string_nr = " ".join(str(num) for num in t_list)
    print(string_nr)

def create_menu():
    print("\n-----:MENY SORTERINGS TEST----------------\n")
    print("1. Använd min egen gjoda BubbleSort")
    print("2. Använd Pythons  sort() funktion")
    print("3. Avsluta programmet\n")

    val = input("\nMata in val: ")

    return val


# import pymongo
import sys
sys.path.append("..")
import pymongo
from pymongo import MongoClient
from config import DatabaseConfig
import pprint
import datetime

class Database:
    def __init__(self) -> None:
        self.myclient = pymongo.MongoClient(DatabaseConfig.server)
        self.my_db = self.myclient[DatabaseConfig.database_name]
        self.my_col = self.my_db[DatabaseConfig.database_collection]
        self._db_schema ={
                   "uuid": "",
                   "input_path": "",
                   "output_path":"",
                   "status":"",
                   "json_count": "",
                   "last_modified":datetime.datetime.now().astimezone().isoformat()
        }

    def insert(self,id,status,input_path,output_path= None, json_count=None) -> bool:
        get_data = self.get(id)
        if get_data is not None:
            return False
        self._db_schema ={
                   "uuid": id,
                   "status":status,
                   "input_path": input_path,
                   "output_path":output_path,
                   "json_count": json_count,
                   "last_modified":datetime.datetime.now().astimezone().isoformat()
        }
        self.my_col.insert_one(self._db_schema)
        return True

    def update(self,id,output_path,status,json_count,input_path=None):
        get_data = self.get(id)
        if get_data is None:
            return False
        if input_path is None:
            f = {"uuid": id}
            values = {"$set":{"output_path":output_path,
                            "status":status,
                            "json_count":json_count,
                            "last_modified":datetime.datetime.now().astimezone().isoformat()
                            }}
            self.my_col.update_one(f,values)
            return True
        else:
            return False

    def get(self,id):
        entity = self.my_col.find_one({'uuid':id})
        return entity

#if __name__=="__main__":
    #d = Database()
    #data = d.insert("05a4f048-9a40-4aac-9a49-a90a819f588891","","pending","weapon_detection_processing/input/new_222.mp4")
    # data = d.get("05a4f048-9a40-4aac-9a49-a90a819f5888")
    # del data['_id']
    # pprint.pprint(json.dumps(data))
    # data = d.update("05a4f048-9a40-4aac-9a49-a90a819f5888","","Pending")
    # mydict = { "uuid": "@dgdfs@$@@", "Input_path": "xyz.mp4","Output_path":"xyz.avi", "status":"Pending" }
    # x = mycol.insert_one(mydict)


# -*- coding: utf-8 -*-
"""
Created on Sat Dec 16 15:10:51 2017

@author: Edward
"""
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import matplotlib.pylab as plt
import numpy as np
from scipy import sparse

class TwoLayerLinearNet(object):

  def __init__(self, name, X, Ytrue, W1_initial, W2_initial):
    W1 = tf.Variable(W1_initial, trainable=True)
    W2 = tf.Variable(W2_initial, trainable=True)

    # Yhat = W1 W2 X
    Yhat = tf.matmul(W1, tf.matmul(W2, X))
    self.variables = (W1, W2)

    # loss = || Yhat - Ytrue ||^2
    loss = tf.reduce_sum(tf.squared_difference(Yhat, Ytrue))
    self.loss = loss

    # a tensor that stores the sum of the frobenius norms of the gradients of
    # the loss wrt to the parameters
    self.gradient_magnitude = tf.sqrt(sum([
        tf.reduce_sum(dLdvar**2)
        for dLdvar in tf.gradients(loss, self.variables)
    ]))

    # this optimizer must be set before calling run_optimizer
    self.optimizer_op = None
    self.name = name
    self.losses = []
    self.plot_kwargs = {}

  def run_optimizer(self, sess, num_steps):
    self.losses = []
    self.gradient_magnitudes = []

    for it in range(num_steps):
      loss, gradient_magnitude, _ = sess.run([
          self.loss,
          self.gradient_magnitude,
          self.optimizer_op
      ])

      self.losses.append(loss)
      self.gradient_magnitudes.append(gradient_magnitude)

      # stop iterating if the loss has diverged
      if not np.isfinite(self.losses[-1]):
        break

class NetGradientDescent(TwoLayerLinearNet):

  def __init__(self, learning_rate, *args, **kwargs):
    TwoLayerLinearNet.__init__(self, 'GD step=%g' % learning_rate,
                               *args, **kwargs)

    self.optimizer_op = tf.train.GradientDescentOptimizer(
        learning_rate).minimize(self.loss, var_list=self.variables)

class NetADAM(TwoLayerLinearNet):

  def __init__(self, learning_rate, *args, **kwargs):
    TwoLayerLinearNet.__init__(self, 'ADAM step=%g' % learning_rate,
                               *args, **kwargs)

    self.optimizer_op = tf.train.AdamOptimizer(
        learning_rate).minimize(self.loss, var_list=self.variables)
    self.plot_kwargs = {'ls': '--'}

def train_nets(xdim=6, wdim=6, ydim=10, nsamples=1000,
               A_condition_number=1e-5):
    W1_initial = np.random.randn(ydim, wdim)
    W2_initial = np.random.randn(wdim, xdim)

    # the true map from x to y
    Atrue = np.linspace(1, A_condition_number, ydim
                       ).reshape(-1, 1) * np.random.rand(ydim, xdim)
    # the inputs
    X = np.random.randn(xdim, nsamples)
    # the y's to fit
    Ytrue = Atrue.dot(X)

    nets = [
        NetGradientDescent(learning_rate, X, Ytrue, W1_initial, W2_initial)
        for learning_rate in [1e-6, 1e-5, 1e-4, 1e-3]
    ] + [
        NetADAM(learning_rate, X, Ytrue, W1_initial, W2_initial)
        for learning_rate in [1e-5, 1e-4, 1e-3, 1e-2]
    ]

    with tf.Session() as sess:
      sess.run(tf.global_variables_initializer())

      for net in nets:
        net.run_optimizer(sess, 10000)

    return nets, (X, Ytrue, W1_initial, W2_initial)
nets, initial_params = train_nets()

def plot_nets(nets, show_to_max=-1):
  fig = plt.figure(figsize=(15, 10))
  ax1 = fig.add_subplot(2,1,1)
  ax2 = fig.add_subplot(2,1,2)

  for net in nets:
    show_to = -1 if show_to_max > len(net.losses) else show_to_max

    if np.isfinite(net.losses[show_to]):
      ax1.semilogy(net.losses[:show_to], label=net.name, **net.plot_kwargs)
      ax2.semilogy(net.gradient_magnitudes[:show_to], label=net.name,
                   **net.plot_kwargs)
    else:
      ax1.semilogy(net.losses[:1], marker='x', label='(diverged) ' + net.name,
                   **net.plot_kwargs)

  ax1.set_ylabel('Loss')
  ax1.legend(loc='best')
  ax2.set_ylabel('Gradient magnitude')
  ax2.legend(loc='best')
  return ax1, ax2

plot_nets(nets, -1);

def unpack_vector(x, *lengths):
  """Split up a sequence into several sequences of the given length.

  Args:
    x: a sequence
    lengths: a sequence of n lengths.
  Returns:
    A list of sequences v1...vN. vi has length lengths[i].
  """
  vectors = []
  i = 0
  for l in lengths:
    v = x[i:i+l]
    vectors.append(v)
    i += l
  assert i == len(x)
  return vectors

class LevenbergMarquardt(object):

  def __init__(self, learning_rate, X, Ytrue, W1_initial, W2_initial):
    self.learning_rate = learning_rate
    self.name = "LM step=%g" % learning_rate
    self.X = X
    self.Ytrue = Ytrue
    self.W1 = W1_initial
    self.W2 = W2_initial
    self.plot_kwargs = {}

  def take_step(self):
    "Form and solve the least squares problem above about W1, W2."

    Yhat = self.W1.dot(self.W2.dot(self.X))
    RHS = -(Yhat - self.Ytrue).T.flatten()

    LHS = np.hstack((
        np.kron(self.W2.dot(self.X).T, np.eye(self.W1.shape[0])),
        np.kron(self.X.T, self.W1)
    ))

    # solve the least squares problem and parse the solution into matrices
    dW1dW2 = np.linalg.lstsq(LHS, RHS)[0]
    dW1, dW2 = unpack_vector(dW1dW2, self.W1.size, self.W2.size)
    dW1 = dW1.reshape(self.W1.T.shape).T
    dW2 = dW2.reshape(self.W2.T.shape).T

    # apply the update to the iterates
    self.W1 = self.W1 + self.learning_rate * dW1
    self.W2 = self.W2 + self.learning_rate * dW2

  def loss(self):
    Yhat = self.W1.dot(self.W2.dot(self.X))
    return np.sum(Yhat - self.Ytrue)**2

  def run_optimizer(self, num_steps):
    self.gradient_magnitudes = []
    self.losses = []
    for _ in range(num_steps):
      self.take_step()
      self.losses.append(self.loss())

def train_lm(X, Ytrue, W1_initial, W2_initial):
  nets = []
  for step_sizes in [.05, .2]:
    net = LevenbergMarquardt(step_sizes, X, Ytrue, W1_initial, W2_initial)
    net.run_optimizer(200)
    nets.append(net)
  return nets

nets_lm = train_lm(*initial_params)