"""Apple.py: File that handle the apple display and collision"""

import pygame
import random

__author__ = "Magalie Vandenbriele"
__credits__ = ["Magalie Vandenbriele", "Pierre Ghyzel", "Irama Chaouch"]
__license__ = "GPL"
__version__ = "1.0"
__maintainer__ = ["Magalie Vandenbriele", "Irama Chaouch"]
__email__ = "magalie.vandenbriele@epitech.eu"

class Apple:
    position = (0, 0)
    sprite_size = 20.0

    def __init__(self, screen, screen_size, position_save=None):
        self._sprite = pygame.image.load("game_module/assets/elements/apple.png")
        self._screen_size = screen_size
        self._screen = screen
        if position_save is not None:
            self.position = position_save

    def is_occupied(self, body_part, head, x, y):
        if x == head[0] and y == head[1]:
            return True
        for part in body_part:
            if part.x == x and part.y == y:
                return True
        return False

    def generate(self, body_part, head):
        x = round(random.randrange(1, round(self._screen_size[0] / self.sprite_size - 1))) * self.sprite_size
        y = round(random.randrange(1, round(self._screen_size[1] / self.sprite_size - 1))) * self.sprite_size

        while self.is_occupied(body_part, head, x, y):
            x = round(random.randrange(1, round(self._screen_size[0] / self.sprite_size - 1))) * self.sprite_size
            y = round(random.randrange(1, round(self._screen_size[1] / self.sprite_size - 1))) * self.sprite_size
        self.position = (x, y)

    def generate_multi(self, body_part, head, body_part_second, second_head, position_apple):
        x = round(random.randrange(1, round(self._screen_size[0] / self.sprite_size - 1))) * self.sprite_size
        y = round(random.randrange(1, round(self._screen_size[1] / self.sprite_size - 1))) * self.sprite_size

        while self.is_occupied(body_part, head, x, y) or self.is_occupied(body_part_second, second_head, x, y) or\
                (x == position_apple[0] and y == position_apple[1]):
            x = round(
                random.randrange(1, round(self._screen_size[0] / self.sprite_size - 1))) * self.sprite_size
            y = round(
                random.randrange(1, round(self._screen_size[1] / self.sprite_size - 1))) * self.sprite_size
        self.position = (x, y)

    def display(self):
        self._screen.blit(self._sprite, self.position)


# -*- coding: utf-8 -*-
from django.views.generic import DetailView
from django.http import FileResponse, HttpResponse
from main.views.base import ClientView, LegalView
from common.utils import get_client_ip
from portfolios.models import LivePortfolio
from statements.chart_configs import ChartData
from statements.models import StatementOfAdvice, RecordOfAdvice, \
    RetirementStatementOfAdvice, LivePortfolioReport, PDFStatement
from django.shortcuts import render_to_response

__all__ = ["StatementView", "RecordView", "RetirementStatementOfAdvice"]

class PDFView(DetailView, ClientView):
    def get_queryset(self):
        return self.model.objects.filter(
            account__primary_owner=self.request.user.client)

    def get(self, request, pk, ext=None):
        obj = self.get_object()
        if(ext.lower() == '.pdf'):
            response = HttpResponse(obj.render_pdf(self.template_name),
                                    content_type='application/pdf')
            response['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(obj.filename)
        else:
            response = HttpResponse(obj.render_template(self.template_name))
        return response

class StatementView(PDFView):
    template_name = StatementOfAdvice.default_template
    model = StatementOfAdvice

class RecordView(PDFView):
    template_name = RecordOfAdvice.default_template
    model = RecordOfAdvice

    def get_queryset(self):
        return RecordOfAdvice.objects.all()

class RetirementView(PDFView):
    template_name = RetirementStatementOfAdvice.default_template
    model = RetirementStatementOfAdvice

    def get_queryset(self):
        return RetirementStatementOfAdvice.objects.all()

    def get(self, request, pk, ext=None):
        obj = RetirementStatementOfAdvice.objects.get(pk=pk)
        client_ip = get_client_ip(request)

        if(ext.lower() == '.pdf'):
            response = HttpResponse(obj.render_pdf(self.template_name, client_ip=client_ip),
                                    content_type='application/pdf')
            response['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(obj.filename)
        else:
            response = HttpResponse(obj.render_template(self.template_name, client_ip=client_ip))
        return response

class FirmPortfolioReportView(DetailView, LegalView):
    template_name = 'statements/firm_portfolio_report/index.html'
    model = LivePortfolioReport

    def get_queryset(self):
        return LivePortfolioReport.objects.all()

    def get(self, request, pk, ext):
        obj = LivePortfolioReport.objects.get(pk=pk)
        if(ext.lower() == '.pdf'):
            response = HttpResponse(obj.pdf, content_type='application/pdf')
            response['Content-Disposition'] = 'inline; filename="{}.pdf"'.format(obj.filename)
        else:
            response = HttpResponse(obj.render_template(self.template_name, configs=None, render_type='html', request=request))
        return response

class FirmPortfolioReportWebView(DetailView, LegalView):
    template_name = 'statements/firm_portfolio_report/index.html'
    model = LivePortfolio

    def get_queryset(self):
        return LivePortfolio.objects.all()

    def get(self, request, pk, ext=None):

        obj = LivePortfolioReport(live_portfolio_id=pk)

        response = HttpResponse(obj.render_template(self.template_name, configs=None, render_type='html', request=request))
        return response

def ChartConfigs(request, lp_pk):
    import json
    chartData = ChartData()
    configs = json.dumps({
            'portfolio_performance': chartData.portfolio_performance_config(),
            'investment_growth': chartData.investment_growth_config(),
            'asset_allocation': chartData.asset_allocation_config(),
            'portfolio_tilts': chartData.portfolio_tilts(),
            'portfolio_weight_risk': chartData.portfolio_weight_risk(),
            'portfolio_weight_return': chartData.portfolio_weight_return(),
            'geographic_exposure': chartData.geographic_exposure(),
            'gics_sector': chartData.gics_sector(),
            'us_economic_chart1': chartData.get_us_economic_chart1(),
            'us_economic_chart2': chartData.get_us_economic_chart2(),
            'eu_economic_chart1': chartData.get_eu_economic_chart1(),
            'eu_economic_chart2': chartData.get_eu_economic_chart2(),
            'jp_economic_chart1': chartData.get_jp_economic_chart1(),
            'jp_economic_chart2': chartData.get_jp_economic_chart2(),
            'au_economic_chart1': chartData.get_au_economic_chart1(),
            'au_economic_chart2': chartData.get_au_economic_chart2(),
            'cn_economic_chart1': chartData.get_cn_economic_chart1(),
            'cn_economic_chart2': chartData.get_cn_economic_chart2(),
            'hk_economic_chart1': chartData.get_hk_economic_chart1(),
            'hk_economic_chart2': chartData.get_hk_economic_chart2(),
            'equities': chartData.equities(),
            'fx': chartData.fx(),
            'fixed_income': chartData.fixed_income(),
            'asset_contributions_returns': chartData.asset_contributions_returns(),
            'asset_contributions_volatility': chartData.asset_contributions_volatility(),
            'portfolio_weight_risk1': chartData.portfolio_weight_risk1(),
            'portfolio_weight_contributions': chartData.portfolio_weight_contributions(),
            'fund_performance': chartData.fund_performance(),
            'fund_risk': chartData.fund_risk(),
            'asset_allocation1': chartData.asset_allocation1(),
            'daa_change': chartData.daa_change(),
            'daa_change1': chartData.daa_change1(),
            'daa_change2': chartData.daa_change2()
    })
    return HttpResponse(configs)


from selenium import webdriver
import requests
from webdriver_manager.chrome import ChromeDriverManager
import time
import pandas as pd
import numpy as np
from bs4 import BeautifulSoup as bs
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--mute-audio")
driver = webdriver.Chrome(ChromeDriverManager().install(),options=chrome_options)
wait = WebDriverWait(driver,5)

base_url = [
'https://www.youtube.com/c/AshleySmithTV/',
'https://www.youtube.com/channel/UC0uHB4d6u0jIJSgPC3WzBFw/',
'https://www.youtube.com/c/msbrittanysarah/',
'https://www.youtube.com/c/vasseurbeauty/',
'https://www.youtube.com/user/cammie919/',
'https://www.youtube.com/channel/UCRXoGyLligcyVA1UWVV0cNg/',
'https://www.youtube.com/channel/UCvkCXERHO-0u5AW2wuzEXWA/',
'https://www.youtube.com/channel/UCDBroOWVP4aN8SYM0br6sJQ/',
'https://www.youtube.com/user/emilynorrisloves/',
'https://www.youtube.com/channel/UC3w9E1N7zukLxJ5bkrU4IKw/',
'https://www.youtube.com/channel/UC7fPf1yuGaYFmbxe0ZrshWw/',
'https://www.youtube.com/c/JettingJulia/',
'https://www.youtube.com/channel/UCP1odR9n2-qGsRdVXIkJqwg/,'
'https://www.youtube.com/channel/UCsxYHogcRJlu-xXFjggC0JA/',
'https://www.youtube.com/c/vlogwithkendra/',
'https://www.youtube.com/channel/UCwEq1lQikxTIjO61JlbHc7Q/',
'https://www.youtube.com/user/PrincessLaurenTV/',
'https://www.youtube.com/channel/UCWoEpiHaC7LOQhaHFT8Rx7A/',
'https://www.youtube.com/c/LisaOnuoha/',
'https://www.youtube.com/c/MaggieMacDonaldVlogs/',
'https://www.youtube.com/c/MissMikaylaG/',
'https://www.youtube.com/c/NadiaAnya/',
'https://www.youtube.com/c/NatalieBarbu/',
'https://www.youtube.com/c/PaytonSartainHH/',
'https://www.youtube.com/c/RisaDoesMakeup/',
'https://www.youtube.com/c/tarahenderson/',
'https://www.youtube.com/c/glamtwinz334/',
'https://www.youtube.com/c/valelorenbeautychannel/',
'https://www.youtube.com/channel/UC63MviKbxyCP7Yw6wxW5JAw/',
'https://www.youtube.com/c/AjaDang/',]

def scroll_down():
    time.sleep(.5)
    driver.execute_script("var scrollingElement = (document.scrollingElement || document.body);scrollingElement.scrollTop = scrollingElement.scrollHeight;")
    time.sleep(.3)
    driver.execute_script("var scrollingElement = (document.scrollingElement || document.body);scrollingElement.scrollTop = scrollingElement.scrollHeight;")
    time.sleep(.3)
    driver.execute_script("var scrollingElement = (document.scrollingElement || document.body);scrollingElement.scrollTop = scrollingElement.scrollHeight;")

def check_exists_by_xpath(xpath):
    try:
        driver.find_element_by_xpath(xpath)
    except NoSuchElementException:
        return False
    return True

def Likes():
        if  check_exists_by_xpath('/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[8]/div[2]/ytd-video-primary-info-renderer/div/div/div[3]/div/ytd-menu-renderer/div/ytd-toggle-button-renderer[1]/a/yt-formatted-string') == True:
            likes = driver.find_element_by_xpath('/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[8]/div[2]/ytd-video-primary-info-renderer/div/div/div[3]/div/ytd-menu-renderer/div/ytd-toggle-button-renderer[1]/a/yt-formatted-string').text
            if "LIKE" in likes:
                likes = likes.rstrip("LIKE")
                likes = 0
                return likes
            elif  "K" in likes:
                likes = likes.rstrip("K")
                likes = float(likes) *1000
                likes = int(likes)
                return likes
            else:
                try:
                    likes = int(likes)
                    return likes
                except ValueError:
                    likes = 0
                    print("likes sckiped")
                    return likes

def Dislikes():
    dislik = driver.find_element_by_xpath('/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[8]/div[2]/ytd-video-primary-info-renderer/div/div/div[3]/div/ytd-menu-renderer/div/ytd-toggle-button-renderer[2]/a/yt-formatted-string').text
    dislik = dislik.rstrip("K")
    dislik = dislik.rstrip("DISLIKE")

    try:
        dislik = float(dislik)
        dislik = float(dislik)
        return dislik
    except ValueError:
        dislik = 0
        return dislik

def Comments():
    retry = 0
    while True:
        try:
            print("comments")
            scroll_down()
            time.sleep(2)
            pres = EC.presence_of_element_located((By.XPATH, '/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/ytd-comments/ytd-item-section-renderer/div[1]/ytd-comments-header-renderer/div[1]/h2/yt-formatted-string/span[1]'))
            WebDriverWait(driver,5).until(pres)
            com = driver.find_element_by_xpath('/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/ytd-comments/ytd-item-section-renderer/div[1]/ytd-comments-header-renderer/div[1]/h2/yt-formatted-string/span[1]').text
            com = int(com.replace(',',''))
            return com
            break
        except TimeoutException:
            retry += 1
            if retry == 2:
                com = 0
                return com
                break
            else:
                driver.refresh()
                scroll_down()

stats = []

for url in base_url:
        rerunlike = 0
        rerundislike = 0
        reruncom = 0
        about_url = url+'about'
        driver.get(about_url)
        views = driver.find_elements_by_xpath('//*[@id="right-column"]/yt-formatted-string[3]')
        subs = driver.find_elements_by_xpath('//*[@id="subscriber-count"]')
        channel = driver.find_element_by_xpath('/html/body/ytd-app/div/ytd-page-manager/ytd-browse/div[3]/ytd-c4-tabbed-header-renderer/tp-yt-app-header-layout/div/tp-yt-app-header/div[2]/div[2]/div/div[1]/div/div[1]/ytd-channel-name/div/div/yt-formatted-string').text
        for p in range(len(views)):
            views = views[p].text.rstrip(" views")
            print("Views Gathered")
        for p in range(len(subs)):
            if "K" in subs[p].text:
                subs = subs[p].text.rstrip("K subscribers")
                subs = float(subs)*1000
                print("Subs Gathered")
            else:
                if "M" in subs[p].text:
                    subs = subs[p].text.rstrip("M subscribers")
                    subs = float(subs)*1000000
                    print("Subs Gathered")

        vid_url = url+'videos'
        driver.delete_all_cookies()
        driver.get(vid_url)
        for x in range(50):
            driver.execute_script("var scrollingElement = (document.scrollingElement || document.body);scrollingElement.scrollTop = scrollingElement.scrollHeight;")
            time.sleep(.1)
            driver.execute_script("var scrollingElement = (document.scrollingElement || document.body);scrollingElement.scrollTop = scrollingElement.scrollHeight;")

        hrefs = driver.find_elements_by_xpath('//*[@id="video-title"]')
        print("HREF gathered")

        href_list =[]
        for p in hrefs:
            href = p.get_attribute('href')
            href_list.append(href)
            lcount = 0
            dcount = 0
            ccount = 0
            pcount = 0
        for href in href_list:
            driver.delete_all_cookies()
            driver.get(str(href))
            time.sleep(3)

            if  check_exists_by_xpath('/html/body/yt-live-chat-app/div/yt-live-chat-renderer/iron-pages/div/yt-live-chat-header-renderer/div[1]/span[2]/yt-sort-filter-sub-menu-renderer/yt-dropdown-menu/tp-yt-paper-menu-button/div/tp-yt-paper-button/div')  ==  True:
                print("Skipped")
                lcount = lcount + 0
                dcount = dcount + 0
                ccount = ccount + 0
                pcount = pcount + 1
                break

            else:
                likes = Likes()
                dislike = int(Dislikes())
                comments = int(Comments())
                lcount = lcount + likes
                dcount = dcount + dislike
                ccount = ccount + comments
                pcount = pcount + 1
                postcount = len(href_list)
                print(channel,": ",pcount,"/",postcount)
                print("Likes: ",lcount," ","Dislikes: ",dcount," ","Comments: ",ccount)

        stat = {"Channel":channel, "Subs":subs,"Views":views,"Posts":pcount,"Likes":lcount,"Dislikes":dcount,"Comments":ccount }
        stats.append(stat)
        dp = pd.DataFrame(stats)
        dp.to_csv("stat.csv")
        print("stat file done")

df = pd.DataFrame(stats)
df.to_csv("youtube.csv")
print("Done go check file")


import numpy as np
import pytest

from mpol import coordinates, gridding
from mpol.constants import *

# cache an instantiated gridder for future imaging ops
@pytest.fixture
def gridder(mock_visibility_data):
    uu, vv, weight, data_re, data_im = mock_visibility_data

    return gridding.Gridder(
        cell_size=0.005,
        npix=800,
        uu=uu,
        vv=vv,
        weight=weight,
        data_re=data_re,
        data_im=data_im,
    )

def test_pytorch_export(gridder):
    gridder.to_pytorch_dataset()

def test_cell_variance_error_pytorch(mock_visibility_data):
    coords = coordinates.GridCoords(cell_size=0.01, npix=400)

    uu, vv, weight, data_re, data_im = mock_visibility_data
    sigma = np.sqrt(1 / weight)
    data_re = np.ones_like(uu) + np.random.normal(loc=0, scale=2 * sigma, size=uu.shape)
    data_im = np.zeros_like(uu) + np.random.normal(
        loc=0, scale=2 * sigma, size=uu.shape
    )

    gridder = gridding.Gridder(
        coords=coords,
        uu=uu,
        vv=vv,
        weight=weight,
        data_re=data_re,
        data_im=data_im,
    )

    with pytest.raises(RuntimeError):
        gridder.to_pytorch_dataset()


import cv2
import numpy as np
from mathutils import Matrix, Quaternion

from geometry import W_PT as landmarks
from geometry import line_idx, vertex
from visualize import draw_landmarks, project_pts_quat_tvec, read_csv

def plot_lines(img, pts, line_idx):
    img = np.ones_like(img) * 255
    img = np.asarray(img, dtype=np.uint8)
    pts = np.asarray(pts / 3, dtype=np.int)
    for idx in line_idx:
        start_pt, end_pt = pts[idx[0]], pts[idx[1]]
        cv2.line(
            img,
            (start_pt[0], start_pt[1]),
            (end_pt[0], end_pt[1]),
            (0, 0, 0),
            3,
            cv2.LINE_AA,
        )
    return img

rot = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
mat = Matrix.Rotation(30 / 180 * np.pi, 3, "X")
quat = Matrix.to_quaternion(mat)
quat.rotate(Matrix.Rotation(10 / 180 * np.pi, 3, "Y").to_quaternion())

img_dir = "./speedplus_small/sunlamp/images"
pose_file = "./csv_files/lightbox_ex_submission_1953_2022_03_30_21_34_58.csv"

img_name = "img000217.jpg"
pose = read_csv(pose_file, "sunlamp")
pose_000017 = pose[img_name]

vertex = np.asarray(vertex)
# vertex_2d = project_pts_quat_tvec(vertex, *pose_000017)
vertex_2d = project_pts_quat_tvec(vertex, quat, pose_000017[1])
keypts = project_pts_quat_tvec(np.asarray(landmarks), quat, pose_000017[1])

img = cv2.imread(f"{img_dir}/{img_name}")
img = plot_lines(img, vertex_2d, line_idx)
img = draw_landmarks(img, keypts / 3)

cv2.imshow("win", img)
cv2.waitKey(0)
cv2.destroyWindow("win")

cv2.imwrite("model.png", img)


from aiohttp import web
from hashlib import sha256

from internal.database.errors import ErrorDatabase
from internal.container import DI_DATABASE_CLIENT, DI_LOGGER
from app.constants import APP_CONTAINER
from app.native.users import (
    MessageCreateUser,
    MessageCreatedUser,
    ErrorLoginAlreadyExists,
)

async def create_user(app: web.Application, msg: MessageCreateUser) -> MessageCreatedUser:
    container = app[APP_CONTAINER]
    client = container.resolve(DI_DATABASE_CLIENT)
    logger = container.resolve(DI_LOGGER)

    password_hash = sha256(msg.password.encode("utf-8")).hexdigest()

    query = """
        select *
        from users.create(
            %(display_name)s,
            %(login)s,
            %(hash)s
        )
    """
    params = {
        "display_name": msg.display_name,
        "login": msg.login,
        "hash": password_hash,
    }
    try:
        result = await client.fetchone(query, params)
    except Exception as err:
        logger.error(f"Failing to database: {type(err)}, {err}")
        raise ErrorDatabase

    error = result.get("error")
    if error is not None:
        if error["reason"] == "exists" and error["description"] == "_login":
            raise ErrorLoginAlreadyExists

    message = MessageCreatedUser(
        user_id=result.get("user_id"),
        created_at=result.get("created_at"),
    )

    logger.info(f"User {message.user_id} created.")

    return message


from __future__ import annotations  # Should become unnecessary in Python 3.10
from typing import Tuple, Union, List

from sage.all import var, diff, Matrix, Rational, I, Expression

from .riemannian import RiemChart
from .base import Chart
from .tensor import Tensor, Form

class CplxChart(Chart):
    """
    Class for charts on complex manifolds, uses (anti-)holomorphic coordinates

    :Attributes:
        * **self.dim** -- real dimension (inherited from Chart)

        * **self.coords** -- coordinate variables (inherited from Chart)

        * **self.cplx_dim** -- complex dimension = self.dim/2

        * **self.hol** -- holomorphic coordinates

        * **self.ahol** -- anti-holomorphic coordinates

    """

    def __init__(self, cplx_dim: int, coords: Tuple[list, list] = None):
        """
        :param cplx_dim: complex dimension of the manifold - becomes self.Cdim
        :param coords: tuple of (holomorphic, anti-holomorphic) coordinates, optional,
            defaults to ((z1, ..., zn), (z1b, ..., znb)) - becomes self.coords and self.hol, self.ahol
        :raises IndexError: if coords does not consist of 2 lists each of length cplx_dim

        Create a chart object for a complex manifold
        """
        self.cplx_dim = cplx_dim
        if coords:
            if len(coords) != 2:
                raise IndexError("Coordinates must be a pair (holomorphic, anti-holomorphic)!")
            elif len(coords[0]) != cplx_dim or len(coords[1]) != cplx_dim:
                raise IndexError(
                    "The number of holomorphic and anti-holomorphic coordinates must match the complex dimension!")
            self.hol = coords[0]
            self.ahol = coords[1]
        else:
            self.hol = [var(f'z{i + 1}') for i in range(self.cplx_dim)]
            self.ahol = [var(f'z{i + 1}b') for i in range(self.cplx_dim)]
        Chart.__init__(self, 2 * cplx_dim, self.hol + self.ahol)

class CplxForm(Form):
    """
    A class for forms on complex manifolds that have defined signature (holomorphic, anti-holomorphic)

    :Attributes:
        * **self.chart** -- The chart on which the form lives (inherited from Form)

        * **self.n** -- the total order of the form (inherited from Form)

        * **self.vals** -- the values of the form, stored as a dictionary with frozenset entries (inherited from Form)

        * **self.signature** -- signature of the form

    """

    def __init__(self, chart: CplxChart, signature: Tuple[int, int], vals: dict = None):
        """
        :param chart: the chart on which the form lives, becomes self.M
        :param signature: the signature of the form, becomes self.signature
        :param vals: the values of the form, becomes self.vals, optional, defaults to 0
        :raises IndexError: if the signature is not a pair
        :raises ValueError: if one (or both) of the components of signature is negative
        :raises NotImplementedError: if chart is not a CplxChart

        Create a Complex form object
        """
        if len(signature) != 2:
            raise IndexError("Signature must consist of 2 integers!")
        if signature[0] < 0 or signature[1] < 0:
            raise ValueError("Signature cannot be negative!")
        if not isinstance(chart, CplxChart):
            raise NotImplementedError('chart must be an instance of CplxChart class!')
        self.signature = signature
        Form.__init__(self, chart, sum(signature), vals)
        self.chart = chart

    def d_hol(self) -> CplxForm:
        """
        :return: d(self)

        The holomorphic exterior derivative
        """

        if self.signature[0] == self.chart.cplx_dim:
            return CplxForm(self.chart, (self.signature[0] + 1, self.signature[1]))

        vals = {}
        for ind in self.vals:
            for i in range(self.chart.cplx_dim):
                if i not in ind:
                    sgn = 1
                    for j in ind:
                        if j < i: sgn *= -1
                    ind_new = set(ind)
                    ind_new.add(i)
                    ind_new = frozenset(ind_new)
                    vals[ind_new] = vals.setdefault(ind_new, 0) + sgn * diff(self.vals[ind], self.chart.coords[i])

        for ind in list(vals.keys()):
            try:
                vals[ind] = vals[ind].simplify_full()
            except:  # noqa
                pass
            if vals[ind] == 0: vals.pop(ind)

        return CplxForm(self.chart, (self.signature[0] + 1, self.signature[1]), vals)

    def d_ahol(self) -> CplxForm:
        """
        :return: \\bar{d}(self)

        The anti-holomorphic exterior derivative
        """

        if self.signature[1] == self.chart.cplx_dim:
            return CplxForm(self.chart, (self.signature[0], self.signature[1] + 1))

        vals = {}
        for ind in self.vals:
            for i in range(self.chart.cplx_dim, self.chart.dim):
                if i not in ind:
                    sgn = 1
                    for j in ind:
                        if j < i: sgn *= -1
                    ind_new = set(ind)
                    ind_new.add(i)
                    ind_new = frozenset(ind_new)
                    vals[ind_new] = vals.setdefault(ind_new, 0) + sgn * diff(self.vals[ind], self.chart.coords[i])

        for ind in list(vals.keys()):
            try:
                vals[ind] = vals[ind].simplify_full()
            except:  # noqa
                pass
            if vals[ind] == 0: vals.pop(ind)

        return CplxForm(self.chart, (self.signature[0], self.signature[1] + 1), vals)

class HermMetric(Tensor):
    """
    Hermitian Metric class (h_{ab} dz^a (x) d\\bar{z}^b)

    :Attributes:
        * **self.chart** -- Chart to which this tensor belongs (inherited from Tensor)

        * **self.typ** -- a 2-tuple: (2,0) (inherited from Tensor)

        * **self.size** -- total size of the tensor: 2 (inherited from Tensor)

        * **self.vals** -- values of the tensor vals[i1][i2] (inherited from Tensor)

        * **self.h_vals** -- values of the tensor as coefficients of dz^a (x) d\\bar{z}^b

    """

    def __init__(self, chart: CplxChart, vals: list = None):
        """
        :param chart: Chart to which this tensor belongs, must be a CplxChart
        :param vals: Values as coefficients of dz^a (x) d\bar{z}^b, optional, defaults to \\sum_a dz^a (x) d\bar{z}^a
            becomes self.h_vals

        Create a Hermitian Metric object
        """
        if not isinstance(chart, CplxChart):
            raise NotImplementedError('chart must be an instance of CplxChart class!')
        if vals:
            if len(vals) != chart.cplx_dim:
                raise IndexError("vals must be n x n where n is the complex dimension of the chart")
            for i in range(chart.cplx_dim):
                if len(vals[i]) != chart.cplx_dim:
                    raise IndexError("vals must be n x n where n is the complex dimension of the chart")
            self.h_vals = vals
        else:
            self.h_vals = [[1 if i == j else 0 for i in range(chart.cplx_dim)] for j in range(chart.cplx_dim)]

        Tensor.__init__(self, chart, chart.cplx_dim, 0,
                        [[self.h_vals[i][j - chart.cplx_dim] if i < chart.cplx_dim <= j else 0
                          for j in range(2 * chart.cplx_dim)] for i in range(2 * chart.cplx_dim)])
        self.chart = chart

    def __add__(self, other: Union[Tensor, HermMetric]) -> Union[Tensor, HermMetric]:
        """
        :param other: either a Hermitian metric, or another (2,0) tensor to be added
        :return: self + other (as Hermitian metric if other is one, otherwise as a (2,0) tensor)
        :raises NotImplementedError: if the two Hermitian metrics live on different charts.

        Add something to this Hermitian metric
        """
        if not isinstance(other, HermMetric):
            return Tensor.__add__(self, other)
        if self.chart != other.chart:
            raise NotImplementedError("Can't add Hermitian metrics that live on different charts")
        new_hv = [[self.h_vals[i][j] + other.h_vals[i][j] for j in range(self.chart.cplx_dim)] for i in
                  range(self.chart.cplx_dim)]
        return HermMetric(self.chart, new_hv)

    def __sub__(self, other: Union[Tensor, HermMetric]) -> Union[Tensor, HermMetric]:
        """
        :param other: either a Hermitian metric, or another (2,0) tensor to be subtracted
        :return: self - other (as Hermitian metric if other is one, otherwise as a (2,0) tensor)
        :raises NotImplementedError: if the two Hermitian metrics live on different charts.

        Add something to this Hermitian metric
        """
        if not isinstance(other, HermMetric):
            return Tensor.__sub__(self, other)
        if self.chart != other.chart:
            raise NotImplementedError("Can't subtract Hermitian metrics that live on different charts")
        new_hv = [[self.h_vals[i][j] - other.h_vals[i][j] for j in range(self.chart.cplx_dim)] for i in
                  range(self.chart.cplx_dim)]
        return HermMetric(self.chart, new_hv)

    def to_riem_metric(self) -> Matrix:
        """
        :return: The resulting Riemannian metric

        Create a (pseudo-)Riemannian metric from this Hermitian metric
        """
        g = Rational(1 / 2) * Matrix(self.vals)
        g += g.transpose()
        return g

    def to_form(self) -> CplxForm:
        """
        :return: The associated (1,1) form

        Create the 2-form associated to this Hermitian metric
        """
        om = CplxForm(self.chart, (1, 1))
        for i in range(self.chart.cplx_dim):
            for j in range(self.chart.cplx_dim):
                if self.h_vals[i][j]:
                    om.vals[frozenset({i, self.chart.cplx_dim + j})] = I * Rational(1 / 2) * self.h_vals[i][j]
        return om

class KahlerChart(RiemChart, CplxChart):
    """
    Class for handling Charts on Kähler manifolds

    Properties:
        * **self.dim** -- dimension (inherited from Chart)

        * **self.coords** -- coordinate variables (inherited from Chart)

        * **self.g** -- metric (inherited from RiemChart)

        * **self.ginv** -- inverse of the metric (inherited from RiemChart)

        * **self.CS** -- Christoffel symbols (computed by self.Compute_CS) (inherited from RiemChart)

        * **self.r** -- Curvature tensor as a list (computed by self.Compute_R) (inherited from RiemChart)

        * **self.r_t** -- Curvature tensor as a tensor object (computed by self.Compute_R) (inherited from RiemChart)

        * **self.ric_t** -- Weighted ricci tensor as a tensor object (computed by self.Compute_Ricci_T) (inherited from RiemChart)

        * **self.Cdim** -- complex dimension = self.n/2 (inherited from CplxChart)

        * **self.hol** -- holomorphic coordinates (inherited from CplxChart)

        * **self.ahol** -- anti-holomorphic coordinates (inherited from CplxChart)

        * **self.potential** -- Kähler potential function

        * **self.HM** -- Hermitian metric

        * **self.om** -- symplectic form

    """

    def __init__(self, coords: Tuple[list, list], potential: Expression = None):
        """
        :param coords: tuple of (holomorphic, anti-holomorphic) coordinates
        :param potential: the Kähler potential function, optional, defaults to (1/2)|z|^2 (Euclidean metric on C^n$
        :raises IndexError: if coords is not a 2-tuple where both components have the same length

        Create a chart for a Kähler manifold from a given Kähler potential
        """
        if len(coords) != 2:
            raise IndexError("Coordinates must be a pair (holomorphic, anti-holomorphic)!")
        elif len(coords[0]) != len(coords[1]):
            raise IndexError(
                "The number of holomorphic and anti-holomorphic coordinates must match the complex dimension!")
        if not potential:
            potential = Rational(1 / 2) * sum(coords[0][i] * coords[1][i] for i in range(len(coords[0])))
        self.potential = potential
        CplxChart.__init__(self, len(coords[0]), coords)
        self.herm_metric = HermMetric(self, [[diff(potential, self.ahol[j], self.hol[i]) for j in range(self.cplx_dim)]
                                             for i in range(self.cplx_dim)])
        self.g = self.herm_metric.to_riem_metric()
        self.ginv = self.g.inverse()
        self.om = self.herm_metric.to_form()

    def to_riem_chart(self, real_coords: List[tuple] = None) -> RiemChart:
        """
        :param real_coords: The names or real coordinates to be used, as a list of pairs (real_part, im_part), optional,
            defaults to [(x1, y1), (x2, y2), ..., (xn, yn)]
        :type real_coords: list of 2-tuples
        :return: Real version of this chart

        Convert this chart into a simple RiemChart object with real coordinates
        """

        def __met_gen(i, j):
            k = i // 2
            l = j // 2
            if (i - j) % 2 == 0:  # g(x_k, x_l) = g(y_k, y_l) = g(zk, zlb) + g(zl, zkb)
                return self.g[k][l + self.cplx_dim] + self.g[l][k + self.cplx_dim]
            elif i % 2:  # g(y_k, x_l) = I*( g(zk, zlb) - g(zl, zkb) )
                return I * (self.g[k][l + self.cplx_dim] - self.g[l][k + self.cplx_dim])
            else:  # g(x_k, y_l) = I*( g(zl, zkb) - g(zk, zlb) )
                return I * (self.g[l][k + self.cplx_dim] - self.g[k][l + self.cplx_dim])

        if real_coords:
            if len(real_coords) != self.cplx_dim:
                raise IndexError("real_coords must be a list of n 2-tuples")
            else:
                for i in range(self.cplx_dim):
                    if len(real_coords[i]) != 2:
                        raise IndexError("real_coords must be a list of n 2-tuples")

        if not real_coords:
            real_coords = [var(f'x{i + 1} y{i + 1}') for i in range(self.cplx_dim)]

        rc_list = []
        for pair in real_coords:
            rc_list += list(pair)

        subs = {**{self.hol[i]: real_coords[i][0] + I * real_coords[i][1] for i in range(self.cplx_dim)},
                **{self.ahol[i]: real_coords[i][0] - I * real_coords[i][1] for i in range(self.cplx_dim)}}
        # The above should be simplified from {**a, **b} to a|b in Python 3.9

        new_metric = Matrix([[__met_gen(i, j) for j in range(2 * self.cplx_dim)] for i in range(2 * self.cplx_dim)])
        new_metric = new_metric.substitute(subs)

        try:
            new_metric = new_metric.simplify_full()
        except:  # noqa
            pass

        return RiemChart(self.dim, rc_list, new_metric)


from flask import Flask, render_template, request, url_for, redirect
import joblib
import numpy as np
from text_proc import text_process
app = Flask(__name__) #creating flask app with unique name
model = joblib.load(open('NB1.joblib','rb'))
posts = {}           #global variable and 0 is unique post_id

@app.route('/')  #home page of web app (decorator)
def home():
        #return 'Hello World!'
    return render_template('home.jinja2',posts=posts)

@app.route('/review/<int:post_id>')  #/post/0
def post(post_id):
    post = posts.get(post_id)
    if not post: #if post not found or None
        return render_template('404.jinja2', message= f'Post with ID {post_id} was not found.')
    return render_template('post.jinja2',post=post)
    #return f"Post {post['title']}, content:\n\n{post['content']} "

#@app.route('/post/form')
#def form():
#   return render_template('create.jinja2')

@app.route("/review/create", methods=['GET','POST'])
def create():
    #title = request.args.get('title')
    #content = request.args.get('content')
    if request.method == 'POST':
        title = request.form.get('title')
        content = request.form.get('content')
        post_id = len(posts)
        data =[content]
        inputs =np.asarray(data)
        my_prediction = model.predict(inputs)
        if my_prediction == 1:
            return render_template('404.jinja2')
        else:

            posts[post_id] = {'id':post_id,'title': title, 'content':content}

            return redirect(url_for('post',post_id=post_id))
    return render_template('create.jinja2')

if __name__ == '__main__':
    app.run(debug=True)     #starting the server and gives debug info


import csv
from collections import defaultdict
import tkinter
from tkinter import filedialog

# 读取种别码文件
def get_seed_code():
    seed = defaultdict(int)
    with open('D:\\2020\\GitHub\\Compiler_Theory\\src\\test.csv', 'r', encoding='UTF-8') as f:
        k = csv.reader(f)
        for i in k:
            seed[str(i[0])] = i[1]
    return seed

# 得到源文件
def get_source_file(filename):
    src = []
    with open(filename, 'r') as f:
        for i in f.readlines():
            if i != '\n':
                src.append(i)
    return src
# ['void main()\n', '{\n', '    int a;\n', '    int result ;\n', '    a=2;\n', '    result =a+10*a ;\n', '}\n', '//comment test']

# 去掉注释

def remove_note(src):
    for i in src:
        for j in range(len(i)):
            if i[j] == '/':
                if i[j+1] == '/' or i[j+1] == '*':
                    src[src.index(i)] = i[:j]
                    break
            break
    for i in src:
        if not i:
            del src[src.index(i)]
    return src

# 标识
def get_identifier(token_word, token_num, line, index, txt2):
    string = ''
    error = 0
    string += str(line[index])
    index += 1
    while index != len(line):
        if line[index].isalpha() or line[index].isdigit():
            string += str(line[index])
            index += 1
        else:
            if line[index] == '_':
                error += 1
                txt2.insert('end', '第'+str(index) +
                            '行存在错误：'+string+line[index]+'\n')
            break
    token_word.append(string)
    token_num.append(700)

    return index, error

# 标识或者关键字
def get_identifier_or_alpha(token_word, token_num, seed, line, index, txt2):
    string = ''
    error = 0
    while index != len(line):
        if line[index].isalpha() or line[index].isdigit() or line[index] == '_':
            string += str(line[index])
            index += 1
        else:
            break
    if token_word:
        if token_word[-1] != '"':
            if string in seed:
                token_word.append(string)
                token_num.append(seed[string])
            else:
                token_word.append(string)
                token_num.append(700)
        else:
            token_word.append(string)
            token_num.append(1100)
    else:
        if string in seed:
            token_word.append(string)
            token_num.append(seed[string])
        else:
            token_word.append(string)
            token_num.append(700)
    return index, error

# 数
def get_number(token_word, token_num, line, index, txt2):
    string = ''
    error = 0
    while index != len(line):
        # 十六进制
        if line[index] == '0':
            if index + 1 != len(line):
                string += str(line[index])
                index += 1
                if line[index].isdigit():
                    error += 1
                    txt2.insert('end', '第' + str(index) +
                                '行存在错误：' + string + line[index] + '\n')
                    break
                if line[index] in ['x', 'X']:
                    string += str(line[index])
                    index += 1
                    while index != len(line):
                        if line[index] in ['x', 'X']:
                            error += 1
                            txt2.insert('end', '第' + str(index) +
                                        '行存在错误：' + string + line[index] + '\n')
                            break
                        if line[index].isalpha() or line[index].isdigit():
                            string += str(line[index])
                            index += 1
                        else:
                            break
                    token_word.append(string)
                    token_num.append(800)
                else:
                    token_word.append(str(0))
                    token_num.append(900)
                    break
            else:
                token_word.append(str(0))
                token_num.append(900)
                break
        # 十进制
        if index != len(line):
            if line[index].isalpha():
                error += 1
                txt2.insert('end', '第' + str(index) + '行存在错误：' +
                            string + line[index] + '\n')
                break
            if line[index].isdigit() and line[index] != 0:
                string += str(line[index])
                index += 1
                while index != len(line):
                    if line[index].isdigit():
                        string += str(line[index])
                        index += 1
                    else:
                        break
                token_word.append(string)
                token_num.append(1000)
            else:
                break

    return index, error

# 判断 +, -, *, /, >, <, =, &
def get_one(token_word, token_num, seed, line, index, txt2):
    string = ''
    error = 0
    string += line[index]
    index += 1
    while index != len(line):
        if line[index] == string or line[index] == '=':
            string += str(line[index])
            index += 1
            break
        else:
            break

    if string in seed:
        token_word.append(string)
        token_num.append(seed[line[index]])

    if string == '**':
        token_word.append(string)
        token_num.append(1200)

    return index, error

# 判断 %, !, :, ?
def get_two(token_word, token_num, seed, line, index, txt2):
    string = ''
    error = 0
    string += line[index]
    index += 1
    while index != len(line):
        if line[index] == '=':
            string += str(line[index])
            index += 1
            break
        else:
            break
    token_word.append(string)
    token_num.append(seed[line[index]])

    return index, error

# 其他字符
def get_other(token, token_word, token_num, seed, line, index, txt2, i, temp_word_row, temp_num_row):
    error = 0
    while index != len(line):
        if not line[index].isalpha() and not line[index].isdigit():
            if line[index] in ['+', '-', '*', '/', '>', '<', '=', '&']:
                index, error_1 = get_one(
                    token_word, token_num, seed, line, index, txt2)
                error += error_1
                token[token_word[-1]].append([i, index - len(token_word[-1])])
                temp_word_row.append(token_word[-1])
                temp_num_row.append(token_num[-1])
                if index == len(line):
                    break

            if line[index] in ['%', '!', ':', '?']:
                index, error_1 = get_two(
                    token_word, token_num, seed, line, index, txt2)
                error += error_1
                token[token_word[-1]].append([i, index - len(token_word[-1])])
                temp_word_row.append(token_word[-1])
                temp_num_row.append(token_num[-1])
                if index == len(line):
                    break

            k = ['{', '}', '[', ']', '(', ')', ';', '.', ';', '"', "'", ',']
            if line[index] in k:
                token_word.append(line[index])
                token_num.append(seed[line[index]])
                index += 1
                token[token_word[-1]].append([i, index - len(token_word[-1])])
                temp_word_row.append(token_word[-1])
                temp_num_row.append(token_num[-1])
                if index == len(line):
                    break
        else:
            break

    return index, error

# 处理数据
def get_token(seed, src, txt2):
    token = defaultdict(list)
    token_word = []
    token_num = []
    error = 0

    token_word_row = []
    token_num_row = []

    for i in src:
        temp_word_row = []
        temp_num_row = []

        # 去掉最后的\n
        line = i.strip('\n')
        # 根据空格分割字符串
        line = line.split()

        for string in line:
            if string in seed:
                token[string].append([src.index(i), line.index(string)])
                token_word.append(string)
                token_num.append(seed[string])
                temp_word_row.append(string)
                temp_num_row.append(seed[string])
            else:
                # 记录当前字符串长度
                line_length = len(string)
                # 当前字符位置
                index = 0

                while index != line_length:
                    # 是否为下划线
                    if string[index] == '_':
                        index, error_1 = get_identifier(
                            token_word, token_num, string, index, txt2)
                        error += error_1
                        token[token_word[-1]
                              ].append([src.index(i), line.index(string)])
                        temp_word_row.append(token_word[-1])
                        temp_num_row.append(token_num[-1])
                        if index == line_length:
                            break
                        else:
                            continue
                    # 是否为字母
                    if string[index].isalpha():
                        index, error_1 = get_identifier_or_alpha(
                            token_word, token_num, seed, string, index, txt2)
                        error += error_1
                        token[token_word[-1]
                              ].append([src.index(i), line.index(string)])
                        temp_word_row.append(token_word[-1])
                        temp_num_row.append(token_num[-1])
                        if index == line_length:
                            break
                        else:
                            continue
                    # 是否为数字
                    if string[index].isdigit():
                        index, error_1 = get_number(
                            token_word, token_num, string, index, txt2)
                        error += error_1
                        token[token_word[-1]
                              ].append([src.index(i), line.index(string)])
                        temp_word_row.append(token_word[-1])
                        temp_num_row.append(token_num[-1])
                        if index == line_length:
                            break
                        else:
                            continue
                    # 是否为其他字符
                    else:
                        index, error_1 = get_other(token, token_word, token_num, seed, string, index, txt2, src.index(
                            i), temp_word_row, temp_num_row)
                        error += error_1
                        if index == line_length:
                            break

        token_word_row.append(temp_word_row)
        token_num_row.append(temp_num_row)
    txt2.insert('end', 'error('+str(error)+')  warring(0)')
    k = [token, token_word, token_num, token_word_row, token_num_row]
    return k

# 读取文件
def get_txt(txt):
    txt.delete(0.0, 'end')
    filename = filedialog.askopenfilename(
        initialdir=r'C:\Users\yu\PycharmProjects\Compile')
    with open(filename) as file:
        text = file.read()
        txt.insert('end', text)
    return filename

# 读取文件
def wri_txt(txt1, k):
    token = k[0]
    token_word = k[1]
    token_num = k[2]
    for i in range(len(token_word)):

        txt1.insert('end', (str(token[token_word[i]][0]) +
                            '\t\t'+str(token_word[i])+'\t'+str(token_num[i])))
        txt1.insert('end', '\n')
        del token[token_word[i]][0]
    return [k[3], k[4]]


from AutomationToolsLib import AutomationPreferences, Logging
import requests
from datetime import datetime
from getpass import getuser
import pathlib
import os

def GetPreferences(*args):
    userPrefs = {}
    for item in args:
        userPrefs.update(AutomationPreferences(item))
    return userPrefs

def FilepathCheck(filepath):
    if pathlib.Path(filepath).exists():
        return True
    else:
        return False

def CreateFilepath(filepath):
    pathlib.Path(filepath).mkdir()

def CreateBackup(filepath):
    currentDate = datetime.today().strftime("%Y-%m-%d")
    patchPrefs = GetPreferences("PATCH_URL", "PATCH_TOKEN")
    logFile = "patchserver_backup.log"
    backupAPI = patchPrefs["PATCH_URL"] + "/api/v1/backup"
    Logging(logFile, currentDate)
    Logging(logFile, "----------------------------------------")
    Logging(logFile, "Creating backup...")
    response = requests.get(
        backupAPI,
        headers={
            "Authorization": "Bearer " + patchPrefs["PATCH_TOKEN"],
            "Accept": "application/zip",
        },
    )
    if response.status_code != 200:
        Logging(logFile, "Error connecting to patchserver.")
        Logging(logFile, response.status_code)
        Logging(logFile, response.content)
        Logging(logFile, "Patchserver database not backed up.")
    else:
        zipFileName = str(currentDate) + "-patchserver-backup.zip"
        zipFile = open(filepath + zipFileName, "wb")
        zipFile.write(response.content)
        zipFile.close()
        Logging(logFile, "Backup successfully created.")
        Logging(logFile, zipFileName + " saved to " + filepath)

def ManageBackups(filepath):
    logFile = "patchserver_backup.log"
    fileList = os.listdir(filepath)
    try:
        fileList.remove(".DS_Store")
    except:
        print("No DS_Store file present")
    sortedFileList = sorted(fileList, reverse=True)
    print(sortedFileList)
    if len(sortedFileList) > 3:
        print("Deleting oldest backup")
        Logging(logFile, "Deleting oldest backup")
        fileToDelete = sortedFileList.pop()
        os.remove(filepath + "/" + fileToDelete)
        print(fileToDelete + " has been deleted")
        Logging(logFile, fileToDelete + " has been deleted")
        Logging(logFile)
    Logging(logFile, str(filepath))

def Main():
    currentUser = getuser()
    backupLocation = "/Users/" + currentUser + "/Documents/Patch_Backups/"
    if not FilepathCheck(backupLocation):
        CreateFilepath(backupLocation)
    CreateBackup(backupLocation)
    ManageBackups(backupLocation)

Main()


from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

import time
import json
import datetime
import requests

# endpoint
data_all = requests.get('https://corona.lmao.ninja/all')
data_by_country = requests.get('https://corona.lmao.ninja/countries/')

def main_api(request):
    fucking_list = ['updated', 'affectedcountries']

    datas_all = []
    for i, j in data_all.json().items():
        if str.lower(i) in fucking_list:
            pass
        else:
            datas_all.append({str.upper(i): j})

    # context
    context = {
        "datas": datas_all,
        "last_update": last_update()
    }
    return context

def card_api(request, limit=None):
    # paginate
    paginate_by = limit if limit is not None else 20
    paginator = Paginator(data_by_country.json(), paginate_by)
    page = request.GET.get('page')
    datas = paginator.get_page(page)

    # context
    context = {
        "total_data": data_all.json()['affectedCountries'],
        "last_update": last_update(),
        "datas": datas,
    }
    return context

def last_update():
    unix_timestamp = data_all.json()['updated']
    last_update = datetime.datetime.fromtimestamp(
        unix_timestamp//1000.0).strftime('%A, %B %d %Y, %H:%M:%S %p (UTC)')
    return last_update


import asyncio

"""
ASYNCIO EVENT
"""

async def waiter(i: int, event: asyncio.Event) -> None:
    print(f"Waiter {i} waititng for event to happen")
    await event.wait()
    print(f"Waiter {i} is dont waiting")

async def main() -> None:
    event = asyncio.Event()
    waiter_tasks = [asyncio.create_task(waiter(i, event)) for i in range(5)]
    await asyncio.sleep(1.0)
    print("\nSetting event")
    event.set()
    await asyncio.gather(*waiter_tasks)
    print("Done")

if __name__ == "__main__":
    asyncio.run(main())


import cv2
import numpy as np
import matplotlib.pyplot as plt

# Load the image
img = cv2.imread('liberty.jpeg')

# Convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Perform Harris corner detection
dst = cv2.cornerHarris(gray, 2, 3, 0.04)

# Deep copy the original image for Harris corners
imgHarris = img.copy()

# Threshold for corner detection
threshold = 0.01

# Loop through and plot detected corners for Harris corners
for i in range(dst.shape[0]):
    for j in range(dst.shape[1]):
        if dst[i, j] > threshold * dst.max():
            cv2.circle(imgHarris, (j, i), 3, (0, 255, 0), -1)  # Adjust color (BGR)

# Display the image with Harris corners
plt.imshow(cv2.cvtColor(imgHarris, cv2.COLOR_BGR2RGB))
plt.title('Harris Corners')
plt.show()

# Perform Shi-Tomasi corner detection
corners = cv2.goodFeaturesToTrack(gray, maxCorners=100, qualityLevel=0.01, minDistance=10)

corners = np.int0(corners)

# Deep copy the original image for Shi-Tomasi corners
imgShiTomasi = img.copy()

# Plot circles at detected corners for Shi-Tomasi corners
for corner in corners:
    x, y = corner.ravel()
    cv2.circle(imgShiTomasi, (x, y), 3, (0, 0, 255), -1)  # Adjust color (BGR)

# Display the image with Shi-Tomasi corners
plt.imshow(cv2.cvtColor(imgShiTomasi, cv2.COLOR_BGR2RGB))
plt.title('Shi-Tomasi Corners')
plt.show()

# Create ORB detector
orb = cv2.ORB_create()

# Find keypoints and descriptors using ORB
keypoints, descriptors = orb.detectAndCompute(gray, None)

# Draw keypoints on the image for ORB
img_ORB = cv2.drawKeypoints(img, keypoints, None, color=(0, 255, 0), flags=0)

# Display the image with ORB keypoints
plt.imshow(cv2.cvtColor(img_ORB, cv2.COLOR_BGR2RGB))
plt.title('ORB Keypoints')
plt.show()


from typing import Callable, Dict, Set, Tuple
import re
from scipy.spatial import distance

Point = Tuple[int, int, int]

def get_input(filename: str) -> str:
    with open(filename, "r") as f:
        contents = f.read()
    return contents

def parse_input(challenge_input: str) -> Dict[int, Set[Point]]:
    scanner_points = dict()
    scanner_inputs = challenge_input.split("\n\n")
    scanner_pattern = re.compile(r"--- scanner (\d+) ---")

    for scanner_input in scanner_inputs:
        scanner_line, *coords = scanner_input.split("\n")
        scanner_number = int(scanner_pattern.search(scanner_line).group(1))
        scanner_points[scanner_number] = {tuple(map(int, coord.split(","))) for coord in coords}
    return scanner_points

if __name__ == "__main__":
    file_contents = get_input("aoc_2021/2021_19.txt")
    scanner_dict = parse_input(file_contents)