from typing import cast

from .kotlin_entities import (
    KotlinEntity,
    KotlinProperty,
    KotlinEntityEnumeration,
    PARSING_ERRORS_PROP_NAME,
    ENTITY_STATIC_CREATOR
)
from ..base import Generator
from ... import utils
from ...config import GenerationMode, GeneratedLanguage, TEMPLATE_SUFFIX
from ...schema.modeling.entities import (
    StringEnumeration,
    EntityEnumeration,
    Entity,
    Object,
    ObjectFormat,
)
from ...schema.modeling.text import Text, EMPTY

class KotlinGenerator(Generator):
    def __init__(self, config):
        super(KotlinGenerator, self).__init__(config)
        self.kotlin_annotations = config.generation.kotlin_annotations
        self._error_collectors = config.generation.errors_collectors
        self._generate_equality = config.generation.generate_equality
        self.generate_serialization = config.generation.generate_serialization

    def filename(self, name: str) -> str:
        return f'{utils.capitalize_camel_case(name)}.kt'

    def _entity_declaration(self, entity: Entity) -> Text:
        entity: KotlinEntity = cast(KotlinEntity, entity)
        entity.__class__ = KotlinEntity
        entity.eval_errors_collector_enabled(self._error_collectors)
        entity.update_bases()

        if entity.generate_as_protocol:
            return self.__declaration_as_interface(entity)
        result: Text = self.__main_declaration_header(entity)

        is_template = entity.generation_mode.is_template

        if is_template:
            result += EMPTY
            result += '    constructor ('
            result += '        env: ParsingEnvironment,'
            result += f'        parent: {utils.capitalize_camel_case(entity.name)}? = null,'
            result += '        topLevel: Boolean = false,'
            result += '        json: JSONObject'
            result += '    ) {'
            result += '        val logger = env.logger'
            constructor = entity.constructor_body(with_commas=False).indented(indent_width=8)
            if constructor.lines:
                result += constructor
            result += '    }'
            result += EMPTY
            result += entity.value_resolving_declaration.indented(indent_width=4)

        if self.generate_serialization:
            result += EMPTY
            result += entity.serialization_declaration.indented(indent_width=4)

        if not is_template and self._generate_equality and not entity.instance_properties:
            result += EMPTY
            result += self.__manual_equals_hash_code_declaration.indented(indent_width=4)

        if not is_template:
            patch = entity.copy_with_new_array_declaration
            if patch:
                result += patch

        static_declarations = entity.static_declarations(self.generate_serialization)
        if static_declarations.lines:
            result += EMPTY
            result += '    companion object {'
            result += static_declarations.indented(indent_width=8)
            result += '    }'
            result += EMPTY

        if entity.inner_types:
            for inner_type in filter(lambda t: not isinstance(t, StringEnumeration) or not is_template,
                                     entity.inner_types):
                result += EMPTY
                result += self._main_declaration(inner_type).indented(indent_width=4)

        result += '}'

        return result

    @staticmethod
    def __declaration_as_interface(entity: KotlinEntity) -> Text:
        result = Text(f'interface {utils.capitalize_camel_case(entity.name)} {{')
        for prop in entity.instance_properties_kotlin:
            result += prop.declaration(overridden=False,
                                       in_interface=True,
                                       with_comma=False,
                                       with_default=False).indented(indent_width=4)
        result += '}'
        return result

    def __main_declaration_header(self, entity: KotlinEntity) -> Text:
        result = Text()
        for annotation in self.kotlin_annotations.classes:
            result += annotation
        data_prefix = 'data '
        if entity.generation_mode.is_template or not self._generate_equality or not entity.instance_properties:
            data_prefix = ''
        prefix = f'{data_prefix}class {utils.capitalize_camel_case(entity.name)}'

        interfaces = ['JSONSerializable'] if self.generate_serialization else []
        protocol_plus_super_entities = entity.protocol_plus_super_entities()
        if protocol_plus_super_entities is not None:
            interfaces.append(protocol_plus_super_entities)
        interfaces = ', '.join(interfaces)
        suffix = f' : {interfaces}' if interfaces else ''
        suffix += ' {'

        def add_instance_properties(text: Text, is_template: bool) -> Text:
            mixed_properties = entity.instance_properties_kotlin
            if entity.errors_collector_enabled:
                mixed_properties.append(KotlinProperty(
                    name=PARSING_ERRORS_PROP_NAME,
                    description='',
                    description_translations={},
                    dict_field='',
                    property_type=Object(name='List<Exception>', object=None, format=ObjectFormat.DEFAULT),
                    optional=True,
                    is_deprecated=False,
                    mode=GenerationMode.NORMAL_WITHOUT_TEMPLATES,
                    supports_expressions_flag=False,
                    default_value=None,
                    platforms=None
                ))
            for prop in mixed_properties:
                overridden = False
                if entity.implemented_protocol is not None:
                    overridden = any(p.name == prop.name for p in entity.implemented_protocol.properties)
                text += prop.declaration(
                    overridden=overridden,
                    in_interface=False,
                    with_comma=not is_template,
                    with_default=not is_template
                ).indented(indent_width=4)
            return text

        if entity.generation_mode.is_template:
            result += prefix + suffix
            if entity.instance_properties:
                result = add_instance_properties(text=result, is_template=True)
        else:
            constructor_prefix = ''
            if self.kotlin_annotations.constructors:
                constructor_annotations = ', '.join(self.kotlin_annotations.constructors)
                constructor_prefix = f' {constructor_annotations} constructor '
            if not entity.instance_properties:
                result += f'{prefix}{constructor_prefix}(){suffix}'
            else:
                result += f'{prefix}{constructor_prefix}('
                result = add_instance_properties(text=result, is_template=False)
                result += f'){suffix}'

        return result

    @property
    def __manual_equals_hash_code_declaration(self) -> Text:
        result = Text('override fun equals(other: Any?) = javaClass == other?.javaClass')
        result += EMPTY
        result += 'override fun hashCode() = javaClass.hashCode()'
        return result

    def _entity_enumeration_declaration(self, entity_enumeration: EntityEnumeration) -> Text:
        entity_enumeration: KotlinEntityEnumeration = cast(KotlinEntityEnumeration, entity_enumeration)
        entity_enumeration.__class__ = KotlinEntityEnumeration
        declaration_name = utils.capitalize_camel_case(entity_enumeration.name)
        entity_declarations = list(map(utils.capitalize_camel_case, entity_enumeration.entity_names))
        default_entity_decl = utils.capitalize_camel_case(str(entity_enumeration.default_entity_declaration))
        result = Text()
        for annotation in self.kotlin_annotations.classes:
            result += annotation
        interfaces = ['JSONSerializable'] if self.generate_serialization else []
        interfaces.append(entity_enumeration.mode.protocol_name(
            lang=GeneratedLanguage.KOTLIN,
            name=entity_enumeration.resolved_prefixed_declaration))
        interfaces = ', '.join(filter(None, interfaces))

        suffix = f' : {interfaces}' if interfaces else ''
        suffix += ' {'

        result += f'sealed class {declaration_name}{suffix}'
        for decl in entity_declarations:
            naming = entity_enumeration.format_case_naming(decl)
            decl = f'class {naming}(val value: {decl}) : {declaration_name}()'
            result += Text(indent_width=4, init_lines=decl)
        result += EMPTY

        result += f'    fun value(): {entity_enumeration.common_interface(GeneratedLanguage.KOTLIN) or "Any"} {{'
        result += '        return when (this) {'
        for decl in entity_declarations:
            naming = entity_enumeration.format_case_naming(decl)
            decl = f'is {naming} -> value'
            result += Text(indent_width=12, init_lines=decl)
        result += '        }'
        result += '    }'
        result += EMPTY

        if self.generate_serialization:
            result += '    override fun writeToJSON(): JSONObject {'
            result += '        return when (this) {'
            for decl in entity_declarations:
                naming = entity_enumeration.format_case_naming(decl)
                decl = f'is {naming} -> value.writeToJSON()'
                result += Text(indent_width=12, init_lines=decl)
            result += '        }'
            result += '    }'
            result += EMPTY

        if entity_enumeration.mode.is_template:
            self_name = entity_enumeration.resolved_prefixed_declaration

            result += f'    override fun resolve(env: ParsingEnvironment, data: JSONObject): {self_name} {{'
            result += '        return when (this) {'
            for decl in entity_declarations:
                case_name = entity_enumeration.format_case_naming(decl)
                line = f'is {case_name} -> {self_name}.{case_name}(value.resolve(env, data))'
                result += Text(indent_width=12, init_lines=line)
            result += '        }'
            result += '    }'
            result += EMPTY

            result += '    val type: String'
            result += '        get() {'
            result += '            return when (this) {'
            for decl in entity_declarations:
                naming = entity_enumeration.format_case_naming(decl)
                line = f'is {naming} -> {decl}.TYPE'
                result += Text(indent_width=16, init_lines=line)
            result += '            }'
            result += '        }'
            result += EMPTY
        elif self._generate_equality:
            result += '    override fun equals(other: Any?): Boolean {'
            result += '        if (this === other) { return true }'
            result += f'        if (other is {declaration_name}) {{'
            result += '            return value().equals(other.value())'
            result += '        }'
            result += '        return false'
            result += '    }'
            result += EMPTY

        if not self.generate_serialization:
            result += '}'
            return result

        result += '    companion object {'
        result += '        @Throws(ParsingException::class)'

        source_name = 'json'
        source_type = 'JSONObject'
        read_type_expr = 'json.read("type", logger = logger, env = env)'
        read_type_opt_expr = 'json.readOptional("type", logger = logger, env = env)'
        throwing_expr = 'throw typeMismatch(json = json, key = "type", value = type)'

        if entity_enumeration.mode.is_template:
            def deserialization_args(s):
                return f'env, parent?.value() as {s}?, topLevel, {source_name}'
            result += '        operator fun invoke('
            result += '            env: ParsingEnvironment,'
            result += '            topLevel: Boolean = false,'
            result += f'            {source_name}: {source_type}'
            result += f'        ): {declaration_name} {{'
            result += '            val logger = env.logger'
            if default_entity_decl:
                result += f'            val receivedType: String = {read_type_opt_expr} ?: {default_entity_decl}Template.TYPE'
            else:
                result += f'            val receivedType: String = {read_type_expr}'
            result += f'            val parent = env.templates[receivedType] as? {declaration_name}'
            result += '            val type = parent?.type ?: receivedType'
        else:
            def deserialization_args(s):
                return f'env, {source_name}'
            result += '        @JvmStatic'
            result += '        @JvmName("fromJson")'
            args = f'env: ParsingEnvironment, {source_name}: {source_type}'
            result += f'        operator fun invoke({args}): {declaration_name} {{'
            result += '            val logger = env.logger'
            if default_entity_decl:
                result += f'            val type: String = {read_type_opt_expr} ?: {default_entity_decl}.TYPE'
            else:
                result += f'            val type: String = {read_type_expr}'
        result += '            when (type) {'
        for decl in entity_declarations:
            naming = entity_enumeration.format_case_naming(decl)
            line = f'{decl}.TYPE -> return {naming}({decl}({deserialization_args(decl)}))'
            result += Text(indent_width=16, init_lines=line)

        if entity_enumeration.mode is GenerationMode.NORMAL_WITH_TEMPLATES:
            result += '            }'
            name = utils.capitalize_camel_case(entity_enumeration.name + TEMPLATE_SUFFIX)
            template_type = entity_enumeration.template_declaration_prefix + name
            result += f'            val template = env.templates.getOrThrow(type, json) as? {template_type}'
            result += '            if (template != null) {'
            result += f'                return template.resolve(env, {source_name})'
            result += '            } else {'
            result += f'                {throwing_expr}'
            result += '            }'
        else:
            result += f'                else -> {throwing_expr}'
            result += '            }'
        result += '        }'

        static_creator_lambda = f'env: ParsingEnvironment, it: JSONObject -> {declaration_name}(env, json = it)'
        result += f'        val {ENTITY_STATIC_CREATOR} = {{ {static_creator_lambda} }}'
        result += '    }'
        result += '}'
        return result

    def _string_enumeration_declaration(self, string_enumeration: StringEnumeration) -> Text:
        declaration_name = utils.capitalize_camel_case(string_enumeration.name)
        cases_declarations = list(map(lambda s: Text(indent_width=16, init_lines=f'{s}.value -> {s}'),
                                      map(lambda s: utils.fixing_first_digit(utils.constant_upper_case(s[0])),
                                          string_enumeration.cases)))
        result = Text(f'enum class {declaration_name}(private val value: String) {{')
        for ind, case in enumerate(string_enumeration.cases):
            terminal = ',' if ind != (len(cases_declarations) - 1) else ';'
            name = utils.fixing_first_digit(utils.constant_upper_case(case[0]))
            value = case[1]
            result += Text(indent_width=4, init_lines=f'{name}("{value}"){terminal}')
        result += EMPTY

        result += '    companion object Converter {'
        result += f'        fun toString(obj: {declaration_name}): String {{'
        result += '            return obj.value'
        result += '        }'
        result += EMPTY

        result += f'        fun fromString(string: String): {declaration_name}? {{'
        result += '            return when (string) {'
        result += cases_declarations
        result += '                else -> null'
        result += '            }'
        result += '        }'
        result += EMPTY

        result += '        val FROM_STRING = { string: String ->'
        result += '            when (string) {'
        result += cases_declarations
        result += '                else -> null'
        result += '            }'
        result += '        }'
        result += '    }'
        result += '}'

        return result


obj=open("Demo.txt","w+")
obj.write("Hello World")
obj.seek(3) #Move to 4th Byte
print(obj.tell()) #Gives the byte number(in terms of index
print(obj.read())
obj.seek(2,0)#Move 2 bytes further from beginning(0[First character at 0]+2=2)
print(obj.read())
obj.close()
obj=open("Demo.txt","rb")
obj.seek(1)
obj.seek(5,1)#Move 5 bytes further from current position[1[Currently at 2nd byte]+5=6]
print(obj.read().decode("utf-8"))
obj.seek(3)
obj.seek(-2,1)#Move 2 bytes back from current position
print(obj.read().decode("utf-8"))
obj.seek(-3,2) #Move 3 bytes backward[Reference position is from end]
print(obj.read().decode("utf-8"))


# Nicolas Gomollon, Lab 6

class Poly:

    def __init__(self,*terms):
        # __str__ uses the name self.terms for the dictionary of terms
        # So __init__ should build this dictionary from terms
        self.terms = {}
        for coeff, power in terms:
            assert type(coeff) in (int, float), "Poly.__init__: illegal coefficient in : {}".format((coeff, power))
            assert (type(power) is int) and (power >= 0), "Poly.__init__: illegal power in : {}".format((coeff, power))
            assert power not in self.terms, "Poly.__init__: power({}) can only be defined once".format(power)
            if coeff != 0: self.terms[power] = coeff

        # Fill in the rest of this method, using *terms to intialize self.terms

    # I have written str(...) because it is used in the bsc.txt file and
    #   it is a bit subtle to get correct. Notice that it assumes that
    #   every Poly object stores a dict whose keys are powers and whose
    #   associated values are coefficients. This function does not depend
    #   on any other method in this class being written correctly.
    def __str__(self):
        def term(c,p,var):
            return (str(c) if p == 0 or c != 1 else '') +\
                   ('' if p == 0 else var+('^'+str(p) if p != 1 else ''))
        if len(self.terms) == 0:
            return '0'
        else:
            return ' + '.join([term(c,p,'x') for p,c in sorted(self.terms.items(),reverse=True)]).replace('+ -','- ')

    def __repr__(self):
        return "Poly({})".format(', '.join((str((coeff, power)) for power, coeff in self.terms.items())))

    def __len__(self):
        if len(self.terms) == 0: return 0
        return max(self.terms)

    def __call__(self,arg):
        return sum([(coeff * (arg ** power)) for power, coeff in self.terms.items()])

    def __iter__(self):
        for power, coeff in sorted(self.terms.items(), reverse=True):
            yield (coeff, power)

    def __getitem__(self,index):
        if (type(index) is not int) or (index < 0):
            raise TypeError("Poly.__getitem__: illegal index : {}".format(index))
        if index not in self.terms:
            return 0
        return self.terms[index]

    def __setitem__(self,index,value):
        if (type(index) is not int) or (index < 0):
            raise TypeError("Poly.__setitem__: illegal index : {}".format(index))
        if (value != 0):
            self.terms[index] = value
        elif index in self.terms:
            self.terms.pop(index)
        return None

    def __delitem__(self,index):
        if (type(index) is not int) or (index < 0):
            raise TypeError("Poly.__delitem__: illegal index : {}".format(index))
        if index in self.terms:
            self.terms.pop(index)
        return None

    def _add_term(self,c,p):
        if type(c) not in (int, float):
            raise TypeError("Poly._add_term: illegal coefficient in : {}".format((c, p)))
        if (type(p) is not int) or (p < 0):
            raise TypeError("Poly._add_term: illegal power in : {}".format((c, p)))
        if (c != 0) and (p not in self.terms):
            self[p] = c
        elif (p in self.terms):
            self[p] += c
        return None

    def __add__(self,right):
        if type(right) is Poly:
            new_terms = dict(self.terms)
            for power, coeff in right.terms.items():
                if power in new_terms:
                    if (new_terms[power] + coeff) != 0:
                        new_terms[power] += coeff
                    else:
                        new_terms.pop(power)
                else:
                    new_terms[power] = coeff
            return Poly(*[(coeff, power) for power, coeff in new_terms.items()])
        elif type(right) in (int, float):
            new_terms = [(coeff, power) for power, coeff in self.terms.items() if power > 0]
            new_terms += [(self[0] + right, 0)]
            return Poly(*new_terms)
        raise TypeError("Poly.__add__: illegal operand : {}".format(right))

    def __radd__(self,left):
        return self.__add__(left)

    def __mul__(self,right):
        if type(right) is Poly:
            new_terms = {}
            for p1, c1 in self.terms.items():
                for p2, c2 in right.terms.items():
                    new_p = p1 + p2
                    new_c = c1 * c2
                    if new_p in new_terms:
                        new_terms[new_p] += new_c
                    else:
                        new_terms[new_p] = new_c
            return Poly(*[(coeff, power) for power, coeff in new_terms.items()])
        elif type(right) in (int, float):
            new_terms = dict(self.terms)
            for power, coeff in new_terms.items():
                new_terms[power] *= right
            return Poly(*[(coeff, power) for power, coeff in new_terms.items()])
        raise TypeError("Poly.__mul__: illegal operand : {}".format(right))

    def __rmul__(self,left):
        return self.__mul__(left)

    def __eq__(self,right):
        if type(right) is Poly:
            return self.terms == right.terms
        elif type(right) in (int, float):
            if (len(self.terms) == 1) and (len(self) == 0):
                return self.terms[0] == right
            return False
        raise TypeError("Poly.__eq__: illegal operand : {}".format(right))

if __name__ == '__main__':
    # Some simple tests; you can comment them out and/or add your own before
    # the driver is called.
    print('Start simple tests')
    p = Poly((3,2),(-2,1), (4,0))
    print('  For Polynomial: 3x^2 - 2x + 4')
    print('  str(p):',p)
    print('  repr(p):',repr(p))
    print('  len(p):',len(p))
    print('  p(2):',p(2))
    print('  list collecting iterator results:',[t for t in p])
    print('  p+p:',p+p)
    print('  p+2:',p+2)
    print('  p*p:',p*p)
    print('  p*2:',p*2)
    print('End simple tests\n')

    import driver
    #driver.default_show_exception=True
    #driver.default_show_exception_message=True
    #driver.default_show_traceback=True
    driver.driver()

ics 33/solutions/ile2 solutions/Lab 6/GomollonNicolas/poly.py


import datetime
import pandas as pd
from tqdm import tqdm
from emailer import Emailer
from shipping import Shipping
from shipstation import Shipstation

def main():

    # Instantiate objects to be used throughout the script
    shipstation = Shipstation()
    shipping = Shipping()

    # Get all shipment information from ShipStation
    print("\nGetting shipments...", end="")
    all_shipments = shipstation.get_shipments()
    print("done!\n")

    # Filter shipments for only those that were delivered, per ShipStation
    print("\nFiltering for delivered shipments...", end="")
    delivered_shipments = [
        shipment for shipment in all_shipments if shipment["confirmation"] == "delivery"
    ]
    print("done!\n")

    # Filter delivered shipments created in the last week for those with orders created in the last week
    print("\nFiltering for orders within the last week...", end="")
    good_shipments = []
    for shipment in tqdm(delivered_shipments, position=0, leave=True):

        order_response = shipstation.get_order(shipment["orderId"])
        order_date = datetime.datetime.strptime(
            order_response["orderDate"], "%Y-%m-%dT%H:%M:%S.%f0"
        )

        if order_date > datetime.datetime.now() - datetime.timedelta(days=8):
            if len(order_response["items"]) == 1:
                good_shipments.append((shipment, order_response))
    print("done!\n")

    # Get tracking info from USPS and UPS
    print("\nGetting tracking info...", end="")
    usps_info = {}
    usps_tracking_numbers = [
        s[0]["trackingNumber"] for s in good_shipments if "usps" in s[0]["serviceCode"]
    ]
    for tracking_number in usps_tracking_numbers:
        usps_info[tracking_number] = shipping.get_ups_tracking(tracking_number)

    ups_info = {}
    ups_tracking_numbers = [
        s[0]["trackingNumber"] for s in good_shipments if "ups" in s[0]["serviceCode"]
    ]
    for tracking_number in ups_tracking_numbers:
        ups_info[tracking_number] = shipping.get_ups_tracking(tracking_number)

    # Combine tracking info into one dictionary
    tracking_info = {**ups_info, **usps_info}

    print("done!\n")

    # Filter shipments for those that were confirmed as delivered during the previous business day by USPS or UPS
    print("\nFiltering for deliveries confirmed by the carrier...", end="")
    actually_delivered = [
        s
        for s in good_shipments
        if tracking_info.get(s[0]["trackingNumber"], [0, False])[1]
        and datetime.datetime.strptime(
            tracking_info.get(s[0]["trackingNumber"], ["2023-01-01 00:00", False])[0],
            "%Y-%m-%d %H:%M",
        ).date()
        == (datetime.datetime.now() - datetime.timedelta(days=3)).date()
    ]
    print("done!\n")

    # Create pandas DataFrame for data to be exported
    print("\nSending to CSV...", end="")
    filename = "shipstation_delivered.csv"
    values = []

    for i in range(len(actually_delivered)):
        shipment_id = actually_delivered[i][0]["shipmentId"]
        order_id = actually_delivered[i][0]["orderId"]
        email = actually_delivered[i][0]["customerEmail"]
        ship_date = actually_delivered[i][0]["shipDate"]

        order_date = actually_delivered[i][1]["createDate"]
        bill_to = actually_delivered[i][1]["billTo"]
        ship_to = actually_delivered[i][1]["shipTo"]
        item = actually_delivered[i][1]["items"][0]["sku"]
        quantity = actually_delivered[i][1]["items"][0]["quantity"]
        tracking_number = actually_delivered[i][0]["trackingNumber"]

        values.append(
            (
                shipment_id,
                order_id,
                email,
                ship_date,
                order_date,
                bill_to,
                ship_to,
                item,
                quantity,
                tracking_number,
            )
        )

    df = pd.DataFrame(
        values,
        columns=[
            "shipmentId",
            "orderId",
            "customerEmail",
            "shipDate",
            "orderDate",
            "billTo",
            "shipTo",
            "sku",
            "quantity",
            "trackingNumber",
        ],
    )
    df["deliveryDate"] = df["trackingNumber"].map(
        {k: v[0] for k, v in usps_info.items()}
    )
    df["deliveryDate"] = pd.to_datetime(df["deliveryDate"])
    df.to_csv(filename, index=False)
    print("done!\n")

    # Sending email to relevant parties
    emailer = Emailer(to_address="matt@jmac.com")
    print("\nSending email...", end="")
    subject = "ShipStation Daily Report"
    body = f"""
           Attached are the {len(df)} cherry-picked orders/shipments that were delivered during the
           previous business day.
           """
    emailer.send_email(subject, body, filename)
    print("done!\n")

if __name__ == "__main__":
    main()


from dsa_stack import DSAStack

import sys
from typing import Union

class TowersOfHanoi:
    def __init__(self, num_pegs: int, num_disks: int) -> None:
        self.num_pegs = num_pegs
        self.num_disks = num_disks
        self.pegs = [
            DSAStack(num_disks),
            DSAStack(num_disks),
            DSAStack(num_disks),
        ]

    def place_disk(self, peg: int, disk: int) -> None:
        peg = self.pegs[peg]
        if peg.is_empty() or disk < peg.top():
            peg.push(disk)
        else:
            raise ValueError(
                "Disk of size {} cannot be placed on disk of size {}.".format(disk, peg.top()))

    def remove_disk(self, peg: int) -> int:
        peg = self.pegs[peg]
        return peg.pop()

    def move_disk(self, src: int, dst: int) -> None:
        self.place_disk(dst, self.remove_disk(src))

    # Gets the disk at the given peg and index from bottom, or None if none
    # exists.
    def disk_at(self, peg: int, i: int) -> Union[int, None]:
        p = self.pegs[peg].as_list()
        if i < len(p):
            d = p[-1 - i]
        else:
            d = None
        return d

# Moves n disks from peg src to peg dst (1-indexed).
def solve(n: int, src: int, dst: int) -> None:
    src -= 1
    dst -= 1

    towers = TowersOfHanoi(3, n)

    for i in range(n, 0, -1):
        towers.place_disk(src, i)

    step = 0
    display_progress(towers, step)

    solve_impl(towers, n, src, dst, step)

# Moves n disks from peg src to peg dst (0-indexed).
# Returns the new step count.
def solve_impl(towers: TowersOfHanoi, n: int, src: int, dst: int, step: int) -> int:
    if n <= 0:
        raise AssertionError("n must be > 0.")
    elif n == 1:
        towers.move_disk(src, dst)
        step += 1
        display_progress(towers, step)
    else:
        other = 3 - src - dst
        step = solve_impl(towers, n - 1, src, other, step)
        towers.move_disk(src, dst)
        step += 1
        display_progress(towers, step)
        step = solve_impl(towers, n - 1, other, dst, step)
    return step

def display_progress(towers: TowersOfHanoi, step: int) -> None:
    header = "Step {}:".format(step)
    indent = " " * (len(header) + 2)
    disk_width = len(str(towers.num_disks))
    print(header)
    for i in range(towers.num_disks - 1, -1, -1):
        print(indent, end="")
        for j in range(towers.num_pegs):
            disk = towers.disk_at(j, i)
            if disk is None:
                s = "|"
            else:
                s = str(disk)
            # Padding for when disk could be multiple columns wide.
            s = " " * (disk_width - len(s)) + s
            print(s + " ", end="")
        print()
    print()

if len(sys.argv) != 4:
    print("Usage: python {} num_disks src_peg dst_peg".format(sys.argv[0]))
else:
    try:
        num_disks = int(sys.argv[1])
        src = int(sys.argv[2])
        dst = int(sys.argv[3])
    except ValueError:
        print("Parameters must be integers.")
    else:
        if num_disks < 1:
            print("num_disks must be > 0.")
        # Currently needs 8 extra stack frames to run, will require adjustment
        # if implementation changes.
        elif sys.getrecursionlimit() < num_disks + 8:
            print("Solving with num_disks={} would exceed max call stack depth."
                .format(num_disks))
        elif not 0 < src <= 3:
            print("src_peg must be > 0 and <= 3.")
        elif not 0 < dst <= 3:
            print("dst_peg must be > 0 and <= 3.")
        else:
            print("Solving Towers of Hanoi with {} pegs and {} disks, starting from peg {} and ending at peg {}."
                .format(3, num_disks, src, dst))
            print("Number of moves required: {}.".format(2 ** num_disks - 1))
            print()
            solve(num_disks, src, dst)


# Face detection is done using classifier
# classifier is an algorithm that decides wherether a face is present or not
# classifier need to be trained images thousands of with and without the faces.
# Opencv have pretrained classifier called haarcascade, localbinary pattern.
import cv2 as cv

img = cv.imread('Images/group.jpg')
cv.imshow('group', img)

# firstly we covert an image into grayscale because face detection does not involve any colors
# haarcascade looks at object in an image and using edges find the faces in an image
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow('GrayScale', gray)

# Now Reading into haarcascade file
haar_cascade = cv.CascadeClassifier('haar_face.xml')

# Detection of Face
face_rect = haar_cascade.detectMultiScale(gray, 1.1, minNeighbors=3) # detects a face and returns list of the rectangle coordinates of each faces
print(f'No. of faces detected : {len(face_rect)}')
# print(face_rect)

for (x,y,w,h) in face_rect:
    cv.rectangle(img, (x,y), (x+w,y+h), (0,0,255), thickness=2)

# so for the group of people haarcascade is more sensitiveto noise which will end up with more no. of faces than the actual no. of faces
# less minNeighbour value leads to more face and vise versa
cv.imshow('Detected_Faces', img)
cv.waitKey(0)


# Import all necessary libraries
from distutils.cmd import Command
import tkinter as tk
from tkinter import ttk
from tkinter import *
from tkinter import font as tkFont
import math

# Initialize tkinter and set the display
root = tk.Tk()
root.configure(bg = "green")
root.title("Calculator MIN 3000")
root.geometry("294x389")
root.resizable(False, False)
options = {"padx": 1, "pady": 1}
relation = ""

#Function to update entered number and syntax in entry box
def button_click(num):
    """This function collects all the selected characters and displays them"""
    global relation
    relation = relation + str(num)
    equation.set(relation)

#Function to evaluate the final expresion
def click_equal():
    """This function evaluates the expression when equal is selected"""
    try:
        global relation
        total = str(eval(relation))
        equation.set(total)
        relation = ""

    except:
        equation.set("error")
        relation = ""

#Function to clear and delete the contents of text entry box
def delete():
    """This function deletes contents of text entry box"""
    global relation
    relation = ""
    equation.set("")

# Define variables and constants
equation = StringVar()
helv36 = tkFont.Font(family='Helvetica', size=20, weight=tkFont.BOLD)
sqrt = math.sqrt
prct = 1/100

# Configuration of the display and buttons
result_display = ttk.Entry(
    root,
    textvariable = equation ,
    width=19,
    font=helv36
    ).grid(
        column=0,
        row=0,
        columnspan=4,
        **options
        )

button_percent = Button(
    root,
    text="%",
    width=3,
    font=helv36,
    bg="#ADD8E6",
    command= lambda: button_click("prct")
    ).grid(
        column=0,
        row=1,
        sticky="nsew",
        **options
        )

button_left_parenthesis = Button(
    root,
    text="(",
    width=3,
    command=lambda: button_click("("),
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=1,
        row=1,
        sticky="nsew",
        **options
        )

button_right_parenthesis = Button(
    root,
    text=")",
    width=3,
    command=lambda: button_click(")"),
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=2,
        row=1,
        sticky="nsew",
        **options
        )

button_del = Button(
    root,
    text="DEL",
    width=3,
    font=helv36,
    command = delete,
    bg="#ADD8E6",
    fg="red"
    ).grid(
        column=3,
        row=1,
        sticky="nsew",
        **options
        )

button_square = Button(
    root,
    text="x^2",
    width=3,
    command=lambda: button_click("**2"),
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=0,
        row=2,
        sticky="nsew",
        **options
        )

button_sqrt = Button(
    root,
    text="√",
    width=3,
    font=helv36,
    bg="#ADD8E6",
    command=lambda: button_click("sqrt")
    ).grid(
        column=1,
        row=2,
        sticky="nsew",
        **options
        )

button_1_devide_x = Button(
    root,
    text="1⁄x",
    width=3,
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=2,
        row=2,
        sticky="nsew",
        **options
        )

button_multiply = Button(
    root,
    text="×",
    width=3,
    command= lambda: button_click("*"),
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=3,
        row=2,
        sticky="nsew",
        **options
        )

button_7 = Button(
    root,
    text="7",
    width=3,
    command=lambda: button_click(7),
    font=helv36
    ).grid(
        column=0,
        row=3,
        sticky="nsew",
        **options
        )

button_8 = Button(
    root,
    text="8",
    width=3,
    command=lambda: button_click(8),
    font=helv36
    ).grid(
        column=1,
        row=3,
        sticky="nsew",
        **options
        )

button_9 = Button(
    root,
    text="9",
    width=3,
    command=lambda: button_click(9),
    font=helv36
    ).grid(
        column=2,
        row=3,
        sticky="nsew",
        **options
        )

button_devide = Button(
    root,
    text="÷",
    width=3,
    command=lambda: button_click("/"),
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=3,
        row=3,
        sticky="nsew",
        **options
        )

button_4 = Button(
    root,
    text="4",
    width=3,
    command=lambda: button_click(4),
    font=helv36
    ).grid(
        column=0,
        row=4,
        sticky="nsew",
        **options
        )

button_5 = Button(
    root,
    text="5",
    width=3,
    command=lambda: button_click(5),
    font=helv36
    ).grid(
        column=1,
        row=4,
        sticky="nsew",
        **options
        )

button_6 = Button(
    root,
    text="6",
    width=3,
    command=lambda: button_click(6),
    font=helv36
    ).grid(
        column=2,
        row=4,
        sticky="nsew",
        **options
        )

button_subtract = Button(
    root,
    text="-",
    width=3,
    command=lambda: button_click("-"),
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=3,
        row=4,
        sticky="nsew",
        **options
        )

button_1 = Button(
    root,
    text="1",
    width=3,
    command=lambda: button_click(1),
    font=helv36
    ).grid(
        column=0,
        row=5,
        sticky="nsew",
        **options
        )

button_2 = Button(
    root,
    text="2",
    width=3,
    command=lambda: button_click(2),
    font=helv36
    ).grid(
        column=1,
        row=5,
        sticky="nsew",
        **options
        )

button_3 = Button(
    root,
    text="3",
    width=3,
    command=lambda: button_click(3),
    font=helv36
    ).grid(
        column=2,
        row=5,
        sticky="nsew",
        **options
        )

button_add = Button(
    root,
    text="+",
    width=3,
    command=lambda: button_click("+"),
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=3,
        row=5,
        sticky="nsew",
        **options
        )

button_0 = Button(
    root,
    text="0",
    width=6,
    command=lambda: button_click(0),
    font=helv36
    ).grid(
        column=0,
        row=6,
        columnspan=2,
        sticky="nsew",
        **options
        )

button_dot = Button(
    root,
    text="∙",
    width=3,
    command=lambda: button_click("."),
    font=helv36
    ).grid(
        column=2,
        row=6,
        sticky="nsew",
        **options
        )

button_equal = Button(
    root,
    text="=",
    width=3,
    command = click_equal,
    font=helv36,
    bg="#ADD8E6"
    ).grid(
        column=3,
        row=6,
        sticky="nsew",
        **options
        )

root.mainloop()


#breakout.py
#A. Colwell (2015)

# graphics2 module returns a TUPLE when using .getOverlap()
# The tuple will have two numbers, indicating which objects
# have overlapped. Only useful if you know the corresponding
# object. In this case, the first brick (brick1) is the first
# object drawn in the window, and therefore the object 1.
# All the bricks are drawn first, so their numbers are 1-36
# Paddle is number 37
# Ball is number 38

# Submitting this document will give you 50% plus:
# 10% if you can add 10 points for every brick hit   Yes
# 10% display points in the window                   Yes
# 10% add 30 points for every brick in top row only  No
# 10% vary direction of ball movement (any angle)    No
# 10% reset and replay game after finished           Yes
Power = 'On'
while Power == 'On':
    Reset = 'y'
    from graphics2 import *
    from time import sleep

    while Reset == 'y':
        winx=600
        winy=400
        win = GraphWin('Brick Breaker',600,400)
        move={'Left':(-1,0),'Right':(1,0),'':(0,0)}
        speed = 4
        #--------------------Start Game-----------------------------
        Start = Text(Point(300,200),'Click anywhere to start the game')
        Start.draw(win)
        coord=win.getMouse()
        x=coord.getX()
        y=coord.getY()
        if x<600 and y<400:
            Start.undraw()
            Esc = Text(Point(500,10),'Press Esc key to close the game')
            Esc.setSize(10)
            Esc.draw(win)

                #--------------------Bricks-----------------------------

            brick1 = Rectangle(Point(0,40),Point(49,49))
            brick1.setFill('red')
            brick1.setOutline('lightgrey')
            brick1.draw(win)

            brick2 = Rectangle(Point(50,40),Point(99,49))
            brick2.setFill('blue')
            brick2.setOutline('lightgrey')
            brick2.draw(win)

            brick3 = Rectangle(Point(100,40),Point(149,49))
            brick3.setFill('yellow')
            brick3.setOutline('lightgrey')
            brick3.draw(win)

            brick4 = Rectangle(Point(150,40),Point(199,49))
            brick4.setFill('green')
            brick4.setOutline('lightgrey')
            brick4.draw(win)

            brick5 = Rectangle(Point(200,40),Point(249,49))
            brick5.setFill('purple')
            brick5.setOutline('lightgrey')
            brick5.draw(win)

            brick6 = Rectangle(Point(250,40),Point(299,49))
            brick6.setFill('red')
            brick6.setOutline('lightgrey')
            brick6.draw(win)

            brick7 = Rectangle(Point(300,40),Point(349,49))
            brick7.setFill('blue')
            brick7.setOutline('lightgrey')
            brick7.draw(win)

            brick8 = Rectangle(Point(350,40),Point(399,49))
            brick8.setFill('green')
            brick8.setOutline('lightgrey')
            brick8.draw(win)

            brick9 = Rectangle(Point(400,40),Point(449,49))
            brick9.setFill('yellow')
            brick9.setOutline('lightgrey')
            brick9.draw(win)

            brick10 = Rectangle(Point(450,40),Point(499,49))
            brick10.setFill('purple')
            brick10.setOutline('lightgrey')
            brick10.draw(win)

            brick11 = Rectangle(Point(500,40),Point(549,49))
            brick11.setFill('red')
            brick11.setOutline('lightgrey')
            brick11.draw(win)

            brick12 = Rectangle(Point(550,40),Point(599,49))
            brick12.setFill('blue')
            brick12.setOutline('lightgrey')
            brick12.draw(win)

            brick13 = Rectangle(Point(0,30),Point(49,39))
            brick13.setFill('green')
            brick13.setOutline('lightgrey')
            brick13.draw(win)

            brick14 = Rectangle(Point(50,30),Point(99,39))
            brick14.setFill('yellow')
            brick14.setOutline('lightgrey')
            brick14.draw(win)

            brick15 = Rectangle(Point(100,30),Point(149,39))
            brick15.setFill('purple')
            brick15.setOutline('lightgrey')
            brick15.draw(win)

            brick16 = Rectangle(Point(150,30),Point(199,39))
            brick16.setFill('red')
            brick16.setOutline('lightgrey')
            brick16.draw(win)

            brick17 = Rectangle(Point(200,30),Point(299,39))
            brick17.setFill('blue')
            brick17.setOutline('lightgrey')
            brick17.draw(win)

            brick18 = Rectangle(Point(250,30),Point(299,39))
            brick18.setFill('green')
            brick18.setOutline('lightgrey')
            brick18.draw(win)

            brick19 = Rectangle(Point(300,30),Point(349,39))
            brick19.setFill('yellow')
            brick19.setOutline('lightgrey')
            brick19.draw(win)

            brick20 = Rectangle(Point(350,30),Point(399,39))
            brick20.setFill('purple')
            brick20.setOutline('lightgrey')
            brick20.draw(win)

            brick21 = Rectangle(Point(400,30),Point(449,39))
            brick21.setFill('red')
            brick21.setOutline('lightgrey')
            brick21.draw(win)

            brick22 = Rectangle(Point(450,30),Point(499,39))
            brick22.setFill('blue')
            brick22.setOutline('lightgrey')
            brick22.draw(win)

            brick23 = Rectangle(Point(500,30),Point(549,39))
            brick23.setFill('green')
            brick23.setOutline('lightgrey')
            brick23.draw(win)

            brick24 = Rectangle(Point(550,30),Point(599,39))
            brick24.setFill('yellow')
            brick24.setOutline('lightgrey')
            brick24.draw(win)

            brick25 = Rectangle(Point(0,20),Point(49,29))
            brick25.setFill('purple')
            brick25.setOutline('lightgrey')
            brick25.draw(win)

            brick26 = Rectangle(Point(50,20),Point(99,29))
            brick26.setFill('red')
            brick26.setOutline('lightgrey')
            brick26.draw(win)

            brick27 = Rectangle(Point(100,20),Point(149,29))
            brick27.setFill('blue')
            brick27.setOutline('lightgrey')
            brick27.draw(win)

            brick28 = Rectangle(Point(150,20),Point(199,29))
            brick28.setFill('green')
            brick28.setOutline('lightgrey')
            brick28.draw(win)

            brick29 = Rectangle(Point(200,20),Point(249,29))
            brick29.setFill('yellow')
            brick29.setOutline('lightgrey')
            brick29.draw(win)

            brick30 = Rectangle(Point(250,20),Point(299,29))
            brick30.setFill('purple')
            brick30.setOutline('lightgrey')
            brick30.draw(win)

            brick31 = Rectangle(Point(300,20),Point(349,29))
            brick31.setFill('red')
            brick31.setOutline('lightgrey')
            brick31.draw(win)

            brick32 = Rectangle(Point(350,20),Point(399,29))
            brick32.setFill('blue')
            brick32.setOutline('lightgrey')
            brick32.draw(win)

            brick33 = Rectangle(Point(400,20),Point(449,29))
            brick33.setFill('green')
            brick33.setOutline('lightgrey')
            brick33.draw(win)

            brick34 = Rectangle(Point(450,20),Point(499,29))
            brick34.setFill('yellow')
            brick34.setOutline('lightgrey')
            brick34.draw(win)

            brick35 = Rectangle(Point(500,20),Point(549,29))
            brick35.setFill('purple')
            brick35.setOutline('lightgrey')
            brick35.draw(win)

            brick36 = Rectangle(Point(550,20),Point(599,29))
            brick36.setFill('red')
            brick36.setOutline('lightgrey')
            brick36.draw(win)

            #bricks 600/12=49 will be width of brick
            #bricks        9 will be height of brick
            #brickname will be based on 25-36  ************
            #                           13-24  ************
            #                            1-12  ************
            #brickList is used to undraw the bricks in main program
            #if a brick is hit, it is undrawn then a 0 is placed in the list
            brickList=[[brick25,brick13,brick1],[brick26,brick14,brick2],
                        [brick27,brick15,brick3],[brick28,brick16,brick4],
                        [brick29,brick17,brick5],[brick30,brick18,brick6],
                        [brick31,brick19,brick7],[brick32,brick20,brick8],
                        [brick33,brick21,brick9],[brick34,brick22,brick10],
                        [brick35,brick23,brick11],[brick36,brick24,brick12]]
            Reset = 'n'

        #--------------------Paddle-----------------------------

        px = winx/2-30
        py = winy-30

        paddle = Rectangle(Point(px,py),Point(px+60,py+10))
        paddle.setFill('black')
        paddle.setOutline('lightgrey')
        paddle.draw(win)

        #--------------------Ball-------------------------------

        bx = winx/2-5
        by = winy/4-5
        dx = 1
        dy = 1
        ball = Circle(Point(bx,by),5)
        ball.setFill('grey')
        ball.setOutline('black')
        ball.draw(win)

        #--------------------Functions--------------------------

        #--------------------Main Loop--------------------------
        score = 0
        scoreText = Text(Point(58,10),score)
        scoreText2 = Text(Point(24,10),'Score:')
        scoreText2.draw(win)

        game = True                             #used in code to stop the game

        while win.isOpen() == True and game == True:
            sleep(.005)                         # speed or slow the game

            #look after the paddle
            m = win.checkKey()
            if m == 'Escape':
                win.close()
            else:
                try:
                    x,y = move[m]
                except:
                    pass
            paddle.move(x*speed,y*speed)
            c=paddle.getCenter()
            if c.getX() > (600-30):
                paddle.move(-1*(c.getX() - 570),0)
            if c.getX() < (0+30):
                paddle.move((-1*c.getX()+30),0)

            #look after ball movement
            bc = ball.getCenter()
            if bc.getX() > 595:
                dx = dx*-1
                ball.move((bc.getX()-595)*-1,0)
            if bc.getX() < 5:
                dx = dx*-1
                ball.move((bc.getX()-5)*-1,0)
            if bc.getY() < 5:
                dy = dy*-1
                ball.move((bc.getY()-5)*-1,0)
            ball.move(dx,dy)

            #check for ball collisions
            if bc.getY() < 50:                  #bricks collision section
                x=int(bc.getX()//50)            #convert width of window to x value (column)
                y=int(bc.getY()//10) - 2        #convert height of bricks area to y value (row)
                if brickList[x][y] != 0 :       #check to see if brick has already been undrawn
                    brickList[x][y].undraw()    #undraw brick
                    brickList[x][y]=0           #replace brick object in list with number 0
                    score = score+10
                    scoreText.undraw()
                    scoreText = Text(Point(58,10),score)
                    scoreText.draw(win)
                    dy = dy*-1                  #change direction of ball movement
                    ball.move(dx,dy+2)          #move ball with a nudge of 2

            if bc.getY() > 365:                 #out of bounds at bottom collision section
                if len(ball.getOverlap())>1:
                    dy*=-1
                    ball.move(dx,dy-2)

                elif bc.getY()>395:             #closes window if ball passes by paddle
                    Replay = 'n'
                    win.close()
       #--------------------Retry--------------------------
        win= GraphWin('Brick Breaker',600,400)

        label1 = Rectangle(Point(0,0),Point(300,405))
        label1.draw(win)
        label2 = Rectangle(Point(300,0),Point(600,405))
        label2.draw(win)
        label1.setFill('red')
        label2.setFill('blue')

        gameOver = Text(Point(300,20),'Game has ended. Your score was')
        gameOver.setSize(25)
        gameOver.draw(win)
        finalScore = Text(Point(300,50),score)
        finalScore.setSize(23)
        finalScore.draw(win)

        Retry = Text(Point(300,70),'Would you like to play again?')
        Retry.setSize(15)
        Retry.draw(win)

        yes = Text(Point(150,200),'Yes')
        no = Text(Point(450,200),'No')
        yes.setSize(20)
        no.setSize(20)
        yes.draw(win)
        no.draw(win)

        coord=win.getMouse()
        x=coord.getX()
        y=coord.getY()
        if x<300 and y<400:
            Reset = 'y'
            win.close()
        if x>300 and y<400:
            Reset = 'n'
            win.close()
        if Reset == 'n':
            Power = 'Off'
#--------------------Final Message--------------------------
win= GraphWin('Brick Breaker',600,200)
win.setBackground('yellow')
End = Text(Point(300,100),'Thank You For Playing!!! :)')
End.draw(win)
End.setSize(36)
End.setTextColor('blue')
Closing = Text(Point(300,150),'Click anywhere to close')
Closing.draw(win)
coord=win.getMouse()
x=coord.getX()
y=coord.getY()
if x<600 and y<200:
    win.close()


#!/usr/bin/python

''' Advent of code - Day 1: Chronal Calibration - Problem 1.2

https://adventofcode.com/2018/day/1#part2
'''

import os, sys

# Reading file
filename = 'input1.txt'
lines = []
input_file_path = "%s/%s" % (os.path.abspath(os.path.dirname(__file__)), filename)

try:
    with open(input_file_path, 'r') as f:
        lines = [line.strip() for line in f]

except Exception as e:
    sys.exit("Error - while reading input file: %s" % e)

# Computing frequency reached twice
total = 0
reachedTwice = False
frequencyDict = {0: 1} # 0 was already reached

while (not reachedTwice):

    for num in lines:
        num = int(num)
        total += num

        if total in frequencyDict:
            reachedTwice = total
            break

        else:
            frequencyDict[total] = 1

if reachedTwice:
    print("First frequency reached twice is: %d" % reachedTwice)
else:
    print("No frequency was reached twice")


import os
from gptwntranslator.helpers.config_helper import Config
from gptwntranslator.helpers.file_helper import write_md_as_epub
from gptwntranslator.helpers.text_helper import write_novel_md, parse_chapters
from gptwntranslator.helpers.ui_helper import print_title, wait_for_user_input
from gptwntranslator.storage.json_storage import JsonStorage
from gptwntranslator.ui.page_base import PageBase
from gptwntranslator.ui.page_message import PageMessage
from gptwntranslator.ui.ui_resources import get_resources

class PageNovelExporting(PageBase):
    def __init__(self) -> None:
        pass

    def render(self, screen, **kwargs) -> tuple[PageBase, dict]:
        resources = get_resources()
        novel_code = kwargs["novel_url_code"]
        targets = kwargs["target"]
        novel_origin = kwargs["novel_origin"]
        storage = JsonStorage()
        config = Config()
        target_language = config.data.config.translator.target_language

        # Print title
        last_y = print_title(screen, resources["title"], 0)

        last_y += 2
        screen.print_at(f"Exporting targets: {targets}", 2, last_y)

        while True:
            last_y += 2
            try:
                message = "(1/3) Parsing chapter targets... "
                screen.print_at(message, 2, last_y)
                screen.refresh()
                targets = parse_chapters(targets)
                screen.print_at("success.", 2 + len(message), last_y)
                screen.refresh()
                last_y += 1
            except Exception as e:
                screen.print_at("failed.", 2 + len(message), last_y)
                last_y += 1
                messages = [
                    f"Error: Chapter targets parsing failed.",
                    f"Error: {e}"]
                target = PageMessage
                params = {"messages": messages, "return_page": self.args["return_page"], "return_kwargs": self.args["return_kwargs"]}
                break

            try:
                message = "(2/3) Loading local storage... "
                screen.print_at(message, 2, last_y)
                screen.refresh()
                novels = storage.get_data()
                novel = [novel for novel in novels if novel.novel_code == novel_code and novel.novel_origin == novel_origin][0]
                screen.print_at("success.", 2 + len(message), last_y)
                screen.refresh()
                last_y += 1
            except Exception as e:
                screen.print_at("failed.", 2 + len(message), last_y)
                last_y += 1
                messages = [
                    f"Error: Error loading local storage.",
                    f"Error: {e}"]
                target = PageMessage
                params = {"messages": messages, "return_page": self.args["return_page"], "return_kwargs": self.args["return_kwargs"]}
                break

            try:
                message = "(3/3) Exporting novel to epub... "
                screen.print_at(message, 2, last_y)
                screen.refresh()
                md_text = write_novel_md(novel, targets)
                output = os.path.join(config.vars["output_path"], f"{novel_origin}-{novel.novel_code}-{target_language}.epub")
                write_md_as_epub(md_text, output)
                screen.print_at("success.", 2 + len(message), last_y)
                screen.refresh()
                last_y += 1
                target, params = self.args["return_page"], self.args["return_kwargs"]
            except Exception as e:
                screen.print_at("failed.", 2 + len(message), last_y)
                last_y += 1
                messages = [
                    f"Error: Error exporting novel to epub.",
                    f"Error: {e}"]
                target = PageMessage
                params = {"messages": messages, "return_page": self.args["return_page"], "return_kwargs": self.args["return_kwargs"]}
            break

        last_y += 1
        screen.refresh()
        wait_for_user_input(screen, 2, last_y)
        return target, params


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.common.action_chains import ActionChains as ac

from selenium.common.exceptions import NoSuchElementException

import pandas as pd

import time

# seamless 로그아웃
def logout(driver):
    driver.find_element_by_xpath('/html/body/div/div/div/div/div[2]/div[2]/span/button').click()
    driver.find_element_by_xpath('/html/body/div/div/div/div/div[2]/div[2]/ul/li[6]/a').click()
    driver.close()

# 스크랩한 기업 삭제
def delete_companies(driver):
    wait(driver, 20).until(EC.element_to_be_clickable((By.XPATH,
                                                       '/html/body/div/div/div/div[2]/div/div[2]/table/thead/tr/th/div/span/div/div/div/label/span'))).click()
    time.sleep(1)
    wait(driver, 10).until(EC.element_to_be_clickable(
        (By.XPATH, '/html/body/div/div/div/div[2]/div/div[2]/div/div[2]/div[2]/div[2]/span/button'))).click()
    time.sleep(1)
    wait(driver, 10).until(EC.element_to_be_clickable(
        (By.XPATH, '/html/body/div/div/div/div[2]/div/div[2]/div/div[2]/div[2]/div[2]/ul/li/a'))).click()
    time.sleep(1)
    wait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div/input'))).send_keys(
        'delete')
    time.sleep(1)
    wait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '/html/body/div[7]/div[2]/div/div/div[3]/button[2]'))).send_keys(
        Keys.ENTER)
    time.sleep(5)

def scrap(keyword, start_page, end_page, columns, file_name):
    driver = webdriver.Chrome('chromedriver.exe')
    driver.get('https://login.seamless.ai/login')
    driver.set_window_size(1500, 1000)

    time.sleep(1)
    driver.find_element_by_name('username').send_keys('********')
    driver.find_element_by_name('password').send_keys('********')
    driver.find_element_by_css_selector('form > button').click()
    time.sleep(3)

    try:
        driver.get('https://login.seamless.ai/search/companies?page=' + str(
            start_page) + '&locations=1&companiesExactMatch=false&companyKeywords=' + keyword)
        driver.execute_script("location.reload(true);")
        time.sleep(1)

        driver.find_element_by_css_selector('button > svg').click()

        for p1 in range(start_page, end_page + 1):
            driver.find_element_by_css_selector('body').send_keys(Keys.HOME)
            time.sleep(5)

            # 페이지 전체 한꺼번에 스크랩
            wait(driver, 60).until(EC.element_to_be_clickable((By.XPATH,
                                                               '/html/body/div/div/div/div[2]/div/div[2]/div[2]/table/thead/tr/th/div/span/div/div/div/label/span'))).click()
            time.sleep(1)
            wait(driver, 60).until(EC.element_to_be_clickable(
                (By.XPATH, '/html/body/div/div/div/div[2]/div/div[2]/div[2]/div/div[2]/button'))).click()

            if p1 < end_page:
                driver.find_element_by_css_selector('body').send_keys(Keys.END)
                time.sleep(20)
                wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div/div/div/div[2]/div/div[2]/div[2]/div[2]/div/button[2]'))).send_keys(
                    Keys.ENTER)
            else:
                time.sleep(10)

        # 스크랩한 기업 정보 가져오기
        all_data = list()  # 정보 저장할 리스트

        wait(driver, 10).until(
            EC.element_to_be_clickable(
                (By.XPATH, '/html/body/div/div/div/div/div/div[3]/a'))).click()  # 스크랩한 기업 목록으로 넘어감
        time.sleep(5)

        item_info = wait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, '/html/body/div/div/div/div[2]/div/div[2]/div/div/div[2]'))).text
        item_len = int(item_info.split()[-1])
        pages = (item_len - 1) // 15 + 1

        for p2 in range(pages):
            if p2 < pages - 1:
                items = 15
            else:
                items = item_len % 15 if item_len % 15 else 15

            for i in range(items):
                company_data = list()
                wait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,
                                                                   '/html/body/div/div/div/div[2]/div/div[2]/table/tbody/tr[' + str(
                                                                       i + 1) + ']/td[2]/div/div/button'))).send_keys(
                    Keys.ENTER)
                time.sleep(5)
                wait(driver, 60).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div/div[2]/button'))).send_keys(Keys.ENTER)
                time.sleep(5)

                wait(driver, 30).until(EC.element_to_be_clickable((By.XPATH,
                                                                   '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[2]/div[2]/div/span/span/span[4]/span/span/a'))).send_keys(
                    Keys.ENTER)
                name = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div/div[2]'))).text
                desc = wait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,
                                                                          '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[2]/div[2]/div/span/span'))).text
                website = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[3]/div[2]'))).text
                industry = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[4]/div[2]'))).text
                size = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[5]/div[2]'))).text
                founded = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[6]/div[2]'))).text
                company_type = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[7]/div[2]'))).text
                revenue = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[8]/div[2]'))).text
                location = wait(driver, 10).until(EC.element_to_be_clickable(
                    (By.XPATH, '/html/body/div[7]/div[2]/div/div/div[2]/div[2]/div/div[2]/div/div[9]/div[2]'))).text

                company_data.extend([name, desc, website, industry, size, founded, company_type, revenue, location])
                all_data.append(company_data)

                time.sleep(20)

                driver.find_element_by_css_selector('body').send_keys(Keys.ESCAPE)

                if i % 5 == 4:
                    time.sleep(1)
                    driver.find_element_by_css_selector('body').send_keys(Keys.PAGE_DOWN)
                    time.sleep(1)

            time.sleep(1)
            driver.find_element_by_css_selector('body').send_keys(Keys.HOME)
            time.sleep(2)

            delete_companies(driver)
    except Exception:
        time.sleep(1)
        driver.find_element_by_css_selector('body').send_keys(Keys.ESCAPE)
        time.sleep(1)
        wait(driver, 10).until(
            EC.element_to_be_clickable(
                (By.XPATH, '/html/body/div/div/div/div/div/div[3]/a'))).click()  # 스크랩한 기업 목록으로 넘어감
        time.sleep(1)
        ac(driver).move_by_offset(0, 500).click().perform()
        time.sleep(5)

        try:
            item_info = wait(driver, 30).until(EC.element_to_be_clickable((
                By.CSS_SELECTOR, 'div.RecordCount__RecordCountContainer-jdtFHI'))).text
            item_len = int(item_info.split()[-1])
            pages = (item_len - 1) // 15 + 1
            for p in range(pages):
                delete_companies(driver)
        except NoSuchElementException:
            pass
    else:
        all_columns = [
            'Company Name', 'Description', 'Website', 'Industry', 'Company Size', 'Founded', 'Company Type',
            'Revenue',
            'Location'
        ]
        all_data.reverse()
        all_data = pd.DataFrame(all_data, columns=all_columns, index=list(range(1, item_len + 1)))[columns]
        all_data.to_excel(file_name, encoding='utf-8-sig')
    finally:
        logout(driver)


import asyncio
import contextlib
import types
import unittest

import pytest
from lsst.ts import salobj, watcher
from lsst.ts.idl.enums.Watcher import AlarmSeverity

# Timeout for normal operations (seconds)
STD_TIMEOUT = 5

class GetRuleClassTestCase(unittest.TestCase):
    """Test `lsst.ts.watcher.get_rule_class`."""

    def test_good_names(self):
        for classname, desired_class in (
            ("Enabled", watcher.rules.Enabled),
            ("test.NoConfig", watcher.rules.test.NoConfig),
            ("test.ConfiguredSeverities", watcher.rules.test.ConfiguredSeverities),
        ):
            rule_class = watcher.get_rule_class(classname)
            assert rule_class == desired_class

    def test_bad_names(self):
        for bad_name in (
            "NoSuchRule",  # no such rule
            "test.NoSuchRule",  # no such rule
            "test.Enabled",  # wrong module
            "NoConfig",  # wrong module
            "test_NoConfig",  # wrong separator
        ):
            with pytest.raises(ValueError):
                watcher.get_rule_class(bad_name)

class ModelTestCase(unittest.IsolatedAsyncioTestCase):
    def setUp(self):
        salobj.set_random_lsst_dds_partition_prefix()

    @contextlib.asynccontextmanager
    async def make_model(self, names, enable, escalation=(), use_bad_callback=False):
        """Make a Model as self.model, with one or more Enabled rules.

        Parameters
        ----------
        names : `list` [`str`]
            Name and index of one or more CSCs.
            Each entry is of the form "name" or name:index".
            The associated alarm names have a prefix of "Enabled.".
        enable : `bool`
            Enable the model?
        escalation : `list` of `dict`, optional
            Escalation information.
            See `CONFIG_SCHEMA` for the format of entries.
        use_bad_callback : `bool`
            If True then specify an invalid callback function:
            one that is synchronous. This should raise TypeError.
        """
        if not names:
            raise ValueError("Must specify one or more CSCs")
        self.name_index_list = [salobj.name_to_name_index(name) for name in names]

        configs = [dict(name=name_index) for name_index in names]
        watcher_config_dict = dict(
            disabled_sal_components=[],
            auto_acknowledge_delay=3600,
            auto_unacknowledge_delay=3600,
            rules=[dict(classname="Enabled", configs=configs)],
            escalation=escalation,
        )
        watcher_config = types.SimpleNamespace(**watcher_config_dict)

        self.read_severities = dict()
        self.read_max_severities = dict()

        self.controllers = []
        for name_index in names:
            name, index = salobj.name_to_name_index(name_index)
            self.controllers.append(salobj.Controller(name=name, index=index))

        if use_bad_callback:

            def bad_callback():
                pass

            alarm_callback = bad_callback
        else:
            alarm_callback = self.alarm_callback

        self.model = watcher.Model(
            domain=self.controllers[0].domain,
            config=watcher_config,
            alarm_callback=alarm_callback,
        )

        for name, rule in self.model.rules.items():
            rule.alarm.init_severity_queue()
            self.read_severities[name] = []
            self.read_max_severities[name] = []

        controller_start_tasks = [
            controller.start_task for controller in self.controllers
        ]
        await asyncio.gather(self.model.start_task, *controller_start_tasks)
        if enable:
            await self.model.enable()

        for rule in self.model.rules.values():
            assert rule.alarm.nominal
            assert not rule.alarm.acknowledged
            assert not rule.alarm.muted
            self.assert_not_muted(rule.alarm)

        try:
            yield
        finally:
            await self.model.close()
            controller_close_tasks = [
                asyncio.create_task(controller.close())
                for controller in self.controllers
            ]
            await asyncio.gather(*controller_close_tasks)

    async def alarm_callback(self, alarm):
        """Callback function for each alarm.

        Updates self.read_severities and self.read_max_severities,
        dicts of alarm_name: list of severity/max_severity.
        """
        self.read_severities[alarm.name].append(alarm.severity)
        self.read_max_severities[alarm.name].append(alarm.max_severity)
        # Print the state to aid debugging test failures.
        print(
            f"alarm_callback({alarm.name}, severity={alarm.severity!r}): "
            f"read_severities={self.read_severities[alarm.name]}"
        )

    async def write_states(self, index, states):
        """Write a sequence of summary states to a specified controller."""
        controller = self.controllers[index]
        controller_name_index = f"{controller.salinfo.name}:{controller.salinfo.index}"
        rule_name = f"Enabled.{controller_name_index}"
        rule = self.model.rules[rule_name]
        previous_state = None
        for state in states:
            await controller.evt_summaryState.set_write(
                summaryState=state, force_output=True
            )
            if self.model.enabled and previous_state != state:
                await asyncio.wait_for(
                    rule.alarm.severity_queue.get(), timeout=STD_TIMEOUT
                )
                assert rule.alarm.severity_queue.empty()
            elif self.model.enabled:
                # State didn't changed should not receive any new event
                with pytest.raises(asyncio.TimeoutError):
                    await asyncio.wait_for(
                        rule.alarm.severity_queue.get(), timeout=STD_TIMEOUT
                    )
                assert rule.alarm.severity_queue.empty()
            else:
                # We don't have any event we can wait for, so sleep a bit
                # to give the model time to react to the data.
                await asyncio.sleep(0.1)
            previous_state = state

    def assert_muted(self, alarm, muted_severity, muted_by):
        """Assert that the specified alarm is muted.

        Parameters
        ----------
        alarm : `lsst.ts.watcher.Alarm`
            Alarm to test.
        muted_severity : `lsst.ts.idl.enums.Watcher.AlarmSeverity`
            Expected value for rule.severity.
        muted_by : `str`
            Expected value for rule.muted_by.
        """
        assert alarm.muted
        assert alarm.muted_severity == muted_severity
        assert alarm.muted_by == muted_by

    def assert_not_muted(self, alarm):
        """Assert that the specified alarm is not muted.

        Parameters
        ----------
        alarm : `lsst.ts.watcher.Alarm`
            Alarm to test.
        """
        assert not alarm.muted
        assert alarm.muted_severity == AlarmSeverity.NONE
        assert alarm.muted_by == ""

    async def test_constructor_bad_callback(self):
        remote_names = ["ScriptQueue:5", "Test:7"]
        with pytest.raises(TypeError):
            async with self.make_model(
                names=remote_names, enable=False, use_bad_callback=True
            ):
                pass

    async def test_acknowledge_full_name(self):
        user = "test_ack_alarm"
        remote_names = ["ScriptQueue:5", "Test:7"]
        nrules = len(remote_names)

        async with self.make_model(names=remote_names, enable=True):
            full_rule_name = f"Enabled.{remote_names[0]}"
            assert full_rule_name in self.model.rules

            # Send STANDBY to all controllers to put all alarms into warning.
            for index in range(nrules):
                await self.write_states(index=index, states=[salobj.State.STANDBY])

            for name, rule in self.model.rules.items():
                assert not rule.alarm.nominal
                assert rule.alarm.severity == AlarmSeverity.WARNING
                assert rule.alarm.max_severity == AlarmSeverity.WARNING

            # Acknowledge one rule by full name but not the other.
            await self.model.acknowledge_alarm(
                name=full_rule_name, severity=AlarmSeverity.WARNING, user=user
            )
            for name, rule in self.model.rules.items():
                if name == full_rule_name:
                    assert rule.alarm.acknowledged
                    assert rule.alarm.acknowledged_by == user
                else:
                    assert not rule.alarm.acknowledged
                    assert rule.alarm.acknowledged_by == ""

    async def test_acknowledge_regex(self):
        user = "test_ack_alarm"
        remote_names = ["ScriptQueue:1", "ScriptQueue:2", "Test:62"]
        nrules = len(remote_names)

        async with self.make_model(names=remote_names, enable=True):
            assert len(self.model.rules) == nrules

            # Send STANDBY to all controllers to put all alarms into warning.
            for index in range(nrules):
                await self.write_states(index=index, states=[salobj.State.STANDBY])

            for rule in self.model.rules.values():
                assert not rule.alarm.nominal
                assert rule.alarm.severity == AlarmSeverity.WARNING
                assert rule.alarm.max_severity == AlarmSeverity.WARNING

            # Acknowledge the ScriptQueue alarms but not Test.
            await self.model.acknowledge_alarm(
                name="Enabled.ScriptQueue:*", severity=AlarmSeverity.WARNING, user=user
            )
            for name, rule in self.model.rules.items():
                if "ScriptQueue" in name:
                    assert rule.alarm.acknowledged
                    assert rule.alarm.acknowledged_by == user
                else:
                    assert not rule.alarm.acknowledged
                    assert rule.alarm.acknowledged_by == ""

    async def test_enable(self):
        remote_names = ["ScriptQueue:5", "Test:7"]

        async with self.make_model(names=remote_names, enable=True):
            assert len(self.model.rules) == 2

            # Enable the model and write ENABLED several times.
            # This triggers the rule callback but that does not
            # change the state of the alarm.
            await self.model.enable()
            for index in range(len(remote_names)):
                await self.write_states(
                    index=index,
                    states=(
                        salobj.State.ENABLED,
                        salobj.State.ENABLED,
                        salobj.State.ENABLED,
                    ),
                )

            for name, rule in self.model.rules.items():
                assert rule.alarm.nominal
                assert self.read_severities[name] == [AlarmSeverity.NONE]
                assert self.read_max_severities[name] == [AlarmSeverity.NONE]

            # Disable the model and issue several events that would
            # trigger an alarm if the model was enabled. Since the
            # model is disabled the alarm does not change states.
            self.model.disable()
            for index in range(len(remote_names)):
                await self.write_states(
                    index=index, states=(salobj.State.FAULT, salobj.State.STANDBY)
                )

            for name, rule in self.model.rules.items():
                assert rule.alarm.nominal
                assert self.read_severities[name] == [AlarmSeverity.NONE]
                assert self.read_max_severities[name] == [AlarmSeverity.NONE]

            # Enable the model. This will trigger a callback with
            # the current state of the event (STANDBY).
            # Note that the earlier FAULT event is is ignored
            # because it arrived while disabled.
            await self.model.enable()
            for name, rule in self.model.rules.items():
                await rule.alarm.assert_next_severity(AlarmSeverity.WARNING)
                assert not rule.alarm.nominal
                assert rule.alarm.severity == AlarmSeverity.WARNING
                assert rule.alarm.max_severity == AlarmSeverity.WARNING
                assert self.read_severities[name] == [
                    AlarmSeverity.NONE,
                    AlarmSeverity.WARNING,
                ]
                assert self.read_max_severities[name] == [
                    AlarmSeverity.NONE,
                    AlarmSeverity.WARNING,
                ]

            # Issue more events; they should be processed normally.
            for index in range(len(remote_names)):
                await self.write_states(
                    index=index, states=(salobj.State.FAULT, salobj.State.STANDBY)
                )

            for name, rule in self.model.rules.items():
                assert not rule.alarm.nominal
                assert rule.alarm.severity == AlarmSeverity.WARNING
                assert rule.alarm.max_severity == AlarmSeverity.CRITICAL
                assert self.read_severities[name] == [
                    AlarmSeverity.NONE,
                    AlarmSeverity.WARNING,
                    AlarmSeverity.CRITICAL,
                    AlarmSeverity.WARNING,
                ]
                assert self.read_max_severities[name] == [
                    AlarmSeverity.NONE,
                    AlarmSeverity.WARNING,
                    AlarmSeverity.CRITICAL,
                    AlarmSeverity.CRITICAL,
                ]

    async def test_escalation(self):
        remote_names = ["ScriptQueue:1", "ScriptQueue:2", "Test:1", "Test:2", "Test:52"]
        # Escalation info for the first two rules;
        # check that case does not have to match.
        esc_info12 = dict(
            alarms=["enabled.scriptqueue:*"],
            responder="chaos",
            delay=0.11,
        )
        # Escalation info for the next two rules
        esc_info34 = dict(
            alarms=["Enabled.Test:?"],
            responder="stella",
            delay=0.12,
        )
        # Escalation info that does not match any alarm names
        esc_notused = dict(
            alarms=["Enabled.NoMatch"],
            responder="someone",
            delay=0.13,
        )

        async with self.make_model(
            names=remote_names,
            enable=False,
            escalation=[esc_info12, esc_info34, esc_notused],
        ):
            alarms = [rule.alarm for rule in self.model.rules.values()]
            assert len(alarms) == len(remote_names)
            for alarm in alarms[0:2]:
                assert alarm.escalation_responder == esc_info12["responder"]
                assert alarm.escalation_delay == esc_info12["delay"]
            for alarm in alarms[2:4]:
                assert alarm.escalation_responder == esc_info34["responder"]
                assert alarm.escalation_delay == esc_info34["delay"]
            for alarm in alarms[4:]:
                assert alarm.escalation_responder == ""
                assert alarm.escalation_delay == 0
            for alarm in alarms:
                assert alarm.timestamp_escalate == 0

    async def test_get_rules(self):
        remote_names = ["ScriptQueue:1", "ScriptQueue:2", "Test:1", "Test:2", "Test:52"]

        async with self.make_model(names=remote_names, enable=False):
            rules = self.model.get_rules("NoSuchName")
            assert len(list(rules)) == 0

            # Search starts at beginning, so Enabled.foo works
            # but foo does not.
            rules = self.model.get_rules("ScriptQueue")
            assert len(list(rules)) == 0

            rules = self.model.get_rules(".*")
            assert len(list(rules)) == len(remote_names)

            rules = self.model.get_rules("Enabled")
            assert len(list(rules)) == len(remote_names)

            rules = self.model.get_rules("Enabled.ScriptQueue")
            assert len(list(rules)) == 2

            rules = self.model.get_rules("Enabled.Test")
            assert len(list(rules)) == 3

    async def test_mute_full_name(self):
        """Test mute and unmute by full alarm name."""
        user = "test_mute_alarm"
        remote_names = ["ScriptQueue:5", "Test:7"]

        async with self.make_model(names=remote_names, enable=True):
            full_rule_name = f"Enabled.{remote_names[0]}"
            assert full_rule_name in self.model.rules

            # Mute one rule by full name.
            await self.model.mute_alarm(
                name=full_rule_name,
                duration=5,
                severity=AlarmSeverity.WARNING,
                user=user,
            )
            for name, rule in self.model.rules.items():
                if name == full_rule_name:
                    self.assert_muted(
                        rule.alarm, muted_severity=AlarmSeverity.WARNING, muted_by=user
                    )
                else:
                    self.assert_not_muted(rule.alarm)

            # Nnmute one rule by full name.
            await self.model.unmute_alarm(name=full_rule_name)
            for rule in self.model.rules.values():
                self.assert_not_muted(rule.alarm)

    async def test_mute_regex(self):
        """Test mute and unmute by regex."""
        user = "test_mute_alarm"
        remote_names = ["ScriptQueue:1", "ScriptQueue:2", "Test:62"]
        nrules = len(remote_names)

        async with self.make_model(names=remote_names, enable=True):
            assert len(self.model.rules) == nrules

            # Mute the ScriptQueue alarms but not Test.
            await self.model.mute_alarm(
                name="Enabled.ScriptQueue.*",
                duration=5,
                severity=AlarmSeverity.WARNING,
                user=user,
            )
            for name, rule in self.model.rules.items():
                if "ScriptQueue" in name:
                    self.assert_muted(
                        rule.alarm, muted_severity=AlarmSeverity.WARNING, muted_by=user
                    )
                else:
                    self.assert_not_muted(rule.alarm)

            # Unmute the ScriptQueue alarms but not Test.
            await self.model.unmute_alarm(name="Enabled.ScriptQueue.*")
            for rule in self.model.rules.values():
                self.assert_not_muted(rule.alarm)


from __future__ import division
from collections import deque

class BiGramDict(object):

	def __init__(self):
		self.count = dict()
		self.dictionary = dict()

	def put(self, key, value):
		if key not in self.dictionary:
			self.count[key] = 0
			self.dictionary[key] = dict()
		if value not in self.dictionary[key]:
			self.dictionary[key][value] = 0
		self.dictionary[key][value] += 1
		self.count[key] += 1

	def normalize(self):
		for key_dict in self.dictionary.iterkeys():
			for value_dict in self.dictionary[key_dict].iterkeys():
				self.dictionary[key_dict][value_dict] /= self.count[key_dict]

	def get(self, key, value):
		if key in self.dictionary and value in self.dictionary[key]:
			return self.dictionary[key][value]
		return False

class TriGramDict(object):

	def __init__(self):
		# Don't need a count. BiGramDict on each gram will maintain a tab
		self.dictionary = dict()

	def put(self, first_gram, second_gram, third_gram):
		if first_gram not in self.dictionary:
			self.dictionary[first_gram] = BiGramDict()
		self.dictionary[first_gram].put(second_gram, third_gram)

	def normalize(self):
		for gram in self.dictionary.iterkeys():
			self.dictionary[gram].normalize()

	def get(self, first_gram, second_gram, third_gram):
		if first_gram not in self.dictionary:
			return False
		return self.dictionary[first_gram].get(second_gram, third_gram)

class HMM(object):

	def __init__(self):
		self.states = set()
		self.trigramDictionary = TriGramDict()
		self.bigramStateDictionary = BiGramDict()
		self.emissionDictionary = BiGramDict()
		self.initDictionary = BiGramDict()
		pass

	def trainHMM(self, filename):

		prevPosTag = None
		prevPosTags = [None] * 2
		with open(filename, "r") as train_file:

			for line in train_file:

				line = line.strip()
				if line == "###/###":
					prevPosTags[1] = None
					continue

				word, posTag = line.split('/')
				posTag = posTag.replace('\n', '')

				self.emissionDictionary.put(posTag, word)

				previous_BiGram_nexists = prevPosTags[1] == None
				if previous_BiGram_nexists:
					self.initDictionary.put('init', posTag)
					prevPosTags[1] = posTag
					continue

				self.bigramStateDictionary.put(prevPosTags[1], posTag)

				prevPosTags[0], prevPosTags[1] = prevPosTags[1], posTag
				self.trigramDictionary.put(prevPosTags[0], prevPosTags[1], posTag)

		self.emissionDictionary.normalize()
		self.bigramStateDictionary.normalize()
		self.initDictionary.normalize()

		self.states.update(self.bigramStateDictionary.dictionary.keys())

	def __initial_probability__(self, state):
		return self.initDictionary.get('init', state) or 0

	def __emission_probability__(self, state, observation):
		return self.emissionDictionary.get(state, observation) or 0.0000015

	def __transition_probability__(self, prevState, nextState):
		return self.bigramStateDictionary.get(prevState, nextState) or 0.0000015

	def testHMM(self, filename):
		with open(filename, "r") as test_file:
			actual_count = 0
			successful_count = 0
			true_states = []
			obs = []
			for line in test_file:
				line = line.strip()
				if line != '###/###':
					word, tag = line.split('/')
					true_states.append(tag)
					obs.append(word)
					continue
				if len(true_states) == 0:
					continue
				(probability, pred_states) = self.__predict_tagsets__(obs)
				for i in xrange(len(true_states)):
					if true_states[i] == pred_states[i]:
						successful_count += 1
					actual_count += 1
				#print pred_states
				#print true_states
				print (actual_count - successful_count)/actual_count * 100
				obs = []
				true_states = []
				#raw_input()

	def __predict_tagsets__(self, observations):
		viterbi = [{}]
		path = {}

		for s0 in self.states:
			viterbi[0][s0] = self.__initial_probability__(s0) * self.__emission_probability__(s0, observations[0])
			path[s0] = [s0]

		for t in range(1, len(observations)):
			viterbi.append({})
			newpath = {}

			for sj in self.states:
				(prob, state) = max((viterbi[t-1][si] * self.__transition_probability__(si, sj) * self.__emission_probability__(sj, observations[t]), si) for si in self.states)
				viterbi[t][sj] = prob
				newpath[sj] = path[state] + [sj]
			path = newpath
		n = 0
		if len(observations) != 1:
			n = len(observations) - 1
		(prob, state) = max((viterbi[n][y], y) for y in self.states)
		return (prob, path[state])

if __name__ == '__main__':
	hmm = HMM()
	hmm.trainHMM("entrain.txt")
	hmm.testHMM("entest.txt")


# Module 5
#   Programming Assignment 6
#       Prob-2.py

# Esther Pisano

from graphics import *

def main():
    # creating a label "win" for the graph that we wish to draw in.
    # titled it "Squares"
    win = GraphWin("Squares", 200, 200)

    # created first rectangle
    shape = Rectangle(Point(50, 50), Point(20, 20))

    # colored the shape
    shape.setOutline("red")
    shape.setFill("red")

    # executed the drawing function
    shape.draw(win)

    # made a loop to make more rectangles.
    # This will loop 5 times
    for i in range(5):
        p = win.getMouse()
        c = shape.getCenter()
        dx = p.getX() - c.getX()
        dy = p.getY() - c.getY()

    # code below will add the new coordinate to the first coordinate (50,50)
    # it will then create a new rectangle where the new float number is (which is where the mouse was clicked)

        new_shape = Rectangle(Point(50+dx, 50+dy), Point(20+dx, 20+dy))
        new_shape.setOutline("red")
        new_shape.setFill("red")
        new_shape.draw(win)

    # create a label to show window is ending
    label = Text(Point(100, 120), "Click once more to quit")
    label.draw(win)
    win.getMouse()
    win.close()

main()


import cv2
import numpy as np

###Color detection

def empty(a):
    pass
def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver

cv2.namedWindow("trackBars")
cv2.resizeWindow("trackBars",640,240)
#name of window,add on which window,initial value, max value, function executed when trak bar value is changed
#Hue ranges from 0 to 255 but opencv supports still 179 so max value 179
cv2.createTrackbar("Hue Min","trackBars",0,179,empty)
cv2.createTrackbar("Hue Max","trackBars",13,179,empty)
cv2.createTrackbar("Sat Min","trackBars",24,255,empty)
cv2.createTrackbar("Sat Max","trackBars",250,255,empty)
cv2.createTrackbar("Value Min","trackBars",119,255,empty)
cv2.createTrackbar("Value Max","trackBars",255,255,empty)

while True:
    img = cv2.imread("lambo.png")
    imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    #trackbar name, window name is which it belongs
    h_min = cv2.getTrackbarPos("Hue Min","trackBars")
    h_max = cv2.getTrackbarPos("Hue Max","trackBars")
    s_min = cv2.getTrackbarPos("Sat Min","trackBars")
    s_max = cv2.getTrackbarPos("Sat Max","trackBars")
    v_min = cv2.getTrackbarPos("Value Min","trackBars")
    v_max = cv2.getTrackbarPos("Value Max","trackBars")
    print(h_min,h_max,s_min,s_max,v_min,v_max)

    lower = np.array([h_min,s_min,v_min])
    upper = np.array([h_max,s_max,v_max])

    #creating a mask
    mask = cv2.inRange(imgHSV,lower,upper)
    #cv2.imshow("lambo ",img)
    #cv2.imshow("lamboHSV ",imgHSV)
    #cv2.imshow("mask  ", mask)
    # keep things in black color if you dont want it

    #which will add 2 images together to create a new image it will check both images and wherever the pixel are both present it will take it has a yes or a 1  and it will store that in new image
    # cv2.bitwise_and(img,img,mask=mask)   source image,output image, mask
    imgResult = cv2.bitwise_and(img,img,mask=mask)
    #cv2.imshow("Result masked image  ", imgResult)

    imgStack = stackImages(0.6,([img,imgHSV],[mask,imgResult]))
    cv2.imshow("Stack Images",imgStack)
    cv2.waitKey(1)


from typing import List
import collections

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:

        q = collections.deque()
        for i in range(1, n + 1):
            q.append([i])

        while q:
            e = q.popleft()
            if len(e) == k:
                q.appendleft(e)
                break
            else:
                for i in range(e[-1] + 1, n + 1):
                    a = e[:]
                    a.append(i)
                    q.append(a)
        return list(q)

n = 3
k = 3
r = Solution().combine(n, k)
print(r)


import time

from telapi import tas_api
from database import db

api_caller = tas_api(db.phone1.accountId, db.phone1.mailboxId)
api_callee = tas_api(db.phone2.accountId, db.phone2.mailboxId)
session_id, caller_party_id = api_caller.callout(db.phone1.deviceId, db.phone2.number)

callee_party_id = api_caller.get_party_by_number(session_id, 2)
if callee_party_id is None:
    print("Impossible to obtain callee party ID.")
    exit(-1)

if api_callee.get_amount_devices() > 1:
    time.sleep(5)

api_callee.answer(session_id, callee_party_id, db.phone2.deviceId)

time.sleep(2)

api_caller.transfer_to_park_orbit(caller_party_id, session_id, db.parkOrbitId)
print(api_caller.get_session(session_id))

time.sleep(2)

body = api_caller.pickup(callee_party_id, session_id, db.phone1.deviceId)
print(body)


import re

re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
# 查全部 没有为[], [('width', '20'), ('height', '10')]

def dashreplace(matchobj):
    """普通替换"""
    if matchobj.group(0) == '-':
        return ' '
    else:
        return ''

re.sub('-{1,4}', dashreplace, 'pro----gram-files')
# program files

def dashreplace2(matchobj):
    """分组替换"""
    # print(matchobj.groupdict()) # {'first_name': 'Malcolm', 'last_name': 'Reynolds'}
    first_name = matchobj.group('first_name')
    last_name = matchobj.group('last_name')
    return f"{first_name}-{last_name}"

re.sub(r'(?P<first_name>\w+) (?P<last_name>\w+)',
       dashreplace2, "Malcolm Reynolds")

# 检查字符串中任何位置的匹配,查第一个 没有为None,
res = re.search(r"\w+", "abc def gh abc")
# <re.Match object; span=(0, 3), match='abc'>

# 检查字符串开头是否匹配
m = re.match(r"(\d+)\.(\d+)", "24.1632")
# m.groups() => ('24', '1632')

m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
# m.groupdict() # {'first_name': 'Malcolm', 'last_name': 'Reynolds'}

# fullmatch: 完全匹配


from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth import get_user_model

class CustomUser(AbstractUser):
    phone = models.CharField(max_length=13, blank=True, null=True)
    bonus_coin = models.IntegerField(default=0)

class NameIt(models.Model):
    name = models.CharField(max_length=255)

    class Meta:
        abstract = True

    def __str__(self):
        return self.name

class Category(NameIt):
    pass

class Product(NameIt):
    price = models.IntegerField(null=False)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, null=False)
    compound = models.TextField(null=True)
    description = models.TextField(null=True)

class ProductImage(models.Model):
    image = models.ImageField(upload_to='images', verbose_name='Изображение_товара')
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='images')
    is_main = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    def __str__(self):
        return "%s" % self.id

class Reviews(models.Model):
    body = models.TextField()
    publish_date = models.DateTimeField(blank=True, null=True)
    is_published = models.BooleanField(default=False)
    author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)

    def __str__(self):
        return self.body

# Create your models here.