#!/usr/bin/env python
"""Example usage and tests for :mod:`orion.core.io.experiment_builder`."""
from __future__ import annotations

import copy
import datetime
import logging
from pathlib import Path

import pytest

import orion.core
from orion.algo.base import BaseAlgorithm
from orion.algo.random import Random
from orion.algo.space import Space
from orion.algo.tpe import TPE
from orion.core.evc.adapters import BaseAdapter
from orion.core.io import experiment_builder
from orion.core.io.config import ConfigurationError
from orion.core.io.database.ephemeraldb import EphemeralDB
from orion.core.io.database.pickleddb import PickledDB
from orion.core.io.space_builder import SpaceBuilder
from orion.core.utils import backward
from orion.core.utils.exceptions import (
    BranchingEvent,
    NoConfigurationError,
    RaceCondition,
    UnsupportedOperation,
)
from orion.core.worker.algo_wrappers import AlgoWrapper
from orion.core.worker.warm_start import KnowledgeBase
from orion.storage.base import setup_storage
from orion.storage.legacy import Legacy
from orion.testing import OrionState

def count_experiments():
    """Count experiments in storage"""
    return len(setup_storage().fetch_experiments({}))

@pytest.fixture
def space():
    """Build a space definition"""
    return {"x": "uniform(-50,50)"}

@pytest.fixture()
def python_api_config():
    """Create a configuration without the cli fluff."""
    new_config = dict(
        name="supernaekei",
        version=1,
        space={"x": "uniform(0,10)"},
        metadata={
            "user": "tsirif",
            "orion_version": "XYZ",
            "VCS": {
                "type": "git",
                "is_dirty": False,
                "HEAD_sha": "test",
                "active_branch": None,
                "diff_sha": "diff",
            },
        },
        max_trials=1000,
        max_broken=5,
        working_dir="",
        algorithm={
            "dumbalgo": {
                "done": False,
                "judgement": None,
                "scoring": 0,
                "seed": None,
                "suspend": False,
                "value": 5,
            }
        },
        _id="fasdfasfa",
        something_to_be_ignored="asdfa",
        refers=dict(root_id="supernaekei", parent_id=None, adapter=[]),
    )

    return new_config

@pytest.fixture()
def algo_unavailable_config(python_api_config):
    python_api_config["algorithm"] = {"idontreallyexist": {"but": "iwishiwould"}}
    return python_api_config

@pytest.fixture()
def new_config(random_dt, script_path):
    """Create a configuration that will not hit the database."""
    new_config = dict(
        name="supernaekei",
        metadata={
            "user": "tsirif",
            "orion_version": "XYZ",
            "user_script": script_path,
            "user_script_config": "config",
            "user_config": "abs_path/hereitis.yaml",
            "user_args": [script_path, "--mini-batch~uniform(32, 256, discrete=True)"],
            "VCS": {
                "type": "git",
                "is_dirty": False,
                "HEAD_sha": "test",
                "active_branch": None,
                "diff_sha": "diff",
            },
        },
        version=1,
        max_trials=1000,
        max_broken=5,
        working_dir="",
        algorithm={
            "dumbalgo": {
                "done": False,
                "judgement": None,
                "scoring": 0,
                "seed": None,
                "suspend": False,
                "value": 5,
            }
        },
        # attrs starting with '_' also
        _id="fasdfasfa",
        # and in general anything which is not in Experiment's slots
        something_to_be_ignored="asdfa",
        refers=dict(root_id="supernaekei", parent_id=None, adapter=[]),
    )

    backward.populate_space(new_config)

    return new_config

@pytest.fixture
def parent_version_config(script_path):
    """Return a configuration for an experiment."""
    config = dict(
        _id="parent_config",
        name="old_experiment",
        version=1,
        algorithm="random",
        metadata={
            "user": "corneauf",
            "datetime": datetime.datetime.utcnow(),
            "user_args": ["--x~normal(0,1)"],
            "user_script": script_path,
            "VCS": {
                "type": "git",
                "is_dirty": False,
                "HEAD_sha": "test",
                "active_branch": None,
                "diff_sha": "diff",
            },
            "orion_version": "XYZ",
        },
    )

    backward.populate_space(config)

    return config

@pytest.fixture
def child_version_config(parent_version_config):
    """Return a configuration for an experiment."""
    config = copy.deepcopy(parent_version_config)
    config["_id"] = "child_config"
    config["version"] = 2
    config["refers"] = {"parent_id": "parent_config"}
    config["metadata"]["datetime"] = datetime.datetime.utcnow()
    config["metadata"]["user_args"].append("--y~+normal(0,1)")
    backward.populate_space(config)
    return config

@pytest.mark.usefixtures("with_user_tsirif", "version_XYZ")
def test_get_cmd_config(raw_config):
    """Test local config (cmdconfig, cmdargs)"""
    cmdargs = {"config": raw_config}
    local_config = experiment_builder.get_cmd_config(cmdargs)

    assert local_config["algorithm"] == "random"
    assert local_config["max_trials"] == 100
    assert local_config["max_broken"] == 5
    assert local_config["name"] == "voila_voici"
    assert local_config["storage"] == {
        "database": {
            "host": "${FILE}",
            "name": "orion_test",
            "type": "pickleddb",
        }
    }
    assert local_config["metadata"] == {"orion_version": "XYZ", "user": "tsirif"}

@pytest.mark.usefixtures("with_user_tsirif", "version_XYZ")
def test_get_cmd_config_from_incomplete_config(incomplete_config_file):
    """Test local config with incomplete user configuration file
    (default, env_vars, cmdconfig, cmdargs)

    This is to ensure merge_configs update properly the subconfigs
    """
    cmdargs = {"config": incomplete_config_file}
    local_config = experiment_builder.get_cmd_config(cmdargs)

    assert "algorithm" not in local_config
    assert "max_trials" not in local_config
    assert "max_broken" not in local_config
    assert "name" not in local_config["storage"]["database"]
    assert (
        local_config["storage"]["database"]["host"] == "mongodb://user:pass@localhost"
    )
    assert local_config["storage"]["database"]["type"] == "incomplete"
    assert local_config["name"] == "incomplete"
    assert local_config["metadata"] == {"orion_version": "XYZ", "user": "tsirif"}

def test_fetch_config_from_db_no_hit():
    """Verify that fetch_config_from_db returns an empty dict when the experiment is not in db"""
    with OrionState(experiments=[], trials=[]) as cfg:
        db_config = experiment_builder.ExperimentBuilder(
            storage=cfg.storage_config
        ).fetch_config_from_db(name="supernaekei")

    assert db_config == {}

@pytest.mark.usefixtures("with_user_tsirif")
def test_fetch_config_from_db_hit(new_config):
    """Verify db config when experiment is in db"""
    with OrionState(experiments=[new_config], trials=[]) as cfg:
        db_config = experiment_builder.ExperimentBuilder(
            storage=cfg.storage_config
        ).fetch_config_from_db(name="supernaekei")

    assert db_config["name"] == new_config["name"]
    assert db_config["refers"] == new_config["refers"]
    assert db_config["metadata"] == new_config["metadata"]
    assert db_config["max_trials"] == new_config["max_trials"]
    assert db_config["max_broken"] == new_config["max_broken"]
    assert db_config["algorithm"] == new_config["algorithm"]
    assert db_config["metadata"] == new_config["metadata"]

@pytest.mark.usefixtures("with_user_tsirif")
def test_get_from_args_no_hit(config_file):
    """Try building experiment view when not in db"""
    cmdargs = {"name": "supernaekei", "config": config_file}

    with OrionState(experiments=[], trials=[]):
        with pytest.raises(NoConfigurationError) as exc_info:
            experiment_builder.get_from_args(cmdargs)
        assert "No experiment with given name 'supernaekei' and version '*'" in str(
            exc_info.value
        )

@pytest.mark.usefixtures("with_user_tsirif")
def test_get_from_args_hit(monkeypatch, raw_config, random_dt, new_config):
    """Try building experiment view when in db"""
    cmdargs = {"name": "supernaekei", "config": raw_config}

    with OrionState(experiments=[new_config], trials=[]) as cfg:
        # This is necessary because storage is instantiated inside
        # `get_from_args` with its own config not the global config set by OrionState
        def get_storage(*args, **kwargs):
            return cfg.storage

        monkeypatch.setattr(experiment_builder, "setup_storage", get_storage)

        exp_view = experiment_builder.get_from_args(cmdargs)

    assert exp_view._id == new_config["_id"]
    assert exp_view.name == new_config["name"]
    assert exp_view.configuration["refers"] == new_config["refers"]
    assert exp_view.metadata == new_config["metadata"]
    assert exp_view.max_trials == new_config["max_trials"]
    assert exp_view.max_broken == new_config["max_broken"]
    assert exp_view.algorithm
    assert exp_view.algorithm.configuration == new_config["algorithm"]

@pytest.mark.usefixtures("with_user_tsirif")
def test_get_from_args_hit_no_conf_file(
    monkeypatch, config_file, random_dt, new_config
):
    """Try building experiment view when in db, and local config file of user script does
    not exist
    """
    cmdargs = {"name": "supernaekei", "config": config_file}
    new_config["metadata"]["user_args"] += [
        "--config",
        new_config["metadata"]["user_config"],
    ]

    with OrionState(experiments=[new_config], trials=[]) as cfg:

        # This is necessary because storage is instantiated inside
        # `get_from_args` with its own config not the global config set by OrionState
        def get_storage(*args, **kwargs):
            return cfg.storage

        monkeypatch.setattr(experiment_builder, "setup_storage", get_storage)

        exp_view = experiment_builder.get_from_args(cmdargs)

    assert exp_view._id == new_config["_id"]
    assert exp_view.name == new_config["name"]
    assert exp_view.configuration["refers"] == new_config["refers"]
    assert exp_view.metadata == new_config["metadata"]
    assert exp_view.max_trials == new_config["max_trials"]
    assert exp_view.max_broken == new_config["max_broken"]
    assert exp_view.algorithm
    assert exp_view.algorithm.configuration == new_config["algorithm"]

@pytest.mark.usefixtures("with_user_dendi")
def test_build_from_args_no_hit(
    monkeypatch, config_file, random_dt, script_path, new_config
):
    """Try building experiment when not in db"""
    cmdargs = {
        "name": "supernaekei",
        "config": config_file,
        "user_args": [script_path, "x~uniform(0,10)"],
    }

    with OrionState(experiments=[], trials=[]) as cfg:
        with pytest.raises(NoConfigurationError) as exc_info:
            experiment_builder.get_from_args(cmdargs)
        assert "No experiment with given name 'supernaekei' and version '*'" in str(
            exc_info.value
        )

        # This is necessary because storage is instantiated inside
        # `get_from_args` with its own config not the global config set by OrionState
        def get_storage(*args, **kwargs):
            return cfg.storage

        monkeypatch.setattr(experiment_builder, "setup_storage", get_storage)

        exp = experiment_builder.build_from_args(cmdargs)

        assert exp.name == cmdargs["name"]
        assert exp.configuration["refers"] == {
            "adapter": [],
            "parent_id": None,
            "root_id": exp._id,
        }
        assert exp.metadata["datetime"] == random_dt
        assert exp.metadata["user"] == "dendi"
        assert exp.metadata["user_script"] == cmdargs["user_args"][0]
        assert exp.metadata["user_args"] == cmdargs["user_args"]
        assert exp.max_trials == 100
        assert exp.max_broken == 5
        assert exp.algorithm
        assert exp.algorithm.configuration == {"random": {"seed": None}}

@pytest.mark.usefixtures(
    "version_XYZ", "with_user_tsirif", "mock_infer_versioning_metadata"
)
def test_build_from_args_hit(monkeypatch, old_config_file, script_path, new_config):
    """Try building experiment when in db (no branch)"""
    cmdargs = {
        "name": "supernaekei",
        "config": old_config_file,
        "user_args": [script_path, "--mini-batch~uniform(32, 256, discrete=True)"],
    }

    with OrionState(experiments=[new_config], trials=[]) as cfg:

        # This is necessary because storage is instantiated inside
        # `get_from_args` with its own config not the global config set by OrionState
        def get_storage(*args, **kwargs):
            return cfg.storage

        monkeypatch.setattr(experiment_builder, "setup_storage", get_storage)

        # Test that experiment already exists
        experiment_builder.get_from_args(cmdargs)

        exp = experiment_builder.build_from_args(cmdargs)

    assert exp._id == new_config["_id"]
    assert exp.name == new_config["name"]
    assert exp.version == 1
    assert exp.configuration["refers"] == new_config["refers"]
    assert exp.metadata == new_config["metadata"]
    assert exp.max_trials == new_config["max_trials"]
    assert exp.max_broken == new_config["max_broken"]
    assert exp.algorithm
    assert exp.algorithm.configuration == new_config["algorithm"]

@pytest.mark.usefixtures("with_user_bouthilx")
def test_build_from_args_force_user(new_config):
    """Try building experiment view when in db"""
    cmdargs = {"name": new_config["name"]}
    cmdargs["user"] = "tsirif"
    with OrionState(experiments=[new_config], trials=[]):
        # Test that experiment already exists
        exp_view = experiment_builder.build_from_args(cmdargs)
    assert exp_view.metadata["user"] == "tsirif"

def test_build_from_args_debug_mode(monkeypatch, script_path, storage):
    """Try building experiment in debug mode"""

    experiment = experiment_builder.build_from_args(
        {
            "name": "whatever",
            "user_args": [script_path, "--mini-batch~uniform(32, 256)"],
        }
    )

    storage = experiment._storage
    assert isinstance(storage, Legacy)
    assert isinstance(storage._db, PickledDB)

    experiment = experiment_builder.build_from_args(
        {
            "name": "whatever",
            "user_args": [script_path, "--mini-batch~uniform(32, 256)"],
            "debug": True,
        }
    )

    storage = experiment._storage
    assert isinstance(storage, Legacy)
    assert isinstance(storage._db, EphemeralDB)

storage_instance = ""

def test_get_from_args_debug_mode(monkeypatch, script_path, storage):
    """Try building experiment view in debug mode"""

    old_factory = experiment_builder.setup_storage

    def retrieve_storage(*args, **kwargs):
        global storage_instance

        storage_instance = old_factory(*args, **kwargs)
        return storage_instance

    monkeypatch.setattr(experiment_builder, "setup_storage", retrieve_storage)

    # Can't build view if none exist. It's fine we only want to test the storage creation.
    with pytest.raises(NoConfigurationError):
        experiment_builder.get_from_args({"name": "whatever"})

    assert isinstance(storage_instance._db, PickledDB)

    # Can't build view if none exist. It's fine we only want to test the storage creation.
    with pytest.raises(NoConfigurationError):
        experiment_builder.get_from_args({"name": "whatever", "debug": True})

    assert isinstance(storage_instance._db, EphemeralDB)

@pytest.mark.usefixtures("with_user_tsirif", "version_XYZ")
def test_build_no_hit(config_file, random_dt, script_path):
    """Try building experiment from config when not in db"""
    name = "supernaekei"
    space = {"x": "uniform(0, 10)"}
    max_trials = 100
    max_broken = 5

    with OrionState(experiments=[], trials=[]):

        with pytest.raises(NoConfigurationError) as exc_info:
            experiment_builder.load(name)
        assert "No experiment with given name 'supernaekei' and version '*'" in str(
            exc_info.value
        )

        exp = experiment_builder.build(
            name, space=space, max_trials=max_trials, max_broken=max_broken
        )

        assert exp.name == name
        assert exp.configuration["refers"] == {
            "adapter": [],
            "parent_id": None,
            "root_id": exp._id,
        }
        assert exp.metadata == {
            "datetime": random_dt,
            "user": "tsirif",
            "orion_version": "XYZ",
        }
        assert exp.configuration["space"] == space
        assert exp.max_trials == max_trials
        assert exp.max_broken == max_broken
        assert not exp.is_done
        assert exp.algorithm
        assert exp.algorithm.configuration == {"random": {"seed": None}}

def test_build_no_commandline_config():
    """Try building experiment with no commandline configuration."""
    with OrionState(experiments=[], trials=[]):
        with pytest.raises(NoConfigurationError):
            experiment_builder.build("supernaekei")

@pytest.mark.usefixtures(
    "with_user_tsirif", "mock_infer_versioning_metadata", "version_XYZ"
)
def test_build_hit(python_api_config):
    """Try building experiment from config when in db (no branch)"""
    name = "supernaekei"

    with OrionState(experiments=[python_api_config], trials=[]):

        # Test that experiment already exists (this should fail otherwise)
        experiment_builder.load(name=name)

        exp = experiment_builder.build(**python_api_config)

    assert exp._id == python_api_config["_id"]
    assert exp.name == python_api_config["name"]
    assert exp.configuration["refers"] == python_api_config["refers"]
    assert exp.metadata == python_api_config["metadata"]
    assert exp.max_trials == python_api_config["max_trials"]
    assert exp.max_broken == python_api_config["max_broken"]
    assert exp.algorithm
    assert exp.algorithm.configuration == python_api_config["algorithm"]

@pytest.mark.usefixtures("with_user_tsirif", "version_XYZ")
def test_build_without_config_hit(python_api_config):
    """Try building experiment without commandline config when in db (no branch)"""
    name = "supernaekei"

    with OrionState(experiments=[python_api_config], trials=[]):

        # Test that experiment already exists (this should fail otherwise)
        experiment_builder.load(name=name)

        exp = experiment_builder.build(name=name)

    assert exp._id == python_api_config["_id"]
    assert exp.name == python_api_config["name"]
    assert exp.configuration["refers"] == python_api_config["refers"]
    assert exp.metadata == python_api_config["metadata"]
    assert exp.max_trials == python_api_config["max_trials"]
    assert exp.max_broken == python_api_config["max_broken"]
    assert exp.algorithm
    assert exp.algorithm.configuration == python_api_config["algorithm"]

@pytest.mark.usefixtures(
    "with_user_tsirif", "version_XYZ", "mock_infer_versioning_metadata"
)
def test_build_from_args_without_cmd(
    monkeypatch, old_config_file, script_path, new_config
):
    """Try building experiment without commandline when in db (no branch)"""
    name = "supernaekei"

    cmdargs = {"name": name, "config": old_config_file}

    with OrionState(experiments=[new_config], trials=[]) as cfg:

        # This is necessary because storage is instantiated inside
        # `get_from_args` with its own config not the global config set by OrionState
        def get_storage(*args, **kwargs):
            return cfg.storage

        monkeypatch.setattr(experiment_builder, "setup_storage", get_storage)

        # Test that experiment already exists (this should fail otherwise)
        experiment_builder.get_from_args(cmdargs)

        exp = experiment_builder.build_from_args(cmdargs)

    assert exp._id == new_config["_id"]
    assert exp.name == new_config["name"]
    assert exp.configuration["refers"] == new_config["refers"]
    assert exp.metadata == new_config["metadata"]
    assert exp.max_trials == new_config["max_trials"]
    assert exp.max_broken == new_config["max_broken"]
    assert exp.algorithm
    assert exp.algorithm.configuration == new_config["algorithm"]

# TODO: Remove for v0.4
class TestStrategyDeprecated:
    def test_strategy_not_defined(self, caplog, space):
        """Verify there is no warning"""
        with OrionState():
            with caplog.at_level(logging.WARNING):
                exp = experiment_builder.build(name="whatever", space=space)
            assert "`strategy` option is not supported anymore." not in caplog.text

    def test_strategy_defined_in_global_config(self, caplog, space, monkeypatch):
        """Verify there is a warning"""

        with monkeypatch.context() as m:
            m.setattr(
                orion.core.config.experiment,
                "strategy",
                {"this is deprecated": "and should be ignored"},
            )
            with OrionState():
                with caplog.at_level(logging.WARNING):
                    exp = experiment_builder.build(name="whatever", space=space)
                assert "`strategy` option is not supported anymore." in caplog.text

    def test_strategy_defined_in_config(self, caplog, space):
        """Verify there is a warning"""
        with OrionState():
            with caplog.at_level(logging.WARNING):
                exp = experiment_builder.build(
                    name="whatever",
                    space=space,
                    strategy={"this is deprecated": "and should be ignored"},
                )
            assert "`strategy` option is not supported anymore." in caplog.text

@pytest.mark.usefixtures(
    "with_user_tsirif", "version_XYZ", "mock_infer_versioning_metadata"
)
class TestExperimentVersioning:
    """Create new Experiment with auto-versioning."""

    def test_new_experiment_wout_version(self, space):
        """Create a new and never-seen-before experiment without a version."""
        with OrionState():
            exp = experiment_builder.build(name="exp_wout_version", space=space)

        assert exp.version == 1

    def test_new_experiment_w_version(self, space):
        """Create a new and never-seen-before experiment with a version."""
        with OrionState():
            exp = experiment_builder.build(
                name="exp_wout_version", version=1, space=space
            )

        assert exp.version == 1

    def test_experiment_overwritten_evc_disabled(self, parent_version_config, caplog):
        """Build an existing experiment with different config, overwriting previous config."""
        parent_version_config.pop("version")

        # Note: this is a bit of a hack, but we need to make sure the config is also compatible with gridsearch.
        parent_version_config = copy.deepcopy(parent_version_config)
        parent_version_config["space"] = {"/x": "uniform(0, 1)"}
        with OrionState(experiments=[parent_version_config]):

            with caplog.at_level(logging.WARNING):

                exp = experiment_builder.build(name=parent_version_config["name"])
                assert "Running experiment in a different state" not in caplog.text

            assert exp.version == 1
            assert exp.configuration["algorithm"] == {"random": {"seed": None}}

            new_algo = "gridsearch"
            with caplog.at_level(logging.WARNING):

                exp = experiment_builder.build(
                    name=parent_version_config["name"], algorithm=new_algo
                )
                assert "Running experiment in a different state" in caplog.text

            assert exp.version == 1
            assert list(exp.configuration["algorithm"].keys())[0] == new_algo

            caplog.clear()
            with caplog.at_level(logging.WARNING):

                exp = experiment_builder.load(name=parent_version_config["name"])
                assert "Running experiment in a different state" not in caplog.text

            assert exp.version == 1
            assert list(exp.configuration["algorithm"].keys())[0] == new_algo

    def test_backward_compatibility_no_version(self, parent_version_config):
        """Branch from parent that has no version field."""
        parent_version_config.pop("version")
        with OrionState(experiments=[parent_version_config]):
            exp = experiment_builder.build(
                name=parent_version_config["name"],
                space={"y": "uniform(0, 10)"},
                branching={"enable": True},
            )

        assert exp.version == 2

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_old_experiment_wout_version(self, parent_version_config):
        """Create an already existing experiment without a version."""
        with OrionState(experiments=[parent_version_config]):
            exp = experiment_builder.build(name=parent_version_config["name"])

        assert exp.version == 1

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_old_experiment_2_wout_version(
        self, parent_version_config, child_version_config
    ):
        """Create an already existing experiment without a version and getting last one."""
        with OrionState(experiments=[parent_version_config, child_version_config]):
            exp = experiment_builder.build(name=parent_version_config["name"])

        assert exp.version == 2

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_old_experiment_w_version(
        self, parent_version_config, child_version_config
    ):
        """Create an already existing experiment with a version."""
        with OrionState(experiments=[parent_version_config, child_version_config]):
            exp = experiment_builder.build(
                name=parent_version_config["name"], version=1
            )

        assert exp.version == 1

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_old_experiment_w_version_bigger_than_max(
        self, parent_version_config, child_version_config
    ):
        """Create an already existing experiment with a too large version."""
        with OrionState(experiments=[parent_version_config, child_version_config]):
            exp = experiment_builder.build(
                name=parent_version_config["name"], version=8
            )

        assert exp.version == 2

@pytest.mark.usefixtures("with_user_tsirif", "version_XYZ")
class TestBuild:
    """Test building the experiment"""

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_good_set_before_init_hit_no_diffs_exc_max_trials(self, new_config):
        """Trying to set, and NO differences were found from the config pulled from db.

        Everything is normal, nothing changes. Experiment is resumed,
        perhaps with more trials to evaluate (an exception is 'max_trials').
        """
        with OrionState(experiments=[new_config], trials=[]):

            new_config["max_trials"] = 5000

            exp = experiment_builder.build(**new_config)

        # Deliver an external configuration to finalize init
        new_config["algorithm"]["dumbalgo"]["done"] = False
        new_config["algorithm"]["dumbalgo"]["judgement"] = None
        new_config["algorithm"]["dumbalgo"]["scoring"] = 0
        new_config["algorithm"]["dumbalgo"]["suspend"] = False
        new_config["algorithm"]["dumbalgo"]["value"] = 5
        new_config["algorithm"]["dumbalgo"]["seed"] = None
        new_config.pop("something_to_be_ignored")
        new_config["knowledge_base"] = None
        assert exp.configuration == new_config

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_good_set_before_init_no_hit(self, random_dt, new_config):
        """Trying to set, overwrite everything from input."""
        with OrionState(experiments=[], trials=[]):
            exp = experiment_builder.build(**new_config)
            found_config = list(
                setup_storage().fetch_experiments(
                    {"name": "supernaekei", "metadata.user": "tsirif"}
                )
            )

        new_config["metadata"]["datetime"] = exp.metadata["datetime"]

        assert len(found_config) == 1
        _id = found_config[0].pop("_id")
        assert _id != "fasdfasfa"
        assert exp._id == _id
        new_config["refers"] = {}
        new_config.pop("_id")
        new_config.pop("something_to_be_ignored")
        new_config["algorithm"]["dumbalgo"]["done"] = False
        new_config["algorithm"]["dumbalgo"]["judgement"] = None
        new_config["algorithm"]["dumbalgo"]["scoring"] = 0
        new_config["algorithm"]["dumbalgo"]["suspend"] = False
        new_config["algorithm"]["dumbalgo"]["value"] = 5
        new_config["algorithm"]["dumbalgo"]["seed"] = None
        new_config["refers"] = {"adapter": [], "parent_id": None, "root_id": _id}
        new_config["knowledge_base"] = None
        assert found_config[0] == new_config
        assert exp.name == new_config["name"]
        assert exp.configuration["refers"] == new_config["refers"]
        assert exp.metadata == new_config["metadata"]
        assert exp.max_trials == new_config["max_trials"]
        assert exp.max_broken == new_config["max_broken"]
        assert exp.working_dir == new_config["working_dir"]
        assert exp.version == new_config["version"]
        assert exp.algorithm
        assert exp.algorithm.configuration == new_config["algorithm"]

    def test_working_dir_is_correctly_set(self, new_config):
        """Check if working_dir is correctly changed."""
        with OrionState():
            new_config["working_dir"] = "./"
            exp = experiment_builder.build(**new_config)
            storage = setup_storage()
            found_config = list(
                storage.fetch_experiments(
                    {"name": "supernaekei", "metadata.user": "tsirif"}
                )
            )

            found_config = found_config[0]
            exp = experiment_builder.build(**found_config)
            assert exp.working_dir == "./"

    def test_working_dir_works_when_db_absent(self, database, new_config):
        """Check if working_dir is correctly when absent from the database."""
        with OrionState(experiments=[], trials=[]):
            exp = experiment_builder.build(**new_config)
            storage = setup_storage()
            found_config = list(
                storage.fetch_experiments(
                    {"name": "supernaekei", "metadata.user": "tsirif"}
                )
            )

            found_config = found_config[0]
            exp = experiment_builder.build(**found_config)
            assert exp.working_dir == ""

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_configuration_hit_no_diffs(self, new_config):
        """Return a configuration dict according to an experiment object.

        Before initialization is done, it can be the case that the pair (`name`,
        user's name) has not hit the database. return a yaml compliant form
        of current state, to be used with :mod:`orion.core.cli.esolve_config`.
        """
        with OrionState(experiments=[new_config], trials=[]):
            experiment_count_before = count_experiments()
            exp = experiment_builder.build(**new_config)
            assert experiment_count_before == count_experiments()

        new_config["algorithm"]["dumbalgo"]["done"] = False
        new_config["algorithm"]["dumbalgo"]["judgement"] = None
        new_config["algorithm"]["dumbalgo"]["scoring"] = 0
        new_config["algorithm"]["dumbalgo"]["suspend"] = False
        new_config["algorithm"]["dumbalgo"]["value"] = 5
        new_config["algorithm"]["dumbalgo"]["seed"] = None
        new_config.pop("something_to_be_ignored")
        new_config["knowledge_base"] = None
        assert exp.configuration == new_config

    def test_instantiation_after_init(self, new_config):
        """Verify that algo, space and refers was instantiated properly"""
        with OrionState(experiments=[new_config], trials=[]):
            exp = experiment_builder.build(**new_config)

        assert isinstance(exp.algorithm, AlgoWrapper)
        assert isinstance(exp.space, Space)
        assert isinstance(exp.refers["adapter"], BaseAdapter)

    @pytest.mark.usefixtures("mock_infer_versioning_metadata")
    def test_algo_case_insensitive(self, new_config):
        """Verify that algo with uppercase or lowercase leads to same experiment"""
        with OrionState(experiments=[new_config], trials=[]):
            new_config["algorithm"]["DUMBALGO"] = new_config["algorithm"].pop(
                "dumbalgo"
            )
            exp = experiment_builder.build(**new_config)

            assert exp.version == 1

    def test_hierarchical_space(self, new_config):
        """Verify space can have hierarchical structure"""
        space = {
            "a": {"x": "uniform(0, 10, discrete=True)"},
            "b": {"y": "loguniform(1e-08, 1)", "z": "choices(['voici', 'voila', 2])"},
        }

        with OrionState(experiments=[], trials=[]):
            exp = experiment_builder.build("hierarchy", space=space)

            exp2 = experiment_builder.build("hierarchy")

        assert "a.x" in exp.space
        assert "b.y" in exp.space
        assert "b.z" in exp.space

        # Make sure it can be fetched properly from db as well
        assert "a.x" in exp2.space
        assert "b.y" in exp2.space
        assert "b.z" in exp2.space

    def test_try_set_after_race_condition(self, new_config, monkeypatch):
        """Cannot set a configuration after init if it looses a race
        condition.

        The experiment from process which first writes to db is initialized
        properly. The experiment which looses the race condition cannot be
        initialized and needs to be rebuilt.
        """
        with OrionState(experiments=[new_config], trials=[]) as cfg:
            experiment_count_before = count_experiments()

            def insert_race_condition(*args, **kwargs):
                if insert_race_condition.count == 0:
                    data = {}
                else:
                    data = new_config

                insert_race_condition.count += 1

                return data

            insert_race_condition.count = 0

            builder = experiment_builder.ExperimentBuilder(cfg.storage)
            monkeypatch.setattr(builder, "fetch_config_from_db", insert_race_condition)

            builder.build(**new_config)

            assert experiment_count_before == count_experiments()

        # Should be called
        # - once in build(),
        #     -> then register fails,
        # - then called once again in build,
        # - then called in load to evaluate the conflicts
        assert insert_race_condition.count == 3

    def test_algorithm_config_with_just_a_string(self):
        """Test that configuring an algorithm with just a string is OK."""
        name = "supernaedo3"
        space = {"x": "uniform(0,10)"}
        algorithm = "dumbalgo"

        with OrionState(experiments=[], trials=[]):
            exp = experiment_builder.build(name=name, space=space, algorithm=algorithm)

        assert exp.configuration["algorithm"] == {
            "dumbalgo": {
                "done": False,
                "judgement": None,
                "scoring": 0,
                "suspend": False,
                "value": (5,),
                "seed": None,
            }
        }

    def test_new_child_with_branch(self):
        """Check that experiment is not incremented when branching with a new name."""
        name = "parent"
        space = {"x": "uniform(0, 10)"}

        with OrionState(experiments=[], trials=[]):
            parent = experiment_builder.build(name=name, space=space)

            assert parent.name == name
            assert parent.version == 1

            child_name = "child"

            child = experiment_builder.build(
                name=name, branching={"branch_to": child_name, "enable": True}
            )

            assert child.name == child_name
            assert child.version == 1
            assert child.refers["parent_id"] == parent.id

            child_name = "child2"

            child = experiment_builder.build(
                name=child_name, branching={"branch_from": name, "enable": True}
            )

            assert child.name == child_name
            assert child.version == 1
            assert child.refers["parent_id"] == parent.id

    def test_no_increment_when_child_exist(self):
        """Check that experiment cannot be incremented when asked for v1 while v2 exists."""
        name = "parent"
        space = {"x": "uniform(0,10)"}

        with OrionState(experiments=[], trials=[]):
            parent = experiment_builder.build(name=name, space=space)
            child = experiment_builder.build(
                name=name, space={"x": "loguniform(1,10)"}, branching={"enable": True}
            )
            assert child.name == parent.name
            assert parent.version == 1
            assert child.version == 2

            with pytest.raises(BranchingEvent) as exc_info:
                experiment_builder.build(
                    name=name,
                    version=1,
                    space={"x": "loguniform(1,10)"},
                    branching={"enable": True},
                )
            assert "Configuration is different and generates a branching" in str(
                exc_info.value
            )

    def test_race_condition_wout_version(self, monkeypatch):
        """Test that an experiment losing the race condition during version increment raises
        RaceCondition if version number was not specified.
        """
        name = "parent"
        space = {"x": "uniform(0,10)"}

        with OrionState(experiments=[], trials=[]):
            parent = experiment_builder.build(name, space=space)
            child = experiment_builder.build(
                name=name, space={"x": "loguniform(1,10)"}, branching={"enable": True}
            )
            assert child.name == parent.name
            assert parent.version == 1
            assert child.version == 2

            # Either
            # 1.
            #     fetch_config_from_db only fetch parent
            #     test_version finds other child
            #     -> Detect race condition looking at conflicts
            # 2.
            #     fetch_config_from_db only fetch parent
            #     test_version do not find other child
            #     -> DuplicateKeyError

            def insert_race_condition_1(self, query):
                is_auto_version_query = query == {
                    "name": name,
                    "refers.parent_id": parent.id,
                }
                if is_auto_version_query:
                    data = [child.configuration]
                # First time the query returns no other child
                elif insert_race_condition_1.count < 1:
                    data = [parent.configuration]
                else:
                    data = [parent.configuration, child.configuration]

                insert_race_condition_1.count += int(is_auto_version_query)

                return data

            insert_race_condition_1.count = 0

            monkeypatch.setattr(
                setup_storage().__class__, "fetch_experiments", insert_race_condition_1
            )

            with pytest.raises(RaceCondition) as exc_info:
                experiment_builder.build(
                    name=name,
                    space={"x": "loguniform(1,10)"},
                    branching={"enable": True},
                )
            assert "There was likely a race condition during version" in str(
                exc_info.value
            )

            def insert_race_condition_2(self, query):
                is_auto_version_query = query == {
                    "name": name,
                    "refers.parent_id": parent.id,
                }
                # First time the query returns no other child
                if is_auto_version_query:
                    data = []
                elif insert_race_condition_2.count < 1:
                    data = [parent.configuration]
                else:
                    data = [parent.configuration, child.configuration]

                insert_race_condition_2.count += int(is_auto_version_query)

                return data

            insert_race_condition_2.count = 0

            monkeypatch.setattr(
                setup_storage().__class__, "fetch_experiments", insert_race_condition_2
            )

            with pytest.raises(RaceCondition) as exc_info:
                experiment_builder.build(
                    name=name,
                    space={"x": "loguniform(1,10)"},
                    branching={"enable": True},
                )
            assert "There was a race condition during branching." in str(exc_info.value)

    def test_race_condition_w_version(self, monkeypatch):
        """Test that an experiment losing the race condition during version increment cannot
        be resolved automatically if a version number was specified.

        Note that if we would raise RaceCondition, the conflict would still occur since
        the version number fetched will not be the new one from the resolution but the requested
        one. Therefore raising and handling RaceCondition would lead to infinite recursion in
        the experiment builder.
        """
        name = "parent"
        space = {"x": "uniform(0,10)"}

        with OrionState(experiments=[], trials=[]):
            parent = experiment_builder.build(name, space=space)
            child = experiment_builder.build(
                name=name, space={"x": "loguniform(1,10)"}, branching={"enable": True}
            )
            assert child.name == parent.name
            assert parent.version == 1
            assert child.version == 2

            # Either
            # 1.
            #     fetch_config_from_db only fetch parent
            #     test_version finds other child
            #     -> Detect race condition looking at conflicts
            # 2.
            #     fetch_config_from_db only fetch parent
            #     test_version do not find other child
            #     -> DuplicateKeyError

            def insert_race_condition_1(self, query):
                is_auto_version_query = query == {
                    "name": name,
                    "refers.parent_id": parent.id,
                }
                if is_auto_version_query:
                    data = [child.configuration]
                # First time the query returns no other child
                elif insert_race_condition_1.count < 1:
                    data = [parent.configuration]
                else:
                    data = [parent.configuration, child.configuration]

                insert_race_condition_1.count += int(is_auto_version_query)

                return data

            insert_race_condition_1.count = 0

            monkeypatch.setattr(
                setup_storage().__class__, "fetch_experiments", insert_race_condition_1
            )

            with pytest.raises(BranchingEvent) as exc_info:
                experiment_builder.build(
                    name=name,
                    version=1,
                    space={"x": "loguniform(1,10)"},
                    branching={"enable": True},
                )
            assert "Configuration is different and generates" in str(exc_info.value)

            def insert_race_condition_2(self, query):
                is_auto_version_query = query == {
                    "name": name,
                    "refers.parent_id": parent.id,
                }
                # First time the query returns no other child
                if is_auto_version_query:
                    data = []
                elif insert_race_condition_2.count < 1:
                    data = [parent.configuration]
                else:
                    data = [parent.configuration, child.configuration]

                insert_race_condition_2.count += int(is_auto_version_query)

                return data

            insert_race_condition_2.count = 0

            monkeypatch.setattr(
                setup_storage().__class__, "fetch_experiments", insert_race_condition_2
            )

            with pytest.raises(RaceCondition) as exc_info:
                experiment_builder.build(
                    name=name,
                    version=1,
                    space={"x": "loguniform(1,10)"},
                    branching={"enable": True},
                )
            assert "There was a race condition during branching." in str(exc_info.value)

    def test_build_experiment_with_kb(self, tmp_path: Path):
        """Test that passing a configuration for the KB to `create_experiment` works."""
        exp_storage_file = str(tmp_path / "db.pkl")
        kb_storage_file = str(tmp_path / "kb.pkl")
        experiment = experiment_builder.build(
            "test",
            space={"x": "uniform(0, 10)"},
            storage={
                "type": "legacy",
                "database": {"type": "pickleddb", "host": exp_storage_file},
            },
            knowledge_base={
                KnowledgeBase.__qualname__: {
                    "storage": {
                        "type": "legacy",
                        "database": {"type": "pickleddb", "host": kb_storage_file},
                    }
                }
            },
        )
        assert experiment.knowledge_base is not None
        assert isinstance(experiment.knowledge_base, KnowledgeBase)

class TestInstantiateKB:
    def test_build_experiment_with_bad_kb_config(self):
        """Test that passing a bad configuration for the KB raises an error."""
        with pytest.raises(
            ConfigurationError,
            match="The configuration for the KB should only have one key",
        ):
            experiment_builder._instantiate_knowledge_base(
                {
                    "fooooobar": {
                        "storage": {"type": "legacy", "database": {"type": "bad"}}
                    },
                    "baz": 123,
                }
            )

    def test_kb_class_not_found(self):
        with pytest.raises(
            ConfigurationError,
            match="Unable to find a subclass of KnowledgeBase with the given name",
        ):
            experiment_builder._instantiate_knowledge_base(
                {
                    "NonExistentKB": {
                        "storage": {"type": "legacy", "database": {"type": "bad"}}
                    },
                }
            )

    def test_finds_kb_subclass_and_uses_it(self, tmp_path: Path):
        class MyKB(KnowledgeBase):
            pass

        path = tmp_path / "db.pkl"
        kb = experiment_builder._instantiate_knowledge_base(
            {
                "MyKB": {
                    "storage": {
                        "type": "legacy",
                        "database": {"type": "pickleddb", "host": str(path)},
                    }
                },
            }
        )
        assert isinstance(kb, MyKB)

    def test_multiple_subclasses_match_name(self):
        class KB(KnowledgeBase):  # noqa
            pass

        class KB(KnowledgeBase):  # noqa
            pass

        with pytest.raises(
            ConfigurationError,
            match="Multiple subclasses of KnowledgeBase with the given name",
        ):
            experiment_builder._instantiate_knowledge_base(
                {
                    "KB": {"storage": {"type": "legacy", "database": {"type": "bad"}}},
                }
            )

@pytest.fixture
def space_obj(space: dict[str, str]):
    # todo: Rename `space` above to `space_config` and rename this to just `space`.
    return SpaceBuilder().build(space)

class TestInstantiateAlgo:
    """Tests for the `_instantiate_algo` function."""

    @pytest.mark.parametrize("algo_class_name", ["Random", "TPE"])
    @pytest.mark.parametrize("lowercase", [True, False])
    @pytest.mark.parametrize("max_trials", [None, 10])
    def test_with_class_name(
        self,
        algo_class_name: str,
        space_obj: Space,
        lowercase: bool,
        max_trials: int | None,
    ):
        """Test instantiating an algorithm by passing the class name as a config."""
        algo = experiment_builder._instantiate_algo(
            space=space_obj,
            max_trials=max_trials,
            config=algo_class_name.lower() if lowercase else algo_class_name,
        )
        assert isinstance(algo, BaseAlgorithm)
        assert type(algo.unwrapped).__qualname__ == algo_class_name
        assert algo.max_trials == max_trials

    @pytest.mark.parametrize("algo_class", [Random, TPE])
    @pytest.mark.parametrize("max_trials", [None, 10])
    def test_with_algo_class(
        self, algo_class: type[BaseAlgorithm], space_obj: Space, max_trials: int | None
    ):
        """Test instantiating an algorithm by passing the class as a config."""

        algo = experiment_builder._instantiate_algo(
            space=space_obj,
            max_trials=max_trials,
            config=algo_class,
        )
        assert isinstance(algo, BaseAlgorithm)
        assert isinstance(algo.unwrapped, algo_class)
        assert algo.max_trials == max_trials

    @pytest.mark.parametrize("algo_class", [Random, TPE])
    @pytest.mark.parametrize("max_trials", [None, 10])
    def test_with_dict(
        self, algo_class: type[BaseAlgorithm], space_obj: Space, max_trials: int | None
    ):
        """Test instantiating an algorithm using a config dictionary."""
        algo = experiment_builder._instantiate_algo(
            space=space_obj,
            max_trials=max_trials,
            config={algo_class.__qualname__.lower(): {}},
        )
        assert isinstance(algo, BaseAlgorithm)
        assert isinstance(algo.unwrapped, algo_class)
        assert algo.max_trials == max_trials

def test_load_unavailable_algo(algo_unavailable_config, capsys):
    with OrionState(experiments=[algo_unavailable_config]):
        experiment = experiment_builder.load("supernaekei", mode="r")
        assert experiment.algorithm == algo_unavailable_config["algorithm"]
        assert (
            experiment.configuration["algorithm"]
            == algo_unavailable_config["algorithm"]
        )

        experiment = experiment_builder.load("supernaekei", mode="w")
        assert experiment.algorithm == algo_unavailable_config["algorithm"]
        assert (
            experiment.configuration["algorithm"]
            == algo_unavailable_config["algorithm"]
        )

        with pytest.raises(
            NotImplementedError, match="Could not find implementation of BaseAlgorithm"
        ):
            experiment_builder.build("supernaekei")

class TestInitExperimentReadWrite:
    """Create new Experiment instance that only supports read/write."""

    def test_empty_experiment_rw(self):
        """Hit user name, but exp_name does not hit the db."""
        with OrionState(experiments=[], trials=[]):
            with pytest.raises(NoConfigurationError) as exc_info:
                experiment_builder.load("supernaekei")
            assert "No experiment with given name 'supernaekei' and version '*'" in str(
                exc_info.value
            )

    def test_existing_experiment_read_mode(self, new_config):
        """Hit exp_name + user's name in the db, support read only."""
        with OrionState(experiments=[new_config], trials=[]):
            exp = experiment_builder.load(name="supernaekei", mode="r")

        assert exp.mode == "r"
        exp.fetch_trials()  # Should pass
        with pytest.raises(UnsupportedOperation) as exc:
            exp.fix_lost_trials()
        assert exc.match("to execute `fix_lost_trials()")

    def test_existing_experiment_read_write_mode(self, new_config):
        """Hit exp_name + user's name in the db, support read and write."""
        with OrionState(experiments=[new_config], trials=[]):
            exp = experiment_builder.load(name="supernaekei", mode="w")

        assert exp.mode == "w"
        exp.fetch_trials()  # Should pass
        exp.fix_lost_trials()  # Should pass

        with pytest.raises(UnsupportedOperation) as exc:
            exp.reserve_trial()
        assert exc.match("to execute `reserve_trial()")


import pygame
from ...dependencias import PygameClock
from ...core.general.tiempo import Timer, convertir_a_milisegundos, Segundos, Milisegundos
from .datos_tiempo import DatosTiempo

class ControlTiempo:
    tiempo_setup_y_primer_ciclo: Milisegundos
    tiempo_total: Milisegundos
    fps: int
    reloj: PygameClock

    def __init__(self) -> None:
        self.tiempo_setup_y_primer_ciclo = Milisegundos(0)  # mide el tiempo hasta el primer tick del reloj
        self.timer = Timer()
        self.tiempo_total = Milisegundos(0)

    def crear_reloj(self, fps: int) -> None:
        self.reloj = pygame.time.Clock()
        self.fps = fps

    def imprimir_tiempo(self, datos_tiempo: DatosTiempo) -> None:
        print(f'Tiempo de inicio: {int(self.tiempo_setup_y_primer_ciclo)} milisegundos')
        print(f'Tiempo actual: {int(convertir_a_milisegundos(self.tiempo_actual))} milisegundos')
        print(f'Tiempo total: {int(self.tiempo_total)} milisegundos')
        tiempo_total_vista = sum((dato.vista for dato in datos_tiempo.datos_lag.values()), start=Milisegundos(0))
        print(f'Tiempo total vista: {tiempo_total_vista}')

    @property
    def tiempo_actual(self) -> Segundos:
        return Segundos(self.timer.info())

    def tick_reloj(self) -> Milisegundos:
        if not self.tiempo_total:
            # primer ciclo
            print('Inicializando el tiempo en ControlTiempo')
            self.tiempo_setup_y_primer_ciclo = convertir_a_milisegundos(self.timer.info())
            assert type(self.tiempo_total) == type(self.tiempo_setup_y_primer_ciclo)
            self.tiempo_total = Milisegundos(self.tiempo_total + self.tiempo_setup_y_primer_ciclo)

        milisegundos = Milisegundos(self.reloj.tick(self.fps))
        assert type(self.tiempo_total) == type(milisegundos)
        self.tiempo_total = Milisegundos(self.tiempo_total + milisegundos)
        return milisegundos


import sys
# from apc_log import APC_Log
from socket import *
import json
import cv2
import os
import time
import shutil
import datetime
import numpy as np
from Segmentation import Detectron_inference

detectron = Detectron_inference()

class RECEIVER():
    def __init__(self):
        self.HOST = 'Localhost'
        self.PORT = 5555

    def Connect(self):
        self.Receiver = socket(AF_INET, SOCK_STREAM)
        self.Receiver.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.Receiver.bind((self.HOST, self.PORT))
        print('Receiver Socket binding {}'.format(self.Receiver))
        self.Receiver.listen(5)
        print('Receiver Listening')

    def Get_Tcp_mode(self):
        self.conn, self.addr = self.Receiver.accept()
        self.conn.settimeout(3)
        print('Connection accepted {}'.format(self.addr))
        self.mode_check = self.conn.recv(1024).decode()
        if self.mode_check == 'connect':
            self.conn.sendall('connected'.encode())
        if self.mode_check == 'processing':
            self.conn.sendall('Working'.encode())
        if self.mode_check == 'Health_check':
            self.conn.sendall('Alive'.encode())
        if self.mode_check == 'Make Idle':
            detectron.empty_gpu()
            self.conn.sendall('Idling'.encode())

    def Get_File_Info(self):
        try:
            self.file_info = json.loads(self.conn.recv(4096).decode())
            print('Json dumping done')
        except:
            print('Json dumping failed')
            self.Receiver.close()
            self.Connect()
            pass

    def Get_File(self):
        data_transferred = 0
        data = self.file_info['file_length']

        self.conn.sendall('READY'.encode())
        print('Receiver ready to get a image')
        try:
            with open("./tmp/"+self.file_info['file_name'], 'wb') as f:
                while True:
                    data = self.conn.recv(1024)
                    f.write(data)
                    data_transferred += len(data)
                    if not data:
                        break
        except:
            print('Receiver got a image successfully')
            obj_list, area_list, area_per_list = detectron.Main("./tmp/"+self.file_info['file_name'])
            print('detectron2 processing done!!!')
            self.conn.sendall('READY'.encode())

            return obj_list, area_list, area_per_list
            pass

    def Dump_Json(self, obj_list, area_list, area_per_list, base_path, img_name):
        file_info = {
                    'file_name' : img_name,
                    'file_length' : self.GetFileSize(base_path),
                    'file_reverse_name' : 'test2.jpg',
                    'file_reverse_length' : self.GetFileSize('./test2.jpg'),
                    'create_time' : datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    'obj_list' : obj_list,
                    'area_list' : area_list,
                    'area_per_list' : area_per_list
                    }

        send_data = json.dumps(file_info)
        print(file_info)
        self.conn.send(send_data.encode())
        time.sleep(0.01)

    def GetFileSize(self, base_path):
        filesize = os.path.getsize(base_path)
        return str(filesize)

    def GetFileData(self, base_path):
        data_transferred = 0
        self.conn.settimeout(1)
        with open(base_path, 'rb') as f:
            data = f.read(1024)
            while data:
                data_transferred += self.conn.send(data)
                data = f.read(1024)
        # os.remove(self.base_path)
        print('image returned successfully')
        time.sleep(0.01)

class WB_Process():
    def __init__(self, HOST, PORT):
        self.HOST = HOST
        self.PORT = int(PORT)
        self.connect()

    def connect(self):
        self.receiver = RECEIVER()
        self.receiver.HOST = self.HOST
        self.receiver.PORT = self.PORT
        self.receiver.Connect()
        while True:
            self.receiver.Get_Tcp_mode()
            print(self.receiver.mode_check)
            if self.receiver.mode_check == 'processing':
                self.receiver.Get_File_Info() #get image infomation
                obj_list, area_list, area_per_list = self.receiver.Get_File() #get image file
                self.receiver.Dump_Json(obj_list, area_list, area_per_list, base_path = './test.jpg', img_name = 'test.jpg') #return result info
                status = self.receiver.conn.recv(1024) #check if ready to return result image
                if status.decode() == 'READY':
                    self.receiver.GetFileData(base_path = './test.jpg') #return result image
                    self.receiver.conn.settimeout(3)
                    print(self.receiver.conn.recv(1024).decode())
                    self.receiver.GetFileData(base_path = './test2.jpg')
            else:
                pass
        self.receiver.conn.close()

if __name__ == '__main__':
    wb = WB_Process(HOST = '172.23.69.100', PORT = '5555')


"""Utilities for analysis
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import warnings

from collections import Counter
from collections import defaultdict
import numpy as np
from tqdm import *
import sys

orf_file = sys.argv[1]
print('exporting coverages for all ORFs...')
columns = [
    'ORF_ID', 'ORF_type', 'status', 'phase_score', 'read_count', 'length',
    'valid_codons', 'transcript_id', 'transcript_type', 'gene_id',
    'gene_name', 'gene_type', 'chrom', 'strand', 'start_codon', 'profile\n'
]
to_write = '\t'.join(columns)
formatter = '{}\t' * (len(columns) - 1) + '{}\n'

cnt = 0
with open(orf_file, 'r') as orf, open('filtered_result.txt', 'w') as output:
    header = True
    for line in orf:
        # cnt += 1
        # if cnt > 10:
            # break
        if header:
            header = False
            output.write(to_write)
            continue
        fields = line.strip().split('\t')
        oid = fields[0]
        otype = fields[1]
        status = fields[2]
        phase_score = fields[3]
        read_count = fields[4]
        length = fields[5]
        valid_codons = fields[6]
        tid = fields[7]
        ttype = fields[8]
        gid = fields[9]
        gname = fields[10]
        gtype = fields[11]
        chrom = fields[12]
        strand = fields[13]
        start_codon = fields[14]
        cov = fields[15]
        cov = cov[1:-1]
        cov = [int(x) for x in cov.split(', ')]
        if status == 'nontranslating':
            continue
        if sum([sum(cov[i:i + 3]) > 0 for i in range(0, 30, 3)]) < 5:
            continue
        output.write(line)


from rest_framework import serializers
from .models import Pokemon, Evolution

class EvolutionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Evolution
        fields = (
            'id',
            'name',
            'evolution_type'
        )

class PokemonSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField(source='pokemon_id')
    evolutions = EvolutionSerializer(read_only=True, many=True)

    class Meta:
        model = Pokemon
        fields = (
            'id',
            'name',
            'height',
            'weight',
            'base_stats',
            'evolutions',
        )


################백준 2675번 문자열 반복##################

T = int(input())           # 테스트 케이스 갯수

for i in range(T):
    result = []                 # 빈 리스트 생성
    R, S = input().split()      # R(1<=R<=8)각 테스트 케이스 반복 횟수
                                # S(1<=S<=20) 문자열

    for j in S:                  # 문자열 S를 순차 접근함
        for k in range(int(R)):  # R을 아까 문자열로 입력 받았기떄문에 형변환 해줌
            result.append(j)     # 리스트 result 에다가 순차접근한 문자열S를 R번만큼 넣음

    print(''.join(result))        # --> 리스트 result를 문자열로 표현


# -*- coding: utf-8 -*-
"""
Created on Fri Jul  1 14:22:18 2016

@author: mohithmanohara

This program is meant to simulate a model
of the interaction between CAR T-cells and
3 different cancer species. HER2 will be
represented in the program as c1, EGFR
as c2, and Il13ra2 as c3. Images are
to be saved and compiled into a movie file.

The t-cells are placed randomly in the space in this program.
"""
import matplotlib
matplotlib.use('TkAgg')
from pylab import *
mu1 = 0.005#rate of movement of T-cells
mu2 = 0
mu3 = 0.005
muco = 0.005
d = 0.01#death rate of t cells
n = 102#size of space
k = 350 #Carrying capacity of the cancer cells
K = 1
a = 0.35#rate of growth of each cancer species
b1 = 0.6#death rate of HER2
b2 = 0#death rate of EGFR
b3 = 0.6#death rate of IL13a2
bd = 0.6#death rate of cancer showing coexpression.
Dt = 0.001#diffusion rates of the T-cells and the cancer species
Dc = 0.002
dh = .01 #spacial resolution
dt = 0.01#temporal resolution
q =  25#T-cell distribution coefficient
xcenter = random()
ycenter = random()
xvalues, yvalues = meshgrid(arange(0, 1.02, .01), arange(0, 1.02, .01))
def initialize():
    global t, c0, c1, c2, c3, cco, ctotal, nextt, nextc0, nextc1, nextc2, nextc3, nextcco, nextctotal, ttotal, c0total, c1total, c2total, c3total, ccototal, tplot, c0plot, c1plot, c2plot, c3plot, ccoplot, step, check, tmax, c0max, c1max, c2max, c3max, ccomax, tpend, c0pend, c1pend, c2pend, c3pend, ccopend, steppend
    t = zeros([n, n])#set zero values for each variable in the space
    c0 = zeros([n, n])
    c1 = zeros([n, n])
    c2 = zeros([n, n])
    c3 = zeros([n, n])
    cco = zeros([n, n])
    ctotal = zeros([n, n])#below we set up the initial condition.
    c1 = .396606 * exp(-((xvalues-0.405)**2)/(.135**2) - ((yvalues - .33)**2)/(.24**2))\
         + .373651 * exp(-((xvalues-0.575)**2)/(.035**2) - ((yvalues - .39)**2)/(.05**2))\
         + .403440 * exp(-((xvalues-0.65)**2)/(.04**2) - ((yvalues - .385)**2)/(.085**2))\
         + .739448 * exp(-((xvalues-0.57)**2)/(.02**2) - ((yvalues - .53)**2)/(.02**2))\
         + .553523 * exp(-((xvalues-0.6)**2)/(.01**2) - ((yvalues - .515)**2)/(.015**2))\
         + .500782 * exp(-((xvalues-0.31)**2)/(.03**2) - ((yvalues - .595)**2)/(.025**2))\
         + .478544 * exp(-((xvalues-0.45)**2)/(.03**2) - ((yvalues - .625)**2)/(.035**2))\
         + .490583 * exp(-((xvalues-0.375)**2)/(.015**2) - ((yvalues - .695)**2)/(.015**2))\
         + .443507 * exp(-((xvalues-0.465)**2)/(.025**2) - ((yvalues - .675)**2)/(.005**2))\
         + .432523 * exp(-((xvalues-0.6)**2)/(.18**2) - ((yvalues - .755)**2)/(.115**2))\
         + .399770 * exp(-((xvalues-0.445)**2)/(.075**2) - ((yvalues - .915)**2)/(.045**2))
    c2 = .606893 * exp(-((xvalues-0.405)**2)/(.135**2) - ((yvalues - .33)**2)/(.24**2))\
         + .429825 * exp(-((xvalues-0.575)**2)/(.035**2) - ((yvalues - .39)**2)/(.05**2))\
         + .618103 * exp(-((xvalues-0.65)**2)/(.04**2) - ((yvalues - .385)**2)/(.085**2))\
         + .625116 * exp(-((xvalues-0.57)**2)/(.02**2) - ((yvalues - .53)**2)/(.02**2))\
         + .502399 * exp(-((xvalues-0.6)**2)/(.01**2) - ((yvalues - .515)**2)/(.015**2))\
         + .316215 * exp(-((xvalues-0.31)**2)/(.03**2) - ((yvalues - .595)**2)/(.025**2))\
         + .743633 * exp(-((xvalues-0.45)**2)/(.03**2) - ((yvalues - .625)**2)/(.035**2))\
         + .782661 * exp(-((xvalues-0.375)**2)/(.015**2) - ((yvalues - .695)**2)/(.015**2))\
         + .708838 * exp(-((xvalues-0.465)**2)/(.025**2) - ((yvalues - .675)**2)/(.005**2))\
         + .329171 * exp(-((xvalues-0.6)**2)/(.18**2) - ((yvalues - .755)**2)/(.115**2))\
         + .567646 * exp(-((xvalues-0.445)**2)/(.075**2) - ((yvalues - .915)**2)/(.045**2))
    c3 = .331261 * exp(-((xvalues-0.405)**2)/(.135**2) - ((yvalues - .33)**2)/(.24**2))\
         + .297917 * exp(-((xvalues-0.575)**2)/(.035**2) - ((yvalues - .39)**2)/(.05**2))\
         + .303581 * exp(-((xvalues-0.65)**2)/(.04**2) - ((yvalues - .385)**2)/(.085**2))\
         + .413251 * exp(-((xvalues-0.57)**2)/(.02**2) - ((yvalues - .53)**2)/(.02**2))\
         + .333327 * exp(-((xvalues-0.6)**2)/(.01**2) - ((yvalues - .515)**2)/(.015**2))\
         + .249389 * exp(-((xvalues-0.31)**2)/(.03**2) - ((yvalues - .595)**2)/(.025**2))\
         + .343188 * exp(-((xvalues-0.45)**2)/(.03**2) - ((yvalues - .625)**2)/(.035**2))\
         + .243203 * exp(-((xvalues-0.375)**2)/(.015**2) - ((yvalues - .695)**2)/(.015**2))\
         + .401408 * exp(-((xvalues-0.465)**2)/(.025**2) - ((yvalues - .675)**2)/(.005**2))\
         + .263288 * exp(-((xvalues-0.6)**2)/(.18**2) - ((yvalues - .755)**2)/(.115**2))\
         + .244822 * exp(-((xvalues-0.445)**2)/(.075**2) - ((yvalues - .915)**2)/(.045**2))
    for y in range(n):
        for x in range(n):
            ctotal[x, y] = c0[x, y] + c1[x, y] + c2[x, y] + c3[x, y] + cco[x, y]
    t = q * exp(-((xvalues - xcenter)**2 + (yvalues - ycenter)**2) / (.05**2))
    nextt = zeros([n, n])#must define the "next" variables for the space.
    nextc0 = zeros([n, n])
    nextc1 = zeros([n, n])
    nextc2 = zeros([n, n])
    nextc3 = zeros([n, n])
    nextcco = zeros([n, n])
    nextctotal = zeros([n, n])
    tplot = zeros([n-2, n-2])#Only plotting 100x100, so this is what we need to plot
    c0plot = zeros([n-2, n-2])
    c1plot = zeros([n-2, n-2])
    c2plot = zeros([n-2, n-2])
    c3plot = zeros([n-2, n-2])
    ccoplot = zeros([n-2, n-2])
    ttotal = 0#total populations
    c0total = 0
    c1total = 0
    c2total = 0
    c3total = 0
    ccototal = 0
    check = 50
    step = 0
    for x in range(1, n-1):#sum up the total each cell type.
        for y in range(1, n-1):
            ttotal = ttotal + t[x, y]
            c0total = c0total + c0[x, y]
            c1total = c1total + c1[x, y]
            c2total = c2total + c2[x, y]
            c3total = c3total + c3[x, y]
            ccototal = ccototal + cco[x, y]
    for x in range(1, n-1):#values that are actually plotted
        for y in range(1, n-1):
            tplot[x-1, y-1] = t[x, y]
            c0plot[x-1, y-1] = c0[x, y]
            c1plot[x-1, y-1] = c1[x, y]
            c2plot[x-1, y-1] = c2[x, y]
            c3plot[x-1, y-1] = c3[x, y]
            ccoplot[x-1, y-1] = cco[x, y]
    tmax = 0
    c0max = 0
    c1max = 0
    c2max = 0
    c3max = 0
    ccomax = 0
    for x in range(100):#find the max value to use for the colorbar
        for y in range(100):
            if tplot[x, y] > tmax:
                tmax = tplot[x, y]
            if c0plot[x, y] > c0max:
                c0max = c0plot[x, y]
            if c1plot[x, y] > c1max:
                c1max = c1plot[x, y]
            if c2plot[x, y] > c2max:
                c2max = c2plot[x, y]
            if c3plot[x, y] > c3max:
                c3max = c3plot[x, y]
            if ccoplot[x, y] > ccomax:
                ccomax = ccoplot[x, y]
    tpend = [ttotal]
    c0pend = [c0total]
    c1pend = [c1total]
    c2pend = [c2total]
    c3pend = [c3total]
    ccopend = [ccototal]
    steppend = [step]
def observe():
    global t, c0, c1, c2, c3, cco, ctotal, nextt, nextc0, nextc1, nextc2, nextc3, nextcco, nextctotal, ttotal, c0total, c1total, c2total, c3total, ccototal, tplot, c0plot, c1plot, c2plot, c3plot, ccoplot, step, check, tmax, c0max, c1max, c2max, c3max, ccomax, tpend, c0pend, c1pend, c2pend, c3pend, ccopend, steppend
    clf()
    subplot(5, 5, 1)
    imshow(tplot, vmin=0, vmax = tmax)#show t-cells.
    title('CAR T-cells')
    colorbar()
    subplot(5, 5, 3)
    imshow(c1plot, vmin = 0, vmax = c1max)#show HER2
    title('HER2')
    colorbar()
    subplot(5, 5, 5)
    imshow(c2plot, vmin = 0, vmax = c2max)#show EGFR
    title('EGFR')
    colorbar()
    subplot(5, 5, 11)
    imshow(c3plot, vmin = 0, vmax = c3max)#show IL13ra2
    title('IL13ra2')
    colorbar()
    subplot(5, 5, 21)
    imshow(c0plot, vmin = 0, vmax = c0max)#show no expression
    title('No expression')
    colorbar()
    subplot(5, 5, 13)
    imshow(ccoplot, vmin = 0, vmax = ccomax)#show coexpression
    title('coexpression')
    colorbar()
    subplot(5, 5, 23)
    plot(steppend, tpend, 'b.', label = 'CAR T-cells')
    plot(steppend, c0pend, 'r.', label ='No expression')
    plot(steppend, c1pend, 'g.', label ='HER2')
    plot(steppend, c2pend, 'y.', label ='EGFR')
    plot(steppend, c3pend, 'm.', label ='IL13ra2')
    plot(steppend, ccopend, 'k.', label = 'coexpression')
    legend(bbox_to_anchor=(1.05, 1), prop = {'size':8}, loc=2, borderaxespad=0.)
    title('total population sizes')
    xlabel('Time')
    ylabel('population size')
def update():
    global t, c0, c1, c2, c3, cco, ctotal, nextt, nextc0, nextc1, nextc2, nextc3, nextcco, nextctotal, ttotal, c0total, c1total, c2total, c3total, ccototal, tplot, c0plot, c1plot, c2plot, c3plot, ccoplot, step, check, tmax, c0max, c1max, c2max, c3max, ccomax, tpend, c0pend, c1pend, c2pend, c3pend, ccopend, steppend
    xcenter = random()#set random x and y for where the new dose is placed
    ycenter = random()
    if step<7.001 and step > 6.999 or step <14.001 and step > 13.999 or step < 21.001 and step > 20.999:
        t = t + q * exp(-((xvalues - xcenter)**2 + (yvalues - ycenter)**2) / (.05**2))#add a new dose every 7 days
    for x in range(1, n-1):
        for y in range(1, n-1):
            tC, tR, tL, tU, tD = t[x, y], t[(x + 1), y], t[(x - 1), y], \
                                 t[x, (y + 1)], t[x, (y - 1)]#setting values for neighbor cells
            c0C, c0R, c0L, c0U, c0D = c0[x, y], c0[(x + 1), y], c0[(x - 1), y], \
                                      c0[x, (y + 1)], c0[x, (y - 1)]
            c1C, c1R, c1L, c1U, c1D = c1[x, y], c1[(x + 1), y], c1[(x - 1), y], \
                                      c1[x, (y + 1)], c1[x, (y - 1)]
            c2C, c2R, c2L, c2U, c2D = c2[x, y], c2[(x + 1), y], c2[(x - 1), y], \
                                      c2[x, (y + 1)], c2[x, (y - 1)]
            c3C, c3R, c3L, c3U, c3D = c3[x, y], c3[(x + 1), y], c3[(x - 1), y], \
                                      c3[x, (y + 1)], c3[x, (y - 1)]
            ccoC, ccoR, ccoL, ccoU, ccoD = cco[x, y], cco[(x + 1), y], cco[(x - 1), y], \
                                           cco[x, (y + 1)], cco[x, (y - 1)]
            ctotalC = ctotal[x, y]
            tLapNum = tU + tD + tL + tR - 4 * tC#values of Laplacians
            c0LapNum = c0U + c0D + c0R + c0L - 4 * c0C
            c1LapNum = c1U + c1D + c1R + c1L - 4 * c1C
            c2LapNum = c2U + c2D + c2R + c2L - 4 * c2C
            c3LapNum = c3U + c3D + c3R + c3L - 4 * c3C
            ccoLapNum = ccoU + ccoD + ccoR + ccoL - 4 * ccoC
            #Be warned; the next few equations are HORRIFYINGLY LONG. Have a good day :) ‘’’the equations have the same comments as the samelocbiCAR, so check that out. No I am not being lazy, what are you talking about?’’’
            nextt[x, y] = tC + (-d * tC - mu1 * (((tR - tL) / (2 * dh))*((c1R - c1L) / (2 * dh)) + ((tU - tD) / (2 * dh)) * ((c1U - c1D) / (2 * dh)) + tC * (c1LapNum / dh**2)) - mu2 * (((tR - tL) / (2 * dh))*((c2R - c2L) / (2 * dh)) + ((tU - tD) / (2 * dh)) * ((c2U - c2D) / (2 * dh)) + tC * (c2LapNum / dh**2)) - mu3 * (((tR - tL) / (2 * dh))*((c3R - c3L) / (2 * dh)) + ((tU - tD) / (2 * dh)) * ((c3U - c3D) / (2 * dh)) + tC * (c3LapNum / dh**2))- muco * (((tR - tL) / (2 * dh))*((ccoR - ccoL) / (2 * dh)) + ((tU - tD) / (2 * dh)) * ((ccoU - ccoD) / (2 * dh)) + tC * (ccoLapNum / dh**2)) + Dt * (tLapNum/dh**2)) * dt
            nextc0[x, y] = c0C + (a * c0C * (1 - (ctotalC)/K) + Dc * (c0LapNum / dh**2)) * dt
            nextc1[x, y] = c1C + (a * c1C * (1 - (ctotalC)/K) - b1 * c1C * tC + Dc * (c1LapNum / dh**2)) * dt
            nextc2[x, y] = c2C + (a * c2C * (1 - (ctotalC)/K) - b2 * c2C * tC + Dc * (c2LapNum / dh**2)) * dt
            nextc3[x, y] = c3C + (a * c3C * (1 - (ctotalC)/K) - b3 * c3C * tC + Dc * (c3LapNum / dh**2)) * dt
            nextcco[x, y] = ccoC + (a * ccoC * (1 - (ctotalC)/K) - bd * ccoC * tC + Dc * (ccoLapNum/dh**2)) * dt
            nextctotal[x, y] = c0C + c1C + c2C + c3C + ccoC
    ttotal = 0
    c0total = 0
    c1total = 0
    c2total = 0
    c3total = 0
    ccototal = 0
    for x in range(1, n-1):#sum up the total each cell type.
        for y in range(1, n-1):
            ttotal = ttotal + t[x, y]
            c0total = c0total + c0[x, y]
            c1total = c1total + c1[x, y]
            c2total = c2total + c2[x, y]
            c3total = c3total + c3[x, y]
            ccototal = ccototal + cco[x, y]
    for x in range(1, n-1):
        for y in range(1, n-1):#update plotted variables
            tplot[x-1, y-1] = t[x, y]
            c0plot[x-1, y-1] = c0[x, y]
            c1plot[x-1, y-1] = c1[x, y]
            c2plot[x-1, y-1] = c2[x, y]
            c3plot[x-1, y-1] = c3[x, y]
            ccoplot[x-1, y-1] = cco[x, y]
    tmax = 0
    c0max = 0
    c1max = 0
    c2max = 0
    c3max = 0
    ccomax = 0
    for x in range(100):
        for y in range(100):
            if tplot[x, y] > tmax:
                tmax = tplot[x, y]
            if c0plot[x, y] > c0max:
                c0max = c0plot[x, y]
            if c1plot[x, y] > c1max:
                c1max = c1plot[x, y]
            if c2plot[x, y] > c2max:
                c2max = c2plot[x, y]
            if c3plot[x, y] > c3max:
                c3max = c3plot[x, y]
            if ccoplot[x, y] > ccomax:
                ccomax = ccoplot[x, y]
    t, c0,c1, c2, c3, cco, ctotal, nextt, nextc0, nextc1, nextc2, nextc3, nextcco, nextctotal = nextt, nextc0, nextc1, nextc2, nextc3, nextcco, nextctotal, t, c0, c1, c2, c3, cco, ctotal
    step = step + dt
    check = check + 1#increase image counter thing.
    if check == 50:
        tpend.append(ttotal)
        c0pend.append(c0total)
        c1pend.append(c1total)
        c2pend.append(c2total)
        c3pend.append(c3total)
        ccopend.append(ccototal)
        steppend.append(step)
def takepic():#defining when to take the pic, and what the pic is saved as.
    global t, c0, c1, c2, c3, cco, ctotal, nextt, nextc0, nextc1, nextc2, nextc3, nextcco, nextctotal, ttotal, c0total, c1total, c2total, c3total, ccototal, tplot, c0plot, c1plot, c2plot, c3plot, ccoplot, step, check
    if check == 50:
        observe()
        savefig(str(step) + 'random injections.png')
        check = 0

def picmode():#the mode when we want to save a bunch of figures
    initialize()
    takepic()
    while step < 28:
        update()
        takepic()
    figtext(0.8, 0.4, 'T =' + str(ttotal))#when done, display the total population size on the figure.
    figtext(0.8, 0.35, 'None =' + str(c0total))
    figtext(0.8, 0.3, 'HER2 =' + str(c1total))
    figtext(0.8, 0.25, 'EGFR =' + str(c2total))
    figtext(0.8, 0.2, 'IL13ra2 =' + str(c3total))
    figtext(0.8, 0.15, 'coexpression =' + str(ccototal))
    savefig('finalrandominjections.png')
picmode()


from django.urls import path

from . import views

app_name = 'student'

urlpatterns = [
    path('signup_info/', views.signup_info, name='signup_info'),
    path('dash/', views.dash, name='dash'),
    path('class_select/', views.class_select, name='class_select'),
    path('class_signup/<int:class_id>/', views.class_signup, name='class_signup'),
    path('my_class/', views.my_class, name='my_class'),
    path('take_class/<int:course_id>/<int:enroll_id>/', views.take_class, name='take_class'),
    path('take_lecture/<int:lecture_id>/<int:enroll_id>/', views.take_lecture, name='take_lecture'),
    path('take_lecture_code/<int:lecture_id>/<int:enroll_id>/', views.take_lecture_code, name='take_lecture_code'),
    path('take_quiz/<int:quiz_id>/<int:enroll_id>/', views.take_quiz, name='take_quiz'),
    path('take_final_quiz/<int:final_quiz_id>/<int:enroll_id>/', views.take_final_quiz, name='take_final_quiz'),
    path('my_quiz/', views.my_quiz, name='my_quiz'),
    path('setting_profile/', views.setting_profile, name='setting_profile'),
    path('setting_photo/', views.setting_photo, name='setting_photo'),
    path('setting_account/', views.setting_account, name='setting_account'),
]


#Create an empty tuple
my_tuple=()

#Create a tuple containing names of your sisters and your brothers (imaginary siblings are fine)
my_brothers=("Ian","Ted","Munene")
print(my_brothers)
my_sisters=("Kathomi","Carol")
print(my_sisters)

#Join brothers and sisters tuples and assign it to siblings
my_siblings=my_brothers+my_sisters
print(my_siblings)

#How many siblings do you have?
no_of_siblings=len(my_siblings)
print(no_of_siblings)

#Modify the siblings tuple and add the name of your father and mother and assign it to family_members
my_siblings=list(my_siblings)
my_siblings.extend(["Fredrick","Florence"])
my_family=tuple(my_siblings)
print(my_family)

#Unpack siblings and parents from family_members
for i in range(len(my_family)):
    print(my_family[i])

#Create fruits, vegetables and animal products tuples. Join the three tuples
# and assign it to a variable called food_stuff_tp.
fruits=("mangoes","oranges","pineapples","pomegranate","passion")
vegetables=("onions","mangoes","tomatoes","potatoes","ngwaci")
animal_products=("cheese","yoghurt","milk","meat","eggs")
food_stuff_tp=fruits+vegetables+animal_products
print(food_stuff_tp)

#Change the about food_stuff_tp tuple to a food_stuff_lt list
food_stuff_lt=list(food_stuff_tp)
print(food_stuff_lt)

#Slice out the middle item or items from the food_stuff_tp tuple or food_stuff_lt list.
mid=len(food_stuff_lt)//2
food_stuff_lt.pop(mid)
print(food_stuff_lt)

#Slice out the first three items and the last three items from food_staff_lt list
print(food_stuff_lt[0:4])
#print(food_stuff_lt)

#Delete the food_staff_tp tuple completely
del food_stuff_tp

#Check if an item exists in tuple:
#Check if 'Estonia' is a nordic country
#Check if 'Iceland' is a nordic country

nordic_countries = ('Denmark', 'Finland','Iceland', 'Norway', 'Sweden')
print('Estonia' in nordic_countries)
print('Iceland' in nordic_countries)


import random

import numpy as np
import torch
from rdkit import RDLogger

from grover.util.parsing import parse_args, get_newest_train_args
from grover.util.utils import create_logger
from task.cross_validate import cross_validate
from task.fingerprint import generate_fingerprints
from task.predict import make_predictions, write_prediction
from task.pretrain import pretrain_model
from grover.data.torchvocab import MolVocab

def setup(seed):
    # frozen random seed
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    np.random.seed(seed)
    random.seed(seed)
    torch.backends.cudnn.deterministic = True

if __name__ == '__main__':
    # setup random seed
    setup(seed=42)
    # Avoid the pylint warning.
    a = MolVocab
    # supress rdkit logger
    lg = RDLogger.logger()
    lg.setLevel(RDLogger.CRITICAL)

    # Initialize MolVocab
    mol_vocab = MolVocab

    args = parse_args()
    if args.parser_name == 'finetune':
        logger = create_logger(name='train', save_dir=args.save_dir, quiet=False)
        cross_validate(args, logger)
    elif args.parser_name == 'pretrain':
        logger = create_logger(name='pretrain', save_dir=args.save_dir)
        pretrain_model(args, logger)
    elif args.parser_name == "eval":
        logger = create_logger(name='eval', save_dir=args.save_dir, quiet=False)
        cross_validate(args, logger)
    elif args.parser_name == 'fingerprint':
        train_args = get_newest_train_args()
        logger = create_logger(name='fingerprint', save_dir=None, quiet=False)
        feas = generate_fingerprints(args, logger)
        np.savez_compressed(args.output_path, fps=feas)
    elif args.parser_name == 'predict':
        train_args = get_newest_train_args()
        avg_preds, test_smiles = make_predictions(args, train_args)
        write_prediction(avg_preds, test_smiles, args)


# 모험가 길드
# 공포도를 기준으로 오름차순으로 정렬
# 이후에 공포도가 가장 낮은 모험가로부터 확인하며, 그룹에 포함될 모험가의 수를 계산
# 현재 그룹에 포함된 모험가의 수가 현재 확인하고 있는 공포도보다 크거나 같으면, 그룹을 결성
n = int(input())
data = list(map(int, input().split()))
data.sort()

result = 0 # 총 그룹의 수
count = 0 # 현재 그룹에 포함된 모험가의 수

for i in data:  # 공포도를 낮은 것부터 하나씩 확인하며
    count += 1  # 현재 그룹에 해당 모험가를 포함시키기
    if count >= i:  # 현재 그룹에 포함된 모험가의 수가 현재의 공포도 이상이라면, 그룹 결성
        result += 1 # 총 그룹의 수 증가시키기
        count = 0

print(result)


import logging
import random
import traceback
from datetime import datetime

import numpy as np
import torch

from configs.arguments import TrainingArguments
from dataset.processor import MyDataset
from models.STGDL import STGDL
from trainer import Trainer
from utils.file_utils import ensure_dir

def main(config: TrainingArguments):
    torch.autograd.set_detect_anomaly(True)
    time = datetime.strftime(datetime.now(), "%m%d_%H%M%S")
    setup(config, time)

    try:
        logging.info("Loading dataset...")
        dataset = MyDataset(config)
        # 这里 supports 是接下来要被分解的 G，一般只有一个图，也即邻接矩阵
        # 按理说不应该放在 dataset 这里，但要算 DTW 距离，就放这了
        supports = dataset.supports
        scaler = dataset.scaler

        logging.info("Loading model...")
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        model = STGDL(config, supports, scaler, device).to(device)
        print_parameter_count(model)
        trainer = Trainer(config, model, dataset, time)

        logging.info("Start Training.")
        # --load 0601_235959 加载已训练模型，可能是断点训练也可能是 debug/可视化
        if config.load != "":
            trainer.load(f"saved_dict/{config.load}.ckpt")

        if config.load == "":
            trainer.train(time)
            trainer.load(trainer.save_path)
        elif config.continue_training_epoch != -1:
            trainer.load(trainer.save_path)
            trainer.train(time, config.continue_training_epoch)

        if config.save_graph:
            trainer.visualize("subgraphs")

        trainer.test()
        print_parameter_count(model)
    except Exception as e:
        traceback.print_exc()

def setup(config, time):
    ensure_dir("saved_dict")
    ensure_dir(f"logs/{time}")

    # logging config
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s   %(levelname)s   %(message)s')
    logger = logging.getLogger()
    formats = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    file_handler = logging.FileHandler(f'logs/log{time}.txt')
    file_handler.setFormatter(formats)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(file_handler)

    for x in config:
        logging.info(x)

    setup_seed(config.seed)

def print_parameter_count(model):
    total = sum(p.numel() for p in model.parameters())
    total_req = sum(p.numel() for p in model.parameters() if p.requires_grad)
    logging.info(f"All para: {total}, trainable: {total_req}")

def setup_seed(seed):
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    np.random.seed(seed)
    random.seed(seed)
    torch.backends.cudnn.deterministic = True


from PIL import Image
import requests

from transformers import CLIPProcessor, CLIPModel, M2M100ForConditionalGeneration, M2M100Tokenizer
import pandas as pd
import numpy as np
import torch

import gc

def sample_k(id_array, exception_index, k=9):
    '''
    Given a list of array which represents indices, randomly sample k subsamples except for exception_index
    :param id_array:
    :param exception_index:
    :param k:
    :return:
    '''
    return np.random.choice(np.delete(id_array, exception_index), k, replace=False) # np.delete might not be the best

def get_captions(pandas_data, image_indices):
    '''
    Given an array of image_index, get the corresponding captions and randomly select one of the captions for each index
    :param pandas_data:
    :param image_indices:
    :param k:
    :return:
    '''

    k = len(image_indices)

    temp_pd_df = pandas_data[pandas_data['image_id'].isin(image_indices)]
    # print("temp_pd_df\n", temp_pd_df)
    return temp_pd_df.reset_index().loc[[i * 5 for i in range(k)] + np.random.choice(5, k)].drop(columns=['index'])

# convert the image_id into a file name
def fix_names(name, fixed_len=12):
    name_str = str(name)

    return '0' * (fixed_len - len(name_str)) + name_str + '.jpg'

# translate text into another langauges
def machine_translate(model, tokenizer, texts: int, src_lang, tgt_lang, device="cpu"):
    tokenizer.src_lang = src_lang
    translated_texts = []
    for text in texts:
        encoded_src = tokenizer(texts, return_tensors="pt").to(device)
        generated_tokens = model.generate(**encoded_src, forced_bos_token_id=tokenizer.get_lang_id(tgt_lang))
        out = tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)
        translated_texts.append(out[0])
        print("original text: ", text)
        print("translated text: ", out[0])
    return translated_texts

def return_topk_rank(model, processor, image, texts, k=5, multiple_images=True, device="cpu"):

    inputs = processor(text=texts, images=image, return_tensors="pt", padding=True).to(device)

    outputs = model(**inputs)

    logits_per_image = outputs.logits_per_image  # this is the image-text similarity score

    if multiple_images:
        probs = logits_per_image.softmax(dim=0)
        return_text = texts
        topk = probs.reshape(1, -1).topk(k)

    else:
        if len(texts) < k:
            k = len(texts)
        probs = logits_per_image.softmax(dim=1)
        return_text = texts[probs.argmax()]
        topk = probs.topk(k)

    return probs.detach().cpu().numpy().tolist(), return_text, topk

def open_images(folder_name, file_name):
    '''
    Returns a list of images, if list contains 1 image, returns just an Image Object, not a list
    :param folder_name:
    :param file_name: a list of file names
    :return:
    '''

    if len(file_name) == 1:
        file_name = fix_names(name)

        return Image.open(folder_name + file_name)

    else:
        image_list = []

        for file_name_ in file_name:
            # get the name in the right format
            file_name_ = fix_names(file_name_)

            image_list.append(Image.open(folder_name + file_name_))

        return image_list

if __name__ == '__main__':
    # Find GPU
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    # instantiate the model
    model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32").to(device)
    # preprocessor
    processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

    # MT Model and Processor
    MT_model = M2M100ForConditionalGeneration.from_pretrained("facebook/m2m100_418M").to(device)
    MT_tokenizer = M2M100Tokenizer.from_pretrained("facebook/m2m100_418M")
    # MT_tokenizer = M2M100Tokenizer.from_pretrained("xlm-mlm-100-1280")

    # set the folder name
    folder_name = 'ms-coco-es/images/'

    # read the dataset
    a = pd.read_excel('ms-coco-es/data/train_human_spanish.xlsx')
    # a = pd.read_excel('ms-coco-es/data/train_machine_english.xlsx')

    # get rid of rows that don't have 5 captions. only 1 has fewer than 5
    a = a.groupby('image_id').filter(lambda x: len(x) >= 5)

    # get the unique image_id in the dataset
    image_id = a['image_id'].unique()

    # get the name
    correct = 0
    correct_k = 0
    total = len(image_id) # run 1000 iterations
    # number of negative samples. In case multiple_images == True, memory requirement could increase as batch size increases
    k = 9
    print("No. of Samples: ", k+1)

    # in case one wants to do multiple inages and one text comparison
    multiple_images = True

    # whether translate or directly feed into CLIP
    translate = True
    src_lang = 'es' # Spanish
    tgt_lang = 'en' # English

    for i in range(total):

        name = image_id[i]

        # get the negative samples
        negative_samples = sample_k(image_id, 0, k=k)

        negative_samples = get_captions(a, negative_samples)
        positive_samples = get_captions(a, [name])

        # process the image names
        if multiple_images:
            # in case of multiple images, we append image_id from negative samples
            names = [name] + negative_samples['image_id'].tolist()
            # don't append the captions from negative samples
            text = positive_samples['caption'].tolist()

        else:
            # opposite logic as above
            names = [name]

            text = positive_samples['caption'].tolist() + negative_samples['caption'].tolist()

        # get the images opened
        image = open_images(folder_name, names)

        # translate the text
        if translate:
            text = machine_translate(MT_model, MT_tokenizer, text, src_lang=src_lang, tgt_lang =tgt_lang, device=device)

        # Inference from CLIP
        temp = return_topk_rank(model, processor, image, text, k=5, multiple_images=multiple_images, device=device)

        probs, text, topk = temp

        # NDCG
        rank = np.argwhere(topk.indices.squeeze().cpu().numpy() == 0).squeeze()+1 if 0 in temp[2].indices.squeeze() else None

        num_candidates = len(temp[2].indices.squeeze())
        # print(temp)
        print(f"[{i} / {total}]: image_name: {name}")
        print(f"Rank of Correct Image: {rank} / {num_candidates}\n")

        # top k match
        if 0 in topk.indices.squeeze():
            correct_k += 1

        # top 1 match. We know for sure that the first caption is the ground truth.
        if topk.indices.squeeze()[0] == 0:
            correct += 1

        # To avoid OOM error
        del image
        del text
        del temp
        del probs
        del topk
        gc.collect()
        torch.cuda.empty_cache()
    # 0.847 with spanish.
    # 0.974 with english.

    # post-transation:
    # Top1: 0.906
    # Topk: 1.0
    print("Top 1 Accuracy: ", correct / total)
    print(f"Top {num_candidates} Accuracy: ",correct_k / total)


# -*- coding: utf-8 -*-
import os
import json

import numpy as np
import tensorflow as tf

from preprocess.audio import AudioProcess
from preprocess.data_parse import DataGenerator
from models.language import LanguageHyperParams
from models.acoustics import AcousticsHyperParams
from models.acoustics.cnn_ctc import AcousticsModel
from models.language.transformer import LanguageModel

root = os.path.dirname(os.path.abspath(__file__))

os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
os.environ['KMP_DUPLICATE_LIB_OK'] = "TRUE"

class Predict:

    def __init__(self, file):
        self.file = file

        with open("vocab_json/vocab_counter.json", "r") as f:
            data = json.load(f)
            self.am_vocab_len = data.get("am_vocab")
            self.pny_vocab_len = data.get("pny_vocab")
            self.han_vocab_len = data.get("han_vocab")

        with open("vocab_json/am_vocab.json", "r") as f:
            self.am_vocab = json.load(f)

        with open("vocab_json/pny_vocab.json", "r") as f:
            self.pny_vocab = json.load(f)

        with open("vocab_json/han_vocab.json", "r") as f:
            self.han_vocab = json.load(f)

    def load_acoustics_model(self):
        am_args = AcousticsHyperParams.ap
        am_args.vocab_size = self.am_vocab_len
        am = AcousticsModel(am_args)
        am.ctc_model.load_weights(os.path.join(root, "outcome/acoustics/model.h5"))
        return am

    def load_language_model(self):
        lm_args = LanguageHyperParams.lp
        lm_args.input_vocab_size = self.pny_vocab_len
        lm_args.label_vocab_size = self.han_vocab_len
        lm = LanguageModel(lm_args)
        sess = tf.Session(graph=lm.graph)
        with lm.graph.as_default():
            saver = tf.train.Saver()
        with sess.as_default():
            latest = tf.train.latest_checkpoint(os.path.join(root, "outcome/language"))
            saver.restore(sess, latest)
        return lm, sess

    @staticmethod
    def wav2array(file):
        wav_data_lst = []
        frequency_bank = AudioProcess.frequency_domain(file)
        pad_bank = np.zeros((frequency_bank.shape[0] // 8 * 8 + 8, frequency_bank.shape[1]))
        pad_bank[:frequency_bank.shape[0], :] = frequency_bank
        wav_data_lst.append(pad_bank)
        pad_wav_data, input_length = DataGenerator.wav_padding(wav_data_lst)
        return pad_wav_data

    def run(self):
        pad_wav_data = self.wav2array(self.file)

        am = self.load_acoustics_model()
        lm, sess = self.load_language_model()

        am_predict = am.model.predict(pad_wav_data, steps=1)
        text = AudioProcess.decoder(am_predict, self.am_vocab)
        text = ' '.join(text)
        print("AM:-)", text)

        with sess.as_default():
            text = text.strip('\n').split(' ')
            x = np.array([self.pny_vocab.index(pny) for pny in text])
            x = x.reshape(1, -1)
            lm_predict = sess.run(lm.preds, {lm.x: x})
            got = ''.join(self.han_vocab[idx] for idx in lm_predict[0])
            print("LM:-)", got)
        sess.close()

        return got

if __name__ == "__main__":
    fs = "/Users/Maxwell_Lu/Documents/" \
         "/audio_data/data_thchs30/train/A11_1.wav"
    Predict(fs).run()


def gcd(a, b):
    while b:
        a, b = b, a % b
    return a

num_list = input("Enter a list of numeric values those are separated by spaces\n ").split()
num_list = [int(num) for num in num_list if num.isdigit()]

if len(num_list) < 2:
    print("Please enter at least 2 numeric values\n")

result = num_list[0]
for num in num_list[1:]:
    result = gcd(result, num)

print("Greatest Common Divisor\n", result)


from fastapi import FastAPI
from fastapi import HTTPException
from pydantic import BaseModel
from vncorenlp import VnCoreNLP
import os
import numpy as np
app = FastAPI()

annotator =  VnCoreNLP("./vncorenlp/VnCoreNLP-1.1.jar", annotators="wseg,pos,ner,parse", max_heap_size='-Xmx2g')

# đường đã đến file trả kết quả (gẫn đến thư mục của thuận toán CRF++-0.58)
file_out_khong_tag = "test.data"
# đường đẫn từ thư mục của thuật toán CRF++-0.58 lưu file output.data
ten_file_du_lieu1 = "output.data"
# thư mục chưa code thuật toán crf
dir = ".\\CRF++-0.58\\"

class Item(BaseModel):
    noi_dung: str

def themdauchamcau(list_):
        data = ""
        for a in list_:
            int_ = len(a)
            b = ""
            if (int_ >2):
                if (a[int_-1] != "\n"):
                    if (a[int_-1] not in [".",";","!","?"]):
                        b = a + ".\n"
                    else:
                        b = a
                else:
                    if (a[int_-2] not in [".",";","!","?"]):
                        b = a[:(int_ -1)] + ".\n"
                    else:
                        b = a
            data = data +"\n"+ b
        return data

def tao_file_du_lieu(data_input):
    doc = annotator.annotate(data_input)
    with open(dir + file_out_khong_tag, mode='w', encoding="utf-8" ) as file:
            for cau in doc["sentences"]:
                for tu in cau:
                    tab = "\t"
                    if (len(tu["form"]) <= 15):
                        tab += "\t"
                    if (len(tu["form"]) <= 7):
                        tab += "\t"
                    if(tu["form"] in [".",";","!","?","\n"]):
                        file.writelines("\n")
                    elif(["form"] not in [")",">","/",":", ",", "\"","`","(","<","”","“"]):
                        file.writelines((tu["form"]).lower() + tab + tu["posTag"] + "\n")

def getTrieuChungBenh(ten_file_du_lieu):
    f = open(ten_file_du_lieu, 'r', encoding='UTF-8')
    du_lieu_input = f.readlines()
    output = []
    temp = {'trieu_chung':'','thoi_gian':''}
    count = 0
    count_TG = 0
    for a in du_lieu_input:
        row = a.split()
        rows = np.array(row)
        if (len(rows)==3):
            if (rows[2] in ["B-TC","B-TCTL"]):
                count +=1
            if (rows[2] == "B-TG"):
                count_TG +=1
            if (count <= 1):
                if(rows[2] in ["B-TC","I-TC","B-TCTL","I-TCTL"]):
                    temp["trieu_chung"] += rows[0].replace("_"," ") + " "
                if(rows[2] in ["B-TG","I-TG"]):
                    if( count_TG  >1 and rows[2] == "B-TG"):
                        temp["thoi_gian"] += ", " + rows[0].replace("_"," ") + " "
                    else:
                        temp["thoi_gian"] +=rows[0].replace("_"," ") + " "
            else:
                count = 1
                count_TG = 0
                output.append(temp)
                temp = {'trieu_chung': rows[0].replace("_"," ") + " ",'thoi_gian':''}
    output.append(temp)
    return output

@app.post("/crf_get_trieu_chung/")
async def root(item: Item):

    du_lieu_input = item.noi_dung
    if (du_lieu_input == ""):

        raise HTTPException(status_code=400, detail="Dữ liệu truyền lên rỗng")
    du_lieu_input = du_lieu_input.split("\n")

    data_out = themdauchamcau(du_lieu_input)

    # tạo file dữ liệu test.data
    tao_file_du_lieu(data_out)

    os.chdir(dir)
    os.system("crf_test -m model1 test.data > output.data")

    data_benh = getTrieuChungBenh(dir + ten_file_du_lieu1 )
    if(len(data_benh) == 0):
        return {"message":"Không tìm thấy triệu chứng", "data": data_benh}
    return {"message":"Thành công", "data": data_benh}