from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import CallbackContext
from data_base.connection_db import connection

CALLBACK_BUTTON_ADD_DB = "callback_button_add"
CALLBACK_BUTTON_DELETE_DB = "callback_button_delete"
CALLBACK_BUTTON_COMPILE_ADD_DB = "callback_button_compile_add"
CALLBACK_BUTTON_COMPILE_DELETE_DB = "callback_button_compile_delete"

TITLES = {
    CALLBACK_BUTTON_ADD_DB: "Добавить в избранное ⭐",
    CALLBACK_BUTTON_DELETE_DB: "Удалить из избранных ❌",
    CALLBACK_BUTTON_COMPILE_ADD_DB: "Добавлено ✅",
    CALLBACK_BUTTON_COMPILE_DELETE_DB: "Удалено ⭕"
}

def get_add_keyboard():
    keyword = [
        [
            InlineKeyboardButton(TITLES[CALLBACK_BUTTON_ADD_DB],
                                 callback_data=CALLBACK_BUTTON_ADD_DB)
        ]
    ]
    return InlineKeyboardMarkup(keyword)

def get_delete_keyboard():
    keyword = [
        [
            InlineKeyboardButton(TITLES[CALLBACK_BUTTON_DELETE_DB],
                                 callback_data=CALLBACK_BUTTON_DELETE_DB)
        ]
    ]
    return InlineKeyboardMarkup(keyword)

def get_compiled_add_keyboard():
    keyword = [
        [
            InlineKeyboardButton(TITLES[CALLBACK_BUTTON_COMPILE_ADD_DB],
                                 callback_data=CALLBACK_BUTTON_COMPILE_ADD_DB)
        ]
    ]
    return InlineKeyboardMarkup(keyword)

def get_compiled_delete_keyboard():
    keyword = [
        [
            InlineKeyboardButton(TITLES[CALLBACK_BUTTON_COMPILE_DELETE_DB],
                                 callback_data=CALLBACK_BUTTON_COMPILE_DELETE_DB)
        ]
    ]
    return InlineKeyboardMarkup(keyword)

def keyboard_callback_handler(update: Update, context: CallbackContext):
    query = update.callback_query
    data = query.data
    current_message = update.effective_message.text
    chat_id = update.effective_message.chat_id

    if data == CALLBACK_BUTTON_ADD_DB:
        # добавление в бд
        with connection.cursor() as cursor:
            insert = (f"INSERT INTO Paper "
                      f"VALUES (NULL, {chat_id}, '{current_message[current_message.index('.') + 2:]}');")
            cursor.execute(insert)
            connection.commit()

        query.edit_message_text(
            text=current_message,
            reply_markup=get_compiled_add_keyboard()
        )
    elif data == CALLBACK_BUTTON_DELETE_DB:

        # Удаление записей и бд
        with connection.cursor() as cursor:
            select = (f"DELETE FROM Paper "
                      f"WHERE telegram_id = {chat_id} AND "
                      f"paper = '{current_message[current_message.index('.') + 2:]}'")
            cursor.execute(select)
            connection.commit()
        query.edit_message_text(
            text=current_message,
            reply_markup=get_compiled_delete_keyboard()
        )


import pygame
import sys
import random

pygame.init()

screen_width = 800
screen_height = 800
color = (0, 0, 0)
screen = pygame.display.set_mode((screen_width, screen_height))
screen_rec = screen.get_rect()

star = pygame.image.load("images/star.bmp")
star = pygame.transform.scale(star, (50, 50))
star_rec = star.get_rect()
star_size = 50

range_star_x = (0, screen_width - star_size)
range_star_y = (0, screen_height - star_size)
number_of_stars = 23

def draw_background():
    pygame.draw.rect(screen, color, pygame.Rect(0, 0, 800, 800))

x_values = []
y_values = []
def draw_star():
    for i in range(10):
        if x_values == 10:
            break
        else:
            x = random.randrange(*range_star_x)
            y = random.randrange(*range_star_y)
            x_values.append(x)
            y_values.append(y)

    for i in range(len(x_values)):
        coordinates = (x_values[i], y_values[i])

    screen.blit(star, coordinates)

clock = pygame.time.Clock()
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    draw_background()
    draw_star()

    i = 0

    pygame.display.flip()
    clock.tick(3)


# -*- coding: utf-8 -*-
"""
Created on Mon Apr  6 12:47:19 2020

@author: weineng.zhou
"""

import os
import tkinter
import pygame
from PIL import ImageTk, Image

# 音乐列表
currentroot = os.getcwd()
mp3_dir = './mp3'
mp3_list = os.listdir(mp3_dir)
keys = []
values = []
for i, e in enumerate(mp3_list):
   keys.append(i)
   values.append(e)
dic = dict(zip(keys, values))

# 初始化音乐播放器
app = tkinter.Tk()
app.iconbitmap('image/music.ico')
app.minsize(1000, 300)
app.maxsize(1000, 400)
app.title('音乐播放器')
# app.tk_setPalette(background='#848c8f', foreground='#000000', activeBackground='#ffffff', activeForeground='#000000')

# 播放器背景图片
canvas = tkinter.Canvas(app, width=1000,height=400,bd=0, highlightthickness=0)
imgpath = 'image/猫咪.jpg'
img = Image.open(imgpath)
img = img.resize((1000, 400), Image.ANTIALIAS)
photo = ImageTk.PhotoImage(img)
canvas.create_image(500, 200, image=photo)
canvas.pack()

# 初始化Pygame.mixer
pygame.mixer.init()

i = 0
pos = 200
stopflag = True
flag_pic = True

def rolltext(widget):
   global pos
   global stopflag
   source_str = dic[i][dic[i].rfind('\\')+1:-4] + ' '
   textwidth = 200
   str_len = len(source_str)
   if str_len - pos < 200:
      show_str.set(source_str[pos:pos+textwidth] + source_str[0:200 - str_len + pos])
   else:
      show_str.set(source_str[pos:pos+textwidth])
   pos += 1
   if pos > str_len:
      pos = 0
   if stopflag:
      widget.after(400, rolltext, widget)

def play():
   global stopflag
   stopflag = True
   rolltext(lab_text)
   pygame.mixer.init()
   pygame.mixer.music.load('mp3/' + dic[i])
   pygame.mixer.music.play()

def stop():
   global stopflag
   stopflag = False
   pygame.mixer.music.pause()

def lastone():
    global i
    global stopflag
    stopflag = True
    rolltext(lab_text)
    if i > 0:
       i = i - 1
    else:
       i = 0
    pygame.mixer.music.load('mp3/' + dic[i])
    pygame.mixer.music.play()

def nextone():
    global i
    global stopflag
    stopflag = True
    rolltext(lab_text)
    i = i + 1
    pygame.mixer.music.load('mp3/' + dic[i])
    pygame.mixer.music.play()

def click():
   global flag_pic
   flag_pic = not flag_pic
   if flag_pic:
      btn_stop['image'] = img_stop
      stop()
   else:
      btn_stop['image'] = img_play
      play()
   app.update()

# 标签 初始化显示文本
show_str = tkinter.StringVar(app)
show_str.set('')
lab_text = tkinter.Label(app, fg = '#ffffff', bg='#00b8e5', font = ('微软雅黑', 25), textvariable=show_str)
# lab_text.place(x=300, y=50, width=400, height=60)
lab_text.pack(padx=0, pady=0)

# 按钮
img_lastone = tkinter.PhotoImage(file='image/lastone.png')
img_play = tkinter.PhotoImage(file='image/play.png')
img_stop = tkinter.PhotoImage(file='image/stop.png')
img_nextone = tkinter.PhotoImage(file='image/nextone.png')

# 上一首
btn_last = tkinter.Button(app, image = img_lastone, bg = '#00b8e5', activebackground='#00bc57',
                          font = ('微软雅黑', 20), fg = '#ffffff', bd = 0.5,
                          command = lambda :lastone())  # .place(x = 140, y = 160, width = 200, height = 80)
btn_last.pack(padx=0, pady=0)

# 播放
btn_stop = tkinter.Button(app, image = img_stop, bg = '#00b8e5', activebackground='#00bc57',
                          font = ('微软雅黑', 20), fg = '#000000', bd = 0.5, command = lambda :click())
btn_stop.pack(padx=0, pady=0)

# 下一首
btn_next = tkinter.Button(app, image = img_nextone, bg = '#00b8e5', activebackground='#00bc57',
                          font = ('微软雅黑', 20), fg = '#ffffff', bd = 0.5,
                          command = lambda :nextone())  # .place(x = 640, y = 160, width = 200, height = 80)
btn_next.pack(padx=0, pady=0)

# 放置标签
canvas.create_window(500, 100, width=413, height=70, window=lab_text)
# 放置按钮
canvas.create_window(187, 200, width=213, height=91, window=btn_last)
canvas.create_window(500, 200, width=213, height=91, window=btn_stop)
canvas.create_window(813, 200, width=213, height=91, window=btn_next)

app.mainloop()


from django.urls import path
from . import views

urlpatterns = [
		path('', views.home, name='music-home'),
		path('explore/<int:pk>', views.explore_genre, name='music-explore-genre'),
		path('explore/', views.explore_all, name='music-explore'),
		path('album/<int:pk>', views.show_album, name='music-album'),
		path('my-music', views.my_music, name='music-mymusic')
]


import inspect
import itertools

from django.utils.functional import cached_property
from django.utils.module_loading import import_string

from django.conf import settings

class UserInfoProvider:
    """
    A provider for userinfo claims. To register custom providers, register them in settings file as:

        OPENID_CLAIM_PROVIDERS = ['myapp.openid_providers.MyProvider']
    """

    SCOPE_CLAIMS = {}
    """
    The scopes and claims that are handled by this userinfo provider. A dictionary of scope names -> list of claims
    within the scope. For custom scopes/claims consider using fully qualified names to avoid name collisions.

    Example:
        SCOPE_CLAIMS = {
            'http://myorg.com#idm' : [
                'http://myorg.com#personal_number',
                'http://myorg.com#roles',
            ]
        }
    """

    def get_claims(self, db_access_token):
        """
        Returns userinfo claims.

        This call must be idempotent.

        :param db_access_token:     an instance of OpenIDToken of the user whose claims should be returned
        :return:                    a dictionary of claims.
        """
        return {}

    def get_scope_claims(self):
        return self.SCOPE_CLAIMS

#
# OpenID Connect spec: default scopes and claims:
#
#  profile:
#      name, family_name, given_name, middle_name, nickname, preferred_username,
#      profile, picture, website, gender, birthdate, zoneinfo, locale, and updated_at.
# email
#      email, email_verified
# address
#      address
# phone
#      phone_number, phone_number_verified
#

class DjangoProfileProvider(UserInfoProvider):
    SCOPE_CLAIMS = {
        'profile': ['name', 'family_name', 'given_name', 'preferred_username'],
        # sub is not in a named scope, it is always added
        '': ['sub']
    }

    def get_claims(self, db_access_token, scope_or_claim=None):
        user = db_access_token.user

        return {
            'name': user.get_full_name(),
            'family_name': user.last_name,
            'given_name': user.first_name,
            'preferred_username': settings.OPENID_SUB_PROVIDER(user, db_access_token.client),
            'sub': settings.OPENID_SUB_PROVIDER(user, db_access_token.client),
            # 'middle_name' not set on django user,
            # 'nickname' not set on django user,
            # 'profile' not set on django user,
            # 'picture' not set on django user,
            # 'website' not set on django user,
            # 'gender' not set on django user,
            # 'birthdate' not set on django user,
            # 'zoneinfo' not set on django user,
            # 'locale' not set on django user,
            # 'updated_at' not set on django user.
        }

class DjangoEmailProvider(UserInfoProvider):
    SCOPE_CLAIMS = {
        'email': ['email']
    }

    def get_claims(self, db_access_token, scope_or_claim=None):
        user = db_access_token.user

        return {
            'email': user.email
            # 'email_verified' not set on django user,
        }

class UserInfoProviderRegistry:
    """
    registry of UserInfoProvider instances
    """

    DEFAULT_CLAIM_PROVIDERS = [
        DjangoProfileProvider,
        DjangoEmailProvider
    ]

    def __init__(self, user_claim_providers):
        self.scope_claims = {}
        self.claim_providers = {}
        for provider in itertools.chain(user_claim_providers, self.DEFAULT_CLAIM_PROVIDERS):
            self.register_provider(provider)

    def register_provider(self, provider_class_or_classname_or_instance):
        if isinstance(provider_class_or_classname_or_instance, str):
            provider = import_string(provider_class_or_classname_or_instance)()
        elif inspect.isclass(provider_class_or_classname_or_instance):
            provider = provider_class_or_classname_or_instance()
        else:
            provider = provider_class_or_classname_or_instance

        for scope_name, claims in provider.get_scope_claims().items():
            if scope_name not in self.scope_claims:
                self.scope_claims[scope_name] = []
            for claim in claims:
                if claim not in self.scope_claims[scope_name]:
                    self.scope_claims[scope_name].append(claim)
                if claim not in self.claim_providers:
                    self.claim_providers[claim] = []
                self.claim_providers[claim].append(provider)

    @cached_property
    def supported_scopes(self):
        return [scope for scope in sorted(self.scope_claims.keys()) if scope]

    @cached_property
    def supported_claims(self):
        return list(sorted(self.claim_providers.keys()))

    def get_claims(self, db_access_token, scopes, claims):
        claim_values = {}
        claim_names = set(claims)
        for scope in scopes:
            claim_names.update(self.scope_claims.get(scope, []))
        # add all claims from the unnamed scope
        claim_names.update(self.scope_claims[''])

        cache = {}
        for claim in self._filter_claims(claim_names, db_access_token.client):
            if claim in self.claim_providers:
                for provider in self.claim_providers[claim]:
                    if provider not in cache:
                        provider_data = provider.get_claims(db_access_token)
                        cache[provider] = provider_data
                    else:
                        provider_data = cache[provider]

                    if provider_data is not None:
                        if claim not in provider_data:
                            raise ValueError('Provider "%s" registered for claim "%s" has returned different claim: %s' %
                                             (provider, claim, provider_data))
                        if provider_data[claim]:
                            # set only claim with value
                            claim_values[claim] = provider_data[claim]
                        break

        return claim_values

    def _filter_claims(self, claims, client):
        """filter claims to only those that are allowed for the client"""
        allowed_claims = client.allowed_claims
        if allowed_claims is None:
            allowed_scopes = client.allowed_scopes
            if allowed_scopes is not None:
                allowed_claims = set()
                for scope in allowed_scopes:
                    if scope in self.scope_claims:
                        allowed_claims.update(self.scope_claims[scope])
        else:
            allowed_claims = set(allowed_claims)

        # always return empty scope as well if claims are restricted
        if allowed_claims:
            allowed_claims.update(self.scope_claims[''])

        for claim in claims:
            if not allowed_claims or claim in allowed_claims:
                yield claim


import random
from lxml import etree
from typing import List
from PIL import ImageDraw
from urllib.parse import unquote
from nonebot.log import logger

from .base_handle import BaseHandle, BaseData
from ..config import draw_config
from ..util import remove_prohibited_str, cn2py, load_font
from ..create_img import CreateImg

class AzurChar(BaseData):
    itype: str  # 舰娘类型

    @property
    def star_str(self) -> str:
        return ["白", "蓝", "紫", "金"][self.star - 1]

class AzurHandle(BaseHandle[AzurChar]):
    def __init__(self):
        super().__init__("azur", "碧蓝航线")
        self.max_star = 4
        self.config = draw_config.azur
        self.ALL_CHAR: List[AzurChar] = []

    def get_card(self, pool_name: str, **kwargs) -> AzurChar:
        if pool_name == "轻型":
            itype = ["驱逐", "轻巡", "维修"]
        elif pool_name == "重型":
            itype = ["重巡", "战列", "战巡", "重炮"]
        else:
            itype = ["维修", "潜艇", "重巡", "轻航", "航母"]
        star = self.get_star(
            [4, 3, 2, 1],
            [
                self.config.AZUR_FOUR_P,
                self.config.AZUR_THREE_P,
                self.config.AZUR_TWO_P,
                self.config.AZUR_ONE_P,
            ],
        )
        chars = [
            x
            for x in self.ALL_CHAR
            if x.star == star and x.itype in itype and not x.limited
        ]
        return random.choice(chars)

    def generate_card_img(self, card: AzurChar) -> CreateImg:
        sep_w = 5
        sep_t = 5
        sep_b = 20
        w = 100
        h = 100
        bg = CreateImg(w + sep_w * 2, h + sep_t + sep_b)
        frame_path = str(self.img_path / f"{card.star}_star.png")
        frame = CreateImg(w, h, background=frame_path)
        img_path = str(self.img_path / f"{cn2py(card.name)}.png")
        img = CreateImg(w, h, background=img_path)
        # 加圆角
        frame.circle_corner(6)
        img.circle_corner(6)
        bg.paste(img, (sep_w, sep_t), alpha=True)
        bg.paste(frame, (sep_w, sep_t), alpha=True)
        # 加名字
        text = card.name[:6] + "..." if len(card.name) > 7 else card.name
        font = load_font(fontsize=14)
        text_w, text_h = font.getsize(text)
        draw = ImageDraw.Draw(bg.markImg)
        draw.text(
            (sep_w + (w - text_w) / 2, h + sep_t + (sep_b - text_h) / 2),
            text,
            font=font,
            fill=["#808080", "#3b8bff", "#8000ff", "#c90", "#ee494c"][card.star - 1],
        )
        return bg

    def _init_data(self):
        self.ALL_CHAR = [
            AzurChar(
                name=value["名称"],
                star=int(value["星级"]),
                limited=True if "可以建造" not in value["获取途径"] else False,
                itype=value["类型"],
            )
            for value in self.load_data().values()
        ]

    async def _update_info(self):
        info = {}
        # 更新图鉴
        url = "https://wiki.biligame.com/blhx/舰娘图鉴"
        result = await self.get_url(url)
        if not result:
            logger.warning(f"更新 {self.game_name_cn} 出错")
            return
        dom = etree.HTML(result, etree.HTMLParser())
        contents = dom.xpath(
            "//div[@class='resp-tabs-container']/div[@class='resp-tab-content']"
        )
        for index, content in enumerate(contents):
            char_list = content.xpath("./table/tbody/tr[2]/td/div/div/div/div")
            for char in char_list:
                try:
                    name = char.xpath("./a/@title")[0]
                    frame = char.xpath("./div/a/img/@alt")[0]
                    avatar = char.xpath("./a/img/@srcset")[0]
                except IndexError:
                    continue
                member_dict = {
                    "名称": remove_prohibited_str(name),
                    "头像": unquote(str(avatar).split(" ")[-2]),
                    "星级": self.parse_star(frame),
                    "类型": self.parse_type(index),
                }
                info[member_dict["名称"]] = member_dict
        # 更新额外信息
        for key in info.keys():
            url = f"https://wiki.biligame.com/blhx/{key}"
            result = await self.get_url(url)
            if not result:
                info[key]["获取途径"] = []
                logger.warning(f"{self.game_name_cn} 获取额外信息错误 {key}")
                continue
            try:
                dom = etree.HTML(result, etree.HTMLParser())
                time = dom.xpath(
                    "//table[@class='wikitable sv-general']/tbody[1]/tr[4]/td[2]//text()"
                )[0]
                sources = []
                if "无法建造" in time:
                    sources.append("无法建造")
                elif "活动已关闭" in time:
                    sources.append("活动限定")
                else:
                    sources.append("可以建造")
                info[key]["获取途径"] = sources
            except IndexError:
                info[key]["获取途径"] = []
                logger.warning(f"{self.game_name_cn} 获取额外信息错误 {key}")
        self.dump_data(info)
        logger.info(f"{self.game_name_cn} 更新成功")
        # 下载头像
        for value in info.values():
            await self.download_img(value["头像"], value["名称"])
        # 下载头像框
        idx = 1
        BLHX_URL = "https://patchwiki.biligame.com/images/blhx"
        for url in [
            "/1/15/pxho13xsnkyb546tftvh49etzdh74cf.png",
            "/a/a9/k8t7nx6c8pan5vyr8z21txp45jxeo66.png",
            "/a/a5/5whkzvt200zwhhx0h0iz9qo1kldnidj.png",
            "/a/a2/ptog1j220x5q02hytpwc8al7f229qk9.png",
            "/6/6d/qqv5oy3xs40d3055cco6bsm0j4k4gzk.png",
        ]:
            await self.download_img(BLHX_URL + url, f"{idx}_star")
            idx += 1

    @staticmethod
    def parse_star(star: str) -> int:
        if star == "舰娘头像外框普通.png":
            return 1
        elif star == "舰娘头像外框稀有.png":
            return 2
        elif star == "舰娘头像外框精锐.png":
            return 3
        elif star == "舰娘头像外框超稀有.png":
            return 4
        elif star == "舰娘头像外框海上传奇.png":
            return 5
        elif star in [
            "舰娘头像外框最高方案.png",
            "舰娘头像外框决战方案.png",
            "舰娘头像外框超稀有META.png",
            "舰娘头像外框精锐META.png",
        ]:
            return 6
        else:
            return 6

    @staticmethod
    def parse_type(index: int) -> str:
        azur_types = [
            "驱逐",
            "轻巡",
            "重巡",
            "超巡",
            "战巡",
            "战列",
            "航母",
            "航站",
            "轻航",
            "重炮",
            "维修",
            "潜艇",
            "运输",
        ]
        try:
            return azur_types[index]
        except IndexError:
            return azur_types[0]


#!/usr/bin/env python

'''
Simple example of stereo image matching and point cloud generation.
Resulting .ply file cam be easily viewed using MeshLab ( http://meshlab.sourceforge.net/ )
'''

# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2
import pickle

ply_header = '''ply
format ascii 1.0
element vertex %(vert_num)d
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
end_header
'''

def write_ply(fn, verts, colors):

    verts = verts.reshape(-1, 3)
    colors = colors.reshape(-1, 3)
    mask = ~np.isnan(verts).any(axis=1)
    verts = verts[mask]
    colors = colors[mask]
    mask = ~np.isinf(verts).any(axis=1)
    verts = verts[mask]
    colors = colors[mask]
    verts = np.hstack([verts, colors])
    with open(fn, 'wb') as f:
        f.write((ply_header % dict(vert_num=len(verts))).encode('utf-8'))
        np.savetxt(f, verts, fmt='%f %f %f %d %d %d ')

def get_disparity(imgL, imgR):
    window_size = 3
    min_disp = 16
    num_disp = 112-min_disp

def read_images(video_left, video_right):
    cap_left = cv2.VideoCapture(video_left)
    cap_right = cv2.VideoCapture(video_right)
    left_buf, right_buf = [], []
    while True:
        if cap_left.grab():
            flag, frame = cap_left.retrieve()
            left_buf.append(frame)
        if cap_left.get(cv2.CAP_PROP_POS_FRAMES) == cap_left.get(cv2.CAP_PROP_FRAME_COUNT):
            break

    while True:
        if cap_right.grab():
            flag, frame = cap_right.retrieve()
            right_buf.append(frame)
        if cap_right.get(cv2.CAP_PROP_POS_FRAMES) == cap_right.get(cv2.CAP_PROP_FRAME_COUNT):
            break

    print(len(left_buf),len(right_buf))
    left_buf = np.array(left_buf)
    right_buf = np.array(right_buf)
    return left_buf,right_buf

# https://blog.csdn.net/bcj296050240/article/details/52778741
# important:https://blog.csdn.net/bcj296050240/article/details/52778741
if __name__ == '__main__':
    print('loading images...')
    img_left, img_right = read_images(video_left="/home/ye/programming/TaurusCpp/python/video2/video_l.mp4",
                                      video_right="/home/ye/programming/TaurusCpp/python/video2/video_r.mp4")
    with open('cam_model.pickle', 'rb') as handle:
        cam = pickle.load(handle)
        M1, M2 = cam["M1"], cam["M2"]
        d1, d2 = cam["dist1"], cam["dist2"]
        r1, r2 = cam["rvecs1"], cam["rvecs2"]
        R, T = cam["R"], cam["T"]
        E, F = cam["E"], cam["F"]
        R1, R2 = cam["R1"], cam["R2"]
        P1, P2 = cam["P1"], cam["P2"]
        Q = cam["Q"]
        print(Q)

    # line 90:
    #https://github.com/MegaYEye/Taurus-Misc/blob/master/IE590%20Group%20Project/TaurusStereo/TaurusStereo/main.cpp
    # https://blog.csdn.net/bcj296050240/article/details/52778741

    # https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html
    # what is the homography rectification
    # http://www.bmva.org/bmvc/2010/conference/paper89/abstract89.pdf
    # stereoRectifyUncalibrated
    # 3rd parameter: Optional rectification transformation in the object space (3x3 matrix). R1 or R2 , computed by stereoRectify can be passed here.
    # 4th parameter:  In case of a stereo camera, newCameraMatrix is normally set to P1 or P2 computed by stereoRectify .
    map1x, map1y = cv2.initUndistortRectifyMap(M1, d1, R1, P1, (1280, 720), cv2.CV_32FC1)
    map2x, map2y = cv2.initUndistortRectifyMap(M2, d2, R2, P2, (1280, 720), cv2.CV_32FC1)

    imgU1 = cv2.remap(img_left[110], map1x, map1y, cv2.INTER_LINEAR)
    imgU2 = cv2.remap(img_right[110], map2x, map2y, cv2.INTER_LINEAR)

    # for i, (L, R) in enumerate(zip(img_left, img_right)):
    #     L = cv2.remap(L, map1x, map1y, cv2.INTER_LINEAR)
    #     R = cv2.remap(R, map2x, map2y, cv2.INTER_LINEAR)
    #     cv2.imwrite(f"stereo_rectified_L/{i}.jpg", L)
    #     cv2.imwrite(f"stereo_rectified_R/{i}.jpg", R)
    # pass
    # imgU1 = cv2.GaussianBlur(imgU1, (5, 5), 3)
    # imgU2 = cv2.GaussianBlur(imgU2, (5, 5), 3)
    # imgU1 = cv2.GaussianBlur(imgU1, (5, 5), 3)
    # imgU2 = cv2.GaussianBlur(imgU2, (5, 5), 3)
    # imgU1 = cv2.GaussianBlur(imgU1, (5, 5), 3)
    # imgU2 = cv2.GaussianBlur(imgU2, (5, 5), 3)
    # looks correct before here.

    # while True:
    #     img = np.concatenate([imgU1, imgU2], axis=1)
    #     cv2.imshow("CC",img)
    #     # cv2.imshow("L",imgU1)
    #     # cv2.imshow("R", imgU2)
    #     # cv2.imshow("Lori",img_left[0])
    #     # cv2.imshow("Rori", img_right[0])
    #     cv2.waitKey(10)
    #     # cv2.imwrite("L.jpg",imgU1)
    #     # cv2.imwrite("R.jpg",imgU2)
    #     # exit()

    """
    	sgbm.preFilterCap = 63;
		sgbm.SADWindowSize = 9;//SADWindowSize > 0 ? SADWindowSize : 3;
		int cn = 1;
		sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
		sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
		sgbm.minDisparity = 0;
		sgbm.numberOfDisparities = numberOfDisparities;
		sgbm.uniquenessRatio = 1;
		sgbm.speckleWindowSize = 100;
		sgbm.speckleRange = 32;
		sgbm.disp12MaxDiff = 2;
		sgbm.fullDP = false;
    """

    # window_size = 3
    # min_disp = 32
    # num_disp = 112-min_disp
    # stereo = cv2.StereoSGBM_create(minDisparity = min_disp,
    #     preFilterCap = 63,
    #     numDisparities = num_disp,
    #     blockSize = 16,
    #     P1 = 8*3*window_size**2,
    #     P2 = 32*3*window_size**2,
    #     disp12MaxDiff = 1,
    #     uniquenessRatio = 10,
    #     speckleWindowSize = 100,
    #     speckleRange = 32
    # )
    # # why dividie by 16
    # print('computing disparity...')

    # stereo = cv2.StereoBM_create(
    #     # blockSize=5,
    #     # numDisparities=64,
    # )
    # imgU1=cv2.cvtColor(imgU1, cv2.COLOR_BGR2GRAY)
    # imgU2=cv2.cvtColor(imgU2, cv2.COLOR_BGR2GRAY)
    window_size = 9
	# left matcher is StereoSGBM_create
    stereo = cv2.StereoSGBM_create(
        numDisparities=96,
        blockSize=7,
        P1=8*3*window_size**2,
        P2=32*3*window_size**2,
        disp12MaxDiff=1,
        uniquenessRatio=16,
        speckleRange=2,
        mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
    )
    disp = stereo.compute(imgU1, imgU2).astype(np.float32)/16

    print('generating 3d point cloud...',)
    h, w = imgU1.shape[:2]
    f = 0.8*w                          # guess for focal length
    Q = np.float32([[1, 0, 0, -0.5*w],
                    [0,-1, 0,  0.5*h], # turn points 180 deg around x-axis,
                    [0, 0, 0,     -f], # so that y-axis looks up
                    [0, 0, 1,      0]])
    # https://stackoverflow.com/questions/41503561/whats-the-difference-between-reprojectimageto3dopencv-and-disparity-to-3d-coo
    # however, directly define depth = fb/D needs to ensure the two cameras to be parallel to each other.
    # stereoRectify:The function computes the rotation matrices for each camera that (virtually) make both camera image planes the same plane. Consequently, this makes all the epipolar lines parallel and thus simplifies the dense stereo correspondence problem. The function takes the matrices computed by stereoCalibrate as input. As output, it provides two rotation matrices and also two projection matrices in the new coordinates. The function distinguishes the following two cases:
    # https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html#ga617b1685d4059c6040827800e72ad2b6
    # can output Q	Output 4×4 disparity-to-depth mapping matrix (see reprojectImageTo3D).
    points = cv2.reprojectImageTo3D(disp, Q)
    colors = cv2.cvtColor(imgU1, cv2.COLOR_BGR2RGB)
    mask = disp > disp.min()
    out_points = points[mask]
    out_colors = colors[mask]
    out_fn = 'out.ply'
    write_ply('out.ply', out_points, out_colors)
    print('%s saved' % 'out.ply')

    cv2.imshow('left', imgU1)
    cv2.imshow('disparity', (disp-disp.min()))
    cv2.waitKey()
    cv2.destroyAllWindows()


import torch
import torch.nn as nn
import torch.nn.functional as F

class INELU (nn.Module):
    def __init__ (self, out_ch):
        super (INELU, self).__init__ ()
        self.module = nn.Sequential (
                nn.InstanceNorm2d (out_ch),
                nn.ELU ()
            )

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

class Residual_Conv (nn.Module):
    def __init__ (self, in_ch, out_ch, bias=False):
        super (Residual_Conv, self).__init__ ()
        self.conv1 = nn.Sequential (
            nn.Conv2d (in_ch, out_ch, kernel_size=3,
                padding=1, bias=bias),
            INELU (out_ch))
        self.conv2 = nn.Sequential (
            nn.Conv2d (out_ch, out_ch//2, kernel_size=3,
                padding=1, bias=bias),
            INELU (out_ch))
        self.conv3 = nn.Conv2d (out_ch//2, out_ch, kernel_size=3,
            padding=1, bias=bias)

    def forward (self, x):
        _in = x
        x = self.conv1 (_in)
        x = self.conv2 (x)
        _out = self.conv3 (x)
        return _in + _out

class FusionDown (nn.Module):
    def __init__ (self, in_ch, out_ch, bias=False, kernel_size=3):
        super (FusionDown, self).__init__ ()
        self.conv_in = nn.Sequential (
            nn.Conv2d (in_ch, out_ch, kernel_size=3, stride=2,
                padding=1, bias=bias),
            INELU (out_ch))
        self.residual = Residual_Conv (out_ch, out_ch, bias=bias)
        self.conv_out = nn.Sequential (
            nn.Conv2d (out_ch, out_ch, kernel_size=kernel_size,
                padding=1, bias=bias),
            INELU (out_ch))

    def forward (self, x):
        x = self.conv_in (x)
        x = self.residual (x)
        x = self.conv_out (x)
        return x

class FusionUp (nn.Module):
    def __init__ (self, in_ch, out_ch, bias=False, kernel_size=3):
        super (FusionUp, self).__init__ ()
        self.conv_in = nn.Sequential (
            nn.Conv2d (in_ch, out_ch, kernel_size=kernel_size, padding=1, bias=bias),
            INELU (out_ch))
        self.residual = Residual_Conv (out_ch, out_ch, bias=bias)
        self.deconv_out = nn.Sequential (
            nn.ConvTranspose2d (out_ch, out_ch, kernel_size=3, stride=2,
                bias=bias),
            INELU (out_ch))

    def forward (self, x):
        x = self.conv_in (x)
        x = self.residual (x)
        x = self.deconv_out (x)
        N, C, H, W = x.shape
        x = x [:,:,0:H-1, 0:W-1]
        return x

class FusionNet (nn.Module):

    def __init__ (self, in_ch, features, out_ch):
        super (FusionNet, self).__init__ ()
        self.first_layer = nn.Sequential (INELU (in_ch),
            nn.Conv2d (in_ch, features[0], 3, bias=True, padding=1))
        self.down1 = FusionDown (features[0], features[0])
        self.down2 = FusionDown (features[0], features[1])
        self.down3 = FusionDown (features[1], features[2])
        self.down4 = FusionDown (features[2], features[3])
        self.middle = nn.Dropout (p=0.5)
        self.up4 = FusionUp (features[3], features[2])
        self.up3 = FusionUp (features[2], features[1])
        self.up2 = FusionUp (features[1], features[0])
        self.up1 = FusionUp (features[0], features[0])
        self.last_layer = nn.Sequential (
            nn.Conv2d (features[0], out_ch, 3, padding=1, bias=True),
            nn.Tanh ()
        )

    def forward (self, x):
        x = self.first_layer (x)
        down1 = self.down1 (x)
        down2 = self.down2 (down1)
        down3 = self.down3 (down2)
        down4 = self.down4 (down3)
        middle = self.middle (down4)
        up4 = self.up4 (middle)
        up3 = self.up3 (up4 + down3)
        up2 = self.up2 (up3 + down2)
        up1 = self.up1 (up2 + down1)

        out = (self.last_layer (up1 + x) + 1.0) / 2
        return out

class double_conv(nn.Module):
    '''(conv => BN => ReLU) * 2'''
    def __init__(self, in_ch, out_ch):
        super(double_conv, self).__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_ch, out_ch, 3, padding=1),
            nn.InstanceNorm2d(out_ch),
            nn.ReLU(),
            nn.Conv2d(out_ch, out_ch, 3, padding=1),
            nn.InstanceNorm2d(out_ch),
            nn.ReLU()
        )

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

class inconv(nn.Module):
    def __init__(self, in_ch, out_ch):
        super(inconv, self).__init__()
        self.conv = double_conv(in_ch, out_ch)

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

class UNet_down(nn.Module):
    def __init__(self, in_ch, out_ch):
        super(UNet_down, self).__init__()
        self.mpconv = nn.Sequential(
            nn.MaxPool2d(2),
            double_conv(in_ch, out_ch)
        )

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

class UNet_up(nn.Module):
    def __init__(self, in_ch, out_ch, bilinear=False):
        super(UNet_up, self).__init__()

        #  would be a nice idea if the upsampling could be learned too,
        #  but my machine do not have enough memory to handle all those weights
        if bilinear:
            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
        else:
            self.up = nn.ConvTranspose2d(in_ch//2, in_ch//2, 2, stride=2)

        self.conv = double_conv(in_ch, out_ch)

    def forward(self, x1, x2):
        # # input is CHW
        x1 = self.up (x1)
        # diffY = x2.size()[2] - x1.size()[2]
        # diffX = x2.size()[3] - x1.size()[3]

        # x1 = F.pad(x1, (diffX // 2, diffX - diffX//2,
        #                 diffY // 2, diffY - diffY//2))
        # for padding issues, see
        # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a
        # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd

        x = torch.cat([x2, x1], dim=1)
        x = self.conv(x)
        return x

class outconv(nn.Module):
    def __init__(self, in_ch, out_ch):
        super(outconv, self).__init__()
        self.conv = nn.Conv2d(in_ch, out_ch, 1)

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

class UNet (nn.Module):
    def __init__(self, in_ch, features, out_ch):
        super(UNet, self).__init__()
        self.inc = inconv(in_ch, features [0])
        self.down1 = UNet_down(features[0], features[1])
        self.down2 = UNet_down(features[1], features[2])
        self.down3 = UNet_down(features[2], features[3])
        self.down4 = UNet_down(features[3], features[3])
        self.up1 = UNet_up(features[3] * 2, features[2])
        self.up2 = UNet_up(features[2] * 2, features[1])
        self.up3 = UNet_up(features[1] * 2, features[0])
        self.up4 = UNet_up(features[0] * 2, features[0])
        self.actor = outconv(features [0], out_ch)
        self.critic = outconv (features [0], 1)

    def forward(self, x):
        x1 = self.inc(x)
        x2 = self.down1(x1)
        x3 = self.down2(x2)
        x4 = self.down3(x3)
        x5 = self.down4(x4)
        x = self.up1(x5, x4)

        x = self.up2(x, x3)
        x = self.up3(x, x2)
        x = self.up4(x, x1)
        actor = self.actor (x)
        critic = self.critic (x)
        return critic, actor

def to_numpy (tensor):
    return tensor.cpu ().numpy ().squeeze ()

def debug (tensor):
    tensor_np = to_numpy (tensor)
    shape = tensor_np.shape
    for i in range (shape [0]):
        print (tensor_np [i])

if __name__ == "__main__":
    FEATURES = [16, 32, 64, 128]
    model = UNet (in_ch=5, features=FEATURES, out_ch=2)
    x = torch.zeros ((1,5,256,256), dtype=torch.float32)
    value, logit = model (x)

    # print (torch.rand ((1, 4, 4)))
    # # prob = prob.transpose (1, -1)
    # print (prob.shape)
    # prob = prob.reshape (-1, 2)
    # print (prob.shape)
    # distribution = torch.distributions.Categorical
    # m = distribution (prob)
    # print (m.sample ().shape)

    logit = torch.rand ((1, 2, 3, 4))
    prob = F.softmax (logit, 1)
    debug (prob)
    prob_tp = prob.permute (0, 2, 3, 1)
    distribution = torch.distributions.Categorical (prob_tp)
    sample = distribution.sample ()
    print (prob_tp.shape)
    shape = prob_tp.shape
    action = sample.reshape (1, shape[1], shape[2], 1).permute (0, 3, 1, 2)
    debug (sample)
    action_prob = prob.gather (1, action)
    debug (action_prob)
    print (action_prob.shape)
    print (action_prob[0][0].shape)

    # action_max = prob.max (1)[1]
    # print (action_max.shape)


from flask import Flask,Blueprint,render_template,redirect,url_for
from Shares import db
from Shares.ShareNames.forms import AddForm,DeleteForm
from Shares.models import Company

shares_blueprint = Blueprint('Shares',__name__,template_folder='templates/ShareNames')

@shares_blueprint.route('/add',methods=['GET','POST'])
def add():
    form = AddForm()
    if form.validate_on_submit():
        name = form.name.data
        price = form.price.data
        quantity = form.quantity.data
        Total = price * quantity

        sha = Company(name,price,quantity,Total)
        db.session.add(sha)
        db.session.commit()

        return redirect(url_for('Shares.list'))

    return render_template('add.html',form=form)

@shares_blueprint.route('/list')
def list():
    shar = Company.query.all()
    return render_template('list.html',shar=shar)

@shares_blueprint.route('/delete',methods=['GET','POST'])
def delete():
    form = DeleteForm()

    if form.validate_on_submit():
        id = form.id.data
        pup = Company.query.get(id)
        db.session.delete(pup)
        db.session.commit()

        return redirect(url_for('Shares.list'))
    return render_template('delete.html',form=form)


import datetime
from django.db.models import Q
from core.models import Assurance

def Get_assurances_manquantes_by_inscriptions(famille=None, inscriptions=None):
    # Recherche les individus pour qui l'assurance est obligatoire
    liste_individus = []
    for inscription in inscriptions:
        if inscription.activite.assurance_obligatoire and inscription.individu not in liste_individus:
            liste_individus.append(inscription.individu)

    # Recherche les assurances existantes
    dict_assurances = {}
    conditions = Q(famille=famille) & Q(individu_id__in=liste_individus) & Q(date_debut__lte=datetime.date.today()) & (Q(date_fin__isnull=True) | Q(date_fin__gte=datetime.date.today()))
    for assurance in Assurance.objects.select_related("individu").filter(conditions):
        dict_assurances.setdefault(assurance.individu, [])
        dict_assurances[assurance.individu].append(assurance)

    # Recherche les assurances manquantes
    resultats = [individu for individu in liste_individus if individu not in dict_assurances]

    return resultats


from django.shortcuts import render, redirect
from .models import Room
from django.contrib.auth.models import User
from .forms import RoomForm
from lcsupport import LCSupport
from django.views.decorators import gzip
from django.http import StreamingHttpResponse
from django.http import JsonResponse
from base import data
from base.dbcontroller import DBController
import json
from time import sleep
import cv2
# Create your views here.

# rooms = [
#    {'id': 1, 'name': 'Lets learn python!'},
#    {'id': 2, 'name': 'Design with me'},
#    {'id': 3, 'name': 'Frontend developer'},
# ]
# ---------------------Config---------------------

corY = 187

def read_config():
    try:
        with open('Settings.json') as file:
            data = json.load(file)
            settings = json.loads(data)
            print(settings)
            return settings
    except:
        print("Configfile not found")
        return "LoadingFailed"

# def change_config():
#    with open('Settings.json') as file:
#        data = json.load(file)
 #       settings = json.loads(data)

# ---------------------Seitenrendering---------------------

def landing(request):
    global updateCam
    updateCam = False
    d = data.Data()
    gesamtKundenzahl = gesamtZahlHeute()
    kundenInLaden = kundenzahlInLaden()
    vergleich = gesamtKundenzahl - vergleichVorwoche()
    # For testing
    #gesamtKundenzahl = 24
    #kundenInLaden = 24
    #vergleichVorwoche = 9
    return render(request, 'index.html', {'gesamtKundenzahl': gesamtKundenzahl, 'kundenInLaden': kundenInLaden, 'vergleichVorwoche': vergleich})

def settings(request):
    global corY
    global updateCam
    updateCam = False
    updateCam = True
    f = open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json')
    print(type(f))
    rawdata = f.read()
    data = json.loads(rawdata)

    corY = data["pos"]
    print(corY)

    return render(request, 'einstellungen.html')

def dataanalysis(request):
    global updateCam
    updateCam = False
    d = [['Uhrzeit', 'Kundenzahl Schnitt', 'Kundenzahl'], ['9:00',  1, 1], ['10:00',  2, 3], [
        '11:00',  19, 16], ['12:00',  67, 89], ['13:00',  50, 45], ['14:00',  50, 0], ['15:00',  36, 0]]
    return render(request, 'datenanalyse.html', {'data': d})

# ---------------------API---------------------

def testapi(request):
    data = [['Uhrzeit', 'Kundenzahl Schnitt', 'Kundenzahl'], ['9:00',  1, 1], ['10:00',  2, 3], [
        '11:00',  19, 16], ['12:00',  67, 89], ['13:00',  50, 45], ['14:00',  50, 0], ['15:00',  36, 0]]
    #data = [['9:00',  1, 1], ['10:00',  2, 3], ['11:00',  17, 16], ['12:00',  7, 89], ['13:00',  0, 45]]

    return JsonResponse(data, safe=False)

def chart_ios(request):
    # data = [{"heute": [1, 2, 19, 67, 50, 50, 36],
    # "schnitt": [1, 3, 16, 89, 45, 50, 0], "uhrzeit": ['09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00']}]
    data = [{"heute": [1, 2, 19, 67, 50, 50, 36],
            "schnitt": [1, 3, 16, 89, 45, 50, 0], "uhrzeit": ['09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00']}]
    j = JsonResponse(data, safe=False)
    return j

def test(request, pk, pd):
    return JsonResponse([{"test": pk, "test2": pd}], safe=False)

def homedata(request):
    data = [{"kundengerade": 54, "kundengesamt": 41, "vergleich": -5}]
    jsonString = json.dumps(data, indent=4)
    j = JsonResponse(data, safe=False)
    print("Test ", j.content)
    return j

def get_config(request):
    try:
        with open('Settings.json') as file:
            data = [json.load(file)]
            print(data)
            j = JsonResponse(data, safe=False)
            return j
    except:
        print("Configfile not found")
        return JsonResponse([{"nothing": "found"}], safe=False)

def get_chartdata(request, start, end):
    data = chart_vonbis(start, end)
    r = request
    j = JsonResponse(data, safe=False, )
    return j

def get_chartdata2(request, start):
    data = chart_vonbis2(start)
    r = request
    j = JsonResponse(data, safe=False)
    return j

def get_date_of_first_entry(request):
    data = [{"frist": str(time_of_first_entry())}]
    j = JsonResponse(data, safe=False)
    return j

def move_line_up(request):
    global corY
    corY = corY - 10
    print("down")
    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json') as f:
        data = json.load(f)
    data["pos"] = corY

    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json', 'w') as f:
        json.dump(data, f)
    return livecamera(request)

def move_line_down(request):
    global corY
    corY = corY + 10
    print("down")
    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json') as f:
        data = json.load(f)
    data["pos"] = corY

    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json', 'w') as f:
        json.dump(data, f)
    return livecamera(request)

def deactivateFIK(day):
    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json') as f:
        data = json.load(f)
    data["timestart"][day] = 9999

    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json', 'w') as f:
        json.dump(data, f)
    return True

def updateFIK(day, start, end):
    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json') as f:
        data = json.load(f)
    startI = start[0] + start[1] + start[3] + start[4]
    endI = end[0] + end[1] + end[3] + end[4]
    data["timestart"][day] = int(startI)
    data["timeend"][day] = int(endI)

    with open('/home/pi/Skripte/FrequenzmesserIK0.3/Settings.json', 'w') as f:
        json.dump(data, f)
    return True

# ---------------------Datenbankdaten aufbereiten---------------------

def time_of_first_entry():
    dbc = DBController()
    # Richtige Daten eintragen
    data = dbc.query(
        "SELECT column_name FROM table_name ORDER BY column_name ASC LIMIT 1;")
    return data[0][0]

def chart_vonbis(start, end):
    # SQL-Abfrage Monat in 'mm-dd-yyyy' Format
    dbc = DBController()
    print(start, end)
    # Richtige Daten eintragen
    data = dbc.query(
        f"select kundenzahl, DATE_FORMAT(Datum, '%H %i') from daten where Date(Datum) BETWEEN date(\"{start}\") AND date(\"{end}\")")
    print(data)
    #data = dbc.query(f"select kundenzahl, date(Datum) from daten ")
    return data

def chart_vonbis2(start=""):
    # SQL-Abfrage Monat in 'mm-dd-yyyy' Format
    dbc = DBController()
    # Richtige Daten eintragen

    data = dbc.query(
        f"select kundenzahl from daten where Datum BETWEEN {start[:9]} AND {start[10:]}")
    return data

def gesamtZahlHeute():
    dbc = DBController()
    # richtige Daten eintragen!!!!

    data = dbc.query(
        "select kundenzahl from daten where DATE(Datum) = curdate();")

    gesamtZahlKunden = 0
    letzterWert = 0

    for d in data:
        if (d[0] > letzterWert):
            gesamtZahlKunden += 1
        letzterWert = d[0]

    return gesamtZahlKunden

def kundenzahlInLaden():
    dbc = DBController()
    # richtige Daten eintragen!!!!
    data = dbc.query("select kundenzahl from daten ORDER BY id DESC LIMIT 1;")

    return data[0][0]

def vergleichVorwoche():
    dbc = DBController()
    # richtige Daten eintragen!!!!
    kundenzahlVorwocheData = dbc.query(
        "select kundenzahl from daten where Datum between curdate() - interval 7 day + '00:00:00' and now() - interval 7 day")
    gesamtZahlKundenVorwoche = 0
    letzterWert = 0

    for d in kundenzahlVorwocheData:
        if (d[0] > letzterWert):
            gesamtZahlKundenVorwoche += 1
        letzterWert = d[0]

    return gesamtZahlKundenVorwoche

# ---------------------Livecamera---------------------
cam = LCSupport.cam()
updateCam = False
# Starten des Livefeeds

@gzip.gzip_page
def livecamera(request):
    try:
        global cam
        #cam = LCSupport.cam()
        global updateCam
        updateCam = True
        print("camera started")
        return StreamingHttpResponse(generateFeed(cam), content_type="multipart/x-mixed-replace;boundary=frame")
    except Exception as e:
        print("Error: Camera did not load")
        print(e)
        pass
    return render(request, 'base/index.html')

# Beenden des Livefeeds

def stoplivecamera(request):
    global cam
    del cam
    global updateCam
    updateCam = False
    print("camera off")
    return JsonResponse([{}], safe=False)
# Live camera feed

def generateFeed(camera):
    print("generateFeed")
    global corY
    while updateCam:
        frame = camera.get_frame(corY)
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
        sleep(0.3)
    print("end generateFeed")

"""def home(request):
    rooms = Room.objects.all()
    context = {'rooms': rooms}
    return render(request, 'base/home.html', context)
def room(request, pk):
    room = Room.objects.get(id=pk)
    context = {'room': room}
    return render(request, 'base/room.html', context)
def createRoom(request):
    form = RoomForm()
    if request.method == 'POST':
        form = RoomForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('home')
    context = {'form': form}
    return render(request, 'base/room_form.html', context)
def updateRoom(request, pk):
    room = Room.objects.get(id=pk)
    form = RoomForm(instance=room)
    if request.method == 'POST':
        form = RoomForm(request.POST, instance=room)
        if form.is_valid():
            form.save()
            return redirect('home')
    context = {'form': form}
    return render(request, 'base/room_form.html', context)"""


import atexit
import json
import logging
import os
import sys
import warnings
import xml.etree.ElementTree as ET
from itertools import cycle
from pathlib import Path
from typing import Any, Dict, List, Optional, TypeVar

import jpype
import jpype.imports
import numpy as np
from jpype.imports import registerDomain
from jpype.types import JArray, JInt
from PIL import Image

from rl_algo_impls.microrts.vec_env.microrts_interface import (
    ByteArray,
    MicroRTSInterface,
    MicroRTSInterfaceListener,
)

MICRORTS_MAC_OS_RENDER_MESSAGE = """
gym-microrts render is not available on MacOS. See https://github.com/jpype-project/jpype/issues/906

It is however possible to record the videos via `env.render(mode='rgb_array')`.
See https://github.com/vwxyzjn/gym-microrts/blob/b46c0815efd60ae959b70c14659efb95ef16ffb0/hello_world_record_video.py
as an example.
"""

MicroRTSGridModeVecEnvSelf = TypeVar(
    "MicroRTSGridModeVecEnvSelf", bound="MicroRTSGridModeVecEnv"
)

UTT_VERSION_ORIGINAL_FINETUNED = 2

class MicroRTSGridModeVecEnv(MicroRTSInterface):
    DEBUG_VERIFY = False

    def __init__(
        self,
        num_selfplay_envs,
        num_bot_envs,
        partial_obs=False,
        max_steps=2000,
        render_theme=2,
        frame_skip=0,
        ai2s=[],
        map_paths=["maps/10x10/basesTwoWorkers10x10.xml"],
        reward_weight=np.array([10.0, 1.0, 1.0, 0.2, 1.0, 4.0, 5.25, 6.0, 0]),
        cycle_maps=[],
        bot_envs_alternate_player: bool = False,
        video_frames_per_second: Optional[int] = None,
    ):
        self.num_selfplay_envs = num_selfplay_envs
        self.num_bot_envs = num_bot_envs
        self._num_envs = num_selfplay_envs + num_bot_envs
        assert self.num_bot_envs == len(
            ai2s
        ), "for each environment, a microrts ai should be provided"
        self._partial_obs = partial_obs
        self.max_steps = max_steps
        self.render_theme = render_theme
        self.frame_skip = frame_skip
        self.ai2s = ai2s
        self.players = [i % 2 for i in range(self._num_envs)]
        self.bot_envs_alternate_player = bot_envs_alternate_player
        self.map_paths = map_paths
        if len(map_paths) == 1:
            self.map_paths = [map_paths[0] for _ in range(self.num_envs)]
        else:
            assert (
                len(map_paths) == self.num_envs
            ), "if multiple maps are provided, they should be provided for each environment"
        self.reward_weight = reward_weight
        self.metadata = {
            "render.modes": ["human", "rgb_array"],
            "video.frames_per_second": video_frames_per_second
            if video_frames_per_second is not None
            else 150,
        }

        self.microrts_path = os.path.join(Path(__file__).parent.parent, "java")

        # prepare training maps
        self.cycle_maps = list(
            map(lambda i: os.path.join(self.microrts_path, i), cycle_maps)
        )
        self.next_map = cycle(self.cycle_maps)

        self._heights = []
        self._widths = []
        for mp in self.map_paths:
            root = ET.parse(os.path.join(self.microrts_path, mp)).getroot()
            h = int(root.get("height"))
            w = int(root.get("width"))
            self._heights.append(h)
            self._widths.append(w)

        # launch the JVM
        if not jpype._jpype.isStarted():
            registerDomain("ts", alias="tests")
            registerDomain("ai")
            jars = [
                "RAISocketAI.jar",
                "lib/microrts.jar",
                "lib/bots/Coac.jar",
                "lib/bots/Droplet.jar",
                "lib/bots/GRojoA3N.jar",
                "lib/bots/Izanagi.jar",
                "lib/bots/MixedBot.jar",
                "lib/bots/TiamatBot.jar",
                "lib/bots/UMSBot.jar",
                "lib/bots/mayariBot.jar",  # "MindSeal.jar"
            ]
            for jar in jars:
                jpype.addClassPath(os.path.join(self.microrts_path, jar))
            jpype.startJVM(convertStrings=False)
            atexit.register(jpype.shutdownJVM)

        # start microrts client
        from rts.units import UnitTypeTable

        self.real_utt = UnitTypeTable(UTT_VERSION_ORIGINAL_FINETUNED)
        from ai.reward import (
            AttackRewardFunction,
            ProduceBuildingRewardFunction,
            ProduceHeavyUnitRewardFunction,
            ProduceLightUnitRewardFunction,
            ProduceRangedUnitRewardFunction,
            ProduceWorkerRewardFunction,
            RAIWinLossRewardFunction,
            ResourceGatherRewardFunction,
            RewardFunctionInterface,
            ScoreRewardFunction,
        )

        self.rfs = JArray(RewardFunctionInterface)(
            [
                RAIWinLossRewardFunction(),
                ResourceGatherRewardFunction(),
                ProduceWorkerRewardFunction(),
                ProduceBuildingRewardFunction(),
                AttackRewardFunction(),
                ProduceLightUnitRewardFunction(),
                ProduceRangedUnitRewardFunction(),
                ProduceHeavyUnitRewardFunction(),
                ScoreRewardFunction(),
                # CloserToEnemyBaseRewardFunction(),
            ]
        )
        self.raw_names = [str(rf) for rf in self.rfs]
        self.start_client()

        self.delta_rewards = np.zeros(self.num_envs, dtype=np.float32)

    def start_client(self):
        from ai.core import AI
        from ts import RAIGridnetVecClient as Client

        self.vec_client = Client(
            self.num_selfplay_envs,
            self.num_bot_envs,
            self.max_steps,
            self.rfs,
            os.path.expanduser(self.microrts_path),
            self.map_paths,
            JArray(AI)([ai2(self.real_utt) for ai2 in self.ai2s]),
            self.real_utt,
            self.partial_obs,
        )
        self.render_client = (
            self.vec_client.selfPlayClients[0]
            if len(self.vec_client.selfPlayClients) > 0
            else self.vec_client.clients[0]
        )
        # get the unit type table
        self._utt = json.loads(str(self.render_client.sendUTT()))

    def reset(self):
        self.delta_rewards = np.zeros_like(self.delta_rewards)

        responses = self.vec_client.reset(self.players)
        self._resources = to_byte_array_list(responses.resources)
        self._terrain = to_byte_array_list(responses.terrain)
        return (
            to_byte_array_list(responses.observation),
            to_byte_array_list(responses.mask),
        )

    def _encode_info(
        self, batch_rewards: np.ndarray, done: np.ndarray
    ) -> List[Dict[str, Any]]:
        infos = []
        for idx, (rewards, d) in enumerate(zip(batch_rewards, done)):
            score_reward = rewards[self.raw_names.index("ScoreRewardFunction")]
            delta_reward = score_reward - self.delta_rewards[idx]
            info = {
                "raw_rewards": rewards,
                "score_reward": {
                    "reward": score_reward,
                    "delta_reward": delta_reward,
                },
            }
            if d:
                winloss = rewards[self.raw_names.index("RAIWinLossRewardFunction")]
                if np.sign(score_reward) != np.sign(winloss) and np.sign(winloss) != 0:
                    logging.warn(
                        f"score_reward {score_reward} must be same sign as winloss {winloss}"
                    )
                info["results"] = {
                    "score_reward": score_reward,
                    "WinLoss": winloss,
                    "win": int(winloss == 1),
                    "draw": int(winloss == 0),
                    "loss": int(winloss == -1),
                }
            infos.append(info)
            self.delta_rewards[idx] = score_reward if not d else 0
        return infos

    def step_async(self, actions):
        self.actions = JArray(JArray(JArray(JInt)))(
            [
                JArray(JArray(JInt))([JArray(JInt)(a) for a in actions_in_env])
                for actions_in_env in actions
            ]
        )

    def step_wait(self):
        responses = self.vec_client.gameStep(self.actions, self.players)
        reward, done = np.array(responses.reward), np.array(responses.done)
        obs = to_byte_array_list(responses.observation)
        mask = to_byte_array_list(responses.mask)
        self._resources = to_byte_array_list(responses.resources)
        infos = self._encode_info(reward, done[:, 0])
        # check if it is in evaluation, if not, then change maps
        if len(self.cycle_maps) > 0:
            # check if an environment is done, if done, reset the client, and replace the observation
            for done_idx, d in enumerate(done[:, 0]):
                if not d:
                    continue
                if done_idx < self.num_selfplay_envs:
                    if done_idx % 2 == 1:
                        continue
                    self.vec_client.selfPlayClients[done_idx // 2].mapPath = next(
                        self.next_map
                    )
                    self.vec_client.selfPlayClients[done_idx // 2].reset(
                        self.players[done_idx]
                    )
                    p0_response = self.vec_client.selfPlayClients[
                        done_idx // 2
                    ].getResponse(0)
                    p1_response = self.vec_client.selfPlayClients[
                        done_idx // 2
                    ].getResponse(1)
                    obs[done_idx] = np.array(p0_response.observation)
                    obs[done_idx + 1] = np.array(p1_response.observation)
                    mask[done_idx] = np.array(p0_response.mask)
                    mask[done_idx + 1] = np.array(p1_response.mask)
                    self._terrain[done_idx] = np.array(p0_response.terrain)
                    self._terrain[done_idx + 1] = np.array(p1_response.terrain)
                    self._resources[done_idx] = np.array(p0_response.resources)
                    self._resources[done_idx + 1] = np.array(p1_response.resources)
                else:
                    env_idx = done_idx - self.num_selfplay_envs
                    self.vec_client.clients[env_idx].mapPath = next(self.next_map)
                    if self.bot_envs_alternate_player:
                        self.players[done_idx] = (self.players[done_idx] + 1) % 2
                    response = self.vec_client.clients[env_idx].reset(
                        self.players[done_idx]
                    )
                    obs[done_idx] = np.array(response.observation)
                    mask[done_idx] = np.array(response.mask)
                    self._terrain[done_idx] = np.array(response.terrain)
                    self._resources[done_idx] = np.array(response.resources)
        else:
            if self.bot_envs_alternate_player:
                for done_idx, d in enumerate(done[:, 0]):
                    if not d:
                        continue
                    if done_idx < self.num_selfplay_envs:
                        continue
                    self.players[done_idx] = (self.players[done_idx] + 1) % 2
                    env_idx = done_idx - self.num_selfplay_envs
                    response = self.vec_client.clients[env_idx].reset(
                        self.players[done_idx]
                    )
                    obs[done_idx] = np.array(response.observation)
                    mask[done_idx] = np.array(response.mask)
                    self._terrain[done_idx] = np.array(response.terrain)
                    self._resources[done_idx] = np.array(response.resources)
        return obs, mask, reward @ self.reward_weight, done[:, 0], infos

    def step(self, ac):
        self.step_async(ac)
        return self.step_wait()

    @property
    def num_envs(self):
        return self._num_envs

    @property
    def heights(self) -> List[int]:
        return self._heights

    @property
    def widths(self) -> List[int]:
        return self._widths

    @property
    def utt(self) -> Dict[str, Any]:
        return self._utt

    @property
    def partial_obs(self) -> bool:
        return self._partial_obs

    def terrain(self, env_idx: int) -> np.ndarray:
        return self._terrain[env_idx].reshape(
            (self._heights[env_idx], self._widths[env_idx])
        )

    def terrain_md5(self, env_idx: int) -> str:
        import hashlib

        hash_obj = hashlib.md5()
        hash_obj.update(self.terrain(env_idx).tobytes())
        return hash_obj.hexdigest()

    def resources(self, env_idx: int) -> np.ndarray:
        return self._resources[env_idx]

    def render(self, mode="human"):
        if mode == "human":
            self.render_client.render(False)
            # give warning on macos because the render is not available
            if sys.platform == "darwin":
                warnings.warn(MICRORTS_MAC_OS_RENDER_MESSAGE)
        elif mode == "rgb_array":
            bytes_array = np.array(self.render_client.render(True))
            image = Image.frombytes("RGB", (640, 640), bytes_array)
            return np.array(image)[:, :, ::-1]

    def close(self, **kwargs):
        if jpype._jpype.isStarted():
            self.vec_client.close()

    def add_listener(self, listener: MicroRTSInterfaceListener) -> None:
        pass

    def remove_listener(self, listener: MicroRTSInterfaceListener) -> None:
        pass

    def debug_matrix_obs(self, env_idx: int) -> Optional[np.ndarray]:
        if not self.DEBUG_VERIFY:
            return None
        from ai.rai import GameStateWrapper

        if env_idx < self.num_selfplay_envs:
            gsw = GameStateWrapper(self.vec_client.selfPlayClients[env_idx // 2].gs)
            player_id = env_idx % 2
        else:
            gsw = GameStateWrapper(
                self.vec_client.clients[env_idx - self.num_selfplay_envs].gs
            )
            player_id = self.players[env_idx]
        return np.transpose(np.array(gsw.getVectorObservation(player_id)), (1, 2, 0))

    def debug_matrix_mask(self, env_idx: int) -> Optional[np.ndarray]:
        if not self.DEBUG_VERIFY:
            return None

        from ai.rai import GameStateWrapper

        if env_idx < self.num_selfplay_envs:
            gsw = GameStateWrapper(self.vec_client.selfPlayClients[env_idx // 2].gs)
            player_id = env_idx % 2
        else:
            gsw = GameStateWrapper(
                self.vec_client.clients[env_idx - self.num_selfplay_envs].gs
            )
            player_id = self.players[env_idx]
        return np.array(gsw.getMasks(player_id))

def to_byte_array_list(java_array) -> List[ByteArray]:
    return [np.array(a) for a in java_array]


from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth.hashers import make_password, check_password
from store.models.product import Product
from store.models.category import Category
from django.views import View

# Create your views here.
# def index(request):
#     products = None
#     categories = Category.get_all_categories()
#
#     # print(request.GET)
#     categoryID = request.GET.get('category')
#     if categoryID:
#         products = Product.get_all_product_by_categoryid(categoryID)
#     else:
#         products = Product.get_all_products()
#     data = {}
#     data['products'] = products
#     data['category'] = categories
#     print('guegsdkvb  :  ',request.session.get('customer_email'))
#     return render(request,'index.html',{'products': data})

class Index(View):
    def get(self,request):
        cart = request.session.get('cart')
        if not cart:
            request.session['cart'] = {}
        products = None
        categories = Category.get_all_categories()

        # print(request.GET)
        categoryID = request.GET.get('category')
        if categoryID:
            products = Product.get_all_product_by_categoryid(categoryID)
        else:
            products = Product.get_all_products()
        data = {}
        data['products'] = products
        data['category'] = categories
        # print('guegsdkvb  :  ', request.session.get('customer_email'))
        return render(request, 'index.html', {'products': data})

    def post(self,request):
        product = request.POST.get('product')
        remove = request.POST.get('remove')
        cart = request.session.get('cart')
        if cart:
            quantity = cart.get(product)
            if quantity:
                if remove:
                    if quantity <= 1:
                        cart.pop(product)
                    else:
                        cart[product] = quantity - 1
                else:
                    cart[product] = quantity + 1
            else:
                cart[product] = 1
        else:
            cart = {}
            cart[product] = 1
        request.session['cart'] = cart
        # print('cart ', request.session['cart'])
        return redirect('homepage')