import tempfile
from collections import UserList, deque
from collections.abc import Mapping
from contextlib import contextmanager
from dataclasses import dataclass, field, InitVar
from itertools import starmap
from time import time
from typing import Sequence

# -------------- External Library -------------- #

from inflection import underscore
from aenum import Enum, AutoValue
from path import Path

# -------------- Hexfarm  Library -------------- #

from ..shell import decoded, Command, me
from ..util import classproperty, map_value_or, value_or

__all__ = (
    "CondorCommand",
    "CONDOR_COMMANDS",
    "current_jobs",
    "user_jobs",
    "Universe",
    "Notification",
    "FileTransferMode",
    "TransferOutputMode",
    "This",
    "condor_format_mapping",
    "condor_format_sequence",
    "extract_job_ids",
    "CONDOR_SUBMIT_COMMANDS",
    "JobConfig",
    "minimal_config",
    "submit_config",
    "Job",
    "job_dict",
    "JobCompletedException",
    "JobMap",
    "ConfigUnitBase",
    "ProcessUnit",
    "ClusterUnit",
    "MultiClusterUnit",
    "ConfigRunner",
    "JobManager",
)

class CondorCommand(Command, prefix="condor_"):
    """Condor Command Object."""

CONDOR_COMMANDS = (
    "advertise",
    "c-gahp",
    "c-gahp_worker_thread",
    "check_userlogs",
    "checkpoint",
    "ckpt_server",
    "cod",
    "collector",
    "compile",
    "config_val",
    "configure",
    "continue",
    "credd",
    "dagman",
    "drain",
    "fetchlog",
    "findhost",
    "ft-gahp",
    "gather_info",
    "gridmanager",
    "gridshell",
    "had",
    "history",
    "hold",
    "init",
    "install",
    "kbdd",
    "master",
    "master_s",
    "negotiator",
    "off",
    "on",
    "ping",
    "power",
    "preen",
    "prio",
    "procd",
    "q",
    "qedit",
    "qsub",
    "reconfig",
    "release",
    "replication",
    "reschedule",
    "restart",
    "rm",
    "root_switchboard",
    "router_history",
    "router_q",
    "router_rm",
    "run",
    "schedd",
    "set_shutdown",
    "shadow",
    "shadow.std",
    "shadow_s",
    "ssh_to_job",
    "startd",
    "starter",
    "starter.std",
    "stats",
    "status",
    "store_cred",
    "submit",
    "submit_dag",
    "suspend",
    "tail",
    "test_match",
    "transfer_data",
    "transferd",
    "updates_stats",
    "userlog",
    "userlog_job_counter",
    "userprio",
    "vacate",
    "vacate_job",
    "version",
    "vm-gahp",
    "vm-gahp-vmware",
    "vm_vmware",
    "vm_vmware.pl",
    "wait",
    "who",
)

def add_condor_commands(commands, command_dict):
    """Build Condor Commands for Globals."""
    name_list = []
    for name in commands:
        setname = (CondorCommand.prefix + name).replace(".", "").replace("-", "_")
        name_list.append(setname)
        command_dict[setname] = CondorCommand(name)
    return tuple(name_list)

__all__ += add_condor_commands(CONDOR_COMMANDS, globals())

def current_jobs(*usernames):
    """List the Current Jobs by Users."""
    query = condor_q(" ".join(usernames)) if usernames else condor_q()
    text = decoded(query).strip().split("\n")
    user_dict = dict()
    for job_id, name, *_ in list(map(lambda l: l.strip().split(), text))[2:-2]:
        if name not in user_dict:
            user_dict[name] = []
        user_dict[name].append(job_id)
    return user_dict

def user_jobs(username=me()):
    """Get User's Jobs."""
    return current_jobs(username)[username]

class NameEnum(Enum, settings=AutoValue):
    """Named Enum Objects."""

    def __str__(self):
        """Get Name as String."""
        return self.name

class Universe(NameEnum):
    """Condor Universe Enum."""

    Vanilla, Standard, Scheduler, Local, Grid, Java, VM, Parallel, Docker

@dataclass
class Notification:
    """Notification Structure."""

    class Status(NameEnum):
        """Notification Status."""

        Always, Complete, Error, Never

    email: str
    status: Status
    attributes: Sequence[str] = field(default_factory=list)

    def __str__(self):
        """Get String Representation of Notification."""
        attributes = f'email_attributes={",".join(self.attributes)}'
        return "\n".join(
            (
                f"notification={self.status}",
                f"notify-user={self.email}",
                f'{attributes if self.attributes else ""}',
            )
        )

class FileTransferMode(NameEnum):
    """File Transfer Mode."""

    Yes, No, IfNeeded

class TransferOutputMode(NameEnum):
    """Transfer Output Mode."""

    OnExit, OnExitOrEvict

class This(NameEnum):
    """Universal Condor Object Variables."""

    ClusterId, Cluster, ProcId, Process, Node, Step, ItemIndex, Row, Item

    def __str__(self):
        """Get String Form of Variable."""
        return f"$({super().__str__()})"

def kv_string(key, value, *, connector="="):
    """Make Key-Value String."""
    return f"{key}{connector}{value}"

def condor_format_mapping(mapping):
    """Format a Mapping According to Condor Conventions."""
    return ";".join(starmap(kv_string, mapping.items()))

def condor_format_sequence(sequence):
    """Format a Sequence According to Condor Conventions."""
    return " ".join(map(str, sequence))

def open_key_value_pairs(self, *pairs, connector="=", ignore_unpacking_error=True):
    """Open Pair and Check for Keys and Values."""
    if not pairs:
        return None, None
    if len(pairs) == 1:
        try:
            key, value = tuple(map(lambda o: o.strip(), pairs[0].split(connector)))
            return ((key, value),)
        except ValueError as value_error:
            if ignore_unpacking_error:
                return ((None, None),)
            raise value_error
    else:
        # TODO: replace recursive implementation
        return sum(tuple(open_key_value_pairs(line) for line in pairs), ())

def extract_job_ids(condor_submit_text):
    """Extract Job Ids from Condor Submit Text."""
    _, _, count, *_, cluster = condor_submit_text.strip().split()
    for process in map(str, range(int(count))):
        yield cluster + process

class WriteModeMixin:
    """
    Writing Mode Mixin Class.

    """

    def __init_subclass__(
        cls, write_mode_keywords, write_mode_invalid_keywords=None, **kwargs
    ):
        """Initialize Write-Mode Keywords for Class."""
        super().__init_subclass__(**kwargs)
        cls._write_mode_keywords = set(write_mode_keywords)
        cls._write_mode_invalid_keywords = map_value_or(
            set, write_mode_invalid_keywords, set()
        )

    def _write_mode_insert(self, name, value):
        """Insert Key-Value Pair into Object."""
        return NotImplemented

    def _write_mode_invalid_keyword(self, name, value):
        """Check if Write-Mode Key is valid."""
        raise ValueError(f"Key: {name} is an invalid Keyword.")

    @property
    @contextmanager
    def write_mode(self):
        """Writing Mode Context Manager."""
        try:
            self._write_mode = True
            yield self
        finally:
            self._write_mode = False

    def __setattr__(self, name, value):
        """Set attributes."""
        if self._write_mode:
            if name in type(self)._write_mode_invalid_keywords:
                self._write_mode_invalid_keyword(name, value)
            elif name in type(self)._write_mode_keywords:
                self._write_mode_insert(name, value)
        else:
            super().__setattr__(name, value)

CONDOR_SUBMIT_COMMANDS = {
    "accounting_group",
    "accounting_group_user",
    "allow_startup_script",
    "append_files",
    "arguments",
    "azure_admin_key",
    "azure_admin_username",
    "azure_auth_file",
    "azure_image",
    "azure_location",
    "azure_size",
    "batch_queue",
    "boinc_authenticator_file",
    "buffer_block_size",
    "buffer_files",
    "buffer_size",
    "compress_files",
    "concurrency_limits",
    "concurrency_limits_expr",
    "copy_to_spool",
    "coresize",
    "cream_attributes",
    "cron_day_of_month",
    "cron_day_of_week",
    "cron_hour",
    "cron_minute",
    "cron_month",
    "cron_prep_time",
    "cron_window",
    "dagman_log",
    "deferral_prep_time",
    "deferral_time",
    "deferral_window",
    "delegate_job_GSI_credentials_lifetime",
    "description",
    "docker_image",
    "dont_encrypt_input_files",
    "dont_encrypt_output_files",
    "ec2_access_key_id",
    "ec2_ami_id",
    "ec2_availability_zone",
    "ec2_block_device_mapping",
    "ec2_ebs_volumes",
    "ec2_elastic_ip",
    "ec2_iam_profile_arn",
    "ec2_iam_profile_name",
    "ec2_instance_type",
    "ec2_keypair",
    "ec2_keypair_file",
    "ec2_parameter_",
    "ec2_parameter_names",
    "ec2_secret_access_key",
    "ec2_security_groups",
    "ec2_security_ids",
    "ec2_spot_price",
    "ec2_tag_",
    "ec2_tag_names",
    "ec2_user_data",
    "ec2_user_data_file",
    "ec2_vpc_ip",
    "ec2_vpc_subnet",
    "email_attributes",
    "encrypt_execute_directory",
    "encrypt_input_files",
    "encrypt_output_files",
    "environment",
    "error",
    "executable",
    "fetch_files",
    "file_remaps",
    "gce_auth_file",
    "gce_image",
    "gce_json_file",
    "gce_machine_type",
    "gce_metadata",
    "gce_metadata_file",
    "gce_preemptible",
    "getenv",
    "globus_rematch",
    "globus_resubmit",
    "globus_rsl",
    "grid_resource",
    "hold",
    "hold_kill_sig",
    "image_size",
    "initialdir",
    "input",
    "jar_files",
    "java_vm_args",
    "job_ad_information_attrs",
    "job_batch_name",
    "job_lease_duration",
    "job_machine_attrs",
    "job_max_vacate_time",
    "keep_claim_idle",
    "keystore_alias",
    "keystore_file",
    "keystore_passphrase_file",
    "kill_sig",
    "kill_sig_timeout",
    "leave_in_queue",
    "load_profile",
    "local_files",
    "log",
    "log_xml",
    "machine_count",
    "match_list_length",
    "max_job_retirement_time",
    "max_retries",
    "max_transfer_input_mb",
    "max_transfer_output_mb",
    "my_proxy_credential_name",
    "my_proxy_host",
    "my_proxy_new_proxy_lifetime",
    "my_proxy_password",
    "my_proxy_refresh_threshold",
    "my_proxy_server_dn",
    "next_job_start_delay",
    "nice_user",
    "noop_job",
    "noop_job_exit_code",
    "noop_job_exit_signal",
    "nordugrid_rsl",
    "notification",
    "on_exit_hold",
    "on_exit_hold_reason",
    "on_exit_hold_subcode",
    "on_exit_remove",
    "output",
    "output_destination",
    "periodic_hold",
    "periodic_hold_reason",
    "periodic_hold_subcode",
    "periodic_release",
    "periodic_remove",
    "priority",
    "queue",
    "rank",
    "remote_initialdir",
    "remove_kill_sig",
    "rendezvousdir",
    "request_",
    "request_cpus",
    "request_disk",
    "request_memory",
    "requirements",
    "retry_until",
    "run_as_owner",
    "should_transfer_files",
    "skip_filechecks",
    "stack_size",
    "stream_error",
    "stream_input",
    "stream_output",
    "submit_event_notes",
    "success_exit_code",
    "transfer_error",
    "transfer_executable",
    "transfer_input",
    "transfer_input_files",
    "transfer_output",
    "transfer_output_files",
    "transfer_output_remaps",
    "universe",
    "use_x509userproxy",
    "vm_checkpoint",
    "vm_disk",
    "vm_macaddr",
    "vm_memory",
    "vm_networking",
    "vm_networking_type",
    "vm_no_output_vm",
    "vm_type",
    "vmware_dir",
    "vmware_should_transfer_files",
    "vmware_snapshot_disk",
    "want_graceful_removal",
    "want_name_tag",
    "want_remote_io",
    "when_to_transfer_output",
    "x509userproxy",
    "xen_initrd",
    "xen_kernel",
    "xen_kernel_params",
    "xen_root",
}

class JobConfig(UserList, WriteModeMixin, write_mode_keywords=CONDOR_SUBMIT_COMMANDS):
    """
    Job Configuration Base.

    """

    @classproperty
    def command_names(cls):
        """Get Possible Command Names for Condor Config File."""
        return cls._write_mode_keywords

    @classmethod
    def from_file(
        cls, path, opener=open, *args, clean_input=str.strip, keep_path=True, **kwargs
    ):
        """Load Job Config from File."""
        with opener(path, *args, **kwargs) as file:
            return cls(
                *(clean_input(line) for line in file), path=path if keep_path else None
            )

    def __init_subclass__(cls, special_key_map=None, **kwargs):
        """Initialize Subclasses with Special Key Maps."""
        super().__init_subclass__(**kwargs)
        if special_key_map is not None:
            cls.special_key_map = special_key_map

    def __init__(self, *lines, path=None):
        """Initialize Config."""
        self.__dict__["_write_mode"] = False
        super().__init__(*lines)
        self._path = path

    def _build_path_save_mechanism(self):
        """Build Path Save Mechanism."""
        if hasattr(self, "save"):
            raise AttributeError(
                "JobConfig has no attribute _build_path_save_mechanism."
            )

        def _save(s):
            Path(s.path).write_text(s.as_text)

        def _save_as(s, new_path):
            s._path = new_path
            return s.save()

        self.save = _save
        self.save.__doc__ = """Save Config to File."""
        self.save_as = _save_as
        self.save_as.__doc__ = """Save Config at New Path."""

    @property
    def path(self):
        """Get Path of Config if Exists."""
        if self._path is None:
            raise AttributeError("JobConfig has no attribute path.")
        try:
            self._build_path_save_mechanism()
        except AttributeError:
            pass
        return self._path

    @path.setter
    def path(self, value):
        """Set Path of Config if Exists."""
        self._path = value
        try:
            self._build_path_save_mechanism()
        except AttributeError:
            pass

    @property
    def lines(self):
        """Alias to Inner Structure."""
        return self.data

    @property
    def lines(self, new_lines):
        """Set Inner Structure."""
        self.data = new_lines

    def to_text(self, *, with_newlines=True):
        """Return Config as Multiline Text."""
        return ("\n" if with_newlines else "").join(self)

    @property
    def as_text(self):
        """Return Config as Multiline Text."""
        return self.to_text()

    def __repr__(self):
        """Representation of Config File."""
        data_string = (
            f'[{str(self.data[0:6])[1:-1]}{", ...]" if len(self) > 6 else "]"}'
        )
        return f"{type(self).__name__}({data_string})"

    def __str__(self):
        """Get Config File as a String."""
        return self.as_text

    def append(self, value, *, skip_special_key_search=False):
        """Append to Config."""
        if not skip_special_key_search and hasattr(type(self), "special_key_map"):
            for key, internal_value in open_key_value_pairs(*value.strip().split("\n")):
                try:
                    special_name, factory = type(self).special_key_map[key]
                    setattr(self, special_name, factory(internal_value))
                except KeyError:
                    pass
        super().append(str(value))

    def insert(self, index, value):
        """Insert Value at Index."""
        return NotImplemented

    def append_key_value_pair(self, key, value, *args, **kwargs):
        """Append Key Value Pair to Config."""
        return self.append(kv_string(key, value), *args, **kwargs)

    def _write_mode_insert(self, name, value):
        """Insert Key-Value Pair into Object."""
        return self.append_key_value_pair(name, value)

    def extend(self, other, *args, **kwargs):
        """Extend Config by another Config."""
        for obj in other:
            self.append(str(obj), *args, **kwargs)

    def add_pairs(self, pairs, *args, **kwargs):
        """Append Key Value Pairs to Config."""
        self.extend(starmap(kv_string, pairs.items()), *args, **kwargs)

    def __add__(self, other):
        """Create Sum of Config."""
        if not isinstance(other, type(self)):
            return super().__add__(map(str, other))
        return super().__add__(other)

    def __iadd__(self, other):
        """Add to Config In Place."""
        self.extend(list(other))
        return self

    def with_arguments(self, *args):
        """Add Arguments to Config."""
        self.append_key_value_pair("arguments", condor_format_sequence(args))

    def append_comments(self, *comments):
        """Add Comments to Config."""
        if not comments:
            return
        if len(comments) == 1:
            comments = comments[0].split("\n")
        self.extend(map(lambda c: f"# {c}", comments))

    def append_email_notification(self, *notification):
        """Add Email Notification to Config."""
        if len(notification) == 1 and isinstance(notification[0], Notification):
            notification = str(notification)
        elif len(notification) == 2:
            notification = str(Notification(*notification))
        else:
            raise TypeError("Not a Notification Type.")
        self.extend(notification.split("\n"))

    def file_remapping(self, key="file_remaps", **mapping):
        """Add File Remapping to Config."""
        self.append_key_value_pair(
            str(key), condor_format_mapping(mapping), skip_special_key_search=True
        )

    def transfer_output_remapping(self, **mapping):
        """Transfer File Output Remapping."""
        self.file_remapping(key="transfer_output_remaps", **mapping)

    def request_(self, name, value):
        """Special Request Tag."""
        self.append_key_value_pair(f"request_{name}", value)

    def queue(self, *args):
        """Add Queue to Config."""
        self.append(f'queue{(" " + condor_format_sequence(args)) if args else ""}')

def minimal_config(
    name,
    executable,
    directory,
    *,
    config_ext="cfg",
    log_ext="log",
    out_ext="out",
    error_ext="err",
    use_absolute_paths=True,
    keep_env=False,
):
    """Construct Minimal Job Configuration."""
    directory = Path(directory)
    if use_absolute_paths:
        build_path = lambda ext: (directory / f"{name}.{ext}").abspath()
    else:
        build_path = lambda ext: directory / f"{name}.{ext}"
    config = JobConfig(path=build_path(config_ext))
    config.name = property(lambda s: name)
    with config.write_mode as config:
        config.executable = Path(executable).abspath()
        config.log = build_path(log_ext)
        config.getenv = keep_env
        config.initialdir = directory.abspath() if use_absolute_paths else directory
        config.output = build_path(out_ext)
        config.error = build_path(error_ext)
    return config

def submit_config(config, path=None, logfile=None, *args, **kwargs):
    """Submit Configuration File."""
    # FIXME: (DRY) generalize path making
    if path is None:
        with tempfile.TemporaryDirectory() as temp_dir:
            temp_path = Path(temp_dir) / "config.txt"
            temp_path.touch()
            temp_path.write_text(config.as_text)
            submit_output = decoded(condor_submit(temp_path, *args, **kwargs))
    else:
        if not path.exists():
            path.parent.makedirs_p()
            path.touch()
            path.write_text(config.as_text)
        submit_output = decoded(condor_submit(path, *args, **kwargs))
    return tuple(
        Job(config, job_id, logfile=logfile)
        for job_id in extract_job_ids(submit_output)
    )

class Job:
    """
    Job Object.

    """

    def __init__(self, config, job_id, submitter=me(), logfile=None):
        """Initialize Job Object."""
        self._config = config
        self._job_id = job_id
        self._submitter = submitter
        self._logfile = logfile
        if logfile is None:
            try:
                self._logfile = self.config.logfile
            except AttributeError:
                pass

    @property
    def config(self):
        """Get Configuration for Job."""
        return self._config

    @property
    def job_id(self):
        """Get JobID of Job."""
        return self._job_id

    @property
    def logfile(self):
        """Get Path of Log File for this Job."""
        return self._logfile

    @property
    def submitter(self):
        """Job Submitter."""
        return self._submitter

    @property
    def is_empty_job(self):
        """Check if Job is Empty."""
        return self._job_id is None or self._config is None

    def remove(self, *args, **kwargs):
        """Remove Job."""
        result = condor_rm(self.job_id, *args, **kwargs)
        self._job_id = None
        return result

    def hold(self, *args, **kwargs):
        """Hold Job."""
        return condor_hold(self.job_id, *args, **kwargs)

    def release(self, *args, **kwargs):
        """Release Job."""
        return condor_release(self.job_id, *args, **kwargs)

    def check(self, wait_timeout=None):
        """Check if Job Has Completed."""
        args = ("-wait", str(wait_timeout)) if wait_timeout else ()
        if self.logfile:
            return not bool(condor_wait(Path(self.logfile).abspath(), *args).returncode)
        else:
            return self.job_id not in user_jobs(self.submitter)

    @property
    def has_completed(self):
        """Check if Job Has Completed."""
        return self.check(wait_timeout=1)

    def on_completion(self, f, *args, wait_timeout=None, **kwargs):
        """Run On Completion of Job."""
        if self.check(wait_timeout=wait_timeout):
            return f(self, *args, **kwargs)
        return False

    def __repr__(self):
        """Representation of Job."""
        return str(self)

    def __str__(self):
        """String conversion of Job."""
        return f"Job({self.job_id})"

def job_dict(*jobs):
    """Make Job Dictionary."""
    return {job.job_id: job for job in jobs}

class JobCompletedException(KeyError):
    """Job Completed Exception."""

    def __init__(self, job):
        """Initialize Exception."""
        super().__init__(f"Job {job.job_id} has already completed.")
        self._job = job

    @property
    def job(self):
        """Get Job which had Completed."""
        return self._job

class JobMap(Mapping):
    """
    Job Mapping Object.

    """

    def __init__(self, *jobs, remove_completed_jobs=False, remove_when_clearing=True):
        """Initialize Job Mapping."""
        self._jobs = job_dict(*jobs)
        self.remove_completed_jobs = remove_completed_jobs
        self.remove_when_clearing = remove_when_clearing

    @property
    def job_ids(self):
        """Return Job Ids."""
        return self.keys()

    @property
    def jobs(self):
        """Return Jobs."""
        return self.values()

    def __getitem__(self, key):
        """Get the Job at given Id."""
        job = self._jobs[key]
        if self.remove_completed_jobs and job.has_completed:
            del self._jobs[key]
            raise JobCompletedException(job)
        return job

    def pop_completed(self):
        """Pop off Jobs that have Completed."""
        out = []
        for job_id, job in tuple(self._jobs.items()):
            if job.has_completed:
                out.append(job)
                del self._jobs[job_id]
        return tuple(out)

    def __iter__(self):
        """Return Iterator over Jobs."""
        if self.remove_completed_jobs:
            self.pop_completed()
        return iter(self._jobs)

    def __len__(self):
        """Return Length of Job List."""
        if self.remove_completed_jobs:
            self.pop_completed()
        return len(self._jobs)

    def clear(self):
        """Clear All Jobs."""
        if self.remove_when_clearing:
            for job_id in self:
                self.remove_job(job_id)
        else:
            self._jobs.clear()

    def update(self, other):
        """Extend Job Map."""
        self._jobs.update(other)

    def append(self, *jobs):
        """Append Jobs to JobMap."""
        self.update(job_dict(*jobs))

    def pop(self, key, *default):
        """Pop Job Out of Map."""
        if len(default) not in (0, 1):
            raise TypeError("Only 1 Default Argument Allowed.")
        try:
            if self.remove_when_clearing:
                return self.remove_job(key)[0]
            else:
                return self._jobs.pop(key)
        except KeyError:
            if len(default) == 1:
                return default
            raise KeyError("Job Not Found.")

    def remove_job(self, job_id, *args, **kwargs):
        """Remove Job."""
        job = self[job_id]
        result = job.remove(*args, **kwargs)
        del self._jobs[job_id]
        return job, result

    def hold_job(self, job_id, *args, **kwargs):
        """Hold Job."""
        return self[job_id].hold(*args, **kwargs)

    def release_job(self, job_id, *args, **kwargs):
        """Release Job."""
        return self[job_id].release(*args, **kwargs)

    def __repr__(self):
        """Representation of JobMap."""
        return repr(self._jobs)

    def __str__(self):
        """String Conversion of JobMap."""
        return str(self._jobs)

class ConfigUnitBase(WriteModeMixin, write_mode_keywords=set()):
    """Configuration Unit Base Structure."""

    def __init_subclass__(
        cls,
        class_ad_name,
        class_ad_id_name,
        fixed_keys,
        make_prefix_config=True,
        **kwargs,
    ):
        """Initialize Configuration Subclasses."""
        super().__init_subclass__(**kwargs)
        setattr(
            cls,
            underscore(class_ad_name),
            classproperty(lambda c: f"$({class_ad_name})"),
        )
        setattr(
            cls,
            underscore(class_ad_id_name),
            classproperty(lambda c: f"$({class_ad_id_name})"),
        )
        for name in fixed_keys:
            fget = (
                lambda s, n=name: kv_string(n, getattr(s, n)) if getattr(s, n) else ""
            )
            setattr(cls, f"{underscore(name)}_kv_str", property(fget))
        if make_prefix_config:

            def _prefix_config(s):
                return JobConfig(
                    getattr(s, f"{underscore(name)}_kv_str") for name in fixed_keys
                )

            setattr(cls, "prefix_config", property(_prefix_config))

    def __init__(self, *args, config_path=None, **kwargs):
        """Initialize Configuration Unit."""
        super().__init__(*args, **kwargs)
        self.path = config_path

    def __str__(self):
        """Get String Representation of ConfigUnit."""
        return str(self.config)

class ProcessUnit(
    ConfigUnitBase,
    class_ad_name="Process",
    class_ad_id_name="ProcId",
    fixed_keys=("initialdir", "output", "error"),
    write_mode_keywords=CONDOR_SUBMIT_COMMANDS,
    write_mode_invalid_keywords=("executable", "log"),
):
    """
    Process Configuration Unit.

    """

    def __init__(self, executable, initialdir=None, output=None, error=None, **kwargs):
        """Initialize Process Configuration Unit."""
        super().__init__(**kwargs)
        self.executable = executable
        self.initialdir = map_value_or(Path, initialdir, None)
        self.output = map_value_or(Path, output, None)
        self.error = map_value_or(Path, error, None)
        self._config = JobConfig()

    def _write_mode_insert(self, name, value):
        """Insert Key-Value Pair into Internal Config."""
        self._config._write_mode_insert(name, value)

    def _write_mode_invalid_keyword(self, name, value):
        """Catch Invalid Keywords for Write-Mode."""
        if name == "executable":
            raise TypeError("Cannot modify executable in ProcessUnit Context.")
        if name == "log":
            raise TypeError("Cannot modify log in ProcessUnit Context.")

    @property
    def config(self):
        """Full Configuration."""
        return self.prefix_config + self._config

    def queue(self, n=1, *args, **kwargs):
        """Add Queue Command."""
        self._config.queue(n=n, *args, **kwargs)

    def queue_in(self, n=1, *args, **kwargs):
        """"""
        return NotImplemented

    def queue_matching(self, n=1, *args, **kwargs):
        """"""
        return NotImplemented

    def queue_from(self, n=1, *args, **kwargs):
        """"""
        return NotImplemented

class ClusterUnit(
    ConfigUnitBase,
    class_ad_name="Cluster",
    class_ad_id_name="ClusterId",
    fixed_keys=("executable", "log"),
    write_mode_keywords=CONDOR_SUBMIT_COMMANDS,
):
    """
    Cluster Configuration Unit.

    """

    def __init__(self, executable, log=None, *process_units, **kwargs):
        """Initialize Cluster Configuration Unit."""
        super().__init__(**kwargs)
        self.executable = executable
        self.log = map_value_or(Path, log, None)
        self.process_units = process_units

    def append_process(self, process_unit):
        """Append Process to Cluster Unit."""
        self.process_units.append(process_unit)

    def append_process_units(self, *process_units):
        """Extend Process Units."""
        self.process_units.extend(process_units)

    @property
    def config(self):
        """Full Configuration."""
        return sum(self.process_units, self.prefix_config)

    def save(self, path=None):
        """Save Config To Path."""
        path = value_or(path, self.path)
        if not path:
            raise TypeError(
                "Path argument must be a valid file path if "
                "stored config has no associated path."
            )
        Path(path).write_text(self.config.as_text)

    def submit(self, *args, use_temporary_file=False, **kwargs):
        """Submit Config As a Condor Job."""
        path = None if use_temporary_file else Path(self.path)
        if path and not path.exists():
            raise FileNotFoundError(f"Path {path} cannot be found.")
        return submit_config(self.config, path=path, logfile=self.log, *args, **kwargs)

class MultiClusterUnit:
    """
    Multi-Cluster Configuration Unit.

    """

    def __init__(self, prefix_config, *cluster_units):
        """Initialize Multi-Cluster Unit."""
        self.prefix_config = prefix_config
        self.cluster_units = cluster_units

    def append_cluster(self, cluster_unit):
        """Append Cluster to Units."""
        self.cluster_units.append(cluster_unit)

    def append_custer_units(self, *cluster_units):
        """Extend Cluster Units."""
        self.cluster_units.extend(cluster_units)

    @property
    def total_config(self):
        """Total Configuration."""
        return sum(self.cluster_units, self.prefix_config)

    def submit(self, *args, use_temporary_file=False, **kwargs):
        """Submit Config As a Condor Job."""
        # FIXME: figure out how to parse a multicluster unit condor_submit output so this can be
        #       joined into one file
        return tuple(
            cluster.submit(use_temporary_file=use_temporary_file, *args, **kwargs)
            for cluster in self.cluster_units
        )

@dataclass
class ConfigRunner:
    """
    Configuration Runner.

    """

    config: JobConfig
    path: InitVar[Path]
    logfile: Path
    jobmap: JobMap

    def __post_init__(self, path):
        """Post-Initialize Config Runner."""
        if Path(path).abspath() != Path(self.config.path).abspath():
            self.config.save_as(path)

    @property
    def config_path(self):
        """Get Configuration Path."""
        return self.config.path

    @property
    def running_job_count(self):
        """Get Current Running Job Count."""
        return len(self.jobmap)

    def submit(self, *args, **kwargs):
        """Submit Jobs."""
        jobs = submit_config(
            self.config, path=self.config_path, logfile=self.logfile, *args, **kwargs
        )
        self.jobmap.append(*jobs)
        return jobs

    def submit_while(self, predicate, *args, wait=None, **kwargs):
        """Submit Jobs while predicate holds."""
        while predicate(self):
            self.submit(*args, **kwargs)
            if wait:
                time.sleep(wait)

class JobManager:
    """
    Job Manager.

    """

    def __init__(self):
        """Initialize Job Manager."""
        self._queue = deque()
        self._config_map = dict()

    def add_config(
        self, name, config, path=None, logfile=None, jobmap=None, **job_map_options
    ):
        """Add Configuration to JobManager."""
        if path is None:
            path = getattr(config, "path", None)
        if logfile is None:
            logfile = getattr(config, "log", None)
        self[name] = ConfigRunner(
            config, path, logfile, value_or(jobmap, JobMap(**job_map_options))
        )
        return self[name]

    def __getitem__(self, name):
        """Get Configuration Runner."""
        return self._config_map[name]

    def __setitem__(self, name, value):
        """Set Configuration Runner."""
        self._config_map[name] = value


# Write a program to read a series of numbers  (stop the input by entering 0).
# Print the largest number and the smallest number entered as well as the difference between those
# numbers.
smallest = number = int(input("Enter a number, stop by entering 0: "))
biggest = 0
#
while number != 0:
    if number > smallest:
        biggest = number
    elif number < smallest:
        smallest = number
    number = int(input("Enter a number, stop by entering 0: "))
print("the smallest number is:", smallest, "the biggest number is:", biggest)


from Generation import Generation
class GenStats:
    'class to hold the average complexity and novelty over all repeats for generation'
    def __init__(self, averageComplexity, averageFitness, averageHighestFitness, averageHighestComplexity, highestComplexity, highestFitness):
        self.averageComplexity = averageComplexity
        self.averageFitness = averageFitness
        self.averageHighestFitness = averageHighestFitness
        self.averageHighestComplexity = averageHighestComplexity
        self.highestComplexity = highestComplexity
        self.highestFitness = highestFitness

class Experiment:
    'Class for each experiment which should hold averaged stats for each generation over all repeats'

    def __init__(self, directory, experimentNumber):

        self.generationStats = [None] * 100 # 100 generations per experiment

        #array for avgComplexity over generations
        self.avgComplexityArray = [None] *100
        #array for avgFitness over generations
        self.avgFitnessArray = [None] *100

        # array of the average highest fitness individuals for each generation over the ten repeats
        self.avgHighestFitnessArray = [None] * 100
        # array of the average complexity of the individuals with the highest fitness at each generation over the ten repeats
        self.avgHighestComplexityArray = [None] * 100

        self.maxComplexityArray = [None] *100

        #highest fitness and associated complexity at generation 100 for each of the repeats
        self.highestFitnessPerRepeat = [None] * 10
        self.highestComplexityPerRepeat = [None] * 10
        #average fitness and average complexity at generation 100 for each of the repeats
        self.averageFitnessPerRepeat = [None] * 10
        self.averageComplexityPerRepeat = [None] * 10

        # complexity of individual that achieved the highest fitness
        self.highestComplexityExperiment = 0.0
        # largest fitness score achieved over all repeats and all generations
        self.highestFitnessExperiment = 0.0

        self.lowestFitnessExperiment = 100.0

        # 100 generations per run
        for generationNumber in range(1,101):
            complexity = 0.0
            fitness = 0.0
            highestFitness = 0.0
            highestComplexity =0.0

            lowestFitness = 100.0

            totalMaxComplexity = 0.0

            totalHighestFitness = 0.0
            totalHighestComplexity = 0.0

            # ten repeats for each experiment
            for repeat in range(10):
                genStats = Generation(directory,experimentNumber,repeat,generationNumber)
                complexity = complexity + genStats.averageComplexity
                fitness = fitness + genStats.averageFitness

                totalHighestComplexity += genStats.highestComplexity
                totalHighestFitness += genStats.highestFitness

                if(genStats.highestFitness>highestFitness):
                    highestFitness = genStats.highestFitness
                    highestComplexity = genStats.highestComplexity

                if(genStats.lowestFitness<lowestFitness):
                    lowestFitness = genStats.lowestFitness

                totalMaxComplexity += genStats.maxComplexity

                if(generationNumber==100):
                    self.highestFitnessPerRepeat[repeat] = genStats.highestFitness
                    self.highestComplexityPerRepeat[repeat] = genStats.highestComplexity
                    self.averageFitnessPerRepeat[repeat] = genStats.averageFitness
                    self.averageComplexityPerRepeat[repeat] = genStats.averageComplexity

            # generations labeled from 1 but indexing from 0
            # average over all repeats for avg of pop at given generation
            averageComplexity = complexity/10
            self.avgComplexityArray[generationNumber-1] = averageComplexity
            averageFitness = fitness/10
            self.avgFitnessArray[generationNumber-1] = averageFitness

            self.maxComplexityArray[generationNumber-1] = totalMaxComplexity/10

            averageHighestComplexity = totalHighestComplexity/10
            self.avgHighestComplexityArray[generationNumber-1] = averageHighestComplexity
            averageHighestFitness = totalHighestFitness/10
            self.avgHighestFitnessArray[generationNumber-1] = averageHighestFitness

            self.generationStats[generationNumber-1] = GenStats(averageComplexity,averageFitness,averageHighestFitness, averageHighestComplexity, highestComplexity,highestFitness)

            if(highestFitness > self.highestFitnessExperiment):
                self.highestFitnessExperiment = highestFitness
            if(highestComplexity > self.highestComplexityExperiment):
                self.highestComplexityExperiment = highestComplexity

            if(lowestFitness<self.lowestFitnessExperiment):
                self.lowestFitnessExperiment = lowestFitness


import cv2
import numpy as np
from imutils.video import WebcamVideoStream
import imutils
import os

import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfile

from collections import defaultdict
from io import StringIO
import matplotlib.pyplot as plt

from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as vis_utils

PATH_TO_LABELS = os.path.join('mscoco_label_map.pbtxt')
NUM_CLASSES = 90
PATH_TO_CKPT = os.path.join('ssd_mobilenet_v1_coco_2017_11_17', 'frozen_inference_graph.pb')

# loading a frozen tensorflow model into memory
detection_graph = tf.Graph()
with detection_graph.as_default():
    od_graph_def = tf.GraphDef()
    with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
        serialized_graph = fid.read()
        od_graph_def.ParseFromString(serialized_graph)
        tf.import_graph_def(od_graph_def, name='')

# loading label map
label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)

stream = WebcamVideoStream(src=0).start()

with detection_graph.as_default():
    with tf.Session(graph=detection_graph) as sess:
        while True:
            frame = stream.read()
            frame_expanded = np.expand_dims(frame, axis=0)
            frame_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
            boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
            scores = detection_graph.get_tensor_by_name('detection_scores:0')
            classes = detection_graph.get_tensor_by_name('detection_classes:0')
            num_detections = detection_graph.get_tensor_by_name('num_detections:0')

            (boxes, scores, classes, num_detections) = sess.run(
                [boxes, scores, classes, num_detections],
                feed_dict={frame_tensor : frame_expanded}
            )

            vis_utils.visualize_boxes_and_labels_on_image_array(
                frame,
                np.squeeze(boxes),
                np.squeeze(classes).astype(np.uint32),
                np.squeeze(scores),
                category_index,
                use_normalized_coordinates=True,
                line_thickness=5
            )

            cv2.imshow('Object Detection', frame)
            key = cv2.waitKey(1)
            if key == ord('q'):
                cv2.destroyAllWindows()
                break


class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if nums == []:
            return False
        G = nums[0]
        #使用穷举法，穷举出G能够达到的最大值
        for i in range(1,len(nums)):
            #当G小于i的时候，代表G达不到i，因此返回False
            if G < i:
                return False
            G = max(G, nums[i]+i)

        return G >= len(nums)-1


import es_client as cli

es = cli.get_client()

res = es.search(index="contacts", body={"query": {"match_all": {}}})

print("Found record(s): %d" % res['hits']['total']['value'])

for hit in res['hits']['hits']:
    row = hit["_source"]
    print("[%s] %s (%s)" % (row['timestamp'], row['name'], row['age']))


import RPi.GPIO as GPIO
import time
import curses
from Car import Car
car = Car()
screen = curses.initscr()
curses.noecho()
curses.cbreak() # don't have to press enter
screen.keypad(True)
speed = 50

GPIO.setwarnings(False)

EchoPin = 18
TrigPin = 16
GPIO.setmode(GPIO.BOARD)

GPIO.setup(EchoPin, GPIO.IN)
GPIO.setup(TrigPin, GPIO.OUT)

def distance():
    GPIO.output(TrigPin, GPIO.LOW)
    time.sleep(0.000002)
    GPIO.output(TrigPin, GPIO.HIGH)
    time.sleep(0.000015)
    GPIO.output(TrigPin, GPIO.LOW)

    t3 = time.time()

    while not GPIO.input(EchoPin):
        t4 = time.time()
        if (t4 - t3) > 0.03:
            return -1
    t1 = time.time()
    while GPIO.input(EchoPin):
        t5 = time.time()
        if (t5 - t1) > 0.03:
            return -1

    t2 = time.time()
    time.sleep(0.01)
    return ((t2 - t1) * 340 / 2) * 100

try:
    while True:
        char = screen.getch()
        if char == ord('q'):
            break
        elif char == curses.KEY_UP:
            print("up")
            car.control_car(speed,speed)
        elif char == curses.KEY_DOWN:
            print("down")
            car.control_car(-speed,-speed)
        elif char == curses.KEY_RIGHT:
            print("right")
            car.control_car(speed,-speed)
        elif char == curses.KEY_LEFT:
            print("left")
            car.control_car(-speed,speed)
        elif char == ord('m'):
            print("stop")
            car.control_car(0,0)
        print(f"Distance: {distance()}")
finally:
    curses.nocbreak()
    screen.keypad(0)
    curses.echo()
    curses.endwin()


import datetime
from urllib.request import urlopen

import cv2
import numpy as np
import superai_schema.universal_schema.task_schema_functions as df
from tensorflow import keras
from tensorflow.keras import layers

from superai.meta_ai import BaseModel
from superai.utils import log

class MyEncodeDecodeModel(BaseModel):
    model = None

    def __init__(self, *args, **kwargs):
        super(MyEncodeDecodeModel, self).__init__(*args, **kwargs)
        if self.logger_dir is None:
            self.logger_dir = "logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")

    def load_weights(self, weights_path):
        self.model = self.define_model()
        self.model.load_weights(weights_path)

    def predict(self, input, context=None):
        log.info(f"Predict Input: {input}")
        input = self.preprocess(input)
        pred = self.model.predict(input)
        return self.postprocess(pred)

    def preprocess(self, input, preprocess_params=None):
        image_url = input["image_url"]
        req = urlopen(image_url)
        arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
        img = cv2.imdecode(arr, cv2.IMREAD_GRAYSCALE)
        img = cv2.resize(img, (28, 28), interpolation=cv2.INTER_AREA)
        input = np.reshape(img, (1, 28 * 28))
        return input

    def postprocess(self, pred, postprocess_params=None):
        input = np.argmax(pred[0])
        return [
            {
                "prediction": {
                    "mnist_class": df.exclusive_choice(
                        choices=list(map(str, range(10))),
                        selection=int(input),
                    )
                },
                "score": float(pred[0][int(input)]),
            }
        ]

    def train(
        self,
        model_save_path,
        encoder_trainable=True,
        decoder_trainable=True,
        hyperparameters=None,
        model_parameters=None,
        **kwargs,
    ):
        (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

        # Preprocess the data (these are NumPy arrays)
        x_train = x_train.reshape(60000, 784).astype("float32") / 255
        x_test = x_test.reshape(10000, 784).astype("float32") / 255

        y_train = y_train.astype("float32")
        y_test = y_test.astype("float32")

        # Reserve 10,000 samples for validation
        x_val = x_train[-10000:]
        y_val = y_train[-10000:]
        x_train = x_train[:-10000]
        y_train = y_train[:-10000]

        self.model = self.define_model(encoder_trainable, decoder_trainable)

        self.model.compile(
            optimizer=keras.optimizers.RMSprop(learning_rate=hyperparameters.learning_rate),
            loss=keras.losses.SparseCategoricalCrossentropy(),
            metrics=[keras.metrics.SparseCategoricalAccuracy()],
        )

        tensorboard_callback = keras.callbacks.TensorBoard(log_dir=self.logger_dir, histogram_freq=1)
        # Adapted from https://www.tensorflow.org/tutorials/keras/save_and_load to support encoder decoder structure
        cp_callback = keras.callbacks.ModelCheckpoint(
            filepath=model_save_path,
            save_weights_only=True,
            verbose=1,
        )
        log.info("Fit model on training data")
        history = self.model.fit(
            x_train,
            y_train,
            batch_size=hyperparameters.batch_size,
            epochs=hyperparameters.epochs,
            # We pass some validation for
            # monitoring validation loss and metrics
            # at the end of each epoch
            validation_data=(x_val, y_val),
            callbacks=[tensorboard_callback, cp_callback],
        )

        # Picked from https://www.tensorflow.org/guide/keras/save_and_serialize
        # self.model.save(model_save_path)

        # we could also store the model config in a json format in the save path
        # json_config = self.model.to_json()
        # with open(os.path.join(model_save_path, "model_config.json"), "w") as json_writer:
        #     json.dump(json_config, json_writer)

    def define_model(self, train_encoder=True, train_decoder=True):
        inputs = keras.Input(shape=(784,), name="digits")
        encoder = self._encoder(trainable=train_encoder)(inputs)
        decoder = self._decoder(trainable=train_decoder)(encoder)
        self.model = keras.Model(inputs=inputs, outputs=decoder)
        return self.model

    def _encoder(self, input_data=None, trainable=True):
        encoder = keras.Sequential(
            [
                keras.Input(shape=(784,), name="digits"),
                layers.Dense(64, activation="relu", name="dense_1"),
                layers.Dense(64, activation="relu", name="dense_2"),
            ]
        )
        encoder.trainable = trainable
        return encoder

    def _decoder(self, input_data=None, trainable=True):
        decoder = keras.Sequential(
            [
                keras.Input(shape=(64,)),
                layers.Dense(len(self.output_parameters.choices), activation="softmax", name="predictions"),
            ]
        )
        decoder.trainable = trainable
        return decoder

    def to_tf(self):
        return self.model


# Домашнє завдання:
# 1. Створіть клас для опису товару. У якості атрибутів товару можете використовувати значення ціни товару, опису
# товару, габарити товару. Створіть пару екземплярів вашого класу та протестуйте їхню роботу.
# 2. Створіть клас "Покупець". У якості атрибутів можна використовувати прізвище, ім'я, по батькові, мобільний телефон
# тощо.
# 3. Створіть клас "Замовлення". Замовлення може містити декілька товарів певної кількості. Замовлення має містити дані
# про користувача, який його здійснив. Реалізуйте метод обчислення сумарної вартості замовлення. Визначте метод str()
# для коректного виведення інформації про це замовлення.

from my_except import *
import product
import customer
import order

try:
    product1 = product.Product('apple', 12.00, 1, 'green apple')
    product2 = product.Product('orange', 14.00, 1, 'orange Egypt')
    product3 = product.Product('carrot', 1.00, 1, 'carrot Ukraine')
    product4 = product.Product('raspberry', 122.00, 1, 'raspberry fresh')
except ErrorPrice as er:
    print(er)

cust = customer.Customer('name', 'surname', '123123123')

order1 = order.Order(cust)
try:
    order1.add_product(product1, 8)
    order1.add_product(product2, 5)
    order1.add_product(product3, 9)
    order1.add_product(product4, 5)
    order1.add_product(product3, -1)
    order1.add_product(product4, 6)
except ErrorCounts as er:
    print(er)

print(str(order1))
print(f'{"*" * 30} ITER + ITEM {"*" * 30}')

print(f"len: {len(order1)}")
item, kg = order1[0]
print("\n")
print(f"index {item} count: {kg}")
print("\n")
for item, kg in order1:
    print(f"for {item} count: {kg}")

x = order1[::-1]
print("\n")
for i, j in x:
    print(f"slice:{i} count {j} ")


# 1. CountFactors
# Count factors of given number n.
def divisors(n):
    i = 1
    result = 0
    while (i * i < n):
        if n % i == 0:
            result += 2
        i += 1
    if i *  i == n:
        result += 1
    return result
print(divisors(36))

def primality(n):
    i = 2
    while i * i <= n:
        if n % i == 0:
            return False
        i += 1
    return True
print(primality(36))

def coins0(n):
    result = 0
    coin = [0] * (n+1)
    for i in range(1, n+1):
        k = i
        while k <= n:
            coin[k] = (coin[k] + 1) % 2
            k += i
        result += coin[i]
    return result
print(coins0(9))

def coins(n):
    i = 2
    count = 0
    while i * i <= n:
        if n % i == 0:
            count += 2
        i += 1
    return i-1
print(coins(9))

# 2.MinPerimeterRectangle
# Find the minimal perimeter of any rectangle whose area equals N.
def MinPerimeterRectangle0(N):
    # write your code in Python 3.6
    i = 1
    perimeter = 2 * (1+N)
    while i * i <= N:
        if N % i == 0 :
            if 2*(i + N//i) < perimeter:
                perimeter = 2*(i + N//i)
        i += 1
    return perimeter
print(MinPerimeterRectangle0(30))

# 3.Peaks
# Divide an array into the maximum number of same-sized blocks,
# each of which should contain an index P such that A[P - 1] < A[P] > A[P + 1].
def peaks0(A):
    # write your code in Python 3.6
    n = len(A)
    count = 0
    i = 1
    while (i < n-1):
        if (A[i] > A[i-1]) and (A[i] > A[i+1]):
            count += 1
            i += 2
        i += 1
    return count
print(peaks0([1,2,3,4,5,6]))

def peaks(A):
    peaks = []
    for idx in range(1, len(A)-1):
        if A[idx-1] < A[idx] > A[idx+1]:
            peaks.append(idx)
    if len(peaks) == 0:
        return 0
    for size in range(len(peaks), 0, -1):
        if len(A) % size == 0:
            block_size = len(A) // size
            found = [False] * size
            found_cnt = 0
            for peak in peaks:
                block_nr = peak//block_size
                if found[block_nr] == False:
                    found[block_nr] = True
                    found_cnt += 1
            if found_cnt == size:
                return size
    return 0
print(peaks([1,2,3,4,5,6]))

# 1. Flags
# Find the maximum number of flags that can be set on mountain peaks.
def flags0(A):
    from math import sqrt
    A_len = len(A)
    next_peak = [-1] * A_len
    peaks_count = 0
    first_peak = -1
    # Generate the information, where the next peak is.
    for index in range(A_len-2, 0, -1):
        if A[index] > A[index+1] and A[index] > A[index-1]:
            next_peak[index] = index
            peaks_count += 1
            first_peak = index
        else:
            next_peak[index] = next_peak[index+1]
    if peaks_count < 2:
        # There is no peak or only one.
        return peaks_count
    max_flags = 1
    max_min_distance = int(sqrt(A_len))
    for min_distance in range(max_min_distance + 1, 1, -1):
        # Try for every possible distance.
        flags_used = 1
        flags_have = min_distance-1 # Use one flag at the first peak
        pos = first_peak
        while flags_have > 0:
            if pos + min_distance >= A_len-1:
                # Reach or beyond the end of the array
                break
            pos = next_peak[pos+min_distance]
            if pos == -1:
                # No peak available afterward
                break
            flags_used += 1
            flags_have -= 1
        max_flags = max(max_flags, flags_used)
    return max_flags
print(flags0([1,5,3,4,3,4,1,2,3,4,6,2]))

#binary search method
from math import sqrt
def transform(A):
    peak_pos = len(A)
    last_height = A[-1]
    for p in range(len(A) - 1, 0, -1):
        if (A[p - 1] < A[p] > last_height):
            peak_pos = p
        last_height = A[p]
        A[p] = peak_pos
    A[0] = peak_pos
def can_fit_flags(A, k):
    flag = 1 - k
    for i in range(k):
        # we plant the next flag at A[flag + k]
        if flag + k > len(A) - 1:
            return False
        flag = A[flag + k]
    return flag < len(A)  # last flag planted successfully
def flags(A):
    transform(A)
    lower = 0
    upper = int(sqrt(len(A))) + 2
    assert not can_fit_flags(A, k=upper)
    while lower < upper - 1:
        next = (lower + upper) // 2
        if can_fit_flags(A, k=next):
            lower = next
        else:
            upper = next
    return lower
print(flags([1,5,3,4,3,4,1,2,3,4,6,2]))


from django.contrib import admin
from django.urls import path

from . import views

urlpatterns = [
    path("",views.home),
    path('login',views.login_view,name='login'),
    path('logout',views.logout_view,name='login'),
    path('register',views.register_view,name='register'),
    path('add-blog',views.add_blog,name='add_blog'),
    path('blog_detail/<slug>',views.blog_detail,name='blog_detail'),
]


import argparse
from PIL import Image

def resize_image(input_path, output_path, target_width, target_height):
    try:
        # 打开输入图像
        image = Image.open(input_path)

        # 调整图像大小
        resized_image = image.resize((target_width, target_height), Image.ANTIALIAS)

        # 保存调整后的图像
        resized_image.save(output_path)

        print("图像已成功调整大小并保存到", output_path)
    except Exception as e:
        print("出现错误：", e)

def main():
    parser = argparse.ArgumentParser(description="调整图像大小")
    parser.add_argument("--i", help="输入图像路径", required=True)
    parser.add_argument("--o", help="输出图像路径", required=True)
    parser.add_argument("--w", type=int, help="目标宽度", required=True)
    parser.add_argument("--h", type=int, help="目标高度", required=True)

    args = parser.parse_args()

    resize_image(args.i, args.o, args.w, args.h)

if __name__ == "__main__":
    main()


inp = input('Enter a file name: ')

try:
    fhand = open(inp)
except IOError:
    print('FIle not found!')
    quit()

wordsDic = {}
counter = 0

for line in fhand:
    words = line.split()
    for word in words:
        if word not in wordsDic:
            wordsDic[word] = counter
            counter = counter + 1

print(wordsDic)


import numpy as np
import matplotlib.pyplot as plt

#the characterizing coefficient N
step_size = 0.05

#number of steps
sample_num = 1000

time = np.arange(0, sample_num+1)

#keeping track of all positions throughout the walk
walk = np.zeros((sample_num+1))

#initial position (y-axis) for random walk to begin from
position = 0

#take steps
for step in range(0, sample_num):
    #draw from uniform distribution [0,1)
    r = np.random.rand(1)

    if r<=0.5:
        #step down coeffN units from current position
        position -= step_size
    else:
        #step up coeffN units from current position
        position += step_size

    #update
    walk[step+1] += position

#plot results
plt.plot(time, walk, lw=2)

plt.title("Simulated Random Walk")
plt.xlabel("Time (sec)")
plt.ylabel("Noise Magnitude (unit)")
plt.grid(b=True)
plt.show()


'''
スライド用
'''
# %%
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

#%%
# 半径を指定
r = 1.0

# ラジアンを作成
# q: 0.0 ~ 2.0*np.piとは何か
# a: 0.0 ~ 2.0*np.piの範囲で81個の等間隔の数値を生成
t = np.linspace(start=0.0, stop=2.0 * np.pi, num=81)
u = np.linspace(start=0.0, stop=2.0 * np.pi, num=81)

# 格子点を作成
T, U = np.meshgrid(t, u)

# 球面座標を直交座標に変換
X = r * np.sin(T) * np.cos(U)
Y = r * np.sin(T) * np.sin(U)
Z = r * np.cos(T)

# %%
XYZ = np.stack([X.flatten(), Y.flatten(), Z.flatten()], axis=1)

# %%
# 球面を作図
fig, ax = plt.subplots(
    figsize=(15, 15), facecolor="white", subplot_kw={"projection": "3d"}
)
ax.plot_wireframe(X, Y, Z, alpha=0.5)  # くり抜き曲面
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
fig.suptitle("spherical surface", fontsize=20)
ax.set_aspect("equal")
plt.show()

#%%
# 座標をデータフレームに格納
df = pd.DataFrame(XYZ, columns=["x", "y", "z"])
df.to_csv("geocentric_cartesian_coordinates.csv", index=False)
# %%


#!/usr/bin/python3

def safe_print_list_integers(my_list=[], x=0):
    count = 0
    for i in range(x):
        try:
            print("{:d}".format(my_list[i]), end="")
            count += 1
        except IndexError:
            print("IndexError: list index out of range")
    print()
    return count


import siibra
atlas = siibra.atlases.get("human")
# print the spaces defined in the atlas
print(atlas.spaces)

# %%
# Choose a space
space = atlas.spaces.get("icbm 2009c asym")
print(space.name)
# and a region
v1_left = atlas.get_region("v1 left", parcellation='julich 2.9')
print(v1_left)

# %%
# The `Region.spatial_props()` method computes the centroid and volume of a
# brain region.  Note that a brain region
# might in general consist of multiple separated components in the space.
# Also note that in `siibra`, spatial properties are always represented in
# millimeter units of the physical coordinate system of the reference space,
# not in voxel units.
from pprint import pprint
props = v1_left.spatial_props(space=space)
pprint(props)

# %%
# The returned centroid is `siibra.Point` object. Such spatial primitives are
# covered in more detail in :ref:`locations`. For now, we just acknowledge
# that this minimizes misinterpretation of the coordinates, since a siibra
# Point is explicitly linked to its space.
centroid = props.components[0].centroid
print(centroid)
centroid.space.name

# %%
# We can also generate a binary mask of the region in a given space and maptype, which
# gives us a Nifti1Image object as provided by `nibabel <https://nipy.org/nibabel/>`_,
# and which we can directly visualize using plotting functions like the ones in
# `nilearn <https://nilearn.github.io/stable/index.html>`_:
mask = v1_left.fetch_regional_map(space, maptype="labelled")
from nilearn import plotting
plotting.plot_roi(mask, title=f"Mask of {v1_left.name} in {space.name}")


# A+B-4
list = []

while True:
    try:
        a, b = map(int, input().split())
        sum = a + b
        list.append(sum)
    except EOFError:
        break

n = 0

while n <= len(list)-1:
    print(list[n])
    n = n + 1


import tensorflow as tf

from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt

import utils.plot_utils as plot_utils

print(tf.__version__)

# import and normalize the data
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()

train_images, test_images = train_images / 255.0, test_images / 255.0

print(train_labels[0])

# Display 25 images
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

# plt.figure(figsize=(10,10))

# for i in range(25):
#     plt.subplot(5, 5, i + 1)
#     plt.xticks([])
#     plt.yticks([])
#     plt.grid(False)
#     plt.imshow(train_images[i])
#     plt.xlabel(class_names[train_labels[i][0]])
# plt.show()

# Data Augmentation
data_augmentation = tf.keras.Sequential([
    layers.RandomFlip("horizontal", input_shape = (32, 32, 3)),
    layers.RandomRotation(0.1),
    layers.RandomZoom(0.1)
])

# Add the convolution layers
model = models.Sequential()
model.add(data_augmentation)
model.add(layers.Conv2D(32, (3,3), activation = "relu", input_shape = (32, 32, 3)))
#model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3,3), activation = "relu"))
model.add(layers.Conv2D(64, (3,3), activation = "relu"))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3,3), activation = "relu"))

# Add dropout layer
model.add(layers.Dropout(0.2))

# Add the dense layers to get an output
model.add(layers.Flatten())
model.add(layers.Dense(64, activation = "relu"))
model.add(layers.Dense(10))

model.compile(optimizer = tf.keras.optimizers.Adam(learning_rate = 0.0005),
              loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits = True),
              metrics = ["accuracy"])

history = model.fit(train_images, train_labels, epochs = 50, validation_split = 0.1)

plot_utils.plot_history(history, aspects = ["accuracy", "loss"], to_file = True)

# Convert model to a TF Lite model
converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = converter.convert()

with open("model.tflite", "wb") as f:
    f.write(tflite_model)


favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}

persons = ['siva', 'phil', 'venkat', 'edward']

for person in persons:
  participated_persons = list(favorite_languages.keys())
  if person in participated_persons:
    print(f'Hi {person.title()}, Thank you for reponding')
  else:
    print(f'Hi {person.title()}, Please take my favorite language poll')


def main():
    numbers = []

    while True:
        try:
            num = float(input("Введите число (для завершения введите 0): "))
        except ValueError:
            print("Ошибка: введите корректное число")
            continue

        numbers.append(num)
        if sum(numbers) == 0:
            break

    sum_of_squares = sum(x ** 2 for x in numbers)
    print(f"Сумма квадратов введенных чисел: {sum_of_squares}")

if __name__ == "__main__":
    main()


import copy

from src.common.i_board import IBoard, BoardType
from src.common.action import action_type

class MarbleBoard(IBoard):
    """
    A MarbleBoard is a:
    - list(list(int)):
        2D list representing the 2D board layout with each cell containing either 0 or 1, where a 0 represents no game piece at that spot and 1 represents there is a game piece at that spot and 2 for any dead spot.

    A MarbleBoard represents a square grid of tiles for the game of marble solitaire or peg solitaire (English Board) with layout of the indices as specified below:

    ╔═══════╤═══════╤═══════╗
    ║ (0,0) │ (0,1) │ (0,2) ║
    ╠═══════╪═══════╪═══════╣
    ║ (1,0) │ (1,1) │ (1,2) ║
    ╟───────┼───────┼───────╢
    ║ (2,0) │ (2,1) │ (2,2) ║
    ╚═══════╧═══════╧═══════╝

    This is a initial implementation of this type of board game only dealing with the popular cross configuration with 3x2 sizes as shown below:

        · · ·
        · · ·
    · · · · · · ·
    · · · o · · ·
    · · · · · · ·
        · · ·
        · · ·

    A MarbleBoard implements the IBoard interface.
    """

    HOLE = 0
    HAS_PIECE = 1
    INVALID = 2

    def __init__(self):
        """Initializes a clean marble solitaire board with the cross configuration.
        """
        self.width = 2
        self.height = 3
        self.size = 2 * self.width + self.height
        self.layout = self.generate_cross_layout()

    def generate_cross_layout(self):
        """Generates a cross layout for the marble board.

        Returns:
            list(list(int)): a 2D list representing the cross layout
        """
        cross_layout = []

        for r in range(self.size):
            cross_layout.append([])
            for c in range(self.size):
                if self.valid_posn((r,c)):
                    if not self.is_starting((r,c)):
                        cross_layout[r].append(self.HAS_PIECE)
                    else:
                        cross_layout[r].append(self.HOLE)
                else:
                    cross_layout[r].append(self.INVALID)

        return cross_layout

    def valid_posn(self, posn):
        """Determines whether the given position is a valid position on the marble board, this includes both out of board and the dead spots.

        Args:
            posn (Posn): a position to check

        Returns:
            bool: a boolean with true indicating that the position is valid and false otherwise
        """
        return self.in_bound(posn) \
                    and (self.in_middle_portion(posn) \
                            or self.in_side_portion(posn))

    def in_bound(self, posn):
        """Check whether the given position is in bound of the marble board.

        Args:
            posn (Posn): a position to check

        Returns:
            bool: a boolean with true indicating that it's in bound
        """
        return posn[0] < self.size and posn[0] >= 0 \
                    and posn[1] < self.size and posn[1] >= 0

    def in_middle_portion(self, posn):
        """Check whether the given position is in the middle portion of the marble board with valid column positions extending the whole size of the board.

        Args:
            posn (Posn): a position to check

        Returns:
            bool: a boolean with true indicating that it's in the middle
        """
        return posn[0] >= self.width and posn[0] < (self.size - self.width)

    def in_side_portion(self, posn):
        """Check whether the given position is in the size portion of the marble board with valid column positions extending the just the side of the cross layout of the board.

        Args:
            posn (Posn): a position to check

        Returns:
            bool: a boolean with true indicating that it's in the sid
        """
        return posn[1] >= self.width and posn[1] < (self.size - self.width)

    def is_starting(self, posn):
        """Determines whether the given position is the starting empty position on the marble board.

        Args:
            posn (Posn): a position to check

        Returns:
            bool: a boolean with true indicating that the position is the starting empty position and false otherwise
        """
        return (posn[0] == 3) and (posn[1] == 3)

    def set_layout(self, layout):
        """Sets the layout of the board to the given one.

        Args:
            layout (2d list): 2d list of the board grid layout

        Returns:
            bool: a boolean with true indicating layout set successfully
        """
        try:
            self.layout = copy.deepcopy(layout)
            return True
        except Exception as e:
            print(e)
        return False

    def valid_actions(self, player):
        """Finds a list of valid actions for the player on the marble board, a valid action are any moves that a marble jumps over another into an empty spot.

        Args:
            player (str): a color string representing the player

        Returns:
            list(Action): a list of actions
        """
        return [(from_posn, hole) for hole in self.hole_positions() for from_posn in self.reachable_positions(hole)]

    def hole_positions(self):
        return [(r,c) for r in range(self.size) for c in range(self.size) if self.layout[r][c] == self.HOLE]

    def reachable_positions(self, from_hole):
        """Finds the list of reachable positions from the given hole on the marble board, a position is reachable from a hole if in a straight line the marble from the next position down has a marble to jump over.

        Args:
            from_hole (Posn): a position of a hole

        Returns:
            list(Posn): a list of positions reachable
        """
        reachable_positions = []
        directional_deltas = self.get_directional_deltas()

        for delta_r, delta_c in directional_deltas:
            stepping_stone = (from_hole[0] + delta_r, from_hole[1] + delta_c)
            if self.valid_posn(stepping_stone) \
                    and not self.empty(stepping_stone):
                from_posn = (stepping_stone[0] + delta_r, stepping_stone[1] + delta_c)
                if self.valid_posn(from_posn) and not self.empty(from_posn):
                    reachable_positions.append(from_posn)

        return reachable_positions

    def get_directional_deltas(self):
        """Finds the delta changes of one position for all 4 directional movements on the marble board.

        Returns:
            list(tuple(int, int)): a list of delta changes where each element is a tuple of row and column delta change
        """
        return [(0, 1),(0, -1),(1, 0),(-1, 0)]

    def empty(self, posn):
        return self.layout[posn[0]][posn[1]] == self.HOLE

    def apply_action(self, player, action):
        """Applies the given action for the player on the marble board.

        Args:
            player (str): a color string reprenting the player
            action (Action): an action to apply

        Returns:
            tuple(bool, int): a tuple with the first a boolean indicating whether the action was successful and the second a reward if it was
        """
        success = False
        reward = 0

        if action_type(action).is_valid() \
                and action in self.valid_actions(player):

            self.apply_jump(*action)
            reward = 1
            success = True

        return success, reward

    def apply_jump(self, from_posn, to_posn):
        """Applies the jump from the given positions on the marble board, updates the layout accordingly after the jump.

        Args:
            from_posn (Posn): a postion to jump from
            to_posn (Posn): a position to jump to
        """
        self.layout[to_posn[0]][to_posn[1]] = self.HAS_PIECE
        self.layout[from_posn[0]][from_posn[1]] = self.HOLE

        stepping_r, stepping_c = self.stepping_stone(from_posn, to_posn)
        self.layout[stepping_r][stepping_c] = self.HOLE

    def stepping_stone(self, from_posn, to_posn):
        """Finds the position between the from and to posn used as the stepping stone for the jump.

        Args:
            from_posn (Posn): a position
            to_posn (Posn): a position

        Returns:
            Posn: a position of the stepping stone
        """
        r = from_posn[0]
        c = from_posn[1]

        delta_r = to_posn[0] - from_posn[0]
        if delta_r != 0:
            r += 1 if delta_r > 0 else -1
        else:
            c += 1 if to_posn[1] > from_posn[1] else -1

        return r, c

    def game_over(self):
        """Determines if the game is over with the board state.

        Returns:
            bool: a boolean with true indicating the game is over
        """
        return (not self.valid_actions(""))

    def serialize(self):
        """Serilizes the marbale board into a map of it's data representation.

        Returns:
            dict(X): a dictionary of attributes in the format specified as below:
            {
                "board-type": BoardType.value,
                "info": {
                    "layout: list(list(int)),
                }
            }
        """
        return {
            "board-type": BoardType.MARBLE.value,
            "info": {
                "layout": copy.deepcopy(self.layout),
            }
        }


# aclint: py2 py3
# mypy: allow-untyped-defs
from __future__ import absolute_import, print_function

import os
import typing as T

from skymarshal import parser, syntax_tree, tokenizer

# Path -> packages map of things we already parsed.
FILE_CACHE = dict()  # type: T.Dict[T.Tuple[str, bool], T.List[syntax_tree.Package]]

def merge_packages(packages, package_map=None):
    # type: (T.List[syntax_tree.Package], T.Dict[str, syntax_tree.Package]) -> T.Dict[str, syntax_tree.Package]
    """Converts a list of packages to a map.
    NOTE(matt): This makes copies instead of modifying the input packages.
    """
    if package_map is None:
        package_map = {}
    # Collect lcmtypes by package.
    for package in packages:
        if package.name not in package_map:
            # This is a new package. Create a copy so the original isn't modified.
            package_map[package.name] = syntax_tree.Package(
                name=package.name,
                type_definitions=list(package.type_definitions.values()),
            )
        else:
            # This package already exists: add the new structs and enums to the existing
            # package object.
            package_map[package.name].extend_with_package(package)
    return package_map

def find_lcmtypes_dirs(root_path, excluded_paths=None):
    remaining_excluded_paths = set(excluded_paths or [])
    for dirpath, dirnames, _ in os.walk(root_path, topdown=True, followlinks=False):
        # directory path relative to root
        rel_dir = os.path.relpath(dirpath, root_path)

        if rel_dir in remaining_excluded_paths:
            remaining_excluded_paths.remove(rel_dir)
            dirnames[:] = []
            continue

        if os.path.basename(dirpath) == "lcmtypes":
            yield rel_dir
            # don't recurse into lcmtypes directories
            dirnames[:] = []

def _flatten_paths(lcmtypes_paths):
    # type: (T.Iterable[str]) -> T.Iterable[str]
    for path in lcmtypes_paths:
        if not os.path.exists(path):
            continue

        if os.path.isdir(path):
            for fname in os.listdir(path):
                if fname.endswith(".lcm"):
                    yield os.path.join(path, fname)
        elif path.endswith(".lcm"):
            yield path

def parse_lcmtypes(
    lcmtypes_paths,  # type: T.Iterable[str]
    verbose=False,  # type: bool
    print_debug_tokens=False,  # type: bool
    cache_parser=False,  # type: bool
    allow_unknown_notations=False,  # type: bool
    include_source_paths=True,  # type: bool
):
    # type: (...) -> T.Dict[str, syntax_tree.Package]
    """
    Parse LCM definitions and assemble a map from package to syntax tree nodes.

    :param lcmtypes_paths: Iterable of .lcm file paths, or paths to folders of .lcm files, to parse.
    :param print_debug_tokens: If true, print debug info.
    :param cache_parser: If true, cache YACC parser across each package
    :param include_source_paths: If true, include the source file in the generated bindings
    :return: Map from package name to syntax_tree.Package.
    """
    package_map = {}  # type: T.Dict[str, syntax_tree.Package]

    for path in _flatten_paths(lcmtypes_paths):
        if (path, include_source_paths) in FILE_CACHE:
            # Get the original list from the cache.
            packages = FILE_CACHE[(path, include_source_paths)]
        else:
            with open(path) as src_file:
                src = src_file.read()

            if print_debug_tokens:
                tokenizer.debug_tokens(src)
            if verbose:
                print(path)
            packages = parser.lcmparse(
                src,
                verbose=verbose,
                cache=cache_parser,
                debug_src_path=path,
                allow_unknown_notations=allow_unknown_notations,
            )

            # Add source files to types, which the parser doesn't know about
            if include_source_paths:
                for package in packages:
                    for typedef in package.type_definitions.values():
                        typedef.set_source_file(path)

            # Cache the raw package list for this path.
            FILE_CACHE[(path, include_source_paths)] = packages

        # Copy the packages into the map
        merge_packages(packages, package_map)

    return package_map


from openerp.osv import fields, orm
from openerp.tools.translate import _

class account_invoice_merge(orm.TransientModel):
    _name = 'account.invoice.merge'

    _columns = {
        'grouped' : fields.boolean('Sum quantity of lines'),
        'journal_id' : fields.many2one('account.journal', 'Journal'),
    }

    def _openForm(self, cr, uid, domain, context=None):
        """
            Invoice is merge then Open the merge Invoice in tree view.
        """
        mod_obj = self.pool.get('ir.model.data')
        act_obj =  self.pool.get('ir.actions.act_window')
        inv_obj = self.pool.get('account.invoice')
        type = inv_obj.browse(cr, uid, context.get('active_id'), context=context).type
        if type == 'in_invoice':
            xml_id = 'action_invoice_tree2'
        if type == 'out_invoice':
            xml_id = 'action_invoice_tree1'
        result = mod_obj._get_id(cr, uid, 'account', xml_id)
        id = mod_obj.read(cr, uid, result, ['res_id'])['res_id']
        result = act_obj.read(cr, uid, id, context=context)
        result['domain'] = domain
        return result

    def mergeInvoices(self, cr, uid, ids, context=None):
        """
            Call the merge_invoice method of account.invoice object and pass the related parameter.
        """
        if not context:
            context = {}
        inv_obj = self.pool.get('account.invoice')
        current = self.browse(cr, uid, ids[0], context=context)
        invoice_ids = context.get('active_ids') or []
        new_invoice = inv_obj.merge_invoice(cr, uid, invoice_ids, current.grouped, current.journal_id and current.journal_id.id or False, context=context)
        return self._openForm(cr, uid, "[('id','=', "+ str(new_invoice)  +")]",context)

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:


'''

Test 2 :  Chef will make 2 moves: pick up both the elements in the first two positions (that is, 4 and 2), remove the larger one (4), incurring a cost equal to the smaller one (2). Then pick up the last two elements (2 and 5), remove 2 (the larger one), incurring a cost equal to 2. The total cost incurred will be equal to 4.

'''

def min_cost_operations(a):

    cost = 0

    while len(a) > 1:
        a.sort()
        cost += a[0]
        a.pop(0)
        a.pop(0)

    return cost

if __name__ == '__main__':
    T = int(input())

    for _ in range(T):
        N = int(input())
        a = list(map(int, input().split()))
        print(min_cost_operations(a))


# This is only for testing
import re
import random
import argparse
import datetime as duration
from datetime import datetime
from googletrans import Translator

parser = argparse.ArgumentParser()
parser.add_argument('--file',nargs = "*",type = str, default = ["subtitle_src.srt", "time.time", "subtitle_en.srt"], help = 'Support only two file .srt and .time Default file \"subtitle.srt\", \"time.time\"')
parser.add_argument('--lang',nargs = "*",type = str, default = ["fr", "en"], help = 'use --lang sl dl where sl:source language and dl: destination language default sl:fr and dl:en')
parser.add_argument('--count', default = 2, help = 'use --count to color words of this number')
args = parser.parse_args()

#Global variables
color_counter = 0
translator = Translator()

try:
    args.count = int(args.count)
except Exception as e:
    print("Count Error: " + str(e))
    exit()

#validation
if(len(args.file) > 2):
    print("Please use \"subtitle\" and \"time\" file only")
    exit()

if(len(args.lang) != 2):
    print("Please use valid language")
    exit()

def rwfile(fname, mode, codec='utf8', text = ""):
    try:
        file = open(fname, mode, encoding=codec)
        if mode == 'r':
            text = str(file.read())
        else:
            file.write(text)
    except Exception as e:
        print("Exception: " + str(e))
        if(codec=='latin-1'):
            exit()
        else:
            text = rwfile(fname, mode, 'latin-1', text)

    return text

def filter(text):
    text = re.sub(r'\n',' ', text)
    text = re.sub(r'<.*?>',' ', text)
    text = re.sub(r'\s{1,}',' ', text)
    text = text.strip()
    return text

def color(text):
    global color_counter
    text = filter(text)
    colors = ['ff595e','ffca3a','8ac926','1982c4','6a4c93','ee4266','ffd23f','0ead69','197278','ff5400','db3a34','ffc857','6a994e','a7c957','083d77','f4d35e','247ba0','fb6107','7cb518','80ed99']
    color_counter = (color_counter + 1) if (color_counter < len(colors)-1) else 0
    text = "" + text + ""
    return text

def is_subtitle(text):
    return True if re.search(r'\d{1,}\n\d{2}:\d{2}:\d{2}.*', text) else False

def to_timestamp(text):
    timestamps = text.split('\n')
    temp_stamps = []
    ftime = ['%S','%M:%S','%H:%M:%S']

    for each_stamp in timestamps:
        index = int(len(each_stamp) / 3)

        try:
            each_stamp = datetime.strptime(each_stamp, ftime[index])
            each_stamp = str(each_stamp.strftime("%H:%M:%S"))
            temp_stamps.append(each_stamp)
        except Exception as e:
            print("Problem in timestamp!", e)
            exit()

    index = 0
    for each_stamp in temp_stamps:
        try:
            timestamps[index] = str(index+1) + "\n" \
                                 + temp_stamps[index] \
                                 + ",000 --> " \
                                 + temp_stamps[index+1] + ",000"
            index += 1
        except:
            time = datetime.strptime(temp_stamps[index],"%H:%M:%S")
            time = time + duration.timedelta(0,7)
            time = time.strftime("%H:%M:%S")
            timestamps[index] = str(index+1) + "\n" \
                                 + temp_stamps[index] \
                                 + ",000 --> " \
                                 + time + ",000"

    return  timestamps

def timestamps(text):
    if is_subtitle(text):
        return re.findall(r'\d{1,}\n\d{2}:\d{2}:\d{2}.*', text)
    else:
        return to_timestamp(text)

def dialogues(text):
    temp_dialogues = []
    if is_subtitle(text):
        dialogues = re.split(r'\d{1,}\n\d{2}:\d{2}:\d{2}.*', text)[1:]
        for dialogue in dialogues:
            dialogue = filter(dialogue)
            temp_dialogues.append(dialogue)
        return temp_dialogues
    else:
        dialogues = text.split('\n')
        return dialogues

def to_translated(text, sl='fr', dl='en'):
    try:
        return translator.translate(text, src = sl, dest = dl).text
    except Exception as e:
        print("Translation Error: " + str(e))
        return "Translation Error: " + str(e)

def to_string(rows):
    text = ""
    try:
        for each_row in rows:
            text += each_row + "\n"
        return text
    except Exception as e:
        print ("String Error: " + str(e))
        return False

def apply_timestamps(timestamps, dialogues):
    text = ""
    for t,d in zip(timestamps,dialogues):
        text += t + "\n" + d + "\n\n"
    return text

def meanings(dialogues,count = args.count):
    temp_dialogues = []
    word_count = []
    for dialogue in dialogues:
        words = dialogue.split(' ')
        # words = words + ['.'] * 3 if len(words) < 2 else words
        icount = count if count < len(words) else len(words)

        index = random.sample(range(0,len(words)), icount)

        for i in range(0, len(index)):
            temp_word = re.sub(r'[\[\!\@\#\$\%\^\&\*\(\)_\+\|\"\:\<\>\?\}\{\~\`\=\\\;\,\.\/\"\]]', '', words[index[i]].lower())
            word_count.append(temp_word)
            words[index[i]] = color(words[index[i]])

        temp_dialogues.append(" ".join(words))

    #New method required here
    word_stat = dict((word, word_count.count(word)) for word in word_count)
    list_of_words = "\n".join(map(str,[*sorted(word_stat.items(), key = lambda x:x[1], reverse= True)]))
    rwfile("dictionary.txt", 'w','utf8',list_of_words)

    return temp_dialogues

#sfile:source_file and tfile:time_file
def create_subtitle(sfile = args.file[0], tfile = args.file[1]):
    text = rwfile(sfile, 'r')
    time = rwfile(tfile, 'r')
    dialogues_temp = dialogues(text)
    timestamps_temp = timestamps(text) if is_subtitle(text) else timestamps(time)

    if (len(dialogues_temp) > len(timestamps_temp)):
        timestamps_temp = timestamps_temp + ['exceed'] * (len(dialogues_temp) -len(timestamps_temp))

    rwfile("temp_sub.txt", 'w','utf8', "\n".join(dialogues_temp))
    rwfile("temp_time.txt", 'w','utf8', "\n".join(timestamps_temp))
    dialogues_en = to_translated("\n".join(dialogues_temp)).split('\n')

    dialogues_en = meanings(dialogues_en)
    dialogues_en = apply_timestamps(timestamps_temp, dialogues_en)
    rwfile("subtitle_en.srt", 'w', 'utf8', dialogues_en)

    dialogues_color = meanings(dialogues_temp)
    dialogues_color = apply_timestamps(timestamps_temp, dialogues_color)
    rwfile("subtitle_color.srt", 'w', 'utf8', dialogues_color)

create_subtitle()


notas = []
contador_maior = 0
contador_7 = 0
while True:
    valores = int(input('Digite sua nota: '))
    notas.append(valores)
    if valores == -1:
        break
notas.remove(-1)
print(f'Foram lidos {len(notas)} valores')
print(f'Valores lidos: {notas}')
notas.reverse()
print(f'Valores lidos na ordem inversa: ')
for i in range(len(notas)):
    print(f'{notas[i]}')
notas.reverse()
print(f'Soma dos valores: {sum(notas)}')
print(f'Média dos valores: {sum(notas) / len(notas)}')
for maior in range(len(notas)):
    if notas[maior] > (sum(notas) / len(notas)):
        contador_maior += 1
print(f'Você digitou {contador_maior} valores acima da média')
for l in range(len(notas)):
    if notas[l] < 7:
        contador_7 += 1
print(f'Você digitou {contador_7} valores abaixo de sete')
print('FIM')
print('-=' * 20)


from qqbot import QQBotSlot
from qqbot import _bot as bot
from qqbot.utf8logger import ERROR
import time

__msg_queue = None

@QQBotSlot
def onQQMessage(bot, contact, member, content):
    if bot.isMe(contact, member):
        return
    if contact.ctype != 'buddy' and ('@ME' in content or '@全体成员' in content):
        content = content.strip("[@ME]全体成员 ")
        if content:
            __msg_queue.put(("QQ", "群" + contact.name + '/' + member.name, content))

def log_in(user_qq, msg_queue):
    global __msg_queue
    __msg_queue = msg_queue
    bot.Login(['-q', user_qq])

def main_loop():
    while True:
        try:
            bot.Run()
        except Exception as e:
            ERROR(e)
            time.sleep(3)


import factory
import persisting_theory

class FactoriesRegistry(persisting_theory.Registry):
    look_into = "factories"

    def prepare_name(self, data, name=None):
        return name or data._meta.model._meta.label

registry = FactoriesRegistry()

def ManyToManyFromList(field_name):
    """
    To automate the pattern described in
    http://factoryboy.readthedocs.io/en/latest/recipes.html#simple-many-to-many-relationship
    """

    @factory.post_generation
    def inner(self, create, extracted, **kwargs):
        if not create:
            return

        if extracted:
            field = getattr(self, field_name)
            field.add(*extracted)

    return inner


import inspect
import logging
import allure
import os, os.path

def customLogger():
    # 1.) This is used to get the  class / method name from where this customLogger method is called
    logName = inspect.stack()[1][3]

    # 2.) Create the logging object and pass the logName in it
    logger = logging.getLogger(logName)

    # 3.) Set the Log level
    logger.setLevel(logging.DEBUG)

    # 4.) Create the fileHandler to save the logs in the file
    my_path = os.path.abspath(os.path.dirname(__file__))
    path = os.path.join(my_path, "../reports/Code2Lead.log")
    fileHandler = logging.FileHandler(path, mode='a')
    # C:\\Users\\Ibrahem.taha\\Documents\\Ibrahem\\Appium\\AppiumGoogleNotes\\reports\Code2Lead.log

    # 5.) Set the logLevel for fileHandler
    fileHandler.setLevel(logging.DEBUG)

    # 6.) Create the formatter in which format do you like to save the logs
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s : %(message)s',
                                  datefmt='%d/%m/%y %I:%M:%S %p %A')

    # 7.) Set the formatter to fileHandler
    fileHandler.setFormatter(formatter)

    # 8.) Add file handler to logging
    logger.addHandler(fileHandler)

    #  9.) Finally return the logging object

    return logger

def allureLogs(text):
    with allure.step(text):
        pass


import os
import djcelery
import socket
import warnings
import platform

BASE_PATH=os.path.dirname(__file__)

# Used to initialize the sites model (see: NMTK_server/management/__init__.py)
# This should be overridden by the VHOST name, but it is defaulted to the FQDN
# since in most cases that will be the same.
# It should be noted that if you use any kind of vhost setup, then this
# probably won't work, and will result in all kinds of broken-ness :-)

DEBUG = False
TEMPLATE_DEBUG = TASTYPIE_FULL_DEBUG = DEBUG
from local_settings import *
warnings.filterwarnings('ignore',r"'NoneType' object has no attribute 'finishGEOS_r'")
warnings.filterwarnings('ignore',r"'NoneType' object has no attribute 'destroy_geom'")
djcelery.setup_loader()

MANAGERS = ADMINS
ALLOWED_HOSTS=[SITE_DOMAIN,'127.0.0.1']

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'America/New_York'

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = ''

# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT=os.path.abspath(os.path.join('..', 'htdocs/static'))

# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'

# Additional locations of static files
STATICFILES_DIRS = (
    # Put strings here, like "/home/html/static" or "C:/www/django/static".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
)

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
#     'django.template.loaders.eggs.Loader',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'NMTK_server.middleware.strict_authentication.StrictAuthentication',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'NMTK_apps.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'NMTK_apps.wsgi.application'
TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.

    # This directory adds the templates that are stored in the NMTK_apps directory,
    # Which is not an app - but the underpinnings for everything else.
    os.path.join(BASE_PATH,'templates'),
)

TEMPLATE_CONTEXT_PROCESSORS=("django.contrib.auth.context_processors.auth",
                             "django.core.context_processors.debug",
                             "django.core.context_processors.i18n",
                             "django.core.context_processors.media",
                             "django.core.context_processors.static",
                             "django.core.context_processors.tz",
                             "django.contrib.messages.context_processors.messages",
                             "django.core.context_processors.request",
                              )

INSTALLED_APPS = (
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'djcelery',
    'kombu.transport.django',
    )

TASTYPIE_DEFAULT_FORMATS = ['json',]

if TOOL_SERVER:
    INSTALLED_APPS = INSTALLED_APPS + ('NMTK_tools', # An app used to generate a list of tools.
                                       ) + NMTK_TOOL_APPS
if NMTK_SERVER:
    INSTALLED_APPS = INSTALLED_APPS + ('django.contrib.auth',
                                       'registration',
                                       'widget_tweaks',
                                       'NMTK_server', # The NMTK Server
                                       'django.contrib.admin',
                                       'NMTK_ui', # the UI components for NMTK server
                                       'tastypie',
                                       )

# The test tool only gets installed if debug is set to true.
# if not PRODUCTION and TOOL_SERVER:
#     INSTALLED_APPS=INSTALLED_APPS + (
#                                      'test_tool', # A sample tool designed for testing new stuff.
#                                      )

# Define a GeoJSON serializer so we can serialize and return results of
# various tasks in the GeoJSON format.
SERIALIZATION_MODULES = { 'geojson' : 'NMTK_apps.serializers.geojson' }

# The URL Used for logins
LOGIN_URL='/server/login/'

# if you want to change the logging (to disable debug) do it here..
if DEBUG:
    MIN_LOG_LEVEL='DEBUG' # 'INFO' for non-debug, 'DEBUG' for debugging
else:
    MIN_LOG_LEVEL='INFO'
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'null': {
            'level':'DEBUG',
            'class':'django.utils.log.NullHandler',
        },
        'debug': {
            'level':'DEBUG',
            'class':'logging.handlers.WatchedFileHandler',
            'filename': os.path.join(LOGFILE_PATH,'django-debug.log'),
            'formatter':'standard',
        },
        'default': {
            'level':'INFO',
            'class':'logging.handlers.WatchedFileHandler',
            'filename': os.path.join(LOGFILE_PATH,'django-request.log'),
            'formatter':'standard',
        },
        'apache': {
            'level':'INFO',
            'class':'logging.StreamHandler',
            'formatter':'standard',
        },
    },
    'loggers': {
        '': {
            'handlers': ['debug', 'default'],
            'level': MIN_LOG_LEVEL,
            'propagate': True,
        },
        'django.request': { # Stop request debug from logging to main logger
            'handlers': ['apache'],
            'level': 'INFO',
            'propagate': False,
        },
        'django.db': { # We can turn on db logging by switching the handler to debug
            'handlers': ['null'],
            'level': MIN_LOG_LEVEL,
            'propagate': False,
        },
    }
}

BROKER_URL = 'django://'

# Make our session keys stay for 14 days since the last access.
# because the default SESSION_COOKIE_AGE is 1209600 (60*60*24*14)=14 days in seconds
SESSION_SAVE_EVERY_REQUEST=True

# A list of modules used by the data loader, note that order is important here
# Since the first loader that recognizes a file will process it.
DATA_LOADERS=['NMTK_server.data_loaders.ogr.OGRLoader',
              'NMTK_server.data_loaders.csv.CSVLoader']


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 24/03/2020 15:00
# @Author  : Alan
# @Site    :
# @File    : urls.py
# @Software: PyCharm

from django.urls import path
from crm.views import account,home,project

urlpatterns = [
    path('register/', account.register, name='register'),
    path('send_sms/', account.send_sms, name='send_sms'),
    path('login/sms/', account.login_sms, name="login_sms"),
    path('login/', account.login, name="login"),
    path('image/code/', account.image_code, name="image_code"),
    path('articles/', account.formset, name="articles"),
    path('logout/',account.logout,name="logout"),

    # 项目管理
    path('project/list/',project.project_list,name="project_list")

]


number_of_rooms = int(input())
total_free_chairs = 0
total_chairs = 0
total_visitors = 0
for room in range(1, number_of_rooms + 1):
    data = input().split()
    available_chairs = len(data[0])
    visitors = int(data[1])
    total_chairs += available_chairs
    total_visitors += visitors
    difference = available_chairs - visitors
    if available_chairs >= visitors:
        total_free_chairs += difference
    elif available_chairs < visitors:
        print(f"{abs(difference)} more chairs needed in room {room}")
if total_chairs >= total_visitors:
    print(f"Game On, {total_free_chairs} free chairs left")