import time
import datetime
import json
import re

import requests

class WeiBo:

    def __init__(self):
        self.profile_url = "https://m.weibo.cn/profile/info"
        self.config_url = "https://m.weibo.cn/api/config"
        self.get_ch_url = "https://m.weibo.cn/api/container/getIndex?containerid=100803_-_followsuper&since_id={}"
        self.check_url = "https://api.weibo.cn/2/page/button"
        self.web_check_url = "https://weibo.com/p/aj/general/button"
        self.day_score_url = "https://huati.weibo.cn/aj/super/receivescore"
        self.get_super_score_url = "https://huati.weibo.cn/aj/super/getscore"
        self.pick_url = "https://huati.weibo.cn/aj/super/picktop"
        self.report_story_url = "https://m.weibo.cn/api/statuses/repost"
        self.comment_story_url = "https://m.weibo.cn/api/comments/create"
        self.star_story_url = "https://m.weibo.cn/api/attitudes/create"
        self.seconds = 5
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, "
                          "like Gecko) Chrome/83.0.4103.116 Mobile Safari/537.36 ",
            "cookie": ""
        }
        self.gsid = ""
        self.log = []

    def set_cookie(self, cookies):
        """
        配置类对象的cookie和gsid参数
        :param cookies: 通过 https://m.weibo.cn/ 登陆获取cookie
        :return: None
        """
        self.headers['cookie'] = cookies
        self.gsid = re.findall("SUB=(.*?);", cookies)[0]

    def get_profile(self):
        """
        获取个人信息
        :return: user_dict
        """
        profile_response = requests.get(self.profile_url, headers=self.headers)
        user = profile_response.json()["data"]["user"]
        user_dict = {
            "profile_id": user["id"],
            "profile_name": user["screen_name"],
            "profile_description": user["description"] if user["description"] else "nothing",
            "profile_avatar": user["avatar_hd"],
            "profile_gender": "fmale" if user["gender"] == "f" else "male",
            "statuses_count": user["statuses_count"],
            "follow_count": user["follow_count"],
            "followers_count": user["followers_count"],
            "profile_url": user["profile_url"],
            "all_container_id": profile_response.json()["data"]["more"].split("/")[-1]
        }
        self.log.append(f"""ID: {user["id"]}
NAME: {user["screen_name"]}
简介: {user["description"] if user["description"] else "这个人很懒，什么也没有"}
微博数: {user["statuses_count"]}
关注数: {user["follow_count"]}
粉丝数: {user["followers_count"]}
        """)
        print(f"User:{user['screen_name']}")
        return user_dict

    def get_ch_list(self):
        """
        获取超话关注列表
        :return: ch_list(列表套字典)
        """
        ch_list = []
        since_id = ""
        while True:
            ch_res = requests.get(
                url=self.get_ch_url.format(since_id),
                headers=self.headers
            )
            print(len(ch_res.json()["data"]["cards"]))
            # print(ch_res.json()["data"]["cards"])
            chg_list = []
            for chg in ch_res.json()["data"]["cards"]:
                chg_list.extend(chg["card_group"])
            # ch_json = ch_res.json()["data"]["cards"][0]["card_group"]
            ch_json = chg_list
            # print(ch_json)
            for ch in ch_json:
                if ch["card_type"] == "8":
                    ch_dict = {
                        "title": ch["title_sub"],
                        "level": ch["desc1"],
                        "status": ch["buttons"][0]["name"],
                        "url": ch["scheme"],
                        "id": re.findall('[0-9a-z]{38}', ch["scheme"])[0]
                    }
                    msg = '标题 {}，{}，签到状态 {}'.format(ch_dict["title"], ch_dict["level"], ch_dict["status"])
                    print(msg)
                    # self.log.append(msg)
                    ch_list.append(ch_dict)
            since_id = ch_res.json()["data"]["cardlistInfo"]["since_id"]
            if since_id == "":
                return ch_list

    def get_story_list(self, ch_url):
        """
        获取超话微博（前两页）
        :param ch_url: 超话url
        :return: story_list（列表套字典）
        """
        count = 0
        since_id = ""
        story_list = []
        while True:
            index_url = f"https://m.weibo.cn/api/container/getIndex?{ch_url.split('?')[-1]}&since_id={since_id}"
            index_res = requests.get(index_url, headers=self.headers)
            cards = index_res.json()["data"]["cards"]
            scheme_list = []
            for card_group in cards:
                if card_group["itemid"] == "":
                    for card in card_group["card_group"]:
                        if card["card_type"] == "9":
                            scheme_list.append(card["scheme"])
            for scheme in scheme_list:
                show_url = f"https://m.weibo.cn/statuses/show?id={re.findall('[0-9a-zA-Z]{9}', scheme)[0]}"
                detail_res = requests.get(show_url, headers=self.headers)
                story_dict = {
                    "user": detail_res.json()["data"]["user"]["screen_name"],
                    "mid": detail_res.json()["data"]["id"]
                }
                story_list.append(story_dict)
            since_id = index_res.json()["data"]["pageInfo"]["since_id"]
            count = count + 1
            if count == 2:
                return story_list

    def check_in(self, s, ch_dict):
        """
        微博国际版APP签到接口
        :param s: 特定的数字，抓包获取
        :param ch_dict: 超话信息字典,具体格式请看get_ch_list函数中
        :return:
        """
        check_data = {
            "c": "weicoabroad",
            "s": s,
            "wm": "2468_1001",
            "gsid": self.gsid,
            "from": "1299295010",
            "source": "4215535043",
            "lang": "zh_CN",
            'ua': "Redmi+K20+Pro+Premium+Edition_10_WeiboIntlAndroid_3610",
            "request_url": f"http%3A%2F%2Fi.huati.weibo.com%2Fmobile%2Fsuper%2Factive_checkin%3Fpageid%3D{ch_dict['id']}",
        }
        check_res = requests.get(
            url=self.check_url,
            params=check_data,
        )
        print(check_res.json())
        errmsg = check_res.json().get('errmsg')
        if errmsg:
            msg = f'TopicName：{ch_dict["title"]}  s参数设置有误'
            print(msg)
            self.log.append(msg)
            return msg
        elif check_res.json()['result']==388000:
            msg = f'TopicName：{ch_dict["title"]}  状态异常,需手动签到'
            print(msg)
            self.log.append(msg)
            return msg
        else:
            c_msg = check_res.json()["msg"].replace("\n", "/")
            msg = f'TopicName：{ch_dict["title"]}--{ch_dict["level"][-4:]}\n' \
                  f'Message：{c_msg}'
            print(msg)
            self.log.append(msg)
            return msg

    def get_day_score(self):
        """
         超话每日积分领取
        :return:
        """
        day_score_headers = {
            'X-Requested-With': 'XMLHttpRequest',
            'Referer': 'https://huati.weibo.cn'
        }
        day_score_headers.update(self.headers)
        score_data = {
            'type': 'REQUEST',
            'user_score': 999
        }
        day_score_res = requests.post(
            url=self.day_score_url,
            headers=day_score_headers,
            data=score_data
        )
        if day_score_res.json()["code"] == 100000:
            msg = f'今日签到获取:{day_score_res.json()["data"]["add_score"]}分'
            print(msg)
            self.log.append(msg)
            return msg
        elif day_score_res.json()["code"] == 386011:
            msg = f'{day_score_res.json()["msg"]}'
            print(msg)
            self.log.append(msg)
            return msg
        elif day_score_res.json()["code"] == 100002:
            msg = f'{day_score_res.json()["msg"]}'
            print(msg)
            self.log.append(msg)
            return msg

    def get_score_bang(self, ch_dict):
        """
        获取超话积分&打榜
        :param ch_dict: 超话信息字典,具体格式请看get_ch_list函数中
        :return:
        """
        referer_url = f"https://huati.weibo.cn/aj/super/getscore?page_id={ch_dict['id']}&aid=&from={re.findall('WEIBOCN_FROM=(.*?);', self.headers['cookie'])[0]}"
        get_score_headers = {
            "Referer": referer_url,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36",
            "cookie": self.headers.get("cookie"),
            "X-Requested-With": "XMLHttpRequest"
        }
        score_res = requests.get(referer_url, headers=get_score_headers)
        topic_name = score_res.json()["data"]["topic_name"]
        score = score_res.json()["data"]["score"]
        rank = score_res.json()["data"]["rank"]
        # print(score_res.json())
        if score_res.json()["data"]["user_total_score"] > 100:
            while True:
                pick_data = {
                    "topic_name": ch_dict["title"],
                    "page_id": ch_dict["id"],
                    "score": score_res.json()["data"]["user_total_score"],
                    "is_pub": "0",
                    "cur_rank": score_res.json()["data"]["rank"],
                    "ctg_id": score_res.json()["data"]["ctg_id"],
                    "topic_score": score_res.json()["data"]["score"],
                    "index": "select256",
                    "user_score": score_res.json()["data"]["user_total_score"],
                    "aid": "",
                    "device": '{"timezone":"Asia/Shanghai","lang":"zh","plat":"Win32",'
                              '"ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)'
                              ' Chrome/84.0.4147.105 Safari/537.36","screen":"864*1536","aid":"","from":"1110006030"}',
                    "param": score_res.json()["data"]["encryption_param"]
                }
                pick_res = requests.post(self.pick_url, headers=get_score_headers, data=pick_data)
                if pick_res.json()["code"] == 402001:
                    continue
                elif pick_res.json()["code"] == 302001:
                    print(pick_res.json()["msg"])
                    return pick_res.json()["msg"]
                else:
                    msg = f"TopicName：{topic_name}\nRank：{rank}/{score}分\nMsg：{pick_res.json()['data']['add_int_msg']}"
                    self.log.append(msg)
                    print(msg)
                    return msg
        else:
            msg = f'TopicName：{topic_name}\nRank：{rank}/{score}分\n' \
                  f'Message：当前积分为{score_res.json()["data"]["user_total_score"]}, 积分少于100，暂不打榜'
            self.log.append(msg)
            print(msg)
            return msg

    def get_st(self):
        """
        获取st参数,用于转发评论与点赞
        :return: st
        """
        st_response = requests.get(self.config_url, headers=self.headers)
        if st_response.json()["ok"] == 1:
            if str(st_response.json()["data"]["login"]) == "True":
                st = st_response.json()["data"]["st"]
                return st
            else:
                return ""
        else:
            return ""

    def report_story(self, mid, st, content):
        """
         转发微博
        :param mid: 微博mid
        :param st: get_st()获取
        :param content: 评论内容
        :return:
        """
        report_data = {
            "id": mid,
            "content": content,
            "mid": mid,
            "st": st,
            "_spr": "screen:411x731"
        }
        report_headers = {
            "referer": f"https://m.weibo.cn/compose/repost?id={mid}"
        }
        report_headers.update(self.headers)
        report_res = requests.post(self.report_story_url, headers=report_headers, data=report_data)
        if report_res.json()["ok"] == 1:
            msg = f"转发微博MID：{mid} {report_res.json()['data']['created_at']} " \
                  f"{content} 转发成功 转发后微博MID: {report_res.json()['data']['id']}"
            print(msg)
            # self.log.append(msg)
            # return msg
        else:
            msg = f"{mid} {report_res.json()['msg']}/转发失败"
            print(msg)
            # self.log.append(msg)
            # return msg

    def comment_story(self, mid, st, content):
        """
        评论微博
        :param mid: 微博mid
        :param st: get_st()获取
        :param content: 转发描述
        :return:
        """
        comment_data = {
            "content": content,
            "mid": mid,
            "st": st,
            "_spr": "screen:411x731"
        }
        comment_headers = {
            "referer": f"https://m.weibo.cn/detail/{mid}"
        }
        comment_headers.update(self.headers)
        comment_res = requests.post(self.comment_story_url, headers=comment_headers, data=comment_data)
        if comment_res.json()["ok"] == 1:
            msg = f"评论微博MID：{mid} {comment_res.json()['data']['created_at']} {content} 评论成功"
            print(msg)
            # self.log.append(msg)
            # return msg
        else:
            msg = f"{comment_res.json()['msg']}评论失败"
            print(msg)
            # self.log.append(msg)
            # return msg

    def star_story(self, mid, st):
        """
        点赞微博
        :param mid: 微博mid
        :param st: get_st()获取
        :return:
        """
        star_data = {
            "id": mid,
            "attitudes": "heart",
            "st": st,
            "_spr": "screen:411x731"
        }
        star_headers = {
            "referer": f"https://m.weibo.cn/detail/{mid}"
        }
        star_headers.update(self.headers)
        star_response = requests.post(url=self.star_story_url, headers=star_headers, data=star_data)
        if star_response.json()["ok"] == 1:
            msg = f"点赞微博MID：{mid} {star_response.json()['data']['created_at']} 点赞成功"
            print(msg)
            # self.log.append(msg)
            # return msg
        else:
            msg = "点赞失败"
            print(msg)
            # self.log.append(msg)
            # return msg

    def server_push(self, sckey):
        """
        Sever酱推送
        :param sckey: 微信推送key，通过https://sc.ftqq.com/3.version获取
        :return:
        """
        now_time = datetime.datetime.now()
        bj_time = now_time + datetime.timedelta(hours=8)
        test_day = datetime.datetime.strptime('2020-12-19 00:00:00', '%Y-%m-%d %H:%M:%S')
        date = (test_day - bj_time).days
        text = f"微博超话打卡---{bj_time.strftime('%H:%M:%S')}"
        desp = f"""
------
### 🚁Now：
```
{bj_time.strftime("%Y-%m-%d %H:%M:%S %p")}
```
{self.get_log()}

### 🚀Deadline:
```
考研倒计时--{date}天
```

>
> [GitHub项目地址](https://github.com/ReaJason/WeiBo_SuperTopics)
>
>期待你给项目的star✨
"""
        server_push_headers = {
            "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
        }
        send_url = f"https://sc.ftqq.com/{sckey}.send"
        params = {
            "text": text,
            "desp": desp
        }
        response = requests.post(send_url, data=params, headers=server_push_headers)
        return response.json()["errmsg"]

    def get_log(self):
        """
        获取日志信息
        :return: log_str
        """
        return "\n".join(self.log)

    # 每超话签到+每日积分获取+超话打榜
    def daily_task(self, cookie, s, pick_name, sckey):
        self.set_cookie(cookies=cookie)
        ch_list = self.get_ch_list()
        print("获取个人信息")
        self.log.append("### 💫User：")
        self.log.append("```")
        self.get_profile()
        self.log.append("```")
        print("开始超话签到")
        self.log.append("### ✨CheckIn：")
        self.log.append("```")
        for i in ch_list:
            time.sleep(self.seconds)
            self.check_in(s, i)
        self.log.append("```")
        print("获取每日积分")
        self.log.append("### 🔰DailyScore：")
        self.log.append("```")
        self.get_day_score()
        self.log.append("```")
        # print("开始打榜")
        # self.log.append("### 💓Pick：")
        # self.log.append("```")
        # self.get_score_bang([i for i in ch_list if i["title"] == pick_name][0])
        # self.log.append("```")
        self.server_push(sckey)

if __name__ == '__main__':
    # test()
    cookie = input()
    s = input()
    pick = input()
    sckey = input()
    check = WeiBo()
    check.daily_task(cookie=cookie, s=s, pick_name=pick, sckey=sckey)


#!/usr/bin/env python3
isbns=set()
asins=set()
with open("ca-book-asin_isbn.txt") as f:
    f.readline()
    for line in f:
        try:
            asin,isbn=line.strip().split('\t')
            isbn=isbn.strip()
        except:
            continue
        isbn_len=len(isbn)
        if isbn_len<10:
            isbn=('0'*(10-isbn_len))+isbn
        isbns.add(isbn)
        asins.add(asin)
isbns=list(isbns)
asins=list(asins)
isbns.sort()
asins.sort()
isbn_file=open("isbn.txt",'w')
isbn_file.write('\n'.join(isbns))
isbn_file.close()
asin_file=open("haszhendian-asin.txt",'w')
asin_file.write('\n'.join(asins))
asin_file.close()


# scroll.py

from source.common import scroll
from source.maps import create_field_matrix

import curses

def main(screen):
    curses.curs_set(0)
    world = create_field_matrix(100, 50, '#')
    w, h = len(world[0]), len(world)
    px, py = 0, 0

    while True:
        camera_x = scroll(px, 80, w)
        camera_y = scroll(py, 25, h)
        for y in range(camera_y, camera_y + 25):
            for x in range(camera_x, camera_x + 80):
                c = world[y][x]
                try:
                    screen.addch(y - camera_y, x - camera_x, c)
                except:
                    screen.insch(y - camera_y, x - camera_x, c)

        try:
            screen.addch(py - camera_y, px - camera_x, '@')
        except:
            screen.insch(px - camera_y, py - camera_x, '@')

        screen.refresh()
        c = screen.getch()
        if c == ord('q') or c == 27:
            break
        elif c == curses.KEY_UP:
            py -= 1
        elif c == curses.KEY_DOWN:
            py += 1
        elif c == curses.KEY_LEFT:
            px -= 1
        elif c == curses.KEY_RIGHT:
            px += 1
        px = min(99, max(0, px))
        py = min(49, max(0, py))

if __name__ == "__main__":
    curses.wrapper(main)


import logging

logger = logging.getLogger(__name__)

class AnalysisResult(object):
    def __init__(self,
                 md5,
                 score=0,
                 short_result='',
                 long_result='',
                 last_scan_date=None,
                 last_error_msg='',
                 last_error_date=None,
                 stop_future_scans=False,
                 binary_not_available=False):
        self.md5 = md5
        self.short_result = short_result
        self.long_result = long_result
        self.last_error_msg = last_error_msg
        self.last_error_date = last_error_date
        self.last_scan_date = last_scan_date
        self.score = score
        self.stop_future_scans = stop_future_scans
        self.binary_not_available = binary_not_available


# Задача-1: Написать класс для фигуры-треугольника, заданного координатами трех точек.
# Определить методы, позволяющие вычислить: площадь, высоту и периметр фигуры.
import math
class Triangle:
    def __init__(self, x1, y1, x2, y2, x3, y3):
        self.x1 = x1
        self.x2 = x2
        self.x3 = x3
        self.y1 = y1
        self.y2 = y2
        self.y3 = y3
        self.a = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
        self.b = math.sqrt((x3 - x1) ** 2 + (y3 - y1) ** 2)
        self.c = math.sqrt((x3 - x2) ** 2 + (y3 - y2) ** 2)

    def area(self):  # Площадь
        return abs(self.x1*(self.y2 - self.y3) + self.x2*(self.y3 - self.y1) + self.x3*(self.y1 - self.y2)) / 2.0

    def height(self):  # Высота
        return f'a= {round(2*self.area()/self.a,1)} \n ' \
               f'Высота: b= {round(2*self.area()/self.b,1)} \n ' \
               f'Высота: c= {round(2*self.area()/self.c,1)}'

    def perimeter(self):  # Переметр
        return self.a + self.b + self.c

point = Triangle(1, 1, 2, 4, 3, 2)

print(f'Площадь: {point.area()}')
print(f'Высота: {point.height()}')
print(f'Периметр: {point.perimeter()}')

# Задача-2: Написать Класс "Равнобочная трапеция", заданной координатами 4-х точек.
# Предусмотреть в классе методы:
# проверка, является ли фигура равнобочной трапецией;
# вычисления: длины сторон, периметр, площадь.

class Trapezium:
    def __init__(self,x1,y1,x2,y2,x3,y3,x4,y4):
        self.x1 = x1
        self.x2 = x2
        self.x3 = x3
        self.y1 = y1
        self.y2 = y2
        self.y3 = y3
        self.x4 = x4
        self.y4 = y4

    def proverka(self):
        c = math.sqrt(((self.x2 - self.x1) ** 2) + ((self.y2 - self.y1) ** 2))
        d = math.sqrt(((self.x4 - self.x3) ** 2) + ((self.y4 - self.y3) ** 2))

        if c == d:
            return("Трапеция равнобокая")
        else:
            return("Трапеция неравнобокая")

    def area(self):  # Площадь
        c = math.sqrt(((self.x2 - self.x1) ** 2) + ((self.y2 - self.y1) ** 2))
        d = math.sqrt(((self.x4 - self.x3) ** 2) + ((self.y4 - self.y3) ** 2))
        a = math.sqrt(((self.x3 - self.x2) ** 2) + ((self.y3 - self.y2) ** 2))
        b = math.sqrt(((self.x4 - self.x1) ** 2) + ((self.y4 - self.y1) ** 2))
        return f'Площадь равна: {((a+b)/2)*(math.sqrt((c**2)-((((b-a)**2)+(c**2)-(d**2))/(2*(b-a)))))}'

    def perimeter(self):  # Периметр
        c = math.sqrt(((self.x2 - self.x1) ** 2) + ((self.y2 - self.y1) ** 2))
        d = math.sqrt(((self.x4 - self.x3) ** 2) + ((self.y4 - self.y3) ** 2))
        a = math.sqrt(((self.x3 - self.x2) ** 2) + ((self.y3 - self.y2) ** 2))
        b = math.sqrt(((self.x4 - self.x1) ** 2) + ((self.y4 - self.y1) ** 2))
        return f'Периметр равен: {a + b + c + d}'

    def side(self):  # Длинны сторон
        c = math.sqrt(((self.x2 - self.x1) ** 2) + ((self.y2 - self.y1) ** 2))
        d = math.sqrt(((self.x4 - self.x3) ** 2) + ((self.y4 - self.y3) ** 2))
        a = math.sqrt(((self.x3 - self.x2) ** 2) + ((self.y3 - self.y2) ** 2))
        b = math.sqrt(((self.x4 - self.x1) ** 2) + ((self.y4 - self.y1) ** 2))
        return f'Длина сторон: \nAB: {a} \nBC: {c} \nCD: {d} \nDC: {b}'

    point = Trapezium(0, 1, 2, 3, 4, 5, 6, 7)

    print(point.proverka())
    print(point.perimeter())
    print(point.area())
    print(point.side())


from torch._C import device
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import init
import torch
import numpy as np

class CMD_BLOCK(nn.Module):
    def __init__(self,emb_s=256):
        super(CMD_BLOCK,self).__init__()
        dim = emb_s*2
        # self.emb_Layer = EmbfixLayer()
        self.L1 = nn.Linear(dim,dim)
        self.activation = nn.ReLU()
        self.L2 = nn.Linear(dim,int(dim/2))
        self.L3 = nn.Linear(int(dim/2),int(dim/4))
        self.L4 = nn.Linear(int(dim/4),1)
        self.dropout = nn.Dropout(0.2)
        self.sig_class = nn.Sigmoid()

    def forward(self,x):
        # x = self.emb_Layer(x)
        x = self.L1(x) #.type(torch.FloatTensor)
        x = self.activation(x)
        x = self.L2(x)
        x = self.activation(x)
        x = self.L3(x)
        x = self.activation(x)
        x = self.dropout(x)
        x = self.L4(x)
        # x = self.sig_class(x)
        return x

class CIND_Block(nn.Module):
    def __init__(self, dim = 7):
        super(CIND_Block,self).__init__()
        in_ch = 2048
        n_ch = 256
        self.dim = dim
        # self.op_1 = CIN_diff
        self.cnv1 = nn.Conv2d(n_ch, n_ch, 5, 5)
        self.cnv2 = nn.Conv2d(n_ch, n_ch, 3)
        self.cnv3 = nn.Conv2d(n_ch, n_ch, 3)
        self.relu = nn.ReLU(inplace=True)
        self.bn = nn.BatchNorm2d(n_ch)
        self.avgpool = nn.AdaptiveAvgPool2d(1)
        self.L1 = nn.Linear(n_ch, 1)

    def forward(self, x):

        # x = self.op_1(x)
        x = self.cnv1(x)
        x = self.relu(x)
        x = self.cnv2(x)
        x = self.relu(x)
        x = self.cnv3(x)
        x = self.relu(x)
        x = self.bn(x)
        x = self.avgpool(x)
        #dropout Flatten, Dense, Lambda
        x = x.view(x.size(0), -1)
        x = self.L1(x)

        return x

class CIND(nn.Module):
    def __init__(self):
        super(CIND, self).__init__()
        cind_block = CIND_Block
        self.f_block = self._make_layers(cind_block)

    def _make_layers(self,block):
        layers = []
        layers.append(block())
        return nn.Sequential(*layers)
    def forward(self, x):
        x = self.f_block(x)
        return x

class CMD(nn.Module):
    def __init__(self, emb_s = 256):
        super(CMD, self).__init__()
        cmd_block = CMD_BLOCK
        self.f_block = self._make_layers(cmd_block)
        # device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    def _make_layers(self,block):
        layers = []
        layers.append(block())
        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.f_block(x)
        return x

class EmbfixLayer(nn.Module):
    def __init__(self):
        super(EmbfixLayer,self).__init__()
        # self.no_img, self.emb_size = x.size()[0], x.size()[1]

    def forward(self, x):
        x = torch.cat((
            x.view(1,x.size()[0],x.size()[1]).tile((x.size()[0],1,1)),
            x.tile(1,1,x.size()[0]).reshape(x.size()[0], x.size()[0],x.size()[1])
            ),2).reshape(-1,x.size()[1]*2)
        return x

def CMDLoss(input, target):
    # edit targets
    no_img = target.size()[0]
    t_v = torch.transpose(target.tile(1,no_img),0,1)
    t_h = target.view(no_img,1).tile(1,no_img).view(no_img*no_img,1)
    target_mat = torch.eq(t_v, t_h).type(torch.FloatTensor).to(torch.device('cuda'))
    loss = nn.BCEWithLogitsLoss()
    return loss(input, target_mat)

def CMD_Lbl_maker(target): #(1744, 1)
    if not torch.is_tensor(target):
            target = torch.tensor(target)
    no_img = target.size()[0]
    t = target.view((-1))
    t_v = torch.transpose(t.tile(1,no_img),0,1)
    t_h = t.view(no_img,1).tile(1,no_img).view(no_img*no_img,1)
    t = torch.eq(t_v, t_h).type(torch.FloatTensor).to(torch.device('cuda'))
    return t

def CIN_diff(target): #(32 128 7 7)
    scale = 5
    upsam_op = torch.nn.Upsample(scale_factor=scale,mode='nearest') ## fixit
    pading = torch.nn.ZeroPad2d(2)

    # A to B tiling the batch dimension
    x_r = torch.tile(target,(target.size()[0],1,1,1)) # 123,123,123
    x_l = torch.tile(target,(1,target.size()[0],1,1)).view(-1,target.size()[1],target.size()[2],target.size()[3]) #111,222,333

    # tiling in the spacial dimension
    x_l = upsam_op(x_l)

    x_r = pading(x_r)
    slice_x = []
    slice_y = []
    for x_i in range(2, x_r.size()[2] -2):
        for x_j in range(2, x_r.size()[3]-2):
            slice_y.append(x_r[:,:,x_i-2:x_i+3,x_j-2:x_j+3])
            # print(x_i, x_j)
            # print(x_r[0,0,x_i-2:x_i+3,x_j-2:x_j+3])
        slice_x.append(torch.cat(slice_y,dim=3))
        slice_y= []

    x_r = torch.cat(slice_x,dim=2)

    diff = torch.sub(x_l,x_r)

    # B to A tiling the batch dimension
    x_l = torch.tile(target,(target.size()[0],1,1,1)) # 123,123,123
    x_r = torch.tile(target,(1,target.size()[0],1,1)).view(-1,target.size()[1],target.size()[2],target.size()[3]) #111,222,333

    # tiling in the spacial dimension
    x_l = upsam_op(x_l)

    x_r = pading(x_r)
    slice_x = []
    slice_y = []
    for x_i in range(2, x_r.size()[2] -2):
        for x_j in range(2, x_r.size()[3]-2):
            slice_y.append(x_r[:,:,x_i-2:x_i+3,x_j-2:x_j+3])
        slice_x.append(torch.cat(slice_y,dim=3))
        slice_y= []
    x_r = torch.cat(slice_x,dim=2)

    diff = torch.cat((torch.sub(x_l,x_r),diff),dim=1)

    # for x_i in range(2, x_r.size()[2] -2):
    #     for x_j in range(2, x_r.size()[3]-2):
    #         slice_y.append(x_r[:,:,x_i-2:x_i+3,x_j-2:x_j+3])
    #         print(x_i, x_j)
    #         print(x_r[0,0,x_i-2:x_i+3,x_j-2:x_j+3])
    #         print(x_l[0,0,x_i-2:x_i+3,x_j-2:x_j+3])

    return diff

def CINDLoss(input, target):
    ## NEEDS TO BE IMPLEMENTED
    # x_r = torch.tile(target,(target.size()[0],1,1,1)) # 123,123,123
    # x_l = torch.tile(target,(1,target.size()[0],1,1)).view(-1,target.size()[1],target.size()[2],target.size()[3]) #111,222,333

    no_img = target.size()[0]
    t_v = torch.transpose(target.tile(1,no_img),0,1)
    t_h = target.view(no_img,1).tile(1,no_img).view(no_img*no_img,1)
    target_mat = torch.eq(t_v, t_h).type(torch.FloatTensor).to(torch.device('cuda'))

    loss = nn.BCEWithLogitsLoss()
    return loss(input, target_mat)

# dim = 7
# ch = 128
# emb = 400
# x = torch.arange(0,emb * ch* dim * dim).view([emb, ch, dim, dim]).type(torch.float)
# y = CIND_Block()
# x =  y(x)


# -*- coding: utf-8 -*-
"""
@author: Wei, Shuowen

https://leetcode.com/problems/3sum-closest/

"""
class Solution(object):
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        n = len(nums)
        if n < 3:
            return 0
        nums.sort()

        def twoSum(nums, start, target):
            low = start
            high = len(nums) - 1
            local_delta = 2 ** 32
            while low < high:
                twoSum = nums[low] + nums[high]
                if abs(target - twoSum) < abs(local_delta):
                    local_delta = target - twoSum
                    res = target - local_delta
                if twoSum > target:
                    high -= 1
                else:
                    low += 1
            return res

        delta = 2**32
        res = 0
        for i in range(0, n-2):
            threeSum = nums[i] + twoSum(nums, i + 1, target - nums[i])
            if abs(target - threeSum) < abs(delta):
                delta = target - threeSum
                res = threeSum
        return res


#Jacob Smith Cosi 119A 9/26/2019
#Roomba Assignment, used wander.py as template
#Moves robot backward to demonstrate website ability to add user files
#Demonstrates wall avoiding capabaility neccesary for a ROOMBA robot
#Robot moves for 60 seconds in simulation and real life
#!/usr/bin/env python

#import necesary libraries
import rospy
from geometry_msgs.msg import Twist

# Same code can be a publisher and a subscriber, this is no problem
# be ready to publish the cmd_vel topic of class Twist
cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=1)

# Declare us to be a node
rospy.init_node('roomba')
state_change_time = rospy.Time.now()

#Set up loop to decide if robot is driving forward or turning
rate = rospy.Rate(10)
while not rospy.is_shutdown():
    # Create an all zero Twist() message. Note a new one is created each loop
    twist = Twist()
    twist.linear.x=.5
    #publish robot motion
    cmd_vel_pub.publish(twist)
    # Sleep for 1/rate seconds
    rate.sleep()


#encoding: UTF-8

# Autor: Carlos Pano Hernandez, A01066264
# Descripcion: Se imprime la distancia recorrida en 6 y 10 hrs con cualquier velocidad en Km/h. Se imprime de igual manera el tiempo que toma recorrer 500 km.
# A partir de aquí escribe tu programa

#Paso 1: Introducir velocidad
velocidadValor= input ("Introduce la velocidad del coche:")
velocidad = int(velocidadValor)

#Paso 2: 6 hrs
distanciaSeis = velocidad*6

#Paso 3: 10 hrs
distanciaDiez = velocidad*10

#Paso 4: Tiempo para 500Km
tiempoQuinientos = 500/velocidad

#Paso 4: Imprimir 2, 3 y 4
print ("Distancia recorrida en 6 hrs:",distanciaSeis, "km")
print ("Distancia recorrida en 10 hrs:", distanciaDiez, "km")
print ("Tiempo para recorrer 500 km:", tiempoQuinientos, "hrs.")


import pytest

from gelanis import Row
from gelanis.sql._ast.ast_to_python import parse_expression
from gelanis.sql.types import IntegerType, StructField, StructType

ROW = Row(a=1, b=2, c=3)
SCHEMA = StructType([
    StructField("a", IntegerType()),
    StructField("b", IntegerType()),
])

SCENARIOS = {
    'Least(-1,0,1)': ('least', 'least(-1, 0, 1)', -1),
    'GREATEST(-1,0,1)': ('greatest', 'greatest(-1, 0, 1)', 1),
    'shiftRight ( 42, 1 )': ('shiftright', 'shiftright(42, 1)', 21),
    'ShiftLeft ( 42, 1 )': ('shiftleft', 'shiftleft(42, 1)', 84),
    "concat_ws('/', a, b )": ('concat_ws', 'concat_ws(/, a, b)', "1/2"),
    'instr(a, a)': ('instr', 'instr(a, a)', 1),  # rely on columns
    'instr(a, b)': ('instr', 'instr(a, b)', 0),  # rely on columns
    "instr('abc', 'c')": ('instr', 'instr(abc, c)', 3),  # rely on lit
}

@pytest.mark.parametrize('string, expected', SCENARIOS.items())
def test_functions(string, expected):
    operator, expected_parsed, expected_result = expected
    actual_parsed = parse_expression(string, True)

    assert expected_parsed == str(actual_parsed)
    assert operator == actual_parsed.pretty_name

    actual_result = actual_parsed.eval(ROW, SCHEMA)

    assert expected_result == actual_result


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Documentation source:
# - https://gbdev.gg8.se/wiki/articles/Video_Display

from vsgb.byte_operations import signed_value, flip_byte, check_bit
from vsgb.interrupt_manager import Interrupt, InterruptManager
from vsgb.io_registers import IO_Registers
from vsgb.window import Window
from vsgb.address_space import AddressSpace

class PPU(AddressSpace):

    #Consts
    FRAMEBUFFER_SIZE: int    = Window.SCREEN_WIDTH * Window.SCREEN_HEIGHT
    H_BLANK_STATE: int       = 0
    V_BLANK_STATE: int       = 1
    OAM_READ_STATE: int      = 2
    VMRAM_READ_STATE: int    = 3
    OAM_SCANLINE_TIME: int   = 80
    VRAM_SCANLINE_TIME: int  = 172
    H_BLANK_TIME: int        = 204
    V_BLANK_TIME: int        = 4560

    #Vars
    #framebuffer: list        = [0xffffffff]*FRAMEBUFFER_SIZE
    original_color: list     = [0]*FRAMEBUFFER_SIZE
    bg_priority: list        = [False]*FRAMEBUFFER_SIZE
    mode: int                = V_BLANK_STATE
    modeclock: int           = 0
    vblank_line: int         = 0
    auxillary_modeclock: int = 0
    screen_enabled: bool     = True
    window_line: int         = 0
    cgb_mode: bool           = False

    # Registers
    ly: int   = 0
    stat: int = 0
    lyc: int  = 0
    scx: int  = 0
    scy: int  = 0
    bgp: int  = 0
    wx: int   = 0
    wy: int   = 0
    lcdc: int = 0
    obp0: int = 0
    obp1: int = 0
    vbk: int  = 0

    # Memory
    vram: list = [[0]*0x2000,[0]*0x2000]
    oam: list = [0]*0xa0

    @classmethod
    def accept(cls, address: int) -> bool:
        # 0x8000 <= address < 0xa0000 -> ((address >> 8) & 0b11100000 == 0b10000000)
        return (address  & 0b11100000_00000000 == 0b10000000_00000000) or (0xfe00 <= address < 0xfea0) or (address in [
            IO_Registers.LY,
            IO_Registers.STAT,
            IO_Registers.LYC,
            IO_Registers.SCX,
            IO_Registers.SCY,
            IO_Registers.BGP,
            IO_Registers.WX,
            IO_Registers.WY,
            IO_Registers.LCDC,
            IO_Registers.OBP0,
            IO_Registers.OBP1,
            IO_Registers.VBK
        ])

    @classmethod
    def read(cls, address: int) -> int:
        if 0x8000 <= address < 0xa000:
            return cls.vram[cls.vbk][address - 0x8000]
        if 0xfe00 <= address < 0xfea0:
            return cls.oam[address - 0xfe00]
        if address == IO_Registers.LY:
            return cls.ly
        if address == IO_Registers.STAT:
            return cls.stat
        if address == IO_Registers.LYC:
            return cls.lyc
        if address == IO_Registers.SCX:
            return cls.scx
        if address == IO_Registers.SCY:
            return cls.scy
        if address == IO_Registers.BGP:
            return cls.bgp
        if address == IO_Registers.WX:
            return cls.wx
        if address == IO_Registers.WY:
            return cls.wy
        if address == IO_Registers.LCDC:
            return cls.lcdc
        if address == IO_Registers.OBP0:
            return cls.obp0
        if address == IO_Registers.OBP1:
            return cls.obp1
        if address == IO_Registers.VBK:
            return cls.vbk

    @classmethod
    def write(cls, address: int, value: int):
        if 0x8000 <= address < 0xa000:
            cls.vram[cls.vbk][address - 0x8000] = value
        elif 0xfe00 <= address < 0xfea0:
            cls.oam[address - 0xfe00] = value
        elif address == IO_Registers.LY:
            cls.ly = value
        elif address == IO_Registers.STAT:
            cls.stat = value
        elif address == IO_Registers.LYC:
            cls.lyc = value
        elif address == IO_Registers.SCX:
            cls.scx = value
        elif address == IO_Registers.SCY:
            cls.scy = value
        elif address == IO_Registers.BGP:
            cls.bgp = value
        elif address == IO_Registers.WX:
            cls.wx = value
        elif address == IO_Registers.WY:
            cls.wy = value
        elif address == IO_Registers.LCDC:
            cls.lcdc = value
        elif address == IO_Registers.OBP0:
            cls.obp0 = value
        elif address == IO_Registers.OBP1:
            cls.obp1 = value
        elif address == IO_Registers.VBK:
            cls.vbk = value & 1

    @staticmethod
    def check_stat(old: int, new: int):

        if (new & 0b01000100) & ((~old) & 0b01000100):
        #if (new & 0b01000100):
            InterruptManager.request_interrupt(Interrupt.INTERRUPT_LCDSTAT)
            return

        for i in range(3):
            #if (new & (1 << (3+i))) & ((~old) & (1 << (3+i))) and i == (new & 0b11):
            if (new & (1 << (3+i))) and i == (new & 0b11):
                InterruptManager.request_interrupt(Interrupt.INTERRUPT_LCDSTAT)
                return

    @classmethod
    def step(cls, cycles : int = 1):
        cls.modeclock += cycles
        cls.auxillary_modeclock += cycles
        if LCDControlRegister.lcd_display_enable(cls.lcdc):
            if cls.screen_enabled:
                if cls.mode == cls.H_BLANK_STATE:
                    if cls.modeclock >= cls.H_BLANK_TIME:
                        cls.exec_hblank()
                        Window.refresh = True
                elif cls.mode == cls.V_BLANK_STATE:
                    cls.exec_vblank()
                elif cls.mode == cls.OAM_READ_STATE:
                    if cls.modeclock >= cls.OAM_SCANLINE_TIME:
                        cls.exec_oam()
                elif cls.mode == cls.VMRAM_READ_STATE:
                    if cls.modeclock >= cls.VRAM_SCANLINE_TIME:
                        cls.exec_vram()

            else:
                cls.screen_enabled = True
                cls.modeclock = 0
                cls.mode = 0
                cls.auxillary_modeclock = 0
                cls.window_line = 0
                cls.ly = 0
                cls.update_stat_mode()
                cls.compare_lylc()
        else:
            cls.screen_enabled = False

    @classmethod
    def exec_vram(cls):
        cls.modeclock -= cls.VRAM_SCANLINE_TIME
        cls.mode = cls.H_BLANK_STATE
        cls.scanline()
        cls.update_stat_mode()

    @classmethod
    def exec_oam(cls):
        cls.modeclock -= cls.OAM_SCANLINE_TIME
        cls.mode = cls.VMRAM_READ_STATE
        cls.update_stat_mode()

    @classmethod
    def exec_hblank(cls):
        cls.modeclock -= cls.H_BLANK_TIME
        cls.mode = cls.OAM_READ_STATE
        cls.ly += 1
        cls.compare_lylc()

        if cls.ly == 144:
            cls.mode = cls.V_BLANK_STATE
            cls.auxillary_modeclock = cls.modeclock
            cls.window_line = 0
            InterruptManager.request_interrupt(Interrupt.INTERRUPT_VBLANK)

        cls.update_stat_mode()

    @classmethod
    def exec_vblank(cls):
        if cls.auxillary_modeclock >= 456:
            cls.auxillary_modeclock -= 456
            cls.vblank_line += 1

            if cls.vblank_line <= 9:
                cls.ly += 1
                cls.compare_lylc()

        if cls.modeclock >= cls.V_BLANK_TIME:
            cls.modeclock -= cls.V_BLANK_TIME
            cls.mode = cls.OAM_READ_STATE
            cls.update_stat_mode()
            cls.ly = 0
            cls.vblank_line = 0

    @classmethod
    def scanline(cls):
        if cls.ly <= 144:
            cls.render_background(cls.ly)
            cls.render_window(cls.ly)
            cls.render_sprite(cls.ly)

    @classmethod
    def update_stat_mode(cls):
        # LCD Status Register
        # FF41 - STAT - LCDC Status (R/W)
        # -------------------------------
        # Bit 6 - LYC=LY Coincidence Interrupt (1=Enable) (Read/Write)
        # Bit 5 - Mode 2 OAM Interrupt         (1=Enable) (Read/Write)
        # Bit 4 - Mode 1 V-Blank Interrupt     (1=Enable) (Read/Write)
        # Bit 3 - Mode 0 H-Blank Interrupt     (1=Enable) (Read/Write)
        # Bit 2 - Coincidence Flag  (0:LYC<>LY, 1:LYC=LY) (Read Only)
        # Bit 1-0 - Mode Flag       (Mode 0-3, see below) (Read Only)
        #   0: During H-Blank
        #   1: During V-Blank
        #   2: During Searching OAM
        #   3: During Transferring Data to LCD Driver

        # The two lower STAT bits show the current status of the LCD controller.
        # The LCD controller operates on a 222 Hz = 4.194 MHz dot clock. An entire frame is 154 scanlines, 70224 dots, or 16.74 ms. On scanlines 0 through 143, the LCD controller cycles through modes 2, 3, and 0 once every 456 dots. Scanlines 144 through 153 are mode 1.
        # The following are typical when the display is enabled:

        # Mode 2  2_____2_____2_____2_____2_____2___________________2____
        # Mode 3  _33____33____33____33____33____33__________________3___
        # Mode 0  ___000___000___000___000___000___000________________000
        # Mode 1  ____________________________________11111111111111_____

        new_stat = (cls.stat & 0xfc) | (cls.mode & 0x3)
        cls.check_stat(cls.stat,new_stat)
        cls.STAT = new_stat

    @staticmethod
    def rgb(color_code : int) -> int:
        return {
             0: 0x7fff,
             1: 0x421f,
             2: 0x1cf2,
             3: 0x0000
        }.get(color_code)

    @staticmethod
    def rgb_sprite(color_code : int) -> int:
        return {
             0: 0x7fff,
             1: 0x1bef,
             2: 0x0200,
             3: 0x0000
        }.get(color_code)

    @classmethod
    def compare_lylc(cls):
      if LCDControlRegister.lcd_display_enable(cls.lcdc):

            old_stat = cls.stat

            if cls.lyc == cls.ly:
                stat = cls.stat | 0x4
            else:
                stat = cls.stat & 0xfb
            cls.check_stat(old_stat, stat)
            cls.STAT =  stat

    @classmethod
    def render_background(cls, line : int):
        line_width = (Window.SCREEN_HEIGHT - line -1) * Window.SCREEN_WIDTH

        if LCDControlRegister.bg_window_display_priority(cls.lcdc):
            # tile and map select
            tiles_select = LCDControlRegister.bg_and_window_tile_data_select(cls.lcdc)
            map_select = LCDControlRegister.bg_tile_map_display_select(cls.lcdc)
            # line with y offset
            line_adjusted = (line + cls.scy) & 0xff
            # get position of tile row to read
            y_offset = (line_adjusted // 8) * 32
            # relative line number in tile
            tile_line = line_adjusted % 8
            # relative line number offset
            tile_line_offset = tile_line * 2
            x = 0
            while x < 32:
                tile = 0
                if tiles_select == 0x800:
                    tile = signed_value(cls.vram[0][map_select + y_offset + x])
                    tile += 128
                else:
                    tile = cls.vram[0][map_select + y_offset + x]

                line_pixel_offset = x * 8
                tile_select_offset = tile * 16
                tile_address = tiles_select + tile_select_offset + tile_line_offset

                if not cls.cgb_mode:
                    byte_1 = cls.vram[0][tile_address]
                    byte_2 = cls.vram[0][tile_address + 1]
                else:
                    tile_attributes = TileAttributes(cls.vram[0][map_select + y_offset + x])
                    if tile_attributes.is_vertical_flip():
                        tile_address = tile_address - tile_line_offset + ( 7 - tile_line ) * 2
                    byte_1 = cls.vram[tile_attributes.get_vram_bank()][tile_address]
                    byte_2 = cls.vram[tile_attributes.get_vram_bank()][tile_address + 1]
                    if tile_attributes.is_horizontal_flip():
                        byte_1 = flip_byte(byte_1)
                        byte_2 = flip_byte(byte_2)

                pixelx = 0
                buffer_addr = (line_pixel_offset - cls.scx)
                while pixelx < 8:

                    shift = 0x1 << (7 - pixelx)
                    pixelx += 1

                    buffer_addr &= 0xff

                    if 0 <= buffer_addr < Window.SCREEN_WIDTH:

                        pixel = 1 if (byte_1 & shift > 0) else 0
                        pixel |= 2 if (byte_2 & shift > 0) else 0
                        color = (cls.bgp >> (pixel * 2)) & 0x3

                        position = line_width + buffer_addr % Window.SCREEN_WIDTH
                        cls.original_color[position] = color
                        if not cls.cgb_mode:
                            Window.framebuffer[position] = cls.rgb(color)

                        else:
                            """
                            if cls.mmu.bootstrap_enabled or cls.mmu.rom.is_cgb():
                                color = pixel
                            """

                            #Window.framebuffer[position] = cls.mmu.cgb_palette.get_bg_rgba_palette_color(tile_attributes.get_palette(), color)
                            Window.framebuffer[position] = cls.rgb(color) #FIXME

                            cls.bg_priority[position] = tile_attributes.is_bg_priority()

                    buffer_addr = ( line_pixel_offset + pixelx - cls.scx )

                x += 1
        else:
            for i in range(0, Window.SCREEN_WIDTH):
                Window.framebuffer[line_width + i] = cls.rgb(0)
                cls.original_color[line_width + i] = 0

    @classmethod
    def render_window(cls, line : int):
        line_width = (Window.SCREEN_HEIGHT - line -1) * Window.SCREEN_WIDTH
        # dont render if the window is outside the bounds of the screen or
        # if the LCDC window enable bit flag is not set
        if cls.window_line > 143 or not LCDControlRegister.window_display_enable(cls.lcdc):
            return

        window_pos_x = cls.wx - 7
        window_pos_y = cls.wy

        # don't render if the window is outside the bounds of the screen
        if window_pos_x > 159 or window_pos_y > 143 or window_pos_y > line:
            return

        tiles_select = LCDControlRegister.bg_and_window_tile_data_select(cls.lcdc)
        map_select = LCDControlRegister.window_tile_map_display_select(cls.lcdc)

        line_adjusted = cls.window_line
        y_offset = (line_adjusted // 8) * 32
        tile_line = line_adjusted % 8
        tile_line_offset = tile_line * 2

        for x in range(32):
            tile = 0
            if tiles_select == 0x800:
                tile = signed_value(cls.vram[0][map_select + y_offset + x])
                tile += 128
            else:
                tile = cls.vram[0][map_select + y_offset + x]

            line_pixel_offset = x * 8
            tile_select_offset = tile * 16
            tile_address = tiles_select + tile_select_offset + tile_line_offset

            tile_attributes = TileAttributes(cls.vram[1][map_select + y_offset + x])

            if not cls.cgb_mode:
                byte_1 = cls.vram[0][tile_address]
                byte_2 = cls.vram[0][tile_address + 1]
            else:
                if tile_attributes.is_vertical_flip():
                    tile_address = tile_address - tile_line_offset + ( 7 - tile_line ) * 2
                byte_1 = cls.vram[tile_attributes.get_vram_bank()][tile_address]
                byte_2 = cls.vram[tile_attributes.get_vram_bank()][tile_address + 1]
                if tile_attributes.is_horizontal_flip():
                    byte_1 = flip_byte(byte_1)
                    byte_2 = flip_byte(byte_2)

            for pixelx in range(8):
                buffer_addr = line_pixel_offset + pixelx + window_pos_x

                if buffer_addr < 0 or buffer_addr >= Window.SCREEN_WIDTH:
                    continue

                shift = 0x1 << (7 - pixelx)

                pixel = 0
                if (byte_1 & shift == shift) and (byte_2 & shift == shift):
                    pixel = 3
                elif (byte_1 & shift == 0x0) and (byte_2 & shift == shift):
                    pixel = 2
                elif (byte_1 & shift == shift) and (byte_2 & shift == 0x0):
                    pixel = 1
                elif (byte_1 & shift == 0x0) and (byte_2 & shift == 0x00):
                    pixel = 0
                position = line_width + buffer_addr
                color = (cls.bgp >> (pixel * 2)) & 0x3
                if not cls.cgb_mode:
                    Window.framebuffer[position] = cls.rgb(color)
                    cls.original_color[position] = color
                else:
                    if cls.mmu.bootstrap_enabled or cls.mmu.rom.is_cgb():
                        color = pixel
                    Window.framebuffer[position] = cls.mmu.cgb_palette.get_bg_rgba_palette_color(tile_attributes.get_palette(), color)
                    cls.bg_priority[position] = tile_attributes.is_bg_priority()
                    cls.original_color[position] = color

        cls.window_line += 1

    @classmethod
    def render_sprite(cls, line : int):
        line_width = (Window.SCREEN_HEIGHT - line -1) * Window.SCREEN_WIDTH
        if not LCDControlRegister.sprite_display_enable(cls.lcdc):
            return

        sprite_size = LCDControlRegister.sprite_size(cls.lcdc)

        for sprite in range(39,-1,-1):
            sprite_offset = sprite * 4

            sprite_y = cls.oam[sprite_offset] - 16
            if sprite_y > line or (sprite_y + sprite_size) <= line:
                continue

            sprite_x = cls.oam[sprite_offset + 1] - 8
            if sprite_x < -7 or sprite_x >= Window.SCREEN_WIDTH:
                continue

            sprite_tile_offset = (cls.oam[sprite_offset + 2] & (0xfe if sprite_size == 16 else 0xff)) * 16

            sprite_attributes = SpriteAttributes(cls.oam[sprite_offset + 3])

            tiles = 0
            pixel_y = (15 if sprite_size == 16 else 7) - (line - sprite_y) if sprite_attributes.is_vertical_flip() else line - sprite_y

            pixel_y_2 = 0
            offset = 0

            if sprite_size == 16 and (pixel_y >= 8):
                pixel_y_2 = (pixel_y - 8) * 2
                offset = 16
            else:
                pixel_y_2 = pixel_y * 2

            tile_address = tiles + sprite_tile_offset + pixel_y_2 + offset
            byte_1 = cls.vram[sprite_attributes.get_vram_bank()][tile_address]
            byte_2 = cls.vram[sprite_attributes.get_vram_bank()][tile_address + 1]

            if sprite_attributes.get_palette() == 0:
                palette = cls.obp0
            else:
                palette = cls.obp1

            for pixelx in range(8):
                shift = 0x1 << (pixelx if sprite_attributes.is_horizontal_flip() else 7 - pixelx)
                pixel = 0

                if (byte_1 & shift == shift) and (byte_2 & shift == shift):
                    pixel = 3
                elif (byte_1 & shift == 0x0) and (byte_2 & shift == shift):
                    pixel = 2
                elif (byte_1 & shift == shift) and (byte_2 & shift == 0x0):
                    pixel = 1
                elif (byte_1 & shift == 0x0) and (byte_2 & shift == 0x00):
                    continue

                buffer_x = sprite_x + pixelx
                if buffer_x < 0 or buffer_x >= Window.SCREEN_WIDTH:
                    continue

                position = line_width + buffer_x

                color = (palette >> (pixel * 2)) & 0x3

                if sprite_attributes.is_priority() or cls.original_color[position] == 0 :
                    if not cls.cgb_mode:
                        Window.framebuffer[position] = cls.rgb_sprite(color)

                    elif not cls.bg_priority[position] \
                        or cls.original_color[position] == 0:
                        if cls.mmu.bootstrap_enabled or cls.mmu.rom.is_cgb():
                            color = pixel
                        Window.framebuffer[position] = cls.mmu.cgb_palette.get_ob_rgba_palette_color(sprite_attributes.get_cgb_palette(), color)

class LCDControlRegister:

    """
    LCD Control Register
    Bit 7 - LCD Display Enable             (0=Off, 1=On)
    Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
    Bit 5 - Window Display Enable          (0=Off, 1=On)
    Bit 4 - BG & Window Tile Data Select   (0=8800-97FF, 1=8000-8FFF)
    Bit 3 - BG Tile Map Display Select     (0=9800-9BFF, 1=9C00-9FFF)
    Bit 2 - OBJ (Sprite) Size              (0=8x8, 1=8x16)
    Bit 1 - OBJ (Sprite) Display Enable    (0=Off, 1=On)
    Bit 0 - BG/Window Display/Priority     (0=Off, 1=On)
    """

    @staticmethod
    def lcd_display_enable(lcdc: int) -> int:
        return check_bit(7,lcdc)

    @staticmethod
    def window_tile_map_display_select(lcdc: int) -> int:
        if check_bit(6,lcdc):
            return 0x1c00
        return 0x1800

    @staticmethod
    def window_display_enable(lcdc: int) -> int:
        return check_bit(5,PPU.lcdc)

    @staticmethod
    def bg_and_window_tile_data_select(lcdc: int) -> int:
        if check_bit(4,lcdc):
            return 0
        return 0x800

    @staticmethod
    def bg_tile_map_display_select(lcdc: int) -> int:
        if check_bit(3,lcdc):
            return 0x1c00
        return 0x1800

    @staticmethod
    def sprite_size(lcdc: int) -> int:
        if check_bit(2,lcdc):
            return 16
        return 8

    @staticmethod
    def sprite_display_enable(lcdc: int) -> int:
        return check_bit(1,lcdc)

    @staticmethod
    def bg_window_display_priority(lcdc: int) -> int:
        return check_bit(0,lcdc)

class TileAttributes:

    """
    Map Attributes (CGB Mode only)
    In CGB Mode, an additional map of 32x32 bytes is stored in VRAM Bank 1 (each byte defines attributes for the corresponding tile-number map entry in VRAM Bank 0):
    Bit 0-2  Background Palette number  (BGP0-7)
    Bit 3    Tile VRAM Bank number      (0=Bank 0, 1=Bank 1)
    Bit 4    Not used
    Bit 5    Horizontal Flip            (0=Normal, 1=Mirror horizontally)
    Bit 6    Vertical Flip              (0=Normal, 1=Mirror vertically)
    Bit 7    BG-to-OAM Priority         (0=Use OAM priority bit, 1=BG Priority)
    When Bit 7 is set, the corresponding BG tile will have priority above all OBJs (regardless of the priority bits in OAM memory). There's also an Master Priority flag in LCDC register Bit 0 which overrides all other priority bits when cleared.
    """

    def __init__(self, value):
        self.value = value
        self._palette = self.value & 0b00000111
        self._vram_bank = (self.value & 0b00001000) >> 3
        self._horizontal_flip = self.value & 0b00100000 == 0b00100000
        self._vertical_flip = self.value & 0b01000000 == 0b01000000
        self._bg_priority = self.value & 0b10000000 == 0b10000000

    def get_palette(self):
        return self._palette

    def get_vram_bank(self):
        return self._vram_bank

    def is_horizontal_flip(self):
        return self._horizontal_flip

    def is_vertical_flip(self):
        return self._vertical_flip

    def is_bg_priority(self):
        return self._bg_priority

class SpriteAttributes:

    """
    Attributes/Flags:
    Bit7   OBJ-to-BG Priority (0=OBJ Above BG, 1=OBJ Behind BG color 1-3)
    (Used for both BG and Window. BG color 0 is always behind OBJ)
    Bit6   Y flip          (0=Normal, 1=Vertically mirrored)
    Bit5   X flip          (0=Normal, 1=Horizontally mirrored)
    Bit4   Palette number  **Non CGB Mode Only** (0=OBP0, 1=OBP1)
    Bit3   Tile VRAM-Bank  **CGB Mode Only**     (0=Bank 0, 1=Bank 1)
    Bit2-0 Palette number  **CGB Mode Only**     (OBP0-7)
    """

    def __init__(self, value):
        self.value = value
        self._ob_priority = self.value & 0x80 != 0x80
        self._horizontal_flip = self.value & 0x20 == 0x20
        self._vertical_flip = self.value & 0x40 == 0x40
        self._palette = (self.value & 0b00010000) >> 4
        self._bank = (self.value & 0b00001000) >> 3
        self._cgb_palette = self.value & 0b00000111

    def is_priority(self):
        return self._ob_priority

    def is_horizontal_flip(self):
        return self._horizontal_flip

    def is_vertical_flip(self):
        return self._vertical_flip

    def get_palette(self):
        return self._palette

    def get_cgb_palette(self):
        return self._cgb_palette

    def get_vram_bank(self):
        return self._bank


from __future__ import annotations

import typing as ty
import aurflux
from aurflux.response import Response
import discord
import asyncio
import subprocess

if ty.TYPE_CHECKING:
    import datetime

VERSION = subprocess.check_output(["poetry", "version"]).decode().split(" ")[1]

class Interface(aurflux.AurfluxCog):
    listening_channels = set()

    def route(self):
        @self.aurflux.router.endpoint(":message", decompose=True)
        async def _(message: discord.Message):
            if message.author == self.aurflux.user:
                return
            if isinstance(message.channel, discord.channel.DMChannel):
                embed = discord.Embed(
                    title=f"Pinbot V{VERSION}",
                    description="Use ..help in your server for command details\n" \
                                f"[Click me to add to your server](https://discord.com/oauth2/authorize?client_id={self.aurflux.user.id}&scope=bot&permissions=76816)"
                )
                await Response(embed=embed).execute(aurflux.MessageContext(bot=self.aurflux, message=message))

        @aurflux.CommandCheck.has_permissions(discord.Permissions(manage_guild=True))
        @self._commandeer(name="setup", parsed=False)
        async def setup(ctx: aurflux.MessageContext, args: str):
            """
            setup
            :param ctx:
            :param args:
            :return:
            """
            configs = self.aurflux.CONFIG.of(ctx)
            try:
                print("setup!")
                yield Response("Beginning setup... Type `done` to end setup", delete_after=30)

                header_resp = Response("Please select a pair of channels `#from-channel` to `#to-channel`\n"
                                       "Once there are `max` pinned messages in `#from-channel`, the next pin in `#from-channel` will cause the oldest pin to be converted to an embed and sent in `#to-channel`\n"
                                       # f"You can do this in the future without `{ctx.full_command}` via `{configs['prefix']}map #from #to`"
                                       )
                yield header_resp

                async def check_pair(ev: aurflux.AurfluxEvent) -> bool:
                    m: discord.Message = ev.args[0]
                    print(m)
                    if m.author == m.guild.me:
                        return False
                    if m.author != ctx.author:
                        return False
                    if m.content in ("cancel", "done"):
                        return True
                    if not m.channel_mentions:
                        return False
                    s = aurflux.utils.find_mentions(m.content)
                    return len(s) == 2 or m.content == "done"

                assignment: discord.Message = (await self.aurflux.router.wait_for(":message", check_pair, timeout=45)).args[0]
                if assignment.content == "cancel":
                    yield Response(f"Finished setup {aurflux.utils.EMOJIS['white_check_mark']}")
                    return

                if assignment.content == "done":
                    yield Response(f"Finished setup {aurflux.utils.EMOJIS['white_check_mark']}")
                    return

                from_channel, to_channel = aurflux.utils.find_mentions(assignment.content)
                from_channel, to_channel = self.aurflux.get_channel(from_channel), self.aurflux.get_channel(to_channel)
                # try:
                #     await assignment.delete()
                # except discord.errors.Forbidden:
                #     raise aurflux.errors.BotMissingPermissions(discord.Permissions())
                resp = Response(f"Mapping pins from {from_channel.mention} to embeds in {to_channel.mention}", delete_after=30)
                yield resp

                async with self.aurflux.CONFIG.writeable_conf(ctx.config_identifier) as cfg:
                    cfg["pinmap"] = {**cfg.get("pinmap", {}), from_channel.id: to_channel.id}
                await resp.message.add_reaction(aurflux.utils.EMOJIS["white_check_mark"])

                resp = Response(f"What is the number of native discord pins you would like in {from_channel.mention}? [0-49]\n"
                                f"If you set this to 0, all pins will be immediately turned into embeds\n"
                                f"If you set this to any other number <= 49, {from_channel.mention} will hold that many native discord pins, "
                                f"after which the **oldest** pin will be turned into an embed")
                yield resp

                async def check_max(ev: aurflux.AurfluxEvent) -> bool:
                    m: discord.Message = ev.args[0]
                    if m.author == m.guild.me:
                        return False
                    if m.author != m.author:
                        return False
                    return True

                while True:
                    max_resp: discord.Message = (await self.aurflux.router.wait_for(":message", check_max, timeout=45)).args[0]
                    if max_resp.author == self.aurflux.user:
                        continue
                    try:
                        max_pins = int(max_resp.content)
                        if not 0 <= max_pins <= 49:
                            raise ValueError
                        break
                    except ValueError:
                        yield Response("Please enter a number <= 49 and >= 0", delete_after=10)

                async with self.aurflux.CONFIG.writeable_conf(ctx.config_identifier) as cfg:
                    cfg["maxmap"] = {**cfg.get("maxmap", {}), from_channel.id: max_pins}

                await max_resp.add_reaction(aurflux.utils.EMOJIS["white_check_mark"])
                if max_pins == 0:
                    yield Response(f"Done! When a message is pinned in {from_channel.mention}, it will be converted into an embed in {to_channel.mention}")
                else:
                    yield Response(f"Done! Once there are {max_pins} pins in {from_channel.mention}, the oldest pin will be converted to an embed in {to_channel.mention}")
            except asyncio.exceptions.TimeoutError:
                yield Response(f"Timed out! Stopping setup process. `{configs['prefix']}setup` to restart")

        @self.register
        @self.aurflux.commandeer(name="maps", parsed=False)
        async def _(ctx: aurflux.MessageContext, _):
            """
            Prints out the current set of maps
            :param ctx:
            :return:
            """
            configs = self.aurflux.CONFIG.of(ctx)

            embed = discord.Embed(title="Pinbot Map")
            pinmap = configs["pinmap"].items()
            print(len(pinmap))
            if len(pinmap) == 0:
                embed.description = "No maps set!"
                return Response(embed=embed)

            embed.add_field(name="Map", value="\n".join(f"<#{f}> \u27F6 <#{t}>" for f, t in pinmap), inline=True)
            embed.add_field(name="Max", value="\n".join(str(configs["maxmap"][f]) for f, _ in pinmap), inline=True)

            return Response(embed=embed)

        @self.register
        @self.aurflux.commandeer(name="pinall", parsed=False)
        async def _(ctx: aurflux.MessageContext, _):
            """
            Forces a re-check of all mapped channels for pins
            :param ctx:
            :param _:
            :return:
            """
            configs = self.aurflux.CONFIG.of(ctx)
            print(configs["pinmap"])
            for channel_id in configs["pinmap"]:
                await self.router.submit(event=aurflux.AurfluxEvent(self.aurflux, "aurflux:guild_channel_pins_update", self.aurflux.get_channel(int(channel_id)), None))
            return Response()


#!/usr/bin/env python
# encoding: utf-8
from __future__ import unicode_literals

import re

from markdown.preprocessors import Preprocessor

class NormalizeImg(Preprocessor):
    """ add forgotten {attach}. """

    def run(self, lines):
        source = '\n'.join(lines)
        source = re.sub(r'\!\[([^\]]*)\]\(images\/([^)]*)\)', '![\g<1>]({attach}images/\g<2>)', source)
        return source.split('\n')

class NormalizeLink(Preprocessor):
    """ add forgotten {filename}. """

    def run(self, lines):
        source = '\n'.join(lines)
        source = re.sub(r'\[(.*)\]\((.*\.md)\)', '[\g<1>]({filename}\g<2>)', source)
        return source.split('\n')


import numpy as np
import matplotlib.pyplot as plt

x, y= np.mgrid[-5:5:201j, -5:5:101j]

z = np.zeros_like(x)

for n in range(10):
    x0, y0 = np.random.randn(2)
    z += np.exp( -(x-x0)**2 - (y-y0)**2)

plt.pcolor(x, y, z, cmap=plt.cm.Reds)
plt.axis('tight')
plt.show()

fig = plt.figure(figsize=(9,4))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
pc = ax.pcolor(x, y, z, cmap=plt.cm.Reds)

cb = plt.colorbar(pc)
cb.set_label(r'Energy [m$^3$ s$^{-2}$]')

ax.set_xlabel('Distance [km]')
ax.set_ylabel('Distance [km]')
ax.set_title('one plot to rule them all')
ax.set_aspect(1.0)
ax.set_ylim(-5, 5)
ax.set_xlim(-5, 5)

plt.show()


from typing import Optional
from zlib import crc32
from datetime import datetime
from busio import I2C
from board import SCL, SDA
import adafruit_mcp9808
from .measurements import Measurement, MeasurementError

I2C_ADDRESSES = [ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F ]

def enumerate_sensors():
  sensors = []
  bus = I2C(SCL, SDA)
  for i2c_address in I2C_ADDRESSES:
    try:
      sensor = mcp9808(i2c_dev=bus, i2c_addr=i2c_address)
    except (OSError, AttributeError, ValueError) as error:
      # If no device is found, an AttributeError is raised (possibly ValueError if no device at address?)
      print("Error initialising MCP9808 sensor at I2C address {:#x}: {}".format(i2c_address, str(error)))
    else:
      print("Found MCP9808 sensor with ID {:x} at I2C address {:#x}".format(sensor.serial_number, i2c_address))
      sensors.append(sensor)
  return sensors

class mcp9808(adafruit_mcp9808.MCP9808):

  manufacturer = 'Microchip Technology'
  model = 'MCP9808'
  supported_measurements = [Measurement.TEMPERATURE]

  def __init__(self, i2c_dev=None,
               i2c_addr: Optional[int] = I2C_ADDRESSES[0]):
    self.i2c_address = i2c_addr
    super().__init__(i2c_bus=i2c_dev, address=i2c_addr)

  def update_sensor(self):
    try:
      self._temperature = super().temperature
    except ValueError as error:
      raise MeasurementError(str(error))
    else:
      self.timestamp = datetime.now().isoformat(timespec='seconds')

  # Override super class property for temperature
  # because otherwise there's a name clash
  @property
  def temperature(self):
    return self._temperature

  @property
  def id(self):
    """A unique identifier for the device."""
    return "{model:s}--{serial:08x}".format(model=self.model.replace('-',''), serial=self.serial_number).lower()

  @property
  def serial_number(self):
    """The hardware identifier (serial number) for the device."""
    # Doesn't look like the device supports reading a unique
    # identifier, this cobbles something together from the
    # sensor type and I2C address
    unique_string = ''.join("{}{}{:#x}".format(self.manufacturer, self.model, self.i2c_address).lower().split())
    return crc32(unique_string.encode())


from setuptools import setup, find_packages
import puanchen

with open("README.md", "r") as f:
    long_description = f.read()

setup(
    name=puanchen.__name__,
    version=puanchen.__version__,
    description="a Python implementation of message queue based on pika",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/perfeelab/puanchen",
    author=puanchen.__author__,
    author_email=puanchen.__author_email__,
    packages=find_packages(),
    include_package_data=True,
    install_requires=["pika>=1.0.1"],
    classifiers=[
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ]
)


# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.macosx-10.12-x86_64/egg/tss/serving.py
# Compiled at: 2018-05-01 15:21:11
import tensorflow as tf
from tensorflow.contrib.saved_model.python.saved_model import reader
from tensorflow.contrib.saved_model.python.saved_model import signature_def_utils
import logging

def load_meta_graph(model_path, tags, graph, signature_def_key=None):
    saved_model = reader.read_saved_model(model_path)
    the_meta_graph = None
    for meta_graph_def in saved_model.meta_graphs:
        if sorted(meta_graph_def.meta_info_def.tags) == sorted(tags):
            the_meta_graph = meta_graph_def

    signature_def_key = signature_def_key or tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
    try:
        signature_def = signature_def_utils.get_signature_def_by_key(the_meta_graph, signature_def_key)
    except ValueError as ex:
        try:
            formatted_key = ('default_input_alternative:{}').format(signature_def_key)
            signature_def = signature_def_utils.get_signature_def_by_key(the_meta_graph, formatted_key)
        except ValueError:
            raise ValueError(('Got signature_def_key "{}". Available signatures are {}. Original error:\n{}').format(signature_def_key, list(the_meta_graph.signature_def), ex))

    input_names = {k:v.name for k, v in signature_def.inputs.items()}
    output_names = {k:v.name for k, v in signature_def.outputs.items()}
    feed_tensors = {k:graph.get_tensor_by_name(v) for k, v in input_names.items()}
    fetch_tensors = {k:graph.get_tensor_by_name(v) for k, v in output_names.items()}
    return (feed_tensors, fetch_tensors)

def get_model(model_base_path, version=None):
    versions = {}
    model_base_path = model_base_path.rstrip('/')
    for version in tf.gfile.ListDirectory(model_base_path):
        version = version.rstrip('/')
        if version.isdigit():
            versions[int(version)] = ('/').join([model_base_path, version])

    if version is None:
        version = max(versions.keys())
    logging.info('Choose model_path %s with version %s' % (model_base_path, version))
    return versions[int(version)]

def load_model(model_base_path, model_version):
    model_path = get_model(model_base_path, model_version)
    with tf.Graph().as_default() as (graph):
        sess = tf.Session(graph=graph)
        tags = [tf.saved_model.tag_constants.SERVING]
        tf.saved_model.loader.load(sess, tags, model_path)
        feed_tensors, fetch_tensors = load_meta_graph(model_path, tags, graph)
        return (graph, feed_tensors, fetch_tensors)

def rename_by_mapping(df, tensor_mapping, reverse=False):
    for name, tensor in tensor_mapping.items():
        renames = (
         name, tensor.op.name)
        if reverse:
            renames = reversed(renames)
        df = df.withColumnRenamed(*renames)

    return df

def tf_serving_with_dataframe(df, model_base_path, model_version=None):
    """

    :param df: spark dataframe, batch input for the model
    :param model_base_path: str, tensorflow saved Model model base path
    :param model_version: int, tensorflow saved Model model version, default None
    :return: spark dataframe, with predicted result.
    """
    import tensorframes as tfs
    g, feed_tensors, fetch_tensors = load_model(model_base_path, model_version)
    with g.as_default():
        df = rename_by_mapping(df, feed_tensors)
        df = tfs.analyze(df)
        df = tfs.map_blocks(fetch_tensors.values(), df)
        df = rename_by_mapping(df, feed_tensors, reverse=True)
        return rename_by_mapping(df, fetch_tensors, reverse=True)


import asyncio
import calendar
import datetime
import json
import random

import jdatetime
import pytz
import requests
from asgiref.sync import async_to_sync
from django.db.models import F, Count
from django.db.models.aggregates import Sum
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
from drf_yasg import openapi
from furl import furl
from persiantools.jdatetime import JalaliDateTime
from rest_framework import serializers
from rest_framework.exceptions import APIException
from rest_framework.generics import ListAPIView, RetrieveAPIView
from rest_framework.response import Response

from xproject import settings
from xproject.secret import DEMO
from sms.models import Operator, Message
from pydoc import locate

from django.db.models import Sum

class SumDistinctHACK(Sum):
    allow_distinct = True

def locate_from_api_v1_serializers(path):
    _from = "%s.%s" % ("xapp.api_v1.serializers",
                       path)
    c = locate(_from)
    return c

def generate_code():
    return str(random.randint(10000, 99999))

def generate_table_token():
    return str(random.randint(100000000000, 999999999999))

def get_verification_text(code):
    return _("به کافه پی خوش آمدید: %s" % code)

def send_verification_code(to, code):
    message = Message.objects.create(to=to, message=str(code))

    if DEMO:
        # Don't send actual sms if running on debug mode
        return

    return Operator.objects.get(vendor=Operator.KAVENEGAR).send_message(message)

def get_cafe_simple_json(cafe):
    return {'pk': cafe.pk, 'name': cafe.name}

class OverallRatingField(serializers.JSONField):
    class Meta:
        swagger_schema_fields = {
            "type": openapi.TYPE_OBJECT,
            "title": "Overall Rating Field",
            "properties": {
                "rate": openapi.Schema(
                    title="Overall rating",
                    type=openapi.FORMAT_FLOAT,
                ),
                "count": openapi.Schema(
                    title="Count",
                    type=openapi.TYPE_INTEGER,
                ),
            },
        }

class PaymentInfoField(serializers.JSONField):
    class Meta:
        swagger_schema_fields = {
            "type": openapi.TYPE_OBJECT,
            "title": "Payment Info field",
            "properties": {
                "total_count": openapi.Schema(
                    title="Total count",
                    type=openapi.FORMAT_FLOAT,
                ),
                "total_amount": openapi.Schema(
                    title="Total amount",
                    type=openapi.FORMAT_FLOAT,
                ),
                "payed_amount": openapi.Schema(
                    title="Payed Amount",
                    type=openapi.TYPE_INTEGER,
                ),
                "refund_amount": openapi.Schema(
                    title="Refund Amount",
                    type=openapi.TYPE_INTEGER,
                ),
                "net_amount": openapi.Schema(
                    title="Net Amount",
                    type=openapi.TYPE_INTEGER,
                ),
            },
        }

# small helper serializer

def get_payment_info(pbrs, only_invoices=False):
    """
        :param pbrs: array of product bill relation objects to calculate payment info
        :return: aggregated payment info
    """

    if not pbrs:
        return {
            'total_count': 0,
            'total_amount': 0,
            'payed_amount_pos': 0,
            'payed_amount_cash': 0,
            'payed_amount_online': 0,
            'refund_amount': 0,
            'net_payed_amount': 0,
            'net_amount': 0,
        }

    from xapp.api_v1.consts import InvoiceConsts
    from xapp.models import Invoice

    total_count = pbrs.aggregate(total_count=Sum('count'))

    total_amount = pbrs.aggregate(total_amount=Sum(F('count') * F('original_price') * (100 - F('discount')) / 100))

    payed_invoices = Invoice.objects.filter(tag=InvoiceConsts.PAYED_FOR_PRODUCT,
                                            type=InvoiceConsts.DEPOSIT,
                                            status__in=[InvoiceConsts.INTERNAL, InvoiceConsts.PAYED],
                                            pbr__in=pbrs)
    payed_invoices_pos = payed_invoices.filter(method=InvoiceConsts.POS)
    payed_invoices_cash = payed_invoices.filter(method=InvoiceConsts.CASH)
    payed_invoices_online = payed_invoices.filter(method=InvoiceConsts.ONLINE)

    agg_payed = payed_invoices.aggregate(payed_amount=Sum('amount'))
    agg_payed_pos = payed_invoices_pos.aggregate(payed_amount=Sum('amount'))
    agg_payed_cash = payed_invoices_cash.aggregate(payed_amount=Sum('amount'))
    agg_payed_online = payed_invoices_online.aggregate(payed_amount=Sum('amount'))

    refund_invoices = Invoice.objects.filter(tag=InvoiceConsts.REFUND,
                                             type=InvoiceConsts.WITHDRAW,
                                             pbr__in=pbrs)

    agg_refund = refund_invoices.aggregate(refund_amount=Sum('amount'))

    if only_invoices:
        return {
            'payed_invoices': payed_invoices,
            'refund_invoices': refund_invoices
        }

    clean_null_values(agg_payed)
    clean_null_values(agg_payed_pos)
    clean_null_values(agg_payed_cash)
    clean_null_values(agg_payed_online)
    clean_null_values(agg_refund)
    clean_null_values(total_amount)
    clean_null_values(total_count)

    total_amount = total_amount['total_amount']

    return {
        'total_count': total_count['total_count'],
        'total_amount': total_amount,

        'payed_amount': agg_payed['payed_amount'],
        'payed_amount_pos': agg_payed_pos['payed_amount'],
        'payed_amount_cash': agg_payed_cash['payed_amount'],
        'payed_amount_online': agg_payed_online['payed_amount'],

        'refund_amount': agg_refund['refund_amount'],
        'net_payed_amount': agg_payed['payed_amount'] -
                            agg_refund['refund_amount'],
        'net_amount': (total_amount -
                       agg_payed['payed_amount'] +
                       agg_refund['refund_amount'])
    }

def get_user_profile_basic_info_serializer(phone=False):
    from xapp.models import UserProfile

    class Serializer(serializers.ModelSerializer):
        class Meta:
            model = UserProfile
            fields = ['pk', 'full_name', 'email', 'first_name',
                      'last_name', 'phone_number']

    class SerializerPhone(serializers.ModelSerializer):
        class Meta:
            model = UserProfile
            fields = ['pk', 'full_name', 'email', 'phone_number', 'first_name',
                      'last_name', ]

    if not phone:
        return Serializer

    return SerializerPhone

def get_cafe_info_serializer(simple=False):
    from xapp.models import Cafe
    from xapp.api_v1.serializers.AddressSerializers import CafeRegionDetailedSerializer

    class Serializer(serializers.ModelSerializer):
        if not simple:
            overall_rating = OverallRatingField(read_only=True)
            delivery_regions = CafeRegionDetailedSerializer(many=True)

        avatar = serializers.ImageField()

        class Meta:
            model = Cafe

            if not simple:
                fields = ['pk', 'overall_rating',
                          'has_delivery',
                          'delivery_regions',
                          'name', 'is_open', 'payment_only',
                          'avatar', 'payment_first',
                          'phone',
                          'xproject_fee']
            else:
                fields = ['pk', 'name', 'xproject_fee', 'avatar',
                          'phone', 'has_delivery',
                          'payment_first', 'payment_only']

    return Serializer

def get_basic_menu_serializer():
    from xapp.models import Menu

    class Serializer(serializers.ModelSerializer):
        class Meta:
            model = Menu
            fields = ['pk', 'name', 'staff', 'is_active']

    return Serializer

def get_product_basic_info_serializer():
    from xapp.models import Product

    class _Serializer(serializers.ModelSerializer):
        class Meta:
            model = Product
            fields = ['pk', 'name', 'order']

            ref_name = "pbis"

    return _Serializer

def get_basic_char_field_serializer():
    from xapp.models import CharacterField

    class Serializer(serializers.ModelSerializer):
        class Meta:
            model = CharacterField
            fields = ['pk', 'title', 'cafe',
                      'is_delete', 'menu',
                      'staff', 'type']

    return Serializer

def get_table_simple_serializer():
    from xapp.models import Table

    class Serializer(serializers.ModelSerializer):
        class Meta:
            model = Table
            fields = ['pk', 'number', 'is_preorder']

    return Serializer

def get_table_by_token(token, user_profile):
    from xapp.models import TableToken
    table = get_object_or_404(TableToken, token=token, status=TableToken.ACTIVE).table

    return table

class APIBadRequest(APIException):
    status_code = 400

    def __init__(self, *args, **kwargs):
        self.status_code = kwargs.pop('status_code', 400)
        super(APIBadRequest, self).__init__(*args, **kwargs)

JOIN = '0'
TRANSFER = '2'

def validate_table_operation(t1, t2, op):
    if t1 == t2:
        raise APIBadRequest(detail=_("Same table operations not valid"))

    if t1.cafe != t2.cafe:
        raise APIBadRequest(detail=_("Cafe mismatch"))

    if not t1.active_join and not t2.active_join:
        raise APIBadRequest(detail=_("Empty tables operation not valid"))

    if op == TRANSFER:
        if not t1.active_join:
            raise APIBadRequest(detail=_("Cannot transfer empty table"))

def clean_null_values(aggregated_queryset):
    for key in aggregated_queryset.keys():
        if aggregated_queryset[key] is None:
            aggregated_queryset[key] = 0

def _thread_notifier(table):
    from xapp.api_v1.consumers.DispatchConsumer import DispatchConsumer
    from xapp.models import TableToken

    # todo: send to all joins
    # ----------------- socket notifications
    notify_watcher = async_to_sync(DispatchConsumer.notify_watcher_endpoint)
    _table_token = table.table_tokens.filter(status=TableToken.ACTIVE).first()
    _table_uuid = table.uuid

    notify_watcher(
        'table/%d/join/simple/by-id/' % table.pk
    )

    notify_watcher(
        'table/%d/aggregate/' % table.pk
    )

    notify_watcher(
        'cafe/%d/tables/join/simple/%s/' % (table.cafe.pk, TableToken.SELF_PICKUP)
    )

    notify_watcher(
        'cafe/%d/tables/join/simple/%s/' % (table.cafe.pk, TableToken.PAYMENT_ONLY)
    )

    notify_watcher(
        'cafe/%d/tables/join/simple/any/' % table.cafe.pk
    )

    if _table_token:
        notify_watcher(
            'table/%s/join/simple/by-token/' % _table_token.token)

    if _table_uuid:
        notify_watcher(
            'table/%s/join/simple/by-token/' % _table_uuid)

def _desktop_notification_thread(table):
    if table.is_preorder:
        print("before preorder check passed")

        cafe = table.cafe
        push_endpoints = cafe.push_endpoints.all()
        print("still here")
        push_requests = []
        payload = {
            'title': 'پیش سفارش | کافه پی',
            'body': 'پیش سفارش جدید برای شما ثبت شده است',
            'url': 'https://admin.xproject.app'
        }
        payload_text = json.dumps(payload)

        for push_endpoint in push_endpoints:
            push_requests.append({
                'text': payload_text,
                'keys': push_endpoint.keys,
                'subscription': push_endpoint.text
            })

        data = {
            'data': push_requests
        }

        print("before api call")
        print("request data")
        print(json.dumps(data))
        print("sending request")
        result = requests.post("http://cfpyqr.info:5000/api/vapid-data", json=data, verify=False)

        print("status report")
        print(result.status_code)
        print(result.text)

def _printer_thread_notifier(printer):
    from xapp.api_v1.consumers.DispatchConsumer import DispatchConsumer

    notify_watcher = async_to_sync(DispatchConsumer.notify_watcher_endpoint)

    notify_watcher(
        'cafe/%d/printer/jobs/' % printer.cafe.pk
    )

def notify_watchers(table):
    import threading

    thread1 = threading.Thread(target=_thread_notifier, args=(table,))
    thread1.start()

def notify_printers(printer):
    import threading

    thread1 = threading.Thread(target=_printer_thread_notifier, args=(printer,))
    thread1.start()

def convert_jalali_to_gregorian(date, _time):
    """
    :param date: date - either str or date object (str objects must be validated before passing to this function)
    :param _time: time - either str or time object (str objects must be validated before passing to this function)
    :return: converted and merged datetime object
    """

    if type(date) == str:
        date_data = date.split('-')
    else:
        date_data = str(date).split('-')

    if type(_time) == str:
        time_data = _time.split(':')
    else:
        time_data = str(_time).split(':')

    datetime_data = date_data + time_data
    datetime_data = [int(dt) for dt in datetime_data]

    nytz = pytz.timezone('Asia/Tehran')

    return datetime.datetime.fromtimestamp(
        calendar.timegm(nytz.localize(jdatetime.datetime(*datetime_data).togregorian()).utctimetuple()),
        tz=pytz.timezone("utc"))

def super_advanced_datetime_filter(queryset, datetime_field,
                                   start_date, start_time,
                                   end_date, end_time):
    """
    :param queryset:
    :param datetime_field:
    :param start_date:
    :param start_time:
    :param end_date:
    :param end_time:
    :return: filter a queryset across a date and time frame
    """

    # Scenario 1: start time < end time, perform a regular datetime filter
    if start_time <= end_time:
        return queryset.filter(**{
            "%s__date__gte" % datetime_field: start_date,
            "%s__date__lte" % datetime_field: end_date,
            "%s__time__gte" % datetime_field: start_time,
            "%s__time__lte" % datetime_field: end_time,
        })
    elif end_time < start_time:
        """
        converted time is like: from 01:00 until 11:00

        q1:
        ***********************************
        *  ----  ----  ----  ----  ----  *  00:00
        *  |  |  |  |  |  |  |  |  |  |  *
        *  |  |  |  |  |  |  |  |  |  |  *
        *  ----  ----  ----  ----  ----  *  21:30
        ***********************************

        q2:
                **********************************
                *  ----  ----  ----  ----  ----  *  07:30
                *  |  |  |  |  |  |  |  |  |  |  *
                *  |  |  |  |  |  |  |  |  |  |  *
                *  ----  ----  ----  ----  ----  *  00:00
                **********************************
        """
        q1 = queryset.filter(**{
            "%s__date__gte" % datetime_field: start_date,
            "%s__date__lt" % datetime_field: end_date,
            "%s__time__gte" % datetime_field: start_time
        })

        q2 = queryset.filter(**{
            "%s__date__gt" % datetime_field: start_date,
            "%s__date__lte" % datetime_field: end_date,
            "%s__time__lte" % datetime_field: end_time
        })

        return (q1 | q2).distinct()
    else:
        raise Exception("[ERROR] CPU Malfunction")

class AggregatedListAPIView(ListAPIView):
    """
    ListAPIView with aggregated data on the filtered queryset
    also supports total queryset aggregation when pagination is used
    """

    def get_extra_and_paginated_response(self, page, extra):
        """
        :param page: page of data
        :param extra: a dictionary containing extra fields to be included in the final response
        :return: paginated and extra response
        """

        serializer = self.get_serializer(page, many=True)

        if page is not None:
            response = self.get_paginated_response(serializer.data)
        else:
            response = serializer.data

        for key in extra.keys():
            response.data[key] = extra.get(key, None)

        return response

    def get_aggregated_data(self, queryset):
        """
        return a dictionary containing aggregated data of the given queryset
        """
        return {}

    def list(self, request, *args, **kwargs):
        """
        filter the given queryset
        generate some aggregate data
        return paginated data
        """
        queryset = self.filter_queryset(self.get_queryset())
        aggregated_data = self.get_aggregated_data(queryset=queryset)
        page = self.paginate_queryset(queryset)
        return self.get_extra_and_paginated_response(page, aggregated_data)

class ManagerialReport(RetrieveAPIView):
    """
        start datetime
        end datetime
        aggregation step

        **Managerial reports depend on a specific cafe
        therefore get_object must return the desired cafe
        that the reports may be generated for

    """

    class DateTimeException(Exception):
        pass

    def get_raw_report_params(self):
        """
        :return: {
            'start_datetime',
            'end_datetime',
            'step': 24 (this is default value),
        }
        """

        return {
            'start_datetime': self.request.query_params.get('start_datetime'),
            'end_datetime': self.request.query_params.get('end_datetime'),
            'step': self.request.query_params.get('step', 24)
        }

    def _validate_datetime(self, _datetime):
        """
        Convert _datetime start to actual python datetime objects

        catch any possible TypeError and ValueError exceptions and raise them as DateTimeException
        """
        try:
            return datetime.datetime.strptime(_datetime, "%Y-%m-%dT%H:%M")
        except (TypeError, ValueError) as e:
            if _datetime is None:
                raise self.DateTimeException("this field is required")
            else:
                raise self.DateTimeException(str(e))

    def validated_report_params(self):
        """
        :return: validate raw reports params and return validated data
        """
        raw_report_params = self.get_raw_report_params()
        errors = []

        # parse and validate start/end datetime s
        try:
            start_datetime = self._validate_datetime(raw_report_params.get('start_datetime'))
        except self.DateTimeException as e:
            errors.append({'start_datetime': [str(e), ]})

        try:
            end_datetime = self._validate_datetime(raw_report_params.get('end_datetime'))
        except self.DateTimeException as e:
            errors.append({'end_datetime': [str(e), ]})

        # validate step
        try:
            step = int(raw_report_params.get('step', 24))

            if step % 24 != 0:
                raise ValueError(_("step must be a multiple of 24 hours"))

            step = datetime.timedelta(hours=step)

        except (TypeError, ValueError) as e:
            errors.append({'step': [str(e), ]})

        # in report api's, start_datetime and end_datetime is required
        # and must be convertible to valid python datetime objects
        if not not errors:
            raise APIBadRequest(errors)

        # return the validate query_params data
        return {
            'start_datetime': start_datetime,
            'end_datetime': end_datetime,
            'step': step
        }

    def get_framed_queryset(self, start_datetime, end_datetime):
        """ count of items in the queryset that satisfies the given time constraints"""
        raise NotImplemented(_("Get framed queryset must be implemented"))

    def get_total_queryset_items(self):
        """Total number of items in an unbound (time wise) filter"""
        raise NotImplemented(_("Get total queryset items must be implemented"))

    def get_total_framed_items(self):
        """Total number of items in bounded (time wise) filter"""
        report_params = self.validated_report_params()

        return self.get_framed_queryset(report_params.get('start_datetime'),
                                        report_params.get('end_datetime'))

    def retrieve(self, request, *args, **kwargs):
        validated_params = self.validated_report_params()

        # extract report params
        start_datetime = validated_params.get('start_datetime')
        end_datetime = validated_params.get('end_datetime')
        step = validated_params.get('step')

        # total number of items in the given time frame
        total_bounded = self.get_total_framed_items()

        # total number of items in each step of the filter
        _start_datetime = start_datetime  # used inside the while loop that generates step by step aggregated reports

        step_results = []

        # calculate report result from start to end, excluding the last step
        while _start_datetime + step < end_datetime:
            queryset = self.get_framed_queryset(_start_datetime, _start_datetime + step)
            step_results.append(queryset)

            # increment counter start_datetime
            _start_datetime = _start_datetime + step

        # calculate the last step
        last_step = self.get_framed_queryset(_start_datetime, end_datetime)
        step_results.append(last_step)

        return Response({'total': self.get_total_queryset_items(),
                         'total_bounded': total_bounded,
                         'reports': step_results})

def kavenegar_send_sms(template, tokens, to):
    from xproject import settings
    import requests

    api_endpoint = "https://api.kavenegar.com/v1/{API-KEY}/verify/lookup.json"
    api = furl(api_endpoint.replace('{API-KEY}', settings.KAVENEGAR_API_KEY))
    api.args['receptor'] = to
    api.args['template'] = template

    for key in tokens.keys():
        api.args[key] = tokens.get(key)

    print(api.url)
    requests.get(api.url)

def datetime_to_local_str(date_time):
    asia_tehran = pytz.timezone('Asia/Tehran')
    local_now = date_time.astimezone(asia_tehran)
    return JalaliDateTime.to_jalali(local_now).strftime('%y/%m/%dساعت%H:%M:%S')

def datetime_to_asia_tehran(date_time):
    asia_tehran = pytz.timezone('Asia/Tehran')
    return date_time.astimezone(asia_tehran)


import gzip

class LogReader:

    def __init__(self, file_):
        self.stack_ = [{"data":["0","1","n"]}]
        self.time = 0
        self.current_ = None
        self.next_ = None
        self.done_ = False
        self.changed = False

        if ".gz" in file_:
            self.fp = gzip.open(file_)
            file_ = file_[:-3]
        else:
            self.fp = open(file_)

        self.next()

        self.name = file_
        if "/" in self.name:
            self.name = file_.rsplit("/", 1)[1]
        if self.name[-4:] == ".log":
            self.name = self.name[:-4]
        if self.name == "tracelogging-compile":
            self.name = "Ionmonkey background compilation"
        elif self.name == "tracelogging-gc":
            self.name = "GC background"

    def increase(self, time):
        self.changed = False
        while time >= self.duration:
            time -= self.duration
            self.next()
            self.changed = True

        self.duration -= time

    def next(self):
        while True:
            try:
                line = self.fp.next()
                next_ = line[:-1].split(",")
            except StopIteration:
                # file ends in newline (so last stop is already executed)
                if self.next_ == None:
                  self.done_ = True
                  return

                # file ends in stop statement
                self.current_ = self.next_
                self.next_ = None
                assert self.isStop()
                self.stack_ = self.stack_[:-1]
                return

            # Only process data with timestamp,event
            if len(next_) < 2:
                continue

            # Only process data for start/stop or engine change.
            if next_[1] not in ["1","0","e"]:
                continue

            self.current_ = self.next_
            self.next_ = next_

            if self.current_ == None:
                self.duration = int(self.next_[0])
                return

            self.duration = int(self.next_[0]) - int(self.current_[0])

            if self.isStart():
                self.stack_.append({"data": self.current_})
                # Hack to remove unreported engine between starting a script
                # and logging engine that is running
                if self.next_[1] == "e" and self.current_[2] == "s":
                    self.stack_[-1]["engine"] = self.next_[2][0]

            else:
                if self.isEngineChange():
                    self.stack_[-1]["engine"] = self.current_[2][0]
                else:
                    assert self.isStop()
                    self.stack_ = self.stack_[:-1]
            return

    def isStart(self):
        return self.current_[1] == "1"
    def isStop(self):
        return self.current_[1] == "0"
    def isEngineChange(self):
        return self.current_[1] == "e"
    def info(self):
        return self.stack_[-1]
    def isDone(self):
        return self.done_
    def stack(self):
        return self.stack_