from collections import ChainMap
from collections.abc import Mapping

__version__ = "0.1.1"

def _depth_first_update(target: dict, source: Mapping) -> None:
    for key, val in source.items():
        if not isinstance(val, Mapping):
            target[key] = val
            continue

        if key not in target:
            target[key] = {}
        _depth_first_update(target[key], val)

class DeepChainMap(ChainMap):
    """A recursive subclass of ChainMap"""

    def __getitem__(self, key):
        submaps = [mapping for mapping in self.maps if key in mapping]
        if not submaps:
            return self.__missing__(key)
        if isinstance(submaps[0][key], Mapping):
            return DeepChainMap(*(submap[key] for submap in submaps))
        return super().__getitem__(key)

    def to_dict(self) -> dict:
        d = {}
        for mapping in reversed(self.maps):
            _depth_first_update(d, mapping)
        return d


"""
인터넷에서 유용한 정보를 가져옵니다.

**단어정보, 날씨 정보, 뉴스 정보** 를 가져올 수 있습니다.

Class:
:obj:`~openpibo.collect.Wikipedia`
:obj:`~openpibo.collect.Weather`
:obj:`~openpibo.collect.News`
"""

from urllib.parse import quote
from bs4 import BeautifulSoup
import requests

class Wikipedia:
    """
Functions:
:meth:`~openpibo.collect.Wikipedia.search`

    위키백과에서 단어를 검색합니다.

    example::

        from openpibo.collect import Wikipedia

        pibo_wiki = Wikipedia()
        # 아래의 모든 예제 이전에 위 코드를 먼저 사용합니다.
    """
    def search(self, search_text: str):
        """
        위키백과에서 ``search_text`` 를 검색합니다.

        example::

            result = pibo_wiki.search('강아지')

        :param str search_text: 위키백과에서의 검색어

        :returns: 내용을 dictionary 배열 형태로 반환합니다.

            대부분의 경우 '0'번 항목에 개요를 표시하고, 검색된 내용이 없을 경우 None을 반환합니다.

            example::

                ['0':{
                    'title': '명칭',
                    'content': "한국어 ‘강아지’는 ‘개’에 어린 짐승을 뜻하는 ‘아지’가 붙은 말이다..."
                }, ... ]
                or
                None
        """

        _chapters = {'0':{'title':'개요', 'content':[]}}
        encode_text = quote(search_text)
        url = f'https://ko.wikipedia.org/wiki/{encode_text}'
        resp = requests.get(url, headers={'User-Agent' : 'Mozilla/5.0'})
        soup = BeautifulSoup(resp.content, 'html.parser')
        total_content = soup.find('div', {'class': 'mw-parser-output'})

        if not total_content:
            return None

        # chapter_idx = '3.1', chapter_list = [3, 1]
        chapter_idx, chapter_list = '0', [0]
        parent_num = 0
        for content in total_content:
            tag = content.name
            if tag == None:
                continue
            elif tag[0] == 'h':
                new_parent_num = int(tag[1]) - 2
                if new_parent_num <= parent_num:
                    chapter_list = chapter_list[:new_parent_num+1]
                    chapter_list[-1] += 1
                else:
                    chapter_list.append(1)
                chapter_idx = '.'.join(map(str, chapter_list))
                _chapters[chapter_idx] = {}
                _chapters[chapter_idx]['title'] = content.text.split('[')[0]
                _chapters[chapter_idx]['content'] = []
            elif tag == 'p':
                _chapters[chapter_idx]['content'].append(content.text)
            elif tag == 'ul':
                _chapters[chapter_idx]['content'].append(content.text)

        return _chapters

    def search_for_block(self, search_text: str):
        """
        위키백과에서 ``search_text`` 를 검색합니다. (block 전용)

        example::

            result = pibo_wiki.search_for_block('강아지')

        :param str search_text: 위키백과에서의 검색어

        :returns: search 함수의 반환 값의 content만 추출한 리스트를 반환합니다.

            대부분의 경우 '0'번 항목에 개요를 표시하고, 검색된 내용이 없을 경우 None을 반환합니다.

            example::

                [
                    "한국어 ‘강아지’는 ‘개’에 어린 짐승을 뜻하는 ‘아지’가 붙은 말이다...",
                    ...
                ]
                or
                None
        """

        res = self.search(search_text)
        return [item.strip().replace('\n', '') for _, v in res.items() if len(v['content']) > 0 for item in v['content'] if item != '\n']

class Weather:
    """
Functions:
:meth:`~openpibo.collect.Weather.search`

    종합 예보와 오늘/내일/모레의 날씨 정보를 검색합니다.

    example::

        from openpibo.collect import Weather

        pibo_weather = Weather()
        # 아래의 모든 예제 이전에 위 코드를 먼저 사용합니다.
    """
    region_list = {
        '전국': 108,
        '서울': 109,
        '인천': 109,
        '경기': 109,
        '부산': 159,
        '울산': 159,
        '경남': 159,
        '대구': 143,
        '경북': 143,
        '광주': 156,
        '전남': 156,
        '전북': 146,
        '대전': 133,
        '세종': 133,
        '충남': 133,
        '충북': 131,
        '강원': 105,
        '제주': 184,
    }
    """
    날씨 정보를 검색할 수 있는 지역입니다.
    """

    def search(self, search_region:str='전국'):
        """
        해당 지역(```search_region```)의 날씨 정보(종합예보, 오늘/내일/모레 날씨)를 가져옵니다.

        example::

            result = pibo_weather.search('서울')

        :param str search_region: 검색 가능한 지역 (default: 전국)

            검색할 수 있는 지역은 다음과 같습니다::

                '전국', '서울', '인천', '경기', '부산', '울산', '경남', '대구', '경북',
                '광주', '전남', '전북', '대전', '세종', '충남', '충북', '강원', '제주'

        :returns: 종합예보와 오늘/내일/모레의 날씨 및 최저/최고기온을 반환합니다.

            example::

                {
                    'forecast': '내일 경기남부 가끔 비, 내일까지 바람 약간 강, 낮과 밤의 기온차 큼'
                    'today':
                    {
                        'weather': '전국 대체로 흐림',
                        'minimum_temp': '15.3 ~ 21.6',
                        'highst_temp': '23.1 ~ 27.6'
                    }
                    'tomorrow':
                    {
                        'weather': '전국 대체로 흐림',
                        'minimum_temp': '15.3 ~ 21.6',
                        'highst_temp': '23.1 ~ 27.6'
                    }
                    'after_tomorrow':
                    {
                        'weather': '전국 대체로 흐림',
                        'minimum_temp': '15.3 ~ 21.6',
                        'highst_temp': '23.1 ~ 27.6'
                    }
                }
                or None
        """

        region = Weather.region_list.get(search_region)
        if region == None:
          raise Exception(f'"{search_region}" not support')

        _forecast = ''
        _today = {}
        _tomorrow = {}
        _after_tomorrow = {}

        url = f'https://www.weather.go.kr/w/weather/forecast/short-term.do?stnId={region}'
        resp = requests.get(url, headers={'User-Agent' : 'Mozilla/5.0'})
        soup = BeautifulSoup(resp.content, 'html.parser')
        forecasts = soup.find('div', {'class': 'cmp-view-content'}).text
        forecasts = forecasts.split('□')[1].split('○')
        for forecast in map(str.strip, forecasts):
            split_point = forecast.index(')')
            date = forecast[:split_point+1]
            desc = forecast[split_point+2:]
            if '종합' in date:
                _forecast = desc
            if '오늘' in date:
                _today['weather'] = desc
            if '내일' in date or '~' in date:
                _tomorrow['weather'] = desc
            if '모레' in date:
                _after_tomorrow['weather'] = desc

        temp_table = soup.find('tbody')
        all_temps = list(map(lambda x: x.text, temp_table.select('td')[:10]))
        _today['minimum_temp'], _tomorrow['minimum_temp'], _after_tomorrow['minimum_temp'] = all_temps[2:5]
        _today['highst_temp'], _tomorrow['highst_temp'], _after_tomorrow['highst_temp'] = all_temps[7:10]

        return {'forecast':_forecast, 'today':_today, 'tomorrow':_tomorrow, 'after_tomorrow':_after_tomorrow}

    def search_for_block(self, search_region:str='전국', search_type: str='forecast'):
        """
        해당 지역(```search_region```)의 날씨 정보(종합예보, 오늘/내일/모레 날씨)를 가져옵니다.

        example::

            result = pibo_weather.search('서울')

        :param str search_region: 검색 가능한 지역 (default: 전국)

            검색할 수 있는 지역은 다음과 같습니다::

                '전국', '서울', '인천', '경기', '부산', '울산', '경남', '대구', '경북',
                '광주', '전남', '전북', '대전', '세종', '충남', '충북', '강원', '제주'

        :param str search_type: 검색할 내용 (default: forecast)

            검색할 내용은 다음과 같습니다::

                'forecast', 'today', 'tomorrow', 'after_tomorrow'

        :returns: 종합예보 혹은 오늘/내일/모레의 날씨, 최저기온, 최고기온 리스트를 반환합니다.

            example::

                '내일 경기남부 가끔 비, 내일까지 바람 약간 강, 낮과 밤의 기온차 큼' # forecast
                or
                ['전국 대체로 흐림', 15.3, 27.6]
                # [weather, minimum_temp, highst_temp]  in search_type(today|tomorrow|after_tomorrow)
        """

        res = self.search(search_region)

        if search_type == 'forecast':
            return res['forecast'].strip().replace('\n', ' ')
        else:
            return [res[search_type]['weather'].strip().replace('\n', ' '), res[search_type]['minimum_temp'].split(' ~ ')[0], res[search_type]['highst_temp'].split(' ~ ')[1]]

class News:
    """
Functions:
:meth:`~openpibo.collect.News.search`

    JTBC 뉴스 RSS 서비스를 사용해 뉴스 자료를 가져옵니다.

    example::

        from openpibo.collect import News

        pibo_news = News()
        # 아래의 모든 예제 이전에 위 코드를 먼저 사용합니다.
    """
    topic_list = {
        '속보': 'newsflash',
        '정치': 'politics',
        '경제': 'economy',
        '사회': 'society',
        '국제': 'international',
        '문화': 'culture',
        '연예': 'entertainment',
        '스포츠': 'sports',
        '풀영상': 'fullvideo',
        '뉴스랭킹': 'newsrank',
        '뉴스룸': 'newsroom',
        '아침&': 'morningand',
        '썰전 라이브': 'ssulzunlive',
        '정치부회의': 'politicaldesk',
    }
    """
    뉴스 정보를 검색할 수 있는 주제입니다.
    """

    def search(self, search_topic:str = '뉴스랭킹'):
        """
        해당 주제(```search_topic```)에 맞는 뉴스를 가져옵니다.

        example::

            result = pibo_news.search('속보')

        :param str search_topic: 검색 가능한 뉴스 주제 (default: 뉴스랭킹)

            검색할 수 있는 주제는 다음과 같습니다::

                '속보', '정치', '경제', '사회', '국제', '문화', '연예', '스포츠',
                '풀영상', '뉴스랭킹', '뉴스룸', '아침&', '썰전 라이브', '정치부회의'

        :returns: title, link, description, pubDate 요소가 있는 dictionary 배열입니다.

            example::

                [
                    {
                        'title': '또 소방차 막은 불법주차, 이번엔 가차없이 밀어버렸다',
                        'link': 'https://news.jtbc.joins.com/article/article.aspx?...',
                        'description': '2019년 4월 소방당국의 불법주정차 강경대응 훈련 모습...,
                        'pubDate': '2021.09.03'
                    },
                ]
                or None
        """

        topic = News.topic_list.get(search_topic)
        if topic == None:
          raise Exception(f'"{search_topic}" not support')

        _articles = []
        url = f'https://fs.jtbc.joins.com//RSS/{topic}.xml'
        res = requests.get(url, headers={'User-Agent' : 'Mozilla/5.0'})
        soup = BeautifulSoup(res.content, 'xml')
        items = soup.findAll('item')
        for item in items:
          _articles.append({
            'title':item.find('title').text,
            'link':item.find('link').text,
            'description':item.find('description').text,
            'pubDate':item.find('pubDate').text
          })
        return _articles

    def search_for_block(self, search_topic:str = '뉴스랭킹', search_type:str = "title"):
        """
        해당 주제(```search_topic```)에 맞는 뉴스를 가져옵니다.

        example::

            result = pibo_news.search('속보')

        :param str search_topic: 검색 가능한 뉴스 주제 (default: 뉴스랭킹)

            검색할 수 있는 주제는 다음과 같습니다::

                '속보', '정치', '경제', '사회', '국제', '문화', '연예', '스포츠',
                '풀영상', '뉴스랭킹', '뉴스룸', '아침&', '썰전 라이브', '정치부회의'

        :param str search_type: 검색할 내용 (default: title)

            검색할 내용은 다음과 같습니다::

                'title', 'link', 'description'

        :returns: title, link, description 중 선택한 요소의 리스트

            example::

                [
                    '또 소방차 막은 불법주차, 이번엔 가차없이 밀어버렸다',
                    ...
                ]
                or None
        """

        res = self.search(search_topic)
        return [v[search_type] for v in res if '다시보기' not in v[search_type]]

if __name__ == "__main__":
  wiki = Wikipedia()
  weather = Weather()
  news = News()

  print('wiki:', wiki.search('로봇'))
  print('weather:', weather.search('서울'))
  print('news:', news.search('속보'))


# External imports
import datetime
import pandas as pd
import pytz
import requests
import sys
import yaml

# Internal imports
sys.path.insert(0, '../')
from game import GameState

class LineGenerator:
    default_params = {
                      'SPORT': 'baseball_mlb',
                      'REGIONS': 'us',                 # uk | us | eu | au.
                      'MARKETS': 'h2h,spreads,totals', # h2h | spreads | totals
                      'ODDS_FORMAT': 'decimal',        # decimal | american
                      'DATE_FORMAT': 'iso'             # iso | unix
                     }

    def __init__(self, keyfile, id_prefix_func, params=default_params):
        with open(keyfile, 'r') as yamlfile:
            self.key = yaml.load(yamlfile, Loader=yaml.FullLoader)['api-key']
        self.params = params
        self.remaining, self.used = -1, -1   # unkown at initialization time
        self.get_id_prefix = id_prefix_func

    tchar = lambda name, teams: 'A' if name == teams[0] else 'H'
    ochar = lambda name: 'O' if name == 'over' else 'U'

    to_eastern = lambda time: datetime.datetime.strptime(time, '%Y-%m-%dT%H:%M:%SZ'
                                          ).replace(tzinfo=pytz.utc
                                          ).astimezone(pytz.timezone('US/Eastern'))

    def process_moneyline(prefix, market, teams):
        assert(market['key'] == 'h2h')
        assert(len(market['outcomes']) == 2)
        lines = {}
        for outcome in market['outcomes']:
            assert(outcome['name'] in teams)
            lines[prefix+LineGenerator.tchar(outcome['name'], teams)+'_price'] = outcome['price']
        return lines

    def process_spread(prefix, market, teams):
        assert(market['key'] == 'spreads')
        assert(len(market['outcomes']) == 2)
        lines = {}
        for outcome in market['outcomes']:
            assert(outcome['name'] in teams)
            lines[prefix+LineGenerator.tchar(outcome['name'], teams)+'_price'] = outcome['price']
            lines[prefix+LineGenerator.tchar(outcome['name'], teams)+'_point'] = outcome['point']
        return lines

    def process_total(prefix, market):
        assert(market['key'] == 'totals')
        assert(len(market['outcomes']) == 2)
        lines = {}
        for outcome in market['outcomes']:
            assert(outcome['name'] in ('Over', 'Under'))
            lines[prefix+LineGenerator.ochar(outcome['name'])+'_price'] = outcome['price']
            lines[prefix+LineGenerator.ochar(outcome['name'])+'_point'] = outcome['point']
        return lines

    # Sends get request to the api
    # Returns raw response, unformatted.
    def query(self):
        # Send request to the api and get back a response
        response = requests.get(
                       f"https://api.the-odds-api.com/v4/sports/{self.params['SPORT']}/odds",
                       params={
                           'api_key': self.key,
                           'regions': self.params['REGIONS'],
                           'markets': self.params['MARKETS'],
                           'oddsFormat': self.params['ODDS_FORMAT'],
                           'dateFormat': self.params['DATE_FORMAT']
                       })
        # Update usage stats
        self.update_usage(response.headers['x-requests-remaining'],
                          response.headers['x-requests-used'])
        # Return raw response
        return response.json()

    # Takes raw response from the api and formats it.
    def format_response(self, response):
        games = {}
        for game in response:
            start = LineGenerator.to_eastern(game['commence_time'])
            teams = (game['away_team'], game['home_team'])
            id_prefix = self.get_id_prefix(teams[1], strt_time=start)
            line_info = {}
            for book in game['bookmakers']:
                bpre = book['key']+'_'
                line_info[bpre+'last'] = LineGenerator.to_eastern(book['last_update'])
                for market in book['markets']:
                    mpre = bpre + market['key']+'_'
                    line_info[mpre+'last'] = LineGenerator.to_eastern(market['last_update'])
                    if market['key'] == 'h2h':
                        line_info.update(LineGenerator.process_moneyline(mpre, market, teams))
                    if market['key'] == 'spreads':
                        line_info.update(LineGenerator.process_spread(mpre, market, teams))
                    if market['key'] == 'totals':
                        line_info.update(LineGenerator.process_total(mpre, market))
            games[id_prefix] = (start, pd.Series(line_info))
        return games

    # Queries the api and returns the formatted response
    # Returns a dictionary game_id_prefix -> (commence_time, pd.series of line info)
    def get_lines(self):
        return self.format_response(self.query())

    # Returns usage stats
    def usage(self):
        return self.remaining, self.used

    # Updates usage stats
    def update_usage(self, remaining, used):
        self.remaining = int(remaining)
        self.used = int(used)


# ^_^ coding:utf-8 ^_^

from Bio import SeqIO

def switch(s):
    s = s[::-1]
    # print s
    switch_s = ''
    for i in range(len(s)):
        if s[i] == 'A':
            switch_s += 'T'
        elif s[i] == 'T':
            switch_s += 'A'
        elif s[i] == 'G':
            switch_s += 'C'
        elif s[i] == 'C':
            switch_s += 'G'
    return switch_s

def palindrome(s):
    for i in range(len(s)):
        for j in range(4,13,1):
            if s[i:i+j] == switch(s[i:i+j]) and (i+j <= len(s)):
                print(i+1, j)

if __name__ == "__main__":
    # load data
    seq_name, seq_string = [], []
    with open ("./rosalind_revp.txt",'r') as fa:
        for seq_record  in SeqIO.parse(fa,'fasta'):
            seq_name.append(str(seq_record.name))
            seq_string.append(str(seq_record.seq))
    s = seq_string[0]
    palindrome(s)


import time
from tkinter import *
from pygame import mixer
import requests
from tkinter import font
from PIL import Image, ImageTk
from tkvideo import tkvideo
from DetectorClass import DetectorClass
from FollowClass import FollowDetector
import BodyControlClass

class Circo(Frame):
    def __init__(self, parent=None):
        Frame.__init__(self, parent)
        self.parent = parent
        self.pack()
        self.make_widgets()

    def make_widgets(self):
        # don't assume that self.parent is a root window.
        # instead, call `winfo_toplevel to get the root window
        self.winfo_toplevel().title("Circo de drones")

mixer.init()
mixer.music.load('assets/circo.mp3')
mixer.music.play(10)

root = Tk()
circo = Circo(root)
root.geometry("770x525")

image = Image.open("assets/entrada.png")
image = image.resize((770, 525), Image.ANTIALIAS)

bg = ImageTk.PhotoImage(image)
canvas1 = Canvas(root, width=770, height=525)
canvas1.pack(fill="both", expand=True)
canvas1.create_image(0, 0, image=bg, anchor="nw")

myFont = font.Font(family='Bernard MT Condensed', size=22, weight='bold')

def follow():
    mixer.music.stop()
    mixer.music.load('assets/aplausos.mp3')
    mixer.music.play(10)
    time.sleep(5)
    mixer.music.stop()

    newWindow = Toplevel(root)
    newWindow.title("Sígueme")
    newWindow.geometry("450x650")
    # Presentation mode
    BodyControlClass.main()
    # detector = FollowDetector()
    # frame = detector.buildFrame(newWindow)
    # frame.pack(fill="both", expand="yes", padx=10, pady=10)
    newWindow.mainloop()

def fingers():
    mixer.music.stop()
    mixer.music.load('assets/aplausos.mp3')
    mixer.music.play(10)
    time.sleep(5)
    mixer.music.stop()

    newWindow = Toplevel(root)
    newWindow.title("Dedos")
    newWindow.geometry("450x650")
    detector = DetectorClass()
    frame = detector.buildFrame(newWindow, 'fingers')
    frame.pack(fill="both", expand="yes", padx=10, pady=10)
    newWindow.mainloop()

def pose():
    mixer.music.stop()
    mixer.music.load('assets/aplausos.mp3')
    mixer.music.play(10)
    time.sleep(5)
    mixer.music.stop()

    newWindow = Toplevel(root)
    newWindow.title("Pose")
    newWindow.geometry("450x650")
    detector = DetectorClass()
    frame = detector.buildFrame(newWindow, 'pose')
    frame.pack(fill="both", expand="yes", padx=10, pady=10)
    newWindow.mainloop()

def faces():
    mixer.music.stop()
    mixer.music.load('assets/aplausos.mp3')
    mixer.music.play(10)
    time.sleep(5)
    mixer.music.stop()

    newWindow = Toplevel(root)
    newWindow.title("Pose")
    newWindow.geometry("450x650")
    detector = DetectorClass()
    frame = detector.buildFrame(newWindow, 'face')
    frame.pack(fill="both", expand="yes", padx=10, pady=10)
    newWindow.mainloop()

def bye():
    root.destroy()
    bye = Tk()
    circo1 = Circo(bye)
    bye.geometry("770x525")

    image = Image.open("assets/bye.png")
    image = image.resize((770, 525), Image.ANTIALIAS)
    bg = ImageTk.PhotoImage(image)
    canvas1 = Canvas(bye, width=770, height=525)
    canvas1.pack(fill="both", expand=True)

    canvas1.create_image(0, 0, image=bg, anchor="nw")

    bye.mainloop()

def enter():
    mixer.music.stop()
    mixer.music.load('assets/redoble.mp3')  # Loading Music File
    mixer.music.play(10)
    newWindow = Toplevel(root)
    newWindow.title("Selecciona un acto")
    newWindow.geometry("800x600")
    newWindow.columnconfigure(0, weight=1)
    newWindow.columnconfigure(1, weight=1)
    newWindow.columnconfigure(2, weight=1)
    newWindow.columnconfigure(3, weight=1)
    newWindow.rowconfigure(0, weight=1)
    newWindow.rowconfigure(1, weight=1)

    image2 = Image.open("assets/gallery.png")
    image2 = image2.resize((800, 520), Image.ANTIALIAS)
    bg2 = ImageTk.PhotoImage(image2)
    canvas2 = Canvas(newWindow, width=800, height=520)
    canvas2.grid(row=0, column=0, columnspan=4, padx=5, pady=5, sticky=N + S + E + W)
    canvas2.create_image(0, 0, image=bg2, anchor="nw")

    colorsButton = Button(newWindow, text="Follow Me", height=1, bg='#367E18', fg='#FFE9A0', width=12, command=follow)
    colorsButton.grid(row=0, column=0, padx=5, pady=5)
    colorsButton['font'] = myFont
    poseButton = Button(newWindow, text="Control Poses", height=1, bg='#367E18', fg='#FFE9A0', width=12, command=pose)
    poseButton.grid(row=0, column=1, padx=5, pady=5)
    poseButton['font'] = myFont
    fingersButton = Button(newWindow, text="Control Dedos", height=1, bg='#367E18', fg='#FFE9A0', width=12,
                           command=fingers)
    fingersButton.grid(row=0, column=2, padx=5, pady=5)
    fingersButton['font'] = myFont
    facesButton = Button(newWindow, text="Control Caras", height=1, bg='#367E18', fg='#FFE9A0', width=12, command=faces)
    facesButton.grid(row=0, column=3, padx=5, pady=5)
    facesButton['font'] = myFont

    byeButton = Button(newWindow, text="Salir", height=1, bg='#FFE9A0', fg='#367E18', command=bye)
    byeButton.grid(row=1, column=0, columnspan=4, padx=5, pady=5, sticky=N + S + E + W)
    byeButton['font'] = myFont
    newWindow.mainloop()

enterButton = Button(root, text="Pasen y vean", height=1, bg='#367E18', fg='#FFE9A0', width=12, command=enter)
enterButton['font'] = myFont
enterButton_canvas = canvas1.create_window(770 / 2, 525 / 2 + 50, window=enterButton)

# Execute tkinter
root.mainloop()


from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from routers import router

app = FastAPI(
    title="LangChain UI backend",
    description="The backend for LangChain UI",
    version="0.0.1"
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(router)


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

import sys
import os
import numpy as np
import pandas as pd
from scipy.stats import entropy
from sklearn import naive_bayes
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.metrics import precision_recall_fscore_support
import time
import datetime
import glob

from tqdm import tqdm
import warnings
from sklearn.utils import resample
from pandas.api.types import is_string_dtype
from pandas.api.types import is_numeric_dtype, is_categorical_dtype
import math
from itertools import combinations
import random
import shutil
import argparse
warnings.filterwarnings("ignore")

from sklearn import tree
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC, LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import AdaBoostClassifier
from keras.models import Sequential
from keras.layers import Dense
from keras import backend as K
from sklearn.metrics import accuracy_score
from sklearn.decomposition import PCA
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_breast_cancer

import tensorflow as tf
import gc
gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
for gpu in gpus:
    tf.config.experimental.per_process_gpu_memory_fraction = 0.7
from modules.data_preprocessing import DataPreprocessing

class TriTraining:
    def __init__(self, base_classifier_str = [], X_train = [], y_train = [], X_unlabeled = [], data_pre_type = "", confidence_threshold = None):
        self.setting_dict = {
        "NB" : "naive_bayes.GaussianNB()",
        "AdaBoost" : "AdaBoostClassifier(algorithm='SAMME.R', base_estimator=None, learning_rate=0.6,n_estimators=30, random_state=0)",
        "SVM" : """make_pipeline(StandardScaler(),SVC(C=0.6, break_ties=False, cache_size=2000, class_weight=None, coef0=0.0,
            decision_function_shape='ovr', degree=3, gamma=0.001, kernel='linear',
            max_iter=100, probability=True,random_state=None, shrinking=True,
            tol=0.001, verbose=False))""",
        "RF" : """RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
                                       criterion='gini', max_depth=None,
                                       max_leaf_nodes=None, max_samples=None,
                                       min_impurity_decrease=0.0, min_impurity_split=None,
                                       min_samples_leaf=1, min_samples_split=2,
                                       min_weight_fraction_leaf=0.0, n_estimators=60,
                                       n_jobs=None, oob_score=False, random_state=None,
                                       verbose=0, warm_start=False)""",
        "KNN" : "KNeighborsClassifier(n_neighbors = 10)",
        "DT" : "DecisionTreeClassifier(criterion = 'entropy')"
        }
        self.confidence_threshold = confidence_threshold
        self.threshold_dict = {}
        self.data_pre = DataPreprocessing()
        self.data_pre_type = data_pre_type
        if base_classifier_str != []:
            self.base_classifiers_str = base_classifier_str
            self.feature_pre_models = [0] * len(self.base_classifiers_str)
            self.X_labeled = X_train
            self.y_labeled = y_train
            self.unlabeled_num_sum = 0
            self.unlabeled_nums = [0] * len(self.base_classifiers_str)
            self.turn_nums = [0] * len(self.base_classifiers_str)
            self.X_unlabeled = X_unlabeled
            self.X_combine = []
            self.y_combine = []
            self.X_Si, self.y_Si = self.boostrap_sample()
            self.base_classifiers = self.init_classifier()

    def init_classifier(self):
        result = []
        for i in range(len(self.base_classifiers_str)):
            model = self.different_fit(i, self.X_Si[i], self.y_Si[i])
            result.append(model)
        return result

    def boostrap_sample(self):
        X_Si = []
        y_Si = []
        for i in range(len(self.base_classifiers_str)):
            X_sample, y_sample = resample(self.X_labeled, self.y_labeled, stratify = self.y_labeled)
            X_Si.append(X_sample)
            y_Si.append(y_sample)
            self.X_combine.append(X_sample)
            self.y_combine.append(y_sample)
        return X_Si, y_Si

    def different_fit(self, i, X, y):
        if self.base_classifiers_str[i] in ["NB", "AdaBoost", "XgBoost", "SVM", "RF", "KNN", "DT"]:
            model = eval(self.setting_dict[self.base_classifiers_str[i]])
            model.fit(X, y)
            return model
        else:
            pass

    def different_predict(self, i, X):
        if self.base_classifiers_str[i] in ["NB", "AdaBoost", "XgBoost", "SVM", "RF", "KNN", "DT"]:
            predict = self.base_classifiers[i].predict(X)
            predict = predict.tolist()
            return predict
        else:
            pass

    def different_predict_proba(self, i, X):
        if self.base_classifiers_str[i] in ["NB", "AdaBoost", "XgBoost", "SVM", "RF", "KNN", "DT"]:
            predict = self.base_classifiers[i].predict_proba(X)
            predict = predict.tolist()
            return predict
        else:
            pass

    def remove_Li(self, X, y, remove_num):
        X = np.array(X)
        y = np.array(y)
        remove_list = np.random.choice(len(X), replace = False, size = min(len(X), remove_num))
        X = np.delete(X, remove_list, axis = 0)
        y = np.delete(y, remove_list, axis = 0)
        return X, y

    def subsample(self, pre_error_rate, pre_Li_ln, error_rate, X_Li, y_Li):
        s = math.ceil(pre_error_rate * pre_Li_ln / error_rate - 1)
        X_Li, y_Li = self.remove_Li(X_Li, y_Li, len(X_Li) - s)
        return X_Li, y_Li

    def measure_error(self, i):
        """
        error rate = number of labeled data both classidiers make incorrect classification /
        number of labeled data the classifiers(expect classifier i) have the same prediction
        """
        error_up = 0
        error_down = 0.00001
        predicts = [[] for ele in range(len(self.base_classifiers))]
        for j in range(len(self.base_classifiers)):
            if j != i:
                predicts[j] = self.different_predict(j, self.X_labeled)
        for k in range(len(self.y_labeled)):
            temp = []
            for j in range(len(self.base_classifiers)):
                if j != i:
                    temp.append(predicts[j][k])
            temp = list(set(temp))
            if len(temp) == 1:
                error_down += 1
                if temp[0] != self.y_labeled.iloc[k]:
                    error_up += 1
        return error_up / error_down

    def generate_confidence_table(self, indexs):
        predicts = []
        bFR = True
        for index in indexs:
            predict = self.different_predict_proba(index, self.X_labeled)
            predict = pd.DataFrame(predict)
            if bFR:
                predicts = predict
                bFR = False
            else:
                predicts = pd.concat([predicts, predict], axis = 1)
        return predicts

    def retrain(self, i, X_Li, y_Li):
        model = eval(self.setting_dict[self.base_classifiers_str[i]])
        X_Li = pd.DataFrame(X_Li, columns = self.X_labeled.columns)
        X_combine = self.X_labeled.append(X_Li)
        self.X_combine[i] = X_combine
        y_Li = pd.Series(y_Li, dtype = "category")
        y_Li.cat.set_categories(self.y_labeled.cat.categories, inplace = True)
        y_combine = self.y_labeled.append(y_Li)
        self.y_combine[i] = y_combine
        model = self.different_fit(i, X_combine, y_combine)
        return model

    def train(self):
        bFR = True
        #initialize error rate, previous error rate, and previous length of Li
        pre_error_rate = [0.5 for ele in range(len(self.base_classifiers))]
        error_rate = [0.0 for ele in range(len(self.base_classifiers))]
        pre_Li_ln = [0.0 for ele in range(len(self.base_classifiers))]
        turn_start_time = time.time()
        turn = 0
        while True:
            X_Li = [[] for ele in range(len(self.base_classifiers))]
            y_Li = [[] for ele in range(len(self.base_classifiers))]
            update = [False for ele in range(len(self.base_classifiers))]
            for i in range(len(self.base_classifiers)):
                #use classifiers(expect classifier i) to measure error
                error_rate[i] = self.measure_error(i)
                if error_rate[i] < pre_error_rate[i]:
                    predicts = [[] for ele in range(len(self.base_classifiers))]
                    #use classifiers(expect classifier i) to predict unlabeled data
                    for j in range(len(self.base_classifiers)):
                        if j != i:
                            predicts[j] = self.different_predict(j, self.X_unlabeled)

                    #if two classifiers have the same prediction for unlabeled data: add it to Li
                    for k in range(len(self.X_unlabeled)):
                        temp = []
                        for j in range(len(self.base_classifiers)):
                            if j != i:
                                temp.append(predicts[j][k])
                        temp = list(set(temp))
                        if len(temp) == 1:
                            X_Li[i].append(self.X_unlabeled.iloc[k,:])
                            y_Li[i].append(temp[0])

                    if pre_Li_ln[i] == 0:
                        pre_Li_ln[i] = math.floor(error_rate[i] / (pre_error_rate[i] - error_rate[i]) + 1)
                    """
                    if error rate * length of Li < previous error rate * length of Li:
                        use labeled data and unlabeled data Li to retrain classifiers
                    elif length of Li is too big:
                        use subsampling to reduce the size of Li
                        use labeled data and unlabeled data Li to retrain classifiers
                    """
                    if pre_Li_ln[i] < len(X_Li[i]):
                        if error_rate[i] * len(X_Li[i]) < pre_error_rate[i] * pre_Li_ln[i]:
                            update[i] = True
                            self.turn_nums[i] += 1
                            self.unlabeled_nums[i] += len(X_Li[i])
                        elif pre_Li_ln[i] > error_rate[i] / (pre_error_rate[i] - error_rate[i]):
                            X_Li[i], y_Li[i] = self.subsample(pre_error_rate[i], pre_Li_ln[i], error_rate[i], X_Li[i], y_Li[i])
                            update[i] = True
                            self.turn_nums[i] += 1
                            self.unlabeled_nums[i] += len(X_Li[i])
                        else:
                            pass
            turn += 1
            # if all classifiers don't update this turn: stop the algorithm
            if True not in update:
                turn_end_time = time.time()
                total_time = str(round((turn_end_time - turn_start_time) / 60,1))
                for i in range(len(self.unlabeled_nums)):
                    if self.unlabeled_nums[i] != 0:
                        self.unlabeled_num_sum += self.unlabeled_nums[i] / self.turn_nums[i]
                break
            for i in range(len(self.base_classifiers)):
                if update[i]:
                    self.base_classifiers[i] = self.retrain(i, X_Li[i], y_Li[i])
                pre_error_rate[i] = error_rate[i]
                pre_Li_ln[i] = len(X_Li)

    def select_max_category(self, vote_dict, proba_dict):
        max_vote = max(vote_dict.items(), key = lambda ele : ele[1])[1]
        max_categories = []
        for key, value in vote_dict.items():
            if value == max_vote:
                max_categories.append(key)
        if len(max_categories) > 1:
            compare_list = []
            for category in max_categories:
                compare_list.append([category, proba_dict[category]])
            return max(compare_list, key = lambda ele : ele[1])[0]
        else:
            return max_categories[0]

    def majority_vote(self, X_test):
        predicts = []
        predicts_proba = []
        y_pred = []
        for i in range(len(self.base_classifiers)):
            predicts.append(self.different_predict(i, X_test))
            predicts_proba.append(self.different_predict_proba(i, X_test))

        for k in range(len(predicts[0])):
            count_dict = {}
            proba_dict = {}
            for i in range(len(predicts)):
                temp = count_dict.get(predicts[i][k])
                if temp != None:
                    count_dict[predicts[i][k]] += 1
                else:
                    count_dict.update({predicts[i][k]:1})
                temp = proba_dict.get(predicts[i][k])
                if temp != None:
                    proba_dict[predicts[i][k]] += predicts_proba[i][k]
                else:
                    proba_dict.update({predicts[i][k] : predicts_proba[i][k]})
            y_pred.append(self.select_max_category(count_dict, proba_dict))
        return y_pred

    def evaluate(self, X_test, y_test, avg_type = "weighted", save_pred = True):
        y_pred = self.majority_vote(X_test)
        y_test = y_test.tolist()
        results = []
        precision, recall, fscore, support = precision_recall_fscore_support(y_test, y_pred, average = avg_type)
        score_dict = {}
        score_dict.update({"precision":precision})
        score_dict.update({"recall":recall})
        score_dict.update({"fscore":fscore})
        score_dict.update({"support":support})
        return score_dict, y_pred, self.unlabeled_num_sum

if __name__ == "__main__":
    #algorithm parameters
    parser = argparse.ArgumentParser()
    parser.add_argument("-g", "--groups", type = str, nargs = "+",
                        choices = ["NB", "SVM", "RF", "AdaBoost", "KNN", "DT"],
                        default = ["NB"],
                        help = "the three base classifiers use the same type of classifier")
    parser.add_argument("-t", "--train_size", type = float,
                        default = 0.75,
                        help = "the size of the training dataset")
    parser.add_argument("-l", "--label_rates", type = float, nargs = "+",
                        default = [0.1],
                        help = "the size of the labeled data = train_size * label_rate")
    parser.add_argument("-e", "--experiment_num", type = int,
                        default = 10,
                        help = "number of experiments")
    #data and log parameters
    parser.add_argument("--data_pre_type", type = str,
                        choices = ["all_category", "category_and_numeric"],
                        default = "category_and_numeric",
                        help = """
                        category => 10 equal-width bins
                        numeric => log
                        """)
    parser.add_argument("--data_dir", type = str,
                        default = None,
                        help = """
                        if data_dir == None: read data from sklearn.datasets package
                        else: read csv data from data directory
                        """)
    parser.add_argument("--log_dir", type = str,
                        default = os.path.join(os.getcwd(), "log", "tri_training_" + time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())),
                        help = "log directory")
    parser.add_argument("--avg_types", type = str, nargs = "+",
                        choices = ["micro", "macro", "weighted"],
                        default = ["weighted"],
                        help = """
                        micro => micro average
                        macro => macro average
                        weighted => weighted macro average
                        """)
    parser.add_argument("--save_pred",
                        action = "store_true",
                        help = "whether to save prediction and number of unlabeled")
    args = parser.parse_args()
    os.mkdir(args.log_dir)
    for i in range(len(args.groups)):
        args.groups[i] = [args.groups[i]] * 3
    data_pre = DataPreprocessing()
    total_start_time = time.strftime("%Y/%m/%d, %H:%M:%S", time.localtime())
    if args.data_dir == None:
        print("dataset start : breast_cancer_w")
        dataset_start = datetime.datetime.now()
        if args.save_pred:
            log_dict = {
            "dataset":[],"group":[],"confidence_threshold":[],"label_rate":[],"avg_type":[],"precision":[],"recall":[],"fscore":[],"cv":[],
            "y_pred":[],"y_test":[],"unlabeled_num":[]
            }
        else:
            log_dict = {
            "dataset":[],"group":[],"confidence_threshold":[],"label_rate":[],"avg_type":[],"precision":[],"recall":[],"fscore":[],"cv":[]
            }
        dataset = load_breast_cancer()
        X = dataset["data"]
        y = dataset["target"]
        X = pd.DataFrame(X)
        y = pd.Series(y)
        if args.data_pre_type == "category_and_numeric":
            X = data_pre.category_and_numeric(X)
        elif args.data_pre_type == "all_category":
            X = data_pre.columns_category(X)
        else:
            print("data_pre_type error!")
        X = pd.get_dummies(X)
        y = data_pre.to_category(y)
        bEnd = False
        for ele in range(args.experiment_num):
            print("experiment_num start : " + str(ele))
            experiment_num_start = datetime.datetime.now()
            for label_rate in args.label_rates:
                X_train, X_test, y_train, y_test = train_test_split(X, y, train_size = args.train_size, stratify = y, random_state = ele)
                X_labeled, X_unlabeled, y_labeled, y_unlabeled = train_test_split(X_train, y_train, train_size = label_rate, stratify = y_train, random_state = ele)
                for group in args.groups:
                    print("group start : " + "_".join(group))
                    group_start = datetime.datetime.now()
                    confidence_threshold = None
                    tri_training = TriTraining(group, X_labeled, y_labeled, X_unlabeled, args.data_pre_type,
                    confidence_threshold = confidence_threshold
                    )
                    print("train start : " + time.strftime("%Y/%m/%d, %H:%M:%S", time.localtime()))
                    train_start = datetime.datetime.now()
                    tri_training.train()
                    train_end = datetime.datetime.now()
                    print("seconds : " + str((train_end - train_start).seconds))
                    print("train end : " + time.strftime("%Y/%m/%d, %H:%M:%S", time.localtime()))
                    for avg_type in args.avg_types:
                        score_dict, y_pred, unlabeled_num = tri_training.evaluate(X_test, y_test, avg_type)
                        log_dict["dataset"].append("breast_cancer_w")
                        log_dict["group"].append("_".join(group))
                        log_dict["confidence_threshold"].append(-1)
                        log_dict["label_rate"].append(label_rate)
                        log_dict["avg_type"].append(avg_type)
                        log_dict["precision"].append(score_dict["precision"])
                        log_dict["recall"].append(score_dict["recall"])
                        log_dict["fscore"].append(score_dict["fscore"])
                        log_dict["cv"].append(-1)
                        if args.save_pred:
                            log_dict["y_pred"].append(y_pred)
                            log_dict["y_test"].append(y_test.tolist())
                            log_dict["unlabeled_num"].append(unlabeled_num)
                    group_end = datetime.datetime.now()
                    print("seconds : " + str((group_end - group_start).seconds))
                    print("group end : " + "_".join(group))
            experiment_num_end = datetime.datetime.now()
            print("seconds : " + str((experiment_num_end - experiment_num_start).seconds))
            print("experiment_num end")
            if bEnd:
                break
        if not bEnd:
            data_name = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()) + "_" + "breast_cancer_w.csv"
            df_log = pd.DataFrame(log_dict)
            df_log.to_csv(os.path.join(args.log_dir, data_name), index = False)
        dataset_end = datetime.datetime.now()
        print("seconds: " + str((dataset_end - dataset_start).seconds))
        print("dataset end")
        print("---")
    else:
        for data in glob.glob(os.path.join(args.data_dir, "*.csv")):
            dataset_start = datetime.datetime.now()
            print("dataset start : " + os.path.basename(data))
            if args.save_pred:
                log_dict = {
                "dataset":[],"group":[],"confidence_threshold":[],"label_rate":[],"avg_type":[],"precision":[],"recall":[],"fscore":[],"cv":[],
                "y_pred":[],"y_test":[],"unlabeled_num":[]
                }
            else:
                log_dict = {
                "dataset":[],"group":[],"confidence_threshold":[],"label_rate":[],"avg_type":[],"precision":[],"recall":[],"fscore":[],"cv":[]
                }
            df = pd.read_csv(data)
            if args.data_pre_type == "category_and_numeric":
                df = data_pre.category_and_numeric(df)
            elif args.data_pre_type == "all_category":
                df = data_pre.columns_category(df)
            else:
                print("data_pre_type error!")
            X = df[df.columns[:-1]]
            X = pd.get_dummies(X)
            y = df[df.columns[-1]]
            bEnd = False
            for ele in range(args.experiment_num):
                print("experiment_num start : " + str(ele))
                experiment_num_start = datetime.datetime.now()
                for label_rate in args.label_rates:
                    X_train, X_test, y_train, y_test = train_test_split(X, y, train_size = args.train_size, stratify = y, random_state = ele)
                    X_labeled, X_unlabeled, y_labeled, y_unlabeled = train_test_split(X_train, y_train, train_size = label_rate, stratify = y_train, random_state = ele)
                    for group in args.groups:
                        print("group start:" + "_".join(group))
                        group_start = datetime.datetime.now()
                        confidence_threshold = None
                        tri_training = TriTraining(group, X_labeled, y_labeled, X_unlabeled, args.data_pre_type,
                        confidence_threshold = confidence_threshold
                        )
                        print("train start : " + time.strftime("%Y/%m/%d, %H:%M:%S", time.localtime()))
                        train_start = datetime.datetime.now()
                        tri_training.train()
                        train_end = datetime.datetime.now()
                        print("seconds : " + str((train_end - train_start).seconds))
                        print("train end : " + time.strftime("%Y/%m/%d, %H:%M:%S", time.localtime()))
                        for avg_type in args.avg_types:
                            score_dict, y_pred, unlabeled_num = tri_training.evaluate(X_test, y_test, avg_type)
                            log_dict["dataset"].append(os.path.basename(data))
                            log_dict["group"].append("_".join(group))
                            log_dict["confidence_threshold"].append(-1)
                            log_dict["label_rate"].append(label_rate)
                            log_dict["avg_type"].append(avg_type)
                            log_dict["precision"].append(score_dict["precision"])
                            log_dict["recall"].append(score_dict["recall"])
                            log_dict["fscore"].append(score_dict["fscore"])
                            log_dict["cv"].append(-1)
                            if args.save_pred:
                                log_dict["y_pred"].append(y_pred)
                                log_dict["y_test"].append(y_test.tolist())
                                log_dict["unlabeled_num"].append(unlabeled_num)
                        group_end = datetime.datetime.now()
                        print("seconds : " + str((group_end - group_start).seconds))
                        print("group end : " + "_".join(group))
                experiment_num_end = datetime.datetime.now()
                print("seconds : " + str((experiment_num_end - experiment_num_start).seconds))
                print("experiment_num")
                if bEnd:
                    break
            if not bEnd:
                data_name = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()) + "_" + os.path.basename(data)
                df_log = pd.DataFrame(log_dict)
                df_log.to_csv(os.path.join(args.log_dir, data_name), index = False)
        dataset_end = datetime.datetime.now()
        print("seconds: " + str((dataset_end - dataset_start).seconds))
        print("dataset end")
total_end_time = time.strftime("%Y/%m/%d, %H:%M:%S", time.localtime())
print("finish!")
print(total_start_time)
print(total_end_time)


from typing import Type
import cv2
import config

def add_emotion(frame, emotion_list, n, initialize, scale_factor, flag):
    height, width, channels = frame.shape

    # jpgに変換 画像ファイルをインターネットを介してAPIで送信するのでサイズを小さくしておく
    small = cv2.resize(frame, (int(width * scale_factor),
                       int(height * scale_factor)))
    ret, buf = cv2.imencode('.jpg', small)

    # Amazon RekognitionにAPIを投げる
    rekognition = config.config_AWS()
    response = rekognition.detect_faces(
        Image={'Bytes': buf.tobytes()}, Attributes=['ALL'])
    i = 1  # 個別の計算で使用

    count = 0
    for face in response['FaceDetails']:
        emothions = face['Emotions']

        boundingBox = face['BoundingBox']
        box_height = int(boundingBox['Height']*height)
        box_left = int(boundingBox['Left']*width)
        box_top = int(boundingBox['Top']*height)
        box_width = int(boundingBox['Width']*width)
        # box_image = pil_image.crop((box_left, box_top, box_left + box_width, box_top+ box_height))
        box_image = frame[box_top: box_top + box_height, box_left: box_left + box_width]
        print(flag)
        if flag == 0:
            cv2.imwrite('static/css/images/chart_' + str(count) + '.png', box_image)
        count = count + 1

        if not initialize:
            emotion_list.append([])  # 初期人数分の空配列を作成

        if len(emotion_list) >= i:  # 初期人数以上の人数を検知した場合は処理しない
            for per_emothions in emothions:  # 個々のびびり度を計算
                if per_emothions['Type'] == "SAD" or per_emothions['Type'] == "FEAR" or per_emothions['Type'] == "CONFUSED" or per_emothions['Type'] == "SURPRISED":
                    emotion_list[i-1].append(per_emothions['Confidence'])
        i += 1

def make_chicken_rate_list(emotion_list):
    chicken_rate_list = []
    for i in range(len(emotion_list)):
        chicken_rate = sum(emotion_list[i])/len(emotion_list[i]) # i+1人目のビビり度 = chicken_rate
        chicken_rate_list.append(chicken_rate)
    return chicken_rate_list

def make_emotion_list():
    scale_factor = .15
    video_path = "./uploads/sample.mp4"
    cap = cv2.VideoCapture(video_path)

    if not cap.isOpened():
        raise Exception("例外が発生しました")

    read_fps = cap.get(cv2.CAP_PROP_FPS) # 元のfps
    fps = 1  # 希望のfps（動画1秒あたり何枚切り出して処理したいか）
    thresh = read_fps / fps  # フレーム何枚につき1枚処理するか
    frame_counter = 0

    # digit = len(str(int(cap.get(cv2.CAP_PROP_FRAME_COUNT))))

    initialize = False  # 初期処理
    emotion_list = []  # 4人っていう設定
    n = 0  # フレーム計算で使用

    flag = 0
    isContinued = True
    while isContinued:
        ret, frame = cap.read()
        if ret:
            frame_counter += 1
            if (frame_counter >= thresh):  # フレームカウントがthreshを超えたら処理する

                add_emotion(
                    frame=frame,
                    emotion_list=emotion_list,
                    n=n,
                    initialize=initialize,
                    scale_factor=scale_factor,
                    flag=flag
                )
                flag = 1
                n += 1
                frame_counter = 0  # フレームカウントを0に戻す
                initialize = True

        else:
            isContinued = False

    return emotion_list

if __name__ == '__main__':
    emotion_list = make_emotion_list()
    chicken_rate_list = make_chicken_rate_list(emotion_list=emotion_list)


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

# In[1]:

import pandas as pd
import numpy as np
import os, sys
import json, copy
import csv

# In[2]:

db_form = pd.read_csv('src_forms4\\zp_chronoengine_forms6_2.csv')
row = db_form.iloc[0]
result = pd.DataFrame(columns=db_form.columns)
file_csv = os.scandir('src_forms4\\csv')
file_json = os.scandir('src_forms4\\json')
src_csv = {}
src_json = {}

# In[3]:

for i in file_csv:
    src_csv[i.name.split('.')[0]]  = pd.read_csv(i.path)

# In[4]:

for i in file_json:
    with open(i.path, "rb") as read_file:
        src_json[i.name.split('.')[0]]  = json.load(read_file)

# In[5]:

def form_views(src_csv, src_json, appendix):
   filds = []
   for j in range(src_csv.shape[0]):
       tmp = src_csv.iloc[j].dropna().to_dict()
       tmp['designer_label'] = tmp['label']
       tmp['text'] = tmp['label']
       tmp['params'] = {}
       tmp['params'].update({'value': tmp['value']} if tmp.get('value') else {})
       tmp['params'].update({'name': tmp['name'], 'id': tmp['name']})
       fild = copy.deepcopy(src_json[tmp['type']])
       intersect_keys = set(tmp)
       intersect_keys.intersection_update(set(fild))
       for k in intersect_keys:
           if k == 'params':
               fild[k].update(tmp[k])
           elif k == 'options':
               fild[k] = tmp[k].replace('\\\\', '\\')
           else:
               fild[k] = tmp[k]
       filds.append(fild)
   filds = filds + list(appendix.values())
   filds_dict = {}
   for l,m in enumerate(filds, 1):
       filds_dict.update({str(l): m})
   return json.dumps(filds_dict, ensure_ascii=False)

# In[6]:

result = pd.DataFrame(columns=result.columns)
for i, k in enumerate(src_csv, 10):
    row_tmp = row.copy()
    row_tmp_title = src_csv[k]['label'].iloc[0] + ' на заказ'
    row_tmp['id'] = i
    row_tmp['title'] = row_tmp_title
    row_tmp['alias'] = 'custom_' + k
    row_tmp['views'] = form_views(src_csv[k], src_json['filds'], src_json['contacts']).replace('/','\\\\/').replace('\\"','\\\\"')
    row_tmp_func = json.loads(row_tmp['functions'])
    row_tmp_func['6']['subject'] = row_tmp_title
    row_tmp_func['8']['subject'] = row_tmp_title
    row_tmp['functions'] = json.dumps(row_tmp_func, ensure_ascii=False).replace('/','\\\\/')
    result = result.append(row_tmp)

# In[11]:

result.to_csv('zp_chronoengine_forms61.csv', index=False, quoting=csv.QUOTE_NONNUMERIC, sep=';', header=False)

# In[ ]:


import os
import logging
import json
import base64
import httplib2
import sys
import zipfile
import time
import lithops
from google.cloud import pubsub_v1
from google.oauth2 import service_account
from google_auth_httplib2 import AuthorizedHttp
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.auth import jwt

from lithops.version import __version__
from lithops.utils import version_str
from lithops.constants import COMPUTE_CLI_MSG, JOBS_PREFIX
from lithops.constants import TEMP as TEMP_PATH

from . import config as gcp_config

logger = logging.getLogger(__name__)

ZIP_LOCATION = os.path.join(TEMP_PATH, 'lithops_gcp.zip')
SCOPES = ('https://www.googleapis.com/auth/cloud-platform',
          'https://www.googleapis.com/auth/pubsub')
FUNCTIONS_API_VERSION = 'v1'
PUBSUB_API_VERSION = 'v1'
AUDIENCE = "https://pubsub.googleapis.com/google.pubsub.v1.Publisher"

class GCPFunctionsBackend:
    def __init__(self, gcp_functions_config, internal_storage):
        self.name = 'gcp_functions'
        self.type = 'faas'
        self.gcp_functions_config = gcp_functions_config
        self.package = 'lithops_v' + __version__

        self.region = gcp_functions_config['region']
        self.service_account = gcp_functions_config['service_account']
        self.project = gcp_functions_config['project_name']
        self.credentials_path = gcp_functions_config['credentials_path']
        self.num_retries = gcp_functions_config['retries']
        self.retry_sleep = gcp_functions_config['retry_sleep']

        self.internal_storage = internal_storage

        # Setup Pub/Sub client
        try:  # Get credentials from JSON file
            service_account_info = json.load(open(self.credentials_path))
            credentials = jwt.Credentials.from_service_account_info(service_account_info,
                                                                    audience=AUDIENCE)
            credentials_pub = credentials.with_claims(audience=AUDIENCE)
        except Exception:  # Get credentials from gcp function environment
            credentials_pub = None
        self.publisher_client = pubsub_v1.PublisherClient(credentials=credentials_pub)

        msg = COMPUTE_CLI_MSG.format('GCP Functions')
        logger.info("{} - Region: {} - Project: {}".format(msg, self.region, self.project))

    def _format_function_name(self, runtime_name, runtime_memory):
        runtime_name = (self.package + '_' + runtime_name).replace('.', '-')
        return '{}_{}MB'.format(runtime_name, runtime_memory)

    def _format_topic_name(self, runtime_name, runtime_memory):
        return self._format_function_name(runtime_name, runtime_memory) + '_topic'

    def _unformat_function_name(self, action_name):
        split = action_name.split('_')
        runtime_name = split[2].replace('-', '.')
        runtime_memory = int(split[3].replace('MB', ''))
        return runtime_name, runtime_memory

    def _full_function_location(self, function_name):
        return 'projects/{}/locations/{}/functions/{}'.format(self.project, self.region, function_name)

    def _full_topic_location(self, topic_name):
        return 'projects/{}/topics/{}'.format(self.project, topic_name)

    def _full_default_location(self):
        return 'projects/{}/locations/{}'.format(self.project, self.region)

    def _encode_payload(self, payload):
        return base64.b64encode(bytes(json.dumps(payload), 'utf-8')).decode('utf-8')

    def _get_auth_session(self):
        credentials = service_account.Credentials.from_service_account_file(self.credentials_path,
                                                                            scopes=SCOPES)
        http = httplib2.Http()
        return AuthorizedHttp(credentials, http=http)

    def _get_funct_conn(self):
        http = self._get_auth_session()
        return build('cloudfunctions', FUNCTIONS_API_VERSION, http=http, cache_discovery=False)

    def _get_default_runtime_image_name(self):
        return 'python' + version_str(sys.version_info)

    def _get_runtime_requirements(self, runtime_name):
        if runtime_name in gcp_config.DEFAULT_RUNTIMES:
            return gcp_config.DEFAULT_REQUIREMENTS
        else:
            user_runtimes = self._list_runtimes(default_runtimes=False)
            if runtime_name in user_runtimes:
                raw_reqs = self.internal_storage.get_data(key='/'.join([gcp_config.USER_RUNTIMES_PREFIX, runtime_name]))
                reqs = raw_reqs.decode('utf-8')
                return reqs.splitlines()
            else:
                raise Exception('Runtime {} does not exist. '
                                'Available runtimes: {}'.format(runtime_name,
                                                                gcp_config.DEFAULT_RUNTIMES + user_runtimes))

    def _list_runtimes(self, default_runtimes=True):
        runtimes = []

        if default_runtimes:
            runtimes.extend(gcp_config.DEFAULT_RUNTIMES)

        user_runtimes_keys = self.internal_storage.storage.list_keys(self.internal_storage.bucket,
                                                                     prefix=gcp_config.USER_RUNTIMES_PREFIX)
        runtimes.extend([runtime.split('/', 1)[-1] for runtime in user_runtimes_keys])
        return runtimes

    def _create_handler_zip(self, runtime_name):
        logger.debug("Creating function handler zip in {}".format(ZIP_LOCATION))

        def add_folder_to_zip(zip_file, full_dir_path, sub_dir=''):
            for file in os.listdir(full_dir_path):
                full_path = os.path.join(full_dir_path, file)
                if os.path.isfile(full_path):
                    zip_file.write(full_path, os.path.join('lithops', sub_dir, file), zipfile.ZIP_DEFLATED)
                elif os.path.isdir(full_path) and '__pycache__' not in full_path:
                    add_folder_to_zip(zip_file, full_path, os.path.join(sub_dir, file))

        # Get runtime requirements
        runtime_requirements = self._get_runtime_requirements(runtime_name)
        requirements_file_path = os.path.join(TEMP_PATH, '{}_requirements.txt'.format(runtime_name))
        with open(requirements_file_path, 'w') as reqs_file:
            for req in runtime_requirements:
                reqs_file.write('{}\n'.format(req))

        try:
            with zipfile.ZipFile(ZIP_LOCATION, 'w') as lithops_zip:
                # Add Lithops entryfile to zip archive
                current_location = os.path.dirname(os.path.abspath(__file__))
                main_file = os.path.join(current_location, 'entry_point.py')
                lithops_zip.write(main_file, 'main.py', zipfile.ZIP_DEFLATED)

                # Add runtime requirements.txt to zip archive
                lithops_zip.write(requirements_file_path, 'requirements.txt', zipfile.ZIP_DEFLATED)

                # Add Lithops to zip archive
                module_location = os.path.dirname(os.path.abspath(lithops.__file__))
                add_folder_to_zip(lithops_zip, module_location)
        except Exception as e:
            raise Exception('Unable to create Lithops package: {}'.format(e))

    def _create_function(self, runtime_name, memory, code, timeout=60, trigger='HTTP'):
        logger.debug("Creating function {} - Memory: {} Timeout: {} Trigger: {}".format(runtime_name,
                                                                                memory, timeout, trigger))
        default_location = self._full_default_location()
        function_location = self._full_function_location(self._format_function_name(runtime_name, memory))
        bin_name = self._format_function_name(runtime_name, memory) + '_bin.zip'
        self.internal_storage.put_data(bin_name, code)

        python_runtime_ver = 'python{}'.format(version_str(sys.version_info))

        cloud_function = {
            'name': function_location,
            'description': self.package,
            'entryPoint': 'main',
            'runtime': python_runtime_ver.lower().replace('.', ''),
            'timeout': str(timeout) + 's',
            'availableMemoryMb': memory,
            'serviceAccountEmail': self.service_account,
            'maxInstances': 0,
            'sourceArchiveUrl': 'gs://{}/{}'.format(self.internal_storage.bucket, bin_name)
        }

        if trigger == 'HTTP':
            cloud_function['httpsTrigger'] = {}
        elif trigger == 'Pub/Sub':
            topic_location = self._full_topic_location(self._format_topic_name(runtime_name, memory))
            cloud_function['eventTrigger'] = {
                'eventType': 'providers/cloud.pubsub/eventTypes/topic.publish',
                'resource': topic_location,
                'failurePolicy': {}
            }

        response = self._get_funct_conn().projects().locations().functions().create(
            location=default_location,
            body=cloud_function
        ).execute(num_retries=self.num_retries)

        # Wait until function is completely deployed
        while True:
            response = self._get_funct_conn().projects().locations().functions().get(
                name=function_location
            ).execute(num_retries=self.num_retries)
            logger.debug('Function status is {}'.format(response['status']))
            if response['status'] == 'ACTIVE':
                break
            elif response['status'] == 'OFFLINE':
                raise Exception('Error while deploying Cloud Function')
            elif response['status'] == 'DEPLOY_IN_PROGRESS':
                time.sleep(self.retry_sleep)
                logger.info('Waiting for function to be deployed...')
            else:
                raise Exception('Unknown status {}'.format(response['status']))

        # Delete runtime bin archive from storage
        self.internal_storage.storage.delete_object(self.internal_storage.bucket, bin_name)

    def build_runtime(self, runtime_name, requirements_file, extra_args=[]):
        if requirements_file is None:
            raise Exception('Please provide a `requirements.txt` file with the necessary modules')
        logger.info('Going to create runtime {} ({}) for GCP Functions...'.format(runtime_name, requirements_file))
        runtime_python_ver = 'python{}'.format(version_str(sys.version_info))
        if runtime_python_ver not in gcp_config.DEFAULT_RUNTIMES:
            raise Exception('Runtime {} is not available for GCP Functions, '
                            'please use one of {}'.format(runtime_python_ver, gcp_config.DEFAULT_RUNTIMES))

        with open(requirements_file, 'r') as req_file:
            requirements = req_file.read()

        self.internal_storage.put_data('/'.join([gcp_config.USER_RUNTIMES_PREFIX, runtime_name]), requirements)
        logger.info('Ok - Created runtime {}'.format(runtime_name))
        logger.info('Available runtimes: {}'.format(self._list_runtimes(default_runtimes=True)))

    def deploy_runtime(self, runtime_name, memory, timeout=60):
        logger.debug(f"Deploying runtime: {runtime_name} - Memory: {memory} Timeout: {timeout}")

        # Create topic
        topic_name = self._format_topic_name(runtime_name, memory)
        topic_list_request = self.publisher_client.list_topics(request={'project': 'projects/{}'.format(self.project)})
        topic_location = self._full_topic_location(topic_name)
        topics = [topic.name for topic in topic_list_request]
        if topic_location in topics:
            logger.debug("Topic {} already exists - Restarting queue...".format(topic_location))
            self.publisher_client.delete_topic(topic=topic_location)
        logger.debug("Creating topic {}...".format(topic_location))
        self.publisher_client.create_topic(name=topic_location)

        # Create function
        self._create_handler_zip(runtime_name)
        with open(ZIP_LOCATION, "rb") as action_zip:
            action_bin = action_zip.read()

        self._create_function(runtime_name, memory, code=action_bin, timeout=timeout, trigger='Pub/Sub')

        # Get runtime preinstalls
        runtime_meta = self._generate_runtime_meta(runtime_name, memory)

        return runtime_meta

    def delete_runtime(self, runtime_name, runtime_memory, delete_runtime_storage=True):
        action_name = self._format_function_name(runtime_name, runtime_memory)
        function_location = self._full_function_location(action_name)
        logger.debug('Going to delete runtime {}'.format(action_name))

        # Delete function
        self._get_funct_conn().projects().locations().functions().delete(
            name=function_location,
        ).execute(num_retries=self.num_retries)
        logger.debug('Request Ok - Waiting until function is completely deleted')

        # Wait until function is completely deleted
        while True:
            try:
                response = self._get_funct_conn().projects().locations().functions().get(
                    name=function_location
                ).execute(num_retries=self.num_retries)
                logger.debug('Function status is {}'.format(response['status']))
                if response['status'] == 'DELETE_IN_PROGRESS':
                    time.sleep(self.retry_sleep)
                else:
                    raise Exception('Unknown status: {}'.format(response['status']))
            except HttpError as e:
                logger.debug('Ok - {}'.format(e))
                break

        # Delete Pub/Sub topic attached as trigger for the cloud function
        logger.debug('Listing Pub/Sub topics...')
        topic_name = self._format_topic_name(runtime_name, runtime_memory)
        topic_location = self._full_topic_location(topic_name)
        topic_list_request = self.publisher_client.list_topics(request={'project': 'projects/{}'.format(self.project)})
        topics = [topic.name for topic in topic_list_request]
        logger.debug('Topics: {}'.format(topics))
        if topic_location in topics:
            logger.debug('Going to delete topic {}'.format(topic_name))
            self.publisher_client.delete_topic(topic=topic_location)
            logger.debug('Ok - topic {} deleted'.format(topic_name))

        # Delete user runtime from storage
        user_runtimes = self._list_runtimes(default_runtimes=False)
        if runtime_name in user_runtimes and delete_runtime_storage:
            self.internal_storage.storage.delete_object(self.internal_storage.bucket,
                                                        '/'.join([gcp_config.USER_RUNTIMES_PREFIX, runtime_name]))

    def clean(self):
        logger.debug('Going to delete all deployed runtimes...')
        runtimes = self.list_runtimes()
        for runtime in runtimes:
            if 'lithops_v' in runtime:
                runtime_name, runtime_memory = self._unformat_function_name(runtime)
                self.delete_runtime(runtime_name, runtime_memory)

    def list_runtimes(self, docker_image_name='all'):
        logger.debug('Listing deployed runtimes...')
        response = self._get_funct_conn().projects().locations().functions().list(
            parent=self._full_default_location()
        ).execute(num_retries=self.num_retries)

        runtimes = [function['name'].split('/')[-1] for function in response.get('functions', [])]
        logger.debug('Deployed runtimes: {}'.format(runtimes))
        return runtimes

    def invoke(self, runtime_name, runtime_memory, payload={}):
        topic_location = self._full_topic_location(self._format_topic_name(runtime_name, runtime_memory))

        fut = self.publisher_client.publish(
            topic_location,
            bytes(json.dumps(payload, default=str).encode('utf-8'))
        )
        invocation_id = fut.result()

        return invocation_id

    def get_runtime_key(self, runtime_name, runtime_memory):
        action_name = self._format_function_name(runtime_name, runtime_memory)
        runtime_key = os.path.join(self.name, self.region, action_name)
        logger.debug('Runtime key: {}'.format(runtime_key))
        return runtime_key

    def _generate_runtime_meta(self, runtime_name, memory):
        logger.debug('Generating runtime meta for {}...'.format(runtime_name))

        function_name = self._format_function_name(runtime_name, memory)
        function_location = self._full_function_location(function_name)
        logger.debug('Going to synchronously invoke {} through developer API'.format(function_name))

        payload = {
            'get_preinstalls': {
                'runtime_name': runtime_name,
                'storage_config': self.internal_storage.storage.storage_config
            }
        }

        # Data is b64 encoded so we can treat REST call the same as async pub/sub event trigger
        response = self._get_funct_conn().projects().locations().functions().call(
            name=function_location,
            body={'data': json.dumps({'data': self._encode_payload(payload)})}
        ).execute(num_retries=self.num_retries)

        if 'result' in response and response['result'] == 'OK':
            object_key = '/'.join([JOBS_PREFIX, runtime_name + '.meta'])

            runtime_meta_json = self.internal_storage.get_data(object_key)
            runtime_meta = json.loads(runtime_meta_json)
            self.internal_storage.storage.delete_object(self.internal_storage.bucket, object_key)
            return runtime_meta
        elif 'error' in response:
            raise Exception(response['error'])
        else:
            raise Exception('Error at retrieving runtime meta: {}'.format(response))


import os

import matplotlib.pyplot as plt
import numpy as np
import torch
from PIL import Image
from torchvision import transforms

from SwordNet import SwordNet

plt.rcParams['font.sans-serif'] = ['STSong']

def get_image_info(m_image_dir):
    m_image_info = Image.open(m_image_dir).convert('RGB')  # 是一幅图片
    # 数据预处理方法
    image_transform = transforms.Compose([
        transforms.ToTensor()
    ])
    m_image_info = image_transform(m_image_info)  # torch.Size([3, 224, 224])
    m_image_info = m_image_info.unsqueeze(0)
    return m_image_info  # 变成tensor数据

def get_k_layer_feature_map(m_model, k, x):
    with torch.no_grad():
        for index, layer in enumerate(m_model.children()):  # model的第一个Sequential()是有多层，所以遍历
            x = layer(x)  # torch.Size([1, 64, 55, 55])生成了64个通道
            if k == index:
                return x

#  可视化特征图
def show_feature_map(m_feature_map, layer_name, size=(96, 96)):  # feature_map=torch.Size([1, 64, 55, 55]),feature_map[0].shape=torch.Size([64, 55, 55])
    # feature_map[2].shape     out of bounds
    m_feature_map = m_feature_map.squeeze(0)  # 压缩成torch.Size([64, 55, 55])

    # 以下4行，通过双线性插值的方式改变保存图像的大小
    m_feature_map = m_feature_map.view(1, m_feature_map.shape[0], m_feature_map.shape[1], m_feature_map.shape[2])  # (1,64,55,55)
    upsample = torch.nn.UpsamplingBilinear2d(size=size)  # 这里进行调整大小
    m_feature_map = upsample(m_feature_map)
    m_feature_map = m_feature_map.view(m_feature_map.shape[1], m_feature_map.shape[2], m_feature_map.shape[3])

    feature_map_num = m_feature_map.shape[0]  # 返回通道数
    row_num = int(np.ceil(np.sqrt(feature_map_num)))  # 8
    plt.figure()
    for index in range(1, feature_map_num + 1):  # 通过遍历的方式，将64个通道的tensor拿出
        plt.subplot(row_num, row_num, index)
        plt.imshow(m_feature_map[index - 1], cmap='gray')  # feature_map[0].shape=torch.Size([55, 55])
        # 将上行代码替换成，可显示彩色 plt.imshow(transforms.ToPILImage()(feature_map[index - 1]))#feature_map[0].shape=torch.Size([55, 55])
        plt.axis('off')
    plt.savefig(layer_name)
    plt.show()

def save_all_featureMap(net, img_path, save_path):
    image = get_image_info(img_path)
    image_name = img_path.split('/')[-1].split('.')[0]
    for i in range(len(list(net.children()))):
        m_feature_map = get_k_layer_feature_map(model, i, image)
        if os.path.exists(save_path):
            show_feature_map(m_feature_map, layer_name=os.path.join(save_path, image_name+'_Layer_' + str(i) + '_FeatureMap'))
        else:
            os.makedirs(save_path)
            show_feature_map(m_feature_map, layer_name=os.path.join(save_path, image_name+'_Layer_' + str(i) + '_FeatureMap'))

if __name__ == '__main__':
    image_dir = './FontData/val/行楷/万.png'
    # 定义提取第几层的feature map
    k = 1
    image_info = get_image_info(image_dir)

    # 1.定义模型
    model = SwordNet(3, 18)

    # 2.加载训练好的模型参数
    ckpt_path = './checkpoint/model_best.pt'  # 训练好的模型参数地址
    model.load_state_dict(torch.load(ckpt_path), False)

    feature_map = get_k_layer_feature_map(model, k, image_info)
    # show_feature_map(feature_map, layer_name='Layer_'+str(k)+'_FeatureMap')
    save_all_featureMap(net=model, img_path=image_dir, save_path='./visual')


from owslib.etree import etree
from owslib import util

# default variables

schema = 'http://schemas.opengis.net/filter/1.1.0/filter.xsd'

namespaces = {
    None : 'http://www.opengis.net/ogc',
    'gml': 'http://www.opengis.net/gml',
    'ogc': 'http://www.opengis.net/ogc',
    'xs' : 'http://www.w3.org/2001/XMLSchema',
    'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
}

schema_location = '%s %s' % (namespaces['ogc'], schema)

class FilterRequest(object):
    """ filter class """
    def __init__(self, version='1.1.0'):
        """

        filter Constructor

        Parameters
        ----------

        - parent: parent etree.Element object (default is None)
        - version: version (default is '1.1.0')

        """

        self.version = version

    def setfilter(self, parent=None):
        if parent is None:
            tmp = etree.Element(util.nspath('Filter', namespaces['ogc']))
            tmp.set(util.nspath('schemaLocation', namespaces['xsi']), schema_location)
            return tmp
        else:
            etree.SubElement(parent, util.nspath('Filter', namespaces['ogc']))

    def setpropertyisequalto(self, parent, propertyname, literal, matchcase=True):
        """

        construct a PropertyIsEqualTo

        Parameters
        ----------

        - parent: parent etree.Element object
        - propertyname: the PropertyName
        - literal: the Literal value
        - matchcase: whether to perform a case insensitve query (default is True)

        """

        tmp = etree.SubElement(parent, util.nspath('PropertyIsEqualTo', namespaces['ogc']))
        if matchcase is False:
            tmp.set('matchCase', 'false')
        etree.SubElement(tmp, util.nspath('PropertyName', namespaces['ogc'])).text = propertyname
        etree.SubElement(tmp, util.nspath('Literal', namespaces['ogc'])).text = literal

    def setbbox(self, parent, bbox):
        """

        construct a BBOX search predicate

        Parameters
        ----------

        - parent: parent etree.Element object
        - bbox: the bounding box in the form [minx,miny,maxx,maxy]

        """

        tmp = etree.SubElement(parent, util.nspath('BBOX', namespaces['ogc']))
        etree.SubElement(tmp, util.nspath('PropertyName', namespaces['ogc'])).text = 'ows:BoundingBox'
        tmp2 = etree.SubElement(tmp, util.nspath('Envelope', namespaces['gml']))
        etree.SubElement(tmp2, util.nspath('lowerCorner', namespaces['gml'])).text = '%s %s' % (bbox[0], bbox[1])
        etree.SubElement(tmp2, util.nspath('upperCorner', namespaces['gml'])).text = '%s %s' % (bbox[2], bbox[3])

    def setpropertyislike(self, parent, propertyname, literal, wildcard='%', singlechar='_', escapechar='\\'):
        """

        construct a PropertyIsLike

        Parameters
        ----------

        - parent: parent etree.Element object
        - propertyname: the PropertyName
        - literal: the Literal value
        - wildcard: the wildCard character (default is '%')
        - singlechar: the singleChar character (default is '_')
        - escapechar: the escapeChar character (default is '\')

        """

        tmp = etree.SubElement(parent, util.nspath('PropertyIsLike', namespaces['ogc']))
        tmp.set('wildCard', wildcard)
        tmp.set('singleChar', singlechar)
        tmp.set('escapeChar', escapechar)
        etree.SubElement(tmp, util.nspath('PropertyName', namespaces['ogc'])).text = propertyname
        etree.SubElement(tmp, util.nspath('Literal', namespaces['ogc'])).text = literal

    def setsortby(self, parent, propertyname, order='ASC'):
        """

        constructs a SortBy element

        Parameters
        ----------

        - parent: parent etree.Element object
        - propertyname: the PropertyName
        - order: the SortOrder (default is 'ASC')

        """

        tmp = etree.SubElement(parent, util.nspath('SortBy', namespaces['ogc']))
        tmp2 = etree.SubElement(tmp, util.nspath('SortProperty', namespaces['ogc']))
        etree.SubElement(tmp2, util.nspath('PropertyName', namespaces['ogc'])).text = propertyname
        etree.SubElement(tmp2, util.nspath('SortOrder', namespaces['ogc'])).text = order

class FilterCapabilities(object):
    """ Abstraction for Filter_Capabilities """
    def __init__(self, elem):
        # Spatial_Capabilities
        self.spatial_operands = [f.text for f in elem.findall(util.nspath('Spatial_Capabilities/GeometryOperands/GeometryOperand', namespaces['ogc']))]
        self.spatial_operators = []
        for f in elem.findall(util.nspath('Spatial_Capabilities/SpatialOperators/SpatialOperator', namespaces['ogc'])):
            self.spatial_operators.append(f.attrib['name'])

        # Temporal_Capabilities
        self.temporal_operands = [f.text for f in elem.findall(util.nspath('Temporal_Capabilities/TemporalOperands/TemporalOperand', namespaces['ogc']))]
        self.temporal_operators = []
        for f in elem.findall(util.nspath('Temporal_Capabilities/TemporalOperators/TemporalOperator', namespaces['ogc'])):
            self.temporal_operators.append(f.attrib['name'])

        # Scalar_Capabilities
        self.scalar_comparison_operators = [f.text for f in elem.findall(util.nspath('Scalar_Capabilities/ComparisonOperators/ComparisonOperator', namespaces['ogc']))]


import logging
from contextlib import contextmanager
from datetime import datetime
from typing import ContextManager, List, Optional, Tuple

import discord
from discord.ext import commands
# noinspection PyProtectedMember
from sqlalchemy.engine import Engine
from sqlalchemy.orm import Session, sessionmaker

from bot import constants, helpers
from bot.models import Guild, Period, Submission

logger = logging.getLogger(__file__)
logger.setLevel(constants.LOGGING_LEVEL)

class ContestBot(commands.Bot):
    def __init__(self, engine: Engine, **options):
        super().__init__(self.fetch_prefix, **options)

        self.engine = engine
        self.Session = sessionmaker(bind=engine)

        self.expected_msg_deletions: List[int] = []
        self.expected_react_deletions: List[Tuple[int, int]] = []

    @contextmanager
    def get_session(self, autocommit=True, autoclose=True, rollback=True) -> ContextManager[Session]:
        """Provides automatic commit and closing of Session with exception rollback."""
        session = self.Session()
        try:
            yield session
            if autocommit: session.commit()
        except Exception:
            if rollback: session.rollback()
            raise
        finally:
            if autoclose: session.close()

    async def fetch_prefix(self, bot: 'ContestBot', message: discord.Message):
        """Fetches the prefix used by the relevant guild."""
        user_id = bot.user.id
        base = [f'<@!{user_id}> ', f'<@{user_id}> ']

        if message.guild:
            with self.get_session() as session:
                guild: Guild = session.query(Guild).get(message.guild.id)
                base.append(guild.prefix)
        return base

    async def on_ready(self):
        """Communicate that the bot is online now."""
        logger.info('Bot is now ready and connected to Discord.')
        guild_count = len(self.guilds)
        logger.info(f'Connected as {self.user.name}#{self.user.discriminator} to {guild_count} guild{"s" if guild_count > 1 else ""}.')

        with self.get_session() as session:
            for guild in self.guilds:
                _guild: Guild = session.query(Guild).get(guild.id)
                if _guild is None:
                    logger.warning(
                            f'Guild {guild.name} ({guild.id}) was not inside database on ready. Bot was disconnected or did not add it properly...')
                    session.add(Guild(id=guild.id))

        # TODO: Scan all messages on start for current period and check for new periods/updated vote counts.

    async def on_guild_join(self, guild: discord.Guild) -> None:
        """Handles adding or reactivating a Guild in the database."""
        logger.info(f'Added to new guild: {guild.name} ({guild.id})')

        with self.get_session() as session:
            _guild: Guild = session.query(Guild).get(guild.id)
            if _guild is None:
                session.add(Guild(id=guild.id))
            else:
                # Guild has been seen before. Update last_joined and set as active again.
                _guild.active = True
                _guild.last_joined = datetime.utcnow()

    async def on_guild_remove(self, guild: discord.Guild) -> None:
        """Handles disabling the guild in the database, as well."""
        logger.info(f'Removed from guild: {guild.name} ({guild.id})')

        with self.get_session() as session:
            # Get the associated Guild and mark it as disabled.
            _guild: Guild = session.query(Guild).filter_by(active=True, id=guild.id).first()
            _guild.active = False

            # Shut down any current running Period objects if possible.
            period: Period = _guild.current_period
            if period is not None and period.active:
                period.deactivate()

    async def add_voting_reactions(self, channel: discord.TextChannel, submissions: Optional[List[Submission]] = None) -> None:
        """Adds reactions to all valid submissions in the given channel."""
        if submissions is None:
            with self.get_session() as session:
                period: Period = session.query(Guild).get(channel.guild.id).current_period
                if period is None:
                    logger.error('No valid submissions - current period is not set for the Guild this channel belongs to.')
                    return
                else:
                    submissions = period.submissions

        if len(submissions) == 0:
            logger.warning('Attempted to add voting reactions to submissions, but none were given or could be found.')
            return
        else:
            for submission in submissions:
                message: discord.Message = await channel.fetch_message(submission.id)
                await message.add_reaction(self.get_emoji(constants.Emoji.UPVOTE))

    def get_message(self, channel_id: int, message_id: int) -> discord.PartialMessage:
        """Get a PartialMessage object given raw integer IDs."""
        channel: discord.TextChannel = self.get_channel(channel_id)
        return channel.get_partial_message(message_id)

    async def fetch_message(self, channel_id: int, message_id: int) -> discord.Message:
        """Fetch a full Message object given raw integer IDs."""
        channel: discord.TextChannel = self.get_channel(channel_id)
        return await channel.fetch_message(message_id)

    @staticmethod
    async def reject(message: discord.Message, warning: str, delete_delay: int = 2, warning_duration: int = 5) -> None:
        """Send a warning message and delete the message, then the warning"""
        if delete_delay > 0: await message.delete(delay=delete_delay)
        await message.channel.send(embed=helpers.error_embed(message=warning), delete_after=warning_duration, reference=message)


import discord, os, random, sqlite3
from discord.ext import commands, tasks
from discord.ext.commands import when_mentioned_or
from discord import Intents
from data.secrets import secrets
intents = Intents.all()

def get_prefix(client,message):

    try:
        db = sqlite3.connect("data/prefixes.sqlite")
        cursor = db.cursor()
        cursor.execute(f"SELECT PREFIX FROM guild WHERE GuildID = {message.guild.id}")
        result = cursor.fetchone()

        prefix = result[0]

        return when_mentioned_or(prefix)(client, message)
    except:
        return "-"

client = commands.Bot(
    command_prefix=get_prefix,
    allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=True),
    intents=intents,
    case_sensitive=False,
)

client.remove_command('help')

@client.command(name="load")
async def load(ctx, extension):
    if ctx.author.id == 711444754080071714:
        try:
            client.load_extension(f'cogs.{extension.lower()}')
            await ctx.send(f"> <a:DC_verified2:749472983487217694> loaded {extension}!")
        except:
            await ctx.send(f"{extension} is either not loaded or is not there")
    else:
        await ctx.send("Are you donut?")

@client.command(name="unload")
async def unload(ctx, extension):
    if ctx.author.id == 711444754080071714:
        try:
            client.unload_extension(f'cogs.{extension.lower()}')
            await ctx.send(f"> <a:DC_verified2:749472983487217694> Unloaded {extension}!")
        except:
            await ctx.send(f"{extension} is either not loaded or is not there")
    else:
        await ctx.send("Are you donut?")

@client.command(name="reload")
async def reload(ctx):
    if ctx.author.id == 711444754080071714:
        for filename in os.listdir('./cogs'):
            if filename.endswith('.py'):
                client.unload_extension(f'cogs.{filename[:-3]}')
                client.load_extension(f'cogs.{filename[:-3]}')
                print(f"Loaded {filename[:-3]}")

        await ctx.send(f"> <a:DC_verified2:749472983487217694> Reloaded all!")
    else:
        await ctx.send("Are you donut?")

for filename in os.listdir('./cogs'):
    if filename.endswith('.py'):
        client.load_extension(f'cogs.{filename[:-3]}')
        print(f"Loaded {filename[:-3]}")

@client.event
async def on_ready():
    print(f"Logged in as {client.user}!")
    change_status.start()

status = ['Jamming out to music', 'With Beer 🍻 ', 'Watching Donuts Café!!: https://discord.gg/xV98GwE', 'Minecraft', "Donut's Cafe Security!"]

@tasks.loop(seconds=20)
async def change_status():
    await client.change_presence(activity=discord.Game(random.choice(status)))

@client.event
async def on_guild_join(guild):

    channel = await client.fetch_channel(789054704491429893)
    embed = discord.Embed(title="New Guild Join!", description=f"CubePy was added to {guild.name}, total guilds = {len(client.guilds)}")
    embed.set_thumbnail(url="https://media.discordapp.net/attachments/715556818939805717/789165095980499004/cubepygif.gif")
    await channel.send(embed=embed)

    for channel in guild.text_channels:
        if channel.permissions_for(guild.me).send_messages and channel.permissions_for(guild.me).embed_links:

            array = [1048575, 8137918, 16182940]
            value = random.choice(array)

            join_embed = discord.Embed(title="CubePy Info", description=f"Heya! 👋🏻 Thanks For adding me to your server! The default prefix is `-`, hope you enjoy using me!", color=value)
            join_embed.set_thumbnail(url="https://media.discordapp.net/attachments/715556818939805717/789165095980499004/cubepygif.gif")
            join_embed.add_field(name="Useful Links", value=f"[Invite Me](https://discord.com/api/oauth2/authorize?client_id=787559221880815636&permissions=8&scope=bot) | [Support Server](https://discord.gg/Rp2RJjBEHp)", inline=False)

            await channel.send(embed=join_embed)

            break

@client.event
async def on_guild_remove(guild):

    channel = await client.fetch_channel(789054704491429893)

    embed = discord.Embed(title="Guild Leave:", description=f"CubePy was removed from {guild.name}, total guilds = {len(client.guilds)}")
    embed.set_thumbnail(url="https://media.discordapp.net/attachments/715556818939805717/789165095980499004/cubepygif.gif")

    await channel.send(embed=embed)

@client.event
async def on_command_error(ctx, error):
    error = getattr(error, "original", error)

    # They Didn't run a valid command
    if isinstance(error, commands.errors.CommandNotFound):
        pass

    # They were an Idiot and thought could use that command ;-;
    elif isinstance(error, commands.errors.MissingPermissions):
        permissions = []
        for perm in error.missing_perms:
            permissions.append(f"`{perm}`")
        permissions = ", ".join(permissions)
        await ctx.send(
            f"> <:NO:801699177934618634> You are missing the {permissions} permission(s)!" # works
        )

    # CooooooooooooooooooooooooolDown
    elif isinstance(error, commands.errors.CommandOnCooldown):
        message = await ctx.send(
            f"> <:NO:801699177934618634> You Are on Cool down, Try again in \
{round(ctx.command.get_cooldown_retry_after(ctx))} seconds") # works

    elif isinstance(error, commands.errors.MissingRequiredArgument):
        await ctx.send(f"> <:NO:801699177934618634> {error.param.name} is a required argument :|") #  works

    elif isinstance(error, discord.ext.commands.errors.RoleNotFound):
        await ctx.send(f"> <:NO:801699177934618634> {error.argument} is not a valid role!") # works

    elif isinstance(error, discord.ext.commands.errors.MemberNotFound):
        await ctx.send(f"> <:NO:801699177934618634> {error.argument} is not a valid member!") # works

    elif isinstance(error, discord.ext.commands.errors.ChannelNotFound):
        await ctx.send(f"> <:NO:801699177934618634> {error.argument} is not a valid channel!") # works

    elif isinstance(error, discord.ext.commands.errors.BotMissingPermissions):
        await ctx.send("I dont seem to have the permissions required to do this action..") # works

    elif isinstance(error, discord.Forbidden): # works
        try:
        	await ctx.send("I dont seem to have the permissions required to do this action..")
        except:
            print(f"Some Duffer in the server {ctx.guild.name}, Forgot to give me send_messages Perms. ;-;")
    else:
        raise error

client.run(secrets['token'])


import requests
from bs4 import BeautifulSoup
from nltk.sentiment.vader import SentimentIntensityAnalyzer  # Import VADER
from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
CORS(app, resources={r"/search": {"origins": "http://localhost:3000"}}, methods=["POST"])

# Initialize the VADER sentiment analyzer (global variable)
sia = SentimentIntensityAnalyzer()

# Function to perform the search
def perform_search(keyword):
    try:
        # Construct the search URL with the user's keyword
        search_url = f'https://hn.algolia.com/?q={keyword}'
        print("Performing search with keyword:", keyword)
        print("Search URL:", search_url)  # Print the search URL
        response = requests.get(search_url)
        if response.status_code == 200:
            print("Request successful. Parsing HTML... Status Code:", response.status_code)
            # Pass the URL to analyze_brand_comments and capture the results
            search_results = analyze_brand_comments(search_url, keyword)
            if search_results:
                return search_results  # Return the results
        else:
            print(f'Failed to fetch search results. Status code: {response.status_code}')
            return None
    except Exception as e:
        print(f'Error: {e}')
        return None

# Function to scrape comments, analyze sentiment, and classify
def analyze_brand_comments(url, keyword=None):
    try:
        # Send an HTTP request to the target URL
        response = requests.get(url)

        # Check if the request was successful
        if response.status_code == 200:
            print("Request to", url, "successful. Parsing HTML...")

            # Parse the HTML content
            soup = BeautifulSoup(response.content, "html.parser")

            # Extract article titles from the specified class ("Story_title")
            article_titles = [a.text for a in soup.select(".Story_title span")]

            # Process and analyze comments from each article title
            results = []

            for article_title in article_titles:
                title_text = article_title

                # Check if the keyword is in the article title
                if keyword is not None and keyword.lower() in title_text.lower():
                    # Perform sentiment analysis on the article title using sia
                    sentiment_scores = sia.polarity_scores(title_text)

                    # Determine sentiment based on compound score
                    compound_score = sentiment_scores['compound']

                    if compound_score >= 0.05:
                        sentiment = "positive"
                    elif compound_score <= -0.05:
                        sentiment = "negative"
                    else:
                        sentiment = "neutral"

                    # Add the result to the list
                    results.append({"keyword": keyword, "article_title": title_text, "sentiment": sentiment})

            # Return the list of results
            return results

        # Return an empty list when no matching articles are found
        return []
    except Exception as e:
        print(f'Error in analyze_brand_comments: {e}')
        return None

@app.route('/search', methods=['POST'])
def search_endpoint():
    data = request.get_json()
    keyword = data.get('keyword', '')

    print(f"Performing search for keyword: {keyword}")

    # Call the perform_search function to perform the search
    search_results = perform_search(keyword)

    if search_results:
        print("Search successful.")
        return jsonify(search_results)
    else:
        print("Search failed.")
        return jsonify([])

if __name__ == '__main__':
    app.run(debug=True)