import re
import logging
import json
import pathlib
import inspect
import numpy as np
from os import remove
from os.path import join, dirname, isfile
from typing import List, Tuple
from deprecated import deprecated

import openql as ql

from pycqed.utilities.general import suppress_stdout
from pycqed.utilities.general import is_more_recent
from pycqed.utilities.general import get_file_sha256_hash

log = logging.getLogger(__name__)

"""
FIXME:
concept should support:
- programs with 'runtime' parameters
- retrieval of return (measurement) data
- running a set of programs
- make-like 'update only if needed'
- multiple HW-platforms
- other compilers than OpenQL

"""

class OqlProgram:
    # we use a class global variable 'output_dir' to replace the former OpenQL option of the same name. Since that is a
    # global OpenQL option, it no longer has direct effect now we no longer use the OpenQL generated list of passes (see
    # self._configure_compiler). Additionally, OpenQL options are reset upon ql.initialize, so the value does not persist.
    output_dir = join(dirname(__file__), 'output')

    def __init__(
            self,
            name: str,
            platf_cfg: str,
            nregisters: int = 32
    ):
        """
        create OpenQL Program (and Platform)

        Args:
            name:
                name of the program

            platf_cfg:
                path of the platform configuration file used by OpenQL

            nregisters:
                the number of classical registers required in the program
        """

        # setup OpenQL
        ql.initialize()  # reset options, may initialize more functionality in the future

        # set OpenQL log level before anything else
        ql.set_option('log_level', 'LOG_WARNING')

        # store/initialize some parameters
        self.name = name
        self._platf_cfg = platf_cfg
        self.nregisters = nregisters  # NB: not available via platform
        self.filename = ""
        self.sweep_points = None

        # create Platform and Program
        self.platform = ql.Platform('OpenQL_Platform', platf_cfg)
        self.nqubits = self.platform.get_qubit_number()
        self.program = ql.Program(
            name,
            self.platform,
            self.nqubits,
            self.nregisters
        )  # NB: unused if we use compile_cqasm()

        # detect OpenQL backend ('eqasm_compiler') used by inspecting platf_cfg
        eqasm_compiler = ''
        with open(self._platf_cfg) as f:
            for line in f:
                if 'eqasm_compiler' in line:
                    m = re.search('"eqasm_compiler" *: *"(.*?)"', line)
                    eqasm_compiler = m.group(1)
                    break
        if eqasm_compiler == '':
            log.error(f"key 'eqasm_compiler' not found in file '{self._platf_cfg}'")

        # determine architecture and extension of generated file
        if eqasm_compiler == 'cc_light_compiler':
            # NB: OpenQL>=0.9.0 no longer has a backend for CC-light
            self._arch = 'CCL'
            self._ext = '.qisa'  # CC-light, QCC
        else:
            self._arch = 'CC'
            self._ext = '.vq1asm'  # CC

        # save name of file that OpenQL will generate on compilation to allow uploading
        # NB: for cQasm, the actual name is determined by 'pragma @ql.name' in the source, not by self.name,
        # so users must maintain consistency
        self.filename = join(OqlProgram.output_dir, self.name + self._ext)

        # map file for OpenQL>=0.10.3
        self._map_filename = join(OqlProgram.output_dir, self.name + ".map")

    def add_kernel(self, k: ql.Kernel) -> None:
        self.program.add_kernel(k)

    def create_kernel(
            self,
            kname: str
    ) -> ql.Kernel:
        """
        Wrapper around constructor of openQL "Kernel" class.
        """
        kname = kname.translate(
            {ord(c): "_" for c in "!@#$%^&*()[]{};:,./<>?\|`~-=_+ "})

        k = ql.Kernel(kname, self.platform, self.nqubits, self.nregisters)
        return k

    def compile(
            self,
            quiet: bool = False,
            extra_pass_options: List[Tuple[str, str]] = None
    ) -> None:
        """
        Compile an OpenQL Program created using the legacy Program/Kernel API.

        Args:
            quiet:
                suppress all output (not recommended, because warnings are hidden)

            extra_pass_options:
                extra pass options for OpenQL. These consist of a tuple 'path, value' where path is structured as
                "<passName>.<passOption>" and value is the option value, see
                https://openql.readthedocs.io/en/latest/reference/python.html#openql.Compiler.set_option

                See https://openql.readthedocs.io/en/latest/gen/reference_passes.html for passes and their options
        """

        if quiet:
            with suppress_stdout():
                self.program.compile()
        else:  # show warnings
            c = self._configure_compiler("", extra_pass_options)
            c.compile(self.program)

    def compile_cqasm(
            self,
            src: str,
            extra_pass_options: List[Tuple[str, str]] = None
    ) -> None:
        """
        Compile a string with cQasm source code.

        Note that, contrary to the behaviour of compile(), the program runs just once by default, since looping can be
        easily and more subtly performed in cQasm if desired.

        Args:
            src:
                the cQasm source code string

            extra_pass_options:
                extra pass options for OpenQL. These consist of a tuple 'path, value' where path is structured as
                "<passName>.<passOption>" and value is the option value, see
                https://openql.readthedocs.io/en/latest/reference/python.html#openql.Compiler.set_option

                See https://openql.readthedocs.io/en/latest/gen/reference_passes.html for passes and their options
        """

        # save src to file (as needed by pass 'io.cqasm.Read')
        src_filename = OqlProgram.output_dir+"/"+self.name+".cq"
        pathlib.Path(src_filename).write_text(inspect.cleandoc(src))

        c = self._configure_compiler(src_filename, extra_pass_options)
        c.compile_with_frontend(self.platform)

    def get_map(self) -> dict:
        """
        get map data produced by OpenQL>=0.10.3
        """

        return json.load(self._map_filename)

    def get_measurement_map(self) -> dict:
        """
        get measurements from map data produced by OpenQL>=0.10.3
        """

        data = self.get_map()
        return data["measurements"]

    # NB: used in clifford_rb_oql.py to skip both generation of RB sequences, and OpenQL compilation if
    # contents of platf_cfg or clifford_rb_oql (i.e. the Python file that generates the RB sequence) have changed
    def check_recompilation_needed_hash_based(
            self,
            clifford_rb_oql: str,
            recompile: bool = True,
    ) -> dict:
        """
        Similar functionality to the deprecated `check_recompilation_needed` but
        based on a file that is generated alongside with the program file
        containing hashes of the files that are relevant to the generation of the
        RB sequences and that might be modified somewhat often

        NB: Not intended for stand alone use!
        The code invoking this function should later invoke:
            `os.rename(recompile_dict["tmp_file"], recompile_dict["file"])` # FIXME: create member function for that

        The behavior of this function depends on the recompile argument.
        recompile:
            True -> True, the program should be compiled

            'as needed' -> compares filename to timestamp of config
                and checks if the file exists, if required recompile.
            False -> checks if the file exists, if it doesn't
                compilation is required and raises a ValueError.
                Use carefully, only if you know what you are doing!
                Use 'as needed' to stay safe!
        """

        hashes_ext = ".hashes"
        tmp_ext = ".tmp"
        rb_system_hashes_fn = self.filename + hashes_ext
        tmp_fn = rb_system_hashes_fn + tmp_ext

        platf_cfg_hash = get_file_sha256_hash(self._platf_cfg, return_hexdigest=True)
        this_file_hash = get_file_sha256_hash(clifford_rb_oql, return_hexdigest=True)
        file_hashes = {self._platf_cfg: platf_cfg_hash, clifford_rb_oql: this_file_hash}

        _recompile = False
        if not isfile(self.filename):
            if recompile is False:
                raise ValueError('No file:\n{}'.format(self.filename))
            else:
                # Force recompile, there is no program file
                _recompile |= True  # FIXME: why "|="?

        # Determine if compilation is needed based on the hashed files
        if not isfile(rb_system_hashes_fn):
            # There is no file with the hashes, we must compile to be safe
            _recompile |= True
        else:
            # Hashes exist, we use them to determine if recompilations is needed
            with open(rb_system_hashes_fn) as json_file:
                hashes_dict = json.load(json_file)
            # Remove file to signal a compilation in progress
            remove(rb_system_hashes_fn)

            for fn in file_hashes.keys():
                # Recompile becomes true if any of the hashed files has a different
                # hash now
                _recompile |= hashes_dict.get(fn, "") != file_hashes[fn]

        # Write the updated hashes
        # We use a temporary file such that for parallel compilations, if the
        # process is interrupted before the end there will be no hash and
        # recompilation will be forced
        pathlib.Path(tmp_fn).parent.mkdir(parents=True, exist_ok=True)
        pathlib.Path(tmp_fn).write_text(json.dumps(file_hashes))

        res_dict = {
            "file": rb_system_hashes_fn,
            "tmp_file": tmp_fn
        }

        if recompile is False:
            if _recompile is True:
                log.warning(
                    "`{}` or\n`{}`\n might have been modified! Are you sure you didn't"
                    " want to compile?".format(self._platf_cfg, clifford_rb_oql)
                )
            res_dict["recompile"] = False
        elif recompile is True:
            # Enforce recompilation
            res_dict["recompile"] = True
        elif recompile == "as needed":
            res_dict["recompile"] = _recompile

        return res_dict

    #############################################################################
    # Calibration points
    #############################################################################

    """
    FIXME: while refactoring these from separate functions to class methods, it
     was found that most functions returned the program (that was provided as a
     parameter, which makes no sense), and that the return parameter was mostly
     ignored (which makes no difference). The function documentation was
     inconsistent with the actual code in this respect, probably as a result of
     earlier refactoring.
     Function 'add_multi_q_cal_points' would return different types dependent
     on a boolean parameter 'return_comb', but no cases were found where this
     parameter was set to True, so this behaviour was removed
    """

    def add_single_qubit_cal_points(
            self,
            qubit_idx: int,
            f_state_cal_pts: bool = False,
            measured_qubits=None
    ) -> None:
        """
        Adds single qubit calibration points to an OpenQL program

        Args:
            qubit_idx:
                index of qubit

            f_state_cal_pts:
                if True, add calibration points for the 2nd exc. state

            measured_qubits:
                selects which qubits to perform readout on. If measured_qubits == None, it will default
                to measuring the qubit for which there are cal points.

        Returns:

        """

        if measured_qubits == None:
            measured_qubits = [qubit_idx]

        for i in np.arange(2):
            k = self.create_kernel("cal_gr_" + str(i))
            k.prepz(qubit_idx)
            k.gate('wait', measured_qubits, 0)
            for measured_qubit in measured_qubits:
                k.measure(measured_qubit)
            k.gate('wait', measured_qubits, 0)
            self.add_kernel(k)

        for i in np.arange(2):
            k = self.create_kernel("cal_ex_" + str(i))
            k.prepz(qubit_idx)
            k.gate('rx180', [qubit_idx])
            k.gate('wait', measured_qubits, 0)
            for measured_qubit in measured_qubits:
                k.measure(measured_qubit)
            k.gate('wait', measured_qubits, 0)
            self.add_kernel(k)
        if f_state_cal_pts:
            for i in np.arange(2):
                k = self.create_kernel("cal_f_" + str(i))
                k.prepz(qubit_idx)
                k.gate('rx180', [qubit_idx])
                k.gate('rx12', [qubit_idx])
                k.gate('wait', measured_qubits, 0)
                for measured_qubit in measured_qubits:
                    k.measure(measured_qubit)
                k.gate('wait', measured_qubits, 0)
                self.add_kernel(k)

    def add_two_q_cal_points(
            self,
            q0: int,
            q1: int,
            reps_per_cal_pt: int = 1,
            f_state_cal_pts: bool = False,
            #        f_state_cal_pt_cw: int = 31,
            measured_qubits=None,
            interleaved_measured_qubits=None,
            interleaved_delay=None,
            nr_of_interleaves=1
    ) -> None:
        """
        Adds two qubit calibration points to an OpenQL program

        Args:
            q0:
                index of first qubit

            q1:
                index of second qubit

            reps_per_cal_pt:
                number of times to repeat each cal point

            f_state_cal_pts:
                if True, add calibration points for the 2nd exc. state

            measured_qubits:
                selects which qubits to perform readout on. If measured_qubits == None, it will default
                to measuring the qubit for which there are cal points

            interleaved_measured_qubits:
            interleaved_delay:
            nr_of_interleaves:

        """

        kernel_list = [] # FIXME: not really used (anymore?)
        combinations = (["00"] * reps_per_cal_pt +
                        ["01"] * reps_per_cal_pt +
                        ["10"] * reps_per_cal_pt +
                        ["11"] * reps_per_cal_pt)
        if f_state_cal_pts:
            extra_combs = (['02'] * reps_per_cal_pt + ['20'] * reps_per_cal_pt +
                           ['22'] * reps_per_cal_pt)
            combinations += extra_combs

        if measured_qubits == None:
            measured_qubits = [q0, q1]

        for i, comb in enumerate(combinations):
            k = self.create_kernel('cal{}_{}'.format(i, comb))
            k.prepz(q0)
            k.prepz(q1)
            if interleaved_measured_qubits:
                for j in range(nr_of_interleaves):
                    for q in interleaved_measured_qubits:
                        k.measure(q)
                    k.gate("wait", [0, 1, 2, 3, 4, 5, 6], 0)
                    if interleaved_delay:
                        k.gate('wait', [0, 1, 2, 3, 4, 5, 6],
                               int(interleaved_delay * 1e9))

            if comb[0] == '0':
                k.gate('i', [q0])
            elif comb[0] == '1':
                k.gate('rx180', [q0])
            elif comb[0] == '2':
                k.gate('rx180', [q0])
                # FIXME: this is a workaround
                # k.gate('rx12', [q0])
                k.gate('cw_31', [q0])

            if comb[1] == '0':
                k.gate('i', [q1])
            elif comb[1] == '1':
                k.gate('rx180', [q1])
            elif comb[1] == '2':
                k.gate('rx180', [q1])
                # FIXME: this is a workaround
                # k.gate('rx12', [q1])
                k.gate('cw_31', [q1])

            # Used to ensure timing is aligned
            k.gate('wait', measured_qubits, 0)
            for q in measured_qubits:
                k.measure(q)
            k.gate('wait', measured_qubits, 0)
            kernel_list.append(k)
            self.add_kernel(k)

    def add_multi_q_cal_points(
            self,
            qubits: List[int],
            combinations: List[str] = ["00", "01", "10", "11"],
            reps_per_cal_pnt: int = 1,
            f_state_cal_pt_cw: int = 9,  # 9 is the one listed as rX12 in `mw_lutman`
            nr_flux_dance: int = None,
            flux_cw_list: List[str] = None
    ) -> None:
        """

        Args:
            qubits:
                list of qubit indices

            combinations:
                list with the target multi-qubit state
                e.g. ["00", "01", "10", "11"] or
                ["00", "01", "10", "11", "02", "20", "22"] or
                ["000", "010", "101", "111"]

            reps_per_cal_pnt:
                number of times to repeat each cal point

            f_state_cal_pt_cw:
                the cw_idx for the pulse to the ef transition.

            nr_flux_dance:
            flux_cw_list:
        """

        comb_repeated = []
        for state in combinations:
            comb_repeated += [state] * reps_per_cal_pnt

        state_to_gates = {
            "0": ["i"],
            "1": ["rx180"],
            "2": ["rx180", "cw_{:02}".format(f_state_cal_pt_cw)],
        }

        for i, comb in enumerate(comb_repeated):
            k = self.create_kernel('cal{}_{}'.format(i, comb))

            # NOTE: for debugging purposes of the effect of fluxing on readout,
            #       prepend flux dance before calibration points
            for q_state, q in zip(comb, qubits):
                k.prepz(q)
            k.gate("wait", [], 0)  # alignment

            if nr_flux_dance and flux_cw_list:
                for i in range(int(nr_flux_dance)):
                    for flux_cw in flux_cw_list:
                        k.gate(flux_cw, [0])
                    k.gate("wait", [], 0)
                # k.gate("wait", [], 20) # prevent overlap of flux with mw gates

            for q_state, q in zip(comb, qubits):
                for gate in state_to_gates[q_state]:
                    k.gate(gate, [q])
            k.gate("wait", [], 0)  # alignment
            # k.gate("wait", [], 20)  # alignment

            # for q_state, q in zip(comb, qubits):
            #     k.prepz(q)
            #     for gate in state_to_gates[q_state]:
            #         k.gate(gate, [q])
            # k.gate("wait", [], 0)  # alignment

            for q in qubits:
                k.measure(q)
            k.gate('wait', [], 0)  # alignment
            self.add_kernel(k)

    def add_two_q_cal_points_special_cond_osc(
            self,
            q0: int,
            q1: int,
            q2=None,
            reps_per_cal_pt: int = 1,
            f_state_cal_pts: bool = False,
            #        f_state_cal_pt_cw: int = 31,
            measured_qubits=None,
            interleaved_measured_qubits=None,
            interleaved_delay=None,
            nr_of_interleaves=1
    ) -> None:
        """

        Args:
            q0:
            q1:
            q2:
            reps_per_cal_pt:
                number of times to repeat each cal point

            f_state_cal_pts:
                 if True, add calibration points for the 2nd exc. state

            measured_qubits:
                selects which qubits to perform readout on. If measured_qubits == None, it will default
                to measuring the qubit for which there are cal points.

            interleaved_measured_qubits:
            interleaved_delay:
            nr_of_interleaves:

        Returns:

        """

        combinations = (["00"] * reps_per_cal_pt +
                        ["01"] * reps_per_cal_pt +
                        ["10"] * reps_per_cal_pt +
                        ["11"] * reps_per_cal_pt)
        if f_state_cal_pts:
            extra_combs = (['02'] * reps_per_cal_pt + ['20'] * reps_per_cal_pt +
                           ['22'] * reps_per_cal_pt)
            combinations += extra_combs
        if q2 is not None:
            combinations += ["Park_0", "Park_1"]

        if (measured_qubits == None) and (q2 is None):
            measured_qubits = [q0, q1]
        elif (measured_qubits == None):
            measured_qubits = [q0, q1, q2]

        for i, comb in enumerate(combinations):
            k = self.create_kernel('cal{}_{}'.format(i, comb))
            k.prepz(q0)
            k.prepz(q1)
            if q2 is not None:
                k.prepz(q2)
            if interleaved_measured_qubits:
                for j in range(nr_of_interleaves):
                    for q in interleaved_measured_qubits:
                        k.measure(q)
                    k.gate("wait", [0, 1, 2, 3, 4, 5, 6], 0)
                    if interleaved_delay:
                        k.gate('wait', [0, 1, 2, 3, 4, 5, 6], int(interleaved_delay * 1e9))

            if comb[0] == '0':
                k.gate('i', [q0])
            elif comb[0] == '1':
                k.gate('rx180', [q0])
            elif comb[0] == '2':
                k.gate('rx180', [q0])
                # FIXME: this is a workaround
                # k.gate('rx12', [q0])
                k.gate('cw_31', [q0])

            if comb[1] == '0':
                k.gate('i', [q1])
            elif comb[1] == '1':
                k.gate('rx180', [q1])
            elif comb[1] == '2':
                k.gate('rx180', [q1])
                # FIXME: this is a workaround
                # k.gate('rx12', [q1])
                k.gate('cw_31', [q1])
            if comb[0] == 'P' and comb[-1] == '0':
                k.gate('i', [q2])
            elif comb[0] == 'P' and comb[-1] == '1':
                k.gate('rx180', [q2])

            # Used to ensure timing is aligned
            k.gate('wait', measured_qubits, 0)
            for q in measured_qubits:
                k.measure(q)
            k.gate('wait', measured_qubits, 0)
            self.add_kernel(k)

    #############################################################################
    # Private functions
    #############################################################################

    def _configure_compiler(
            self,
            cqasm_src_filename: str,
            extra_pass_options: List[Tuple[str, str]] = None
    ) -> ql.Compiler:
        # NB: for alternative ways to configure the compiler, see
        # https://openql.readthedocs.io/en/latest/gen/reference_configuration.html#compiler-configuration

        c = self.platform.get_compiler()

        # remove default pass list (this also removes support for most *global* options as defined in
        # https://openql.readthedocs.io/en/latest/gen/reference_options.html, except for 'log_level')
        # NB: this defeats automatic backend selection by OpenQL based on key "eqasm_compiler"
        c.clear_passes()

        # add the passes we need
        compiling_cqasm = cqasm_src_filename != ""
        if compiling_cqasm:
            # cQASM reader as very first step
            c.append_pass(
                'io.cqasm.Read',
                'reader',
                {
                    'cqasm_file': cqasm_src_filename
                }
            )

            # decomposer for legacy decompositions (those defined in the "gate_decomposition" section)
            # FIXME: comment incorrect, also decomposes new-style definitions
            # see https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
            c.append_pass(
                'dec.Instructions',
                # NB: don't change the name 'legacy', see:
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#predicate-key
                'legacy',
            )
        else:  # FIXME: experimental. Also decompose API input to allow use of new style decompositions
            c.append_pass(
                'dec.Instructions',
                # NB: don't change the name 'legacy', see:
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#instruction-decomposer
                # - https://openql.readthedocs.io/en/latest/gen/reference_passes.html#predicate-key
                'legacy',
            )

        # report the initial qasm
        c.append_pass(
            'io.cqasm.Report',
            'initial',
            {
                'output_suffix': '.cq',
                'with_timing': 'no'
            }
        )

        # schedule
        c.append_pass(
            'sch.ListSchedule',
            'scheduler',
            {
                'resource_constraints': 'yes'
            }
        )

        # report scheduled qasm
        c.append_pass(
            'io.cqasm.Report',
            'scheduled',
            {
                'output_suffix': '.cq',
            }
        )

        if self._arch == 'CC':
            # generate code using CC backend
            # NB: OpenQL >= 0.10 no longer has a CC-light backend
            c.append_pass(
                'arch.cc.gen.VQ1Asm',
                'cc_backend'
            )

        # set compiler pass options
        c.set_option('*.output_prefix', f'{OqlProgram.output_dir}/%N.%P')
        if self._arch == 'CC':
            c.set_option('cc_backend.output_prefix', f'{OqlProgram.output_dir}/%N')
        c.set_option('scheduler.scheduler_target', 'alap')
        if compiling_cqasm:
            c.set_option('cc_backend.run_once', 'yes')  # if you want to loop, write a cqasm loop

        # finally, set user pass options
        if extra_pass_options is not None:
            for opt, val in extra_pass_options:
                c.set_option(opt, val)

        log.debug("\n" + c.dump_strategy())
        return c

##########################################################################
# compatibility functions
# FIXME: these are deprecated, but note that many scripts use these.
#  In many functions we return the program object for legacy
#  compatibility, although we specify a return type of " -> None" for
#  those that use PyCharm or an other tool aware of type inconsistencies
#  (which is highly recommended)
##########################################################################

@deprecated(version='0.4', reason="use class OqlProgram")
def create_program(
        name: str,
        platf_cfg: str,
        nregisters: int = 32
) -> OqlProgram:
    return OqlProgram(name, platf_cfg, nregisters)

@deprecated(version='0.4', reason="use class OqlProgram")
def create_kernel(
        kname: str,
        program: OqlProgram
) -> ql.Kernel:
    return program.create_kernel(kname)

@deprecated(version='0.4', reason="use class OqlProgram")
def compile(
        p: OqlProgram,
        quiet: bool = False,
        extra_openql_options: List[Tuple[str,str]] = None
) -> None:
    p.compile(quiet, extra_openql_options)
    return p # legacy compatibility

@deprecated(version='0.4', reason="use class OqlProgram")
def add_single_qubit_cal_points(
        p: OqlProgram,
        qubit_idx: int,
        f_state_cal_pts: bool = False,
        measured_qubits=None
) -> None:
    p.add_single_qubit_cal_points(qubit_idx, f_state_cal_pts, measured_qubits)
    return p # legacy compatibility

@deprecated(version='0.4', reason="use class OqlProgram")
def add_two_q_cal_points(
        p: OqlProgram,
        q0: int,
        q1: int,
        reps_per_cal_pt: int = 1,
        f_state_cal_pts: bool = False,
#        f_state_cal_pt_cw: int = 31, # FIXME: iold, unused parameter
        measured_qubits=None,
        interleaved_measured_qubits=None,
        interleaved_delay=None,
        nr_of_interleaves=1
) -> None:
    p.add_two_q_cal_points(q0, q1, reps_per_cal_pt, f_state_cal_pts, measured_qubits, interleaved_measured_qubits, interleaved_delay, nr_of_interleaves)
    return p # legacy compatibility

@deprecated(version='0.4', reason="use class OqlProgram")
def add_multi_q_cal_points(
    p: OqlProgram,
    qubits: List[int],
    combinations: List[str] = ["00", "01", "10", "11"],
    reps_per_cal_pnt: int = 1,
    f_state_cal_pt_cw: int = 9,  # 9 is the one listed as rX12 in `mw_lutman`
    nr_flux_dance: int = None,
    flux_cw_list: List[str] = None,
    return_comb=False
):
    """
    Add a list of kernels containing calibration points in the program `p`

    Args:
        p               : OpenQL  program to add calibration points to
        qubits          : list of int
        combinations    : list with the target multi-qubit state
            e.g. ["00", "01", "10", "11"] or
            ["00", "01", "10", "11", "02", "20", "22"] or
            ["000", "010", "101", "111"]
        reps_per_cal_pnt : number of times to repeat each cal point
        f_state_cal_pt_cw: the cw_idx for the pulse to the ef transition.
    Returns:
        p
    """
    kernel_list = []  # Not sure if this is needed
    comb_repetead = []
    for state in combinations:
        comb_repetead += [state] * reps_per_cal_pnt

    state_to_gates = {
        "0": ["i"],
        "1": ["rx180"],
        "2": ["rx180", "cw_{:02}".format(f_state_cal_pt_cw)],
    }

    for i, comb in enumerate(comb_repetead):
        k = create_kernel('cal{}_{}'.format(i, comb), p)

        # NOTE: for debugging purposes of the effect of fluxing on readout,
        #       prepend flux dance before calibration points
        for q_state, q in zip(comb, qubits):
            k.prepz(q)
        k.gate("wait", [], 0)  # alignment

        if nr_flux_dance and flux_cw_list:
            for i in range(int(nr_flux_dance)):
                for flux_cw in flux_cw_list:
                    k.gate(flux_cw, [0])
                k.gate("wait", [], 0)
            # k.gate("wait", [], 20) # prevent overlap of flux with mw gates

        for q_state, q in zip(comb, qubits):
            for gate in state_to_gates[q_state]:
                k.gate(gate, [q])
        k.gate("wait", [], 0)  # alignment
        # k.gate("wait", [], 20) # prevent overlap of flux with measurement pulse

        for q in qubits:
            k.measure(q)
        k.gate('wait', [], 0)  # alignment
        kernel_list.append(k)
        p.add_kernel(k)

    if return_comb:
        return comb_repetead
    else:
        return p

@deprecated(version='0.4', reason="use class OqlProgram")
def add_two_q_cal_points_special_cond_osc(
        p, q0: int, q1: int,
        q2=None,
        reps_per_cal_pt: int = 1,
        f_state_cal_pts: bool = False,
        # f_state_cal_pt_cw: int = 31,
        measured_qubits=None,
        interleaved_measured_qubits=None,
        interleaved_delay=None,
        nr_of_interleaves=1
) -> None:
    p.add_two_q_cal_points_special_cond_osc(
        q0, q1, q2,
        reps_per_cal_pt,
        f_state_cal_pts,
        measured_qubits,
        interleaved_measured_qubits,
        interleaved_delay,
        nr_of_interleaves
    )
    return p # legacy compatibility

# FIXME: move?
#############################################################################
# RamZZ measurement
#############################################################################
def measure_ramzz(k, qubit_idx: int, wait_time_ns: int):
    """
    Helper function that adds a ramsey readout sequence to the specified qubit
    on the specified kernel. Assumes that the qubit was already initialised.

    Input pars:
        k:              Kernel to add ramsey readout sequence to
        qubit_idx:      Qubit to undergo ramsey sequence
        wait_time_ns:   Wait time in-between pi/2 pulses
    Output pars:
        None
    """

    k.gate('ry90', [qubit_idx])
    k.gate('wait', wait_time_ns, [qubit_idx])
    k.gate('rym90', [qubit_idx])
    k.measure(qubit_idx)

#############################################################################
# File modifications
#############################################################################

def is_compatible_openql_version_cc() -> bool:
    """
    test whether OpenQL version is compatible with Central Controller
    """
    return ql.get_version() > '0.10.0'  # NB: 0.10.0 does not contain new CC backend yet

def clocks_to_s(time, clock_cycle=20e-9):
    """
    Converts a time in clocks to a time in s
    """
    return time * clock_cycle

#############################################################################
# Recompilation helpers
#############################################################################

def check_recompilation_needed_hash_based(
        program_fn: str,
        platf_cfg: str,
        clifford_rb_oql: str,
        recompile: bool = True,
):
    raise DeprecationWarning("use OqlProgram.check_recompilation_needed_hash_based")

@deprecated(reason="Use `check_recompilation_needed_hash_based`!")
def check_recompilation_needed(
        program_fn: str,
        platf_cfg: str,
        recompile=True
) -> bool:
    """
    determines if compilation of a file is needed based on it's timestamp
    and an optional recompile option

    The behavior of this function depends on the recompile argument.

    recompile:
        True -> True, the program should be compiled

        'as needed' -> compares filename to timestamp of config
            and checks if the file exists, if required recompile.
        False -> checks if the file exists, if it doesn't
            compilation is required and raises a ValueError.
            Use carefully, only if you know what you are doing!
            Use 'as needed' to stay safe!
    """
    if recompile is True:
        return True  # compilation is enforced
    elif recompile == 'as needed':
        # In case you ever think of a hash-based check mind that this
        # function is called in parallel multiprocessing sometime!!!
        if isfile(program_fn) and is_more_recent(program_fn, platf_cfg):
            return False  # program file is good for using
        else:
            return True  # compilation is required
    elif recompile is False:
        if isfile(program_fn):
            if is_more_recent(platf_cfg, program_fn):
                log.warning("File {}\n is more recent"
                    "than program, use `recompile='as needed'` if you"
                    " don't know what this means!".format(platf_cfg))
            return False
        else:
            raise ValueError('No file:\n{}'.format(platf_cfg))
    else:
        raise NotImplementedError(
            'recompile should be True, False or "as needed"')

#############################################################################
# Multiple program loading helpers
#############################################################################

def load_range_of_oql_programs(
        programs,
        counter_param,
        CC
) -> None:
    """
    This is a helper function for running an experiment that is spread over
    multiple OpenQL programs such as RB.
    """
    program = programs[counter_param()]
    counter_param((counter_param() + 1) % len(programs))
    CC.eqasm_program(program.filename)

def load_range_of_oql_programs_from_filenames(
        programs_filenames: list,
        counter_param,
        CC
) -> None:
    """
    This is a helper function for running an experiment that is spread over
    multiple OpenQL programs such as RB.

    [2020-07-04] this is a modification of the above function such that only
    the filename is passed and not a OpenQL program, allowing for parallel
    program compilations using the multiprocessing of python (only certain
    types of data can be returned from the processing running the
    compilations in parallel)
    """
    fn = programs_filenames[counter_param()]
    counter_param((counter_param() + 1) % len(programs_filenames))
    CC.eqasm_program(fn)

def load_range_of_oql_programs_varying_nr_shots(
        programs,
        counter_param,
        CC,
        detector
) -> None:
    """
    This is a helper function for running an experiment that is spread over
    multiple OpenQL programs of varying length such as GST.

    Everytime the detector is called it will also modify the number of sweep
    points in the detector.
    """
    program = programs[counter_param()]
    counter_param((counter_param() + 1) % len(programs))
    CC.eqasm_program(program.filename)

    detector.nr_shots = len(program.sweep_points)


# def dasher(theWord):
#     theFinalWord = ""
#     for letter in theWord:
#         theFinalWord += "-" + letter
#     return theFinalWord+"-"
#
# # print(dasher("hello"))
# # print(dasher(dasher("hello")))
#
#
# def dasher2(theWord):
#     if len(theWord) > 20:
#         return "Fail Whale"
#     return (int((20 - len(theWord))/2) * "-") + theWord + (int((20 - len(theWord))/2) * "-")
#
# print(dasher2("hello"))
# print(dasher2("welcome"))
# print(dasher2("welcomewelcomewelcome"))

# for country in client_counties:
#
# for i in range(10):
#
# for scores in test_scores:
#
# for i in range(len(names)):

# arguments - list (list of numbers)
# return - int (number of zeros)
# arguments - list (list of names)
# return - string (most commonly used name)
# arguments - list (of user entered ints)
# return - tuple (smallest, largest numbers)

def is_lower(ourString):
    for letter in ourString:
        if not letter == letter.lower():
            return False
    return True

def print_lower(listOStrings):
    listOfCrap = []
    for word in listOStrings:
        if is_lower(word):
            listOfCrap.append(word)
    return listOfCrap

print(print_lower(["Lower", "shit", "HAHAHAHAHA", "chicken"]))
print(is_lower("ourhouse"))


import click
import multiprocessing
import subprocess

def simulate(line):
    subprocess.call([line.strip()], shell=True)

def simulate_dry(line):
    subprocess.call(['echo', line.strip()])

@click.command()
@click.argument('filename', type=click.File(mode='r'))
@click.option('--processes', type=int, default=None)
@click.option('--dry/--no-dry', default=False)
def main(filename, processes, dry):
    pool = multiprocessing.Pool(processes=processes)

    if dry:
        target = simulate_dry
    else:
        target = simulate
    pool.map(target, filename)

if __name__ == '__main__':
    main()


import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy.integrate as integ
import scipy.optimize as op
from scipy import stats
from scipy.integrate import odeint

url = 'tunisian_data.csv'
data = pd.read_csv(url)
XX = np.arange(0, len(data), 1)
YY = data.iloc[0:, 2]
ZZ = data.iloc[0:, 3]
Dates = data.iloc[0:, 0]

def model(t, x1, x2, x3):
    return x1 * np.exp(x2 * t) - x3

def estimateParams():
    best_vals, covar = op.curve_fit(model, X, Y)
    x1 = best_vals[0]
    x2 = best_vals[1]
    x3 = best_vals[2]

    return [x1, x2, x3]

def LinReg():
    x3 = estimateParams()[2]
    LogY = np.log(Y + x3)
    slope, intercept, r_value, p_value, std_err = stats.linregress(X, LogY)
    x1 = np.exp(intercept)
    x2 = slope
    t0 = (np.log(x3) - np.log(x1)) / x2

    return [x1, x2, x3, t0]

def CR_fit(t):
    x1 = LinReg()[0]
    x2 = LinReg()[1]
    x3 = LinReg()[2]
    return x1 * np.exp(x2 * t) - x3

def Simu():
    S0 = 11e6  # Population totale
    f = 0.8  # Fraction des cas symptomatiques détectée
    nu = 1 / 7  # 1/nu est le temps moyen durant lequel un infecté reste presymptomatique
    Eta = 1 / 7  # 1/Eta est le temps moyen durant lequel un infecté reste symptomatique (avant de guérir ou décéder)
    nu1 = f * nu
    nu2 = (1 - f) * nu
    Mu = 3.5 / 100
    x1 = LinReg()[0]
    x2 = LinReg()[1]
    x3 = LinReg()[2]
    t0 = LinReg()[3]
    I0 = x3 * x2 / nu1
    tau = (x2 + nu) / S0 * (Eta + x2) / (nu2 + Eta + x2)
    U0 = nu2 / (Eta + x2) * I0
    R0 = tau * S0 / nu * (1 + nu2 / Eta)

    return [nu1, nu2, tau, I0, U0, R0, Eta, Mu]

def I(t):
    I0 = Simu()[3]
    x2 = LinReg()[1]
    t0 = LinReg()[3]
    return I0 * np.exp(x2 * (t - t0))

def U(t):
    U0 = Simu()[4]
    x2 = LinReg()[1]
    t0 = LinReg()[3]
    return U0 * np.exp(x2 * (t - t0))

def deriv(y, t, taut, nu1, nu2, Eta):
    S, I, R, U, RR, RD = y

    tautt = taut(t)
    dS = -tautt * S * (I + U)
    dI = tautt * S * (I + U) - (nu1 + nu2) * I
    dR = nu1 * I - Eta * R
    dU = nu2 * I - Eta * U
    dRR = (Eta * R + Eta * U) * (1 - Simu()[7])
    dRD = (Eta * R + Eta * U) * Simu()[7]

    return dS, dI, dR, dU, dRR, dRD

def SolveSIRU():
    # Conditions initiales
    y0 = 11e6, Simu()[3], 0, Simu()[4], YY[J], ZZ[J]

    # Interval d'intégration de l'ODE
    t = np.asarray(XX)

    # Paramètres du modèle
    nu1 = Simu()[0]
    nu2 = Simu()[1]
    Eta = Simu()[6]

    # Résolution des équations differentielles
    sol = odeint(deriv, y0, t, args=(taut, nu1, nu2, Eta))
    S, I, R, U, RR, RD = sol.T

    CRR = nu1 * integ.cumtrapz(I, initial=t[0]) + YY[J]
    # plt.plot(t, S, label="S")
    plt.plot(t, I, label="I: Infected")
    plt.plot(t, CRR, label="CR: Total Detected")
    plt.plot(t, R, label="R: Detected in quarantine")
    plt.plot(t, U, label="U: Non Detected")
    plt.plot(t, RR, label="RR: Recovered")
    plt.plot(t, RD, label="RD: Dead")
    plt.xlabel("temps en jours")
    plt.ylabel("nombre de cas")
    plt.legend()

    # f = open("CRR.txt", "w+") #a+
    # f = open('CRR.txt', 'r')

    A = np.array(CRR)
    A = A.astype(int)
    with open('CRR.txt', 'w+') as file:
        file.seek(0)
        file.write('\n'.join(str(a) for a in A))
        file.close

    plt.show()

def main():
    p = int(input("Quelle est la vague a analyser ?   "))
    global X, XX, Y, YY, J, taut
    X = np.asarray(XX)
    plt.scatter(X, YY)
    plt.scatter(X, ZZ)

    if p == 1:
        J = 0
        X = XX[0:23]
        Y = YY[0:23]
        print(estimateParams(), Simu()[5])
        X = np.asarray(X)
        fitLine1 = CR_fit(np.asarray(XX[0:45]))
        axes = plt.axes()
        plt.plot(np.asarray(XX[0:45]), fitLine1, c='r')
        axes.grid()
        taut = lambda t: Simu()[2] if t < 23 else 0.315 * Simu()[2]

    elif p == 2:
        J = int(input("A quelle jour demarre la tendance de la deuxieme vague ?   "))
        X = XX[J:len(data)]
        Y = YY[J:len(data)]
        print(LinReg(), Simu()[5])
        X = np.asarray(X)
        XX = np.arange(J, len(data) + 520, 1)
        fitLine2 = CR_fit(XX[0:150])
        plt.plot(XX[0:150], fitLine2, c='r', label="Exponential Fit")
        X = X - J
        Y = Y - YY[J]
        taut = lambda t: Simu()[2] if t < 5000 + 15 else 0.315 * Simu()[2]

    SolveSIRU()

main()


import requests
import sys
import time
import os

# python serviceQuality3.py https://www.baidu.com
def http_Status(arg):
    try:
        html = requests.get(arg)
        code = html.status_code
        print(code)
        if str(code) == '500':
            print(1)
            time.sleep(60)
            html1 = requests.get(arg)
            code1 = html.status_code
            if str(code1) == '500':
                os.system("D:\\auto.bat")
    except:
        # print(1)
        sys.exit()

if __name__ == "__main__":
    code = sys.argv[1]
    # print(http_Status(code))
    http_Status(code)


import sys
import inflect
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def get_data(args):
    file = "resources/dataset_train.csv"
    if len(args) < 2:
        print("No arguments given. Try with \"resources/dataset_train.csv\".")
    else:
        file = args[1]
    try:
        data = pd.read_csv(file)
    except Exception as e:
        print("Can't extract data from {}.".format(file))
        print(e.__doc__)
        sys.exit(0)
    return data

def get_subject_grade_house(df, subject, house):
    return df.loc[df['Hogwarts House'] == house, subject].dropna()

def f_test(huf, gry, rav, sly):
    huf_size = huf.size
    gry_size = gry.size
    rav_size = rav.size
    sly_size = sly.size
    total_size = huf_size + gry_size + rav_size + sly_size

    huf_mean = np.sum(huf) / huf_size
    gry_mean = np.sum(gry) / gry_size
    rav_mean = np.sum(rav) / rav_size
    sly_mean = np.sum(sly) / sly_size
    total_mean = (huf_mean + gry_mean + rav_mean + sly_mean) / 4
    SSWG = (
            np.sum(np.power(huf - huf_mean, 2))
            + np.sum(np.power(gry - gry_mean, 2))
            + np.sum(np.power(rav - rav_mean, 2))
            + np.sum(np.power(sly - sly_mean, 2)))
    SSBG = (
            np.power(huf_mean - total_mean, 2) * huf_size
            + np.power(gry_mean - total_mean, 2) * gry_size
            + np.power(rav_mean - total_mean, 2) * rav_size
            + np.power(sly_mean - total_mean, 2) * sly_size)
    return (SSBG / 3) / (SSWG / (total_size - 4))

def auto_selection(df, houses, subjects):
    F = {}
    for subject in subjects:
        F[subject] = f_test(
                get_subject_grade_house(df, subject, 'Hufflepuff').values,
                get_subject_grade_house(df, subject, 'Gryffindor').values,
                get_subject_grade_house(df, subject, 'Ravenclaw').values,
                get_subject_grade_house(df, subject, 'Slytherin').values)
    # https://web.ma.utexas.edu/users/davis/375/popecol/tables/f005.html
    critical_value = 2.61
    F = {k: v for k, v in sorted(
        F.items(), key=lambda x: x[1], reverse=False)}
    F = {k: v for k, v in F.items() if v <= critical_value}
    homogens_subjects = list(F.keys())
    p = inflect.engine()
    i = 1
    ifig = 3
    for homogen_subject in homogens_subjects:
        plt.figure(ifig)
        for house in houses:
            grade = df.loc[
                    df['Hogwarts House'] == house, homogen_subject].dropna()
            plt.hist(grade, alpha=0.5, label=house)
        plt.legend(loc='upper right')
        plt.xlabel(homogen_subject + ' Grades')
        plt.ylabel('Frequency')
        plt.title(
                    p.ordinal(i)
                    + " homogeneous distribution: "
                    + homogen_subject
                    + " (Auto Selection)")
        df.boxplot(homogen_subject, by='Hogwarts House', figsize=(12, 8))
        plt.ylabel(homogen_subject + ' Grades')
        plt.show()
        ifig += 2
        i += 1

def manual_selection(df, houses):
    plt.figure(1)
    for house in houses:
        grade = df.loc[
                df['Hogwarts House'] == house, 'Care of Magical Creatures'
                ].dropna()
        plt.hist(grade, alpha=0.5, label=house)
    plt.legend(loc='upper right')
    plt.xlabel('Care of Magical Creatures Grades')
    plt.ylabel('Frequency')
    plt.title(
                "Most homogeneous distribution: "
                + "Care of Magical Creatures (Manual Selection)")
    df.boxplot(
                'Care of Magical Creatures',
                by='Hogwarts House',
                figsize=(12, 8))
    plt.ylabel('Care of Magical Creatures Grades')
    plt.show()

def select_features(df):
    houses = df['Hogwarts House'].unique().tolist()
    subjects = list(df.select_dtypes('number').to_dict().keys())
    subjects.remove('Index')
    return houses, subjects

def main():
    df = get_data(sys.argv)
    houses, subjects = select_features(df)
    manual_selection(df, houses)
    auto_selection(df, houses, subjects)

if __name__ == '__main__':
    main()


#!/usr/bin/env python3

import sys
import os
import time
import numpy as np
import math
import yaml
import roslib

class BatteryData:

    #parsing for latest data
    def __init__(self, battery_str):
        arr =  battery_str[:-1].split(',')
        if len(arr) != 6:
            raise ValueError("battery string given was invalid: {0}".format(battery_str))
        self.epoch = int(int(arr[0])/1000000000)
        self.cur_node = arr[5]
        self.life = int(arr[6]) if arr[6] else 0
        self.voltage = float(arr[4]) if arr[4] else 0
        self.is_charging = arr[8] == '1'
        self.current = float(arr[5]) if arr[5] else 0
        self.day = (time.localtime(float(self.epoch))[0], time.localtime(float(self.epoch))[1], time.localtime(float(self.epoch))[2])

def get_files(directories):
    to_process = []
    for directory in directories:
        if not os.path.isdir(directory):
            print("Path {0} is not a directory.".format(directory))
            return

        print("Processing directory {0}".format(directory))

        for root, dirs, files in os.walk(directory):
            if files:
                # reverse to ensure correct alphanumeric order
                to_process.extend(reversed([os.path.abspath(os.path.join(root, f)) for f in files]))

        print("Total {0} files".format(len(to_process)))
    return to_process

def extract_data(files):
    data_objects = []
    for d_file in sorted(files):
        f = open(d_file, encoding = "ISO-8859-1")
        for line in f.readlines():
                if line[0] != '%' or line[0] != '#':
                    try:
                        data_objects.append(BatteryData(line))
                    except ValueError:
                        continue
    print (len(data_objects), 'Original amount of data')
    dated_data = dict()
    print ("Extracting data according to date")
    for data in data_objects:
        if data.day not in dated_data:
            data_l = []
            data_l.append(data)

        else:
            data_l = dated_data[data.day]
            if data_l[-1].epoch == data.epoch - 60:
                data_l.append(data)

        dated_data.update({ data.day : data_l})

    return dated_data

def check_variation_values(data):
    unique = []
    for d in data:
        if d.life not in unique:
             unique.append(d.life)
    if len(unique) > 3:
        return True
    else:
        return False

def get_charging_data(dated_data, boolean):
    print ("Extracting data relevant for charging and discharging")
    cdated_data = dict()
    for day in dated_data:
        c_data = []
        for data in dated_data[day]:
            if data.is_charging == boolean:
                c_data.append(data)
        #if len(c_data) > 10 and check_variation_values(c_data):
        cdated_data.update({day : c_data})

    return cdated_data

# input array of Battery
def get_battery_model(path_to_directory):
    path = '/home/milan/workspace/strands_ws/src/battery_scheduler'
    #path = roslib.packages.get_pkg_dir('battery_scheduler')
    if os.path.isfile(path+'/models/battery_charge_model.yaml') and os.path.isfile(path+'/data/alpha_negative_'+self.data_source+'.yaml'):
        with open (path+'/models/battery_charge_model.yaml', 'r') as f_charge:
            charge_model = yaml.load(f_charge)
        with open (path+'/models/battery_charge_model.yaml', 'r') as f_discharge:
            discharge_model = yaml.load(f_discharge)

    else:
        charge_model = dict()
        discharge_model = dict()
        for model in [charge_model, discharge_model]:
            for i in range (101):
                model.update({ i : dict()})

        dated_data = extract_data(get_files(path_to_directory)) ## specify path to battery files
        for data in dated_data.values():
            for i in range(len(data)):
                current_bs = data[i]
                if i < len(data)-30:
                    next_bs = data[i+30]
                    if (current_bs.is_charging == next_bs.is_charging) and current_bs.is_charging == True:
                        bl_dict = charge_model[current_bs.life]
                        if next_bs.life not in bl_dict:
                            count = 1
                        else:
                            count = bl_dict[next_bs.life] + 1
                        bl_dict.update({next_bs.life : count})
                        charge_model.update({current_bs.life : bl_dict})

                    elif (current_bs.is_charging == next_bs.is_charging) and current_bs.is_charging == False:
                        bl_dict = discharge_model[current_bs.life]
                        if next_bs.life not in bl_dict:
                            count = 1
                        else:
                            count = bl_dict[next_bs.life] + 1
                        bl_dict.update({next_bs.life : count})
                        discharge_model.update({current_bs.life : bl_dict})

        f_discharge = file(path+'/models/battery_discharge_model.yaml', 'w')
        yaml.dump(discharge_model, f_discharge)
        f_charge =file(path+ '/models/battery_charge_model.yaml', 'w')
        yaml.dump(charge_model, f_charge)

    return charge_model, discharge_model


import subprocess
import sys

tests = [
    # (NPolynomes, 	MaxDegree, 	NMonomes, 	no_threads)
      (10, 	        1000, 	    50,		    1),
      (10, 	        1000, 	    50,		    4),
      (10, 	        1000, 	    50,		    6),
      (10, 	        1000, 	    50,		    8),
      (5, 	        10000, 	    100,		1),
      (5, 	        10000, 	    100,		4),
      (5, 	        10000, 	    100,		6),
      (5, 	        10000, 	    100,		8),
]

if __name__ == '__main__':
    #if len(sys.argv) < 2: exit(f"Usage: {argv[0]}")

    for test in tests:
        args = ['py', 'cpp_multiple_run.py', 'report.xlsx',
    	    str(test[0]), str(test[1]), str(test[2]), '5'] +([str(test[3])] if test[3] > 1 else [])

        print(f"[INFO] Running test... N={test[0]:<8}, M={test[1]:<8}, n=m={test[2]:<2} on p={test[3]:<2} threads")
        proc = 	subprocess.Popen(args)
        proc.communicate()


from flask import render_template,request,redirect,url_for,abort
from . import main
from flask_login import login_required
from ..models import User,Feedback,Pitch
from .forms import FeedbackForm,PitchForm
from .. import db

# landing
@main.route('/')
def index():
    '''
    View root page function that returns index page and its data
    '''
    title = 'Pitcher'

    return render_template('index.html', title = title)

# post pitch
@main.route('/new_pitch', methods = ['GET','POST'])
@login_required
def new_pitch():
    form = PitchForm()
    if form.validate_on_submit():
        pitch = Pitch(post=form.post.data,body=form.body.data,category=form.category.data)
        pitch.save_pitch()
        return redirect(url_for('main.index'))
    return render_template('new_pitch.html',form=form)

# profile
@main.route('/user/<uname>')
def profile(uname):
    user = User.query.filter_by(username = uname).first()
    index=Pitch.query.all()
    if user is None:
        abort(404)

    return render_template("profile/profile.html", user = user,index = index)

# feedback
@main.route('/feedback', methods = ['GET','POST'])
@login_required
def new_feedback(id):
    form = FeedbackForm()
    pitch = Pitch.query.get(id)
    if form.validate_on_submit():
        feedback = Feedback(title=form.title.data,feedback=form.feedback.data, pitch=pitch)
        db.session.add(feedback)
        db.session.commit()
    feed_back = Feedback.query.filter_by(pitch=pitch).all()
    return render_template('feedback.html',feed_back=feed_back,form=form)

# product
@main.route('/product', methods = ['GET','POST'])
@login_required
def product():
    product_pitch=Pitch.query.filter_by(category="PRODUCT")
    return render_template('product.html', product_pitch = product_pitch)

# pick_Up
@main.route('/pick_up', methods = ['GET','POST'])
@login_required
def pick():
    pick_Up=Pitch.query.filter_by(category="PICK-UP")
    return render_template('pick_up.html', pick_Up = pick_Up)

# stand up comedy
@main.route('/stand_up_comedy', methods = ['GET','POST'])
@login_required
def stand():
    stand_Up=Pitch.query.filter_by(category="COMEDY")
    return render_template('stand_up_comedy.html', stand_Up = stand_Up)

# PROMOTION
@main.route('/promotion', methods = ['GET','POST'])
@login_required
def promotion():
    promotion_pitch=Pitch.query.filter_by(category="PROMOTION")
    return render_template('promotion.html', promotion_pitch = promotion_pitch)

# INTERVIEW
@main.route('/interview', methods = ['GET','POST'])
@login_required
def interview():
    interview_pitch=Pitch.query.filter_by(category="INTERVIEW")
    return render_template('interview.html', interview_pitch = interview_pitch)


import re
import string
import nltk.classify.util, nltk.metrics
import nltk.classify.util
from nltk.collocations import BigramCollocationFinder
from nltk.metrics import BigramAssocMeasures
import itertools

punctuation = list(string.punctuation)
stopwords = punctuation + ['via', "http", "https"]

def normalizeRepetitiveChars(s):  # look for 2 or more repetitions of character and replace with the character itself
    pattern = re.compile(r"(.)\1{1,}", re.DOTALL)
    return pattern.sub(r"\1\1", s)

def preprocessTweet(text):
    text = text.lower().strip()
    text = re.sub(r"(?:\@|https?\://)\S+", "", text)  # remove url's & mentions
    text = text.replace(" : (", " :(")

    words = text.split()

    result = ""
    for w in words:
        w = normalizeRepetitiveChars(w)  # replace two or more with two occurrences
        w = w.strip('\'"?,.')  # strip punctuation, remove punctuation at the start and ending of the tweets
        if (w not in stopwords and len(w) > 1):
            result = result + " " + w
    return result.strip()

# BOW s
def unigramExtractor(tweet):
    words = nltk.word_tokenize(tweet)
    return dict([(word, True) for word in words])

# Bigrams
def bigramExtractor(tweet, score_fn=BigramAssocMeasures.chi_sq, n=100, includeUnigrams=True):
    words = nltk.word_tokenize(tweet)

    bigram_finder = BigramCollocationFinder.from_words(words)
    bigrams = bigram_finder.nbest(score_fn, n)

    if includeUnigrams:
        # return dict([(ngram, True) for ngram in itertools.chain(words, bigrams)])
        return dict(
            [(ngram, True) for ngram in itertools.chain(zip(words, ["" for _ in range(0, len(words))]), bigrams)])
    else:
        return dict([(ngram, True) for ngram in bigrams])

def printClassifierName(classifier):
    try:
        print(type(classifier._clf))
    except:
        print(type(classifier))

def printMostInformativeFeatures(classifier):
    try:
        classifier.show_most_informative_features(30)
    except:
        pass


import quandl
import pandas as pd
import datetime
import matplotlib.pyplot as plt
from matplotlib import style
style.use('ggplot')

api_key = "*******"

def state_list():
    states = pd.read_html('https://simple.wikipedia.org/wiki/List_of_U.S._states')
    return states[0][1][1:]

def fetch_initial_state_data():
    main_df = pd.DataFrame()
    states = state_list()

    for abbrv in states:
        query = "FMAC/HPI_" + str(abbrv)
        #print("*******************  " + query)
        df = quandl.get(query, authtoken=api_key)
        df['NSA Value'] = (df['NSA Value'] - df['NSA Value'][0]) / df['NSA Value'][0] * 100.0
        if main_df.empty:
            main_df = df
        else:
            main_df = main_df.join(df, lsuffix='_left', rsuffix='_right')

    #print(main_df.head())
    """
        Serializing the data
    """
    main_df.to_pickle('hpi_data2.pickle')

def load_serialied_data():
    pickle_data = pd.read_pickle('hpi_data2.pickle')
    #print(pickle_data.head())
    pickle_data.plot()
    plt.legend().remove()
    plt.show()

if __name__ == '__main__':
    #fetch_initial_state_data()
    load_serialied_data()


# Time:  O(26n)
# Space: O(26)

# 1320 weekly contest 171 1/11/2020

# A B C D E F
# G H I J K L
# M N O P Q R
# S T U V W X
# Y Z

# You have a keyboard layout as shown above in the XY plane, where each English uppercase letter is located at some coordinate,
# for example, the letter A is located at coordinate (0,0), the letter B is located at coordinate (0,1), the letter P is
# located at coordinate (2,3) and the letter Z is located at coordinate (4,1).
#
# Given the string word, return the minimum total distance to type such string using only two fingers. The distance
# between coordinates (x1,y1) and (x2,y2) is |x1 - x2| + |y1 - y2|.
#
# Note that the initial positions of your two fingers are considered free so don't count towards your total distance,
# also your two fingers do not have to start at the first letter or the first two letters.

class Solution(object):
    # Time:  O(52n)
    # Space: O(52)
    def minimumDistance(self, word): # USE THIS: calculate the total distance by using finger 1 or 2 for each char
        def distance(a, b):
            if -1 in [a, b]:
                return 0
            return abs(a//6 - b//6) + abs(a%6 - b%6)

        dp = {(-1, -1): 0} # {finger1, finger2}
        for c in word:
            c = ord(c)-ord('A')
            ndp = {}
            for a, b in dp:
                ndp[c, b] = min(ndp.get((c, b), float("inf")), dp[a, b] + distance(a, c))
                ndp[a, c] = min(ndp.get((a, c), float("inf")), dp[a, b] + distance(b, c))
            dp = ndp
        return min(dp.values())

    def minimumDistance2(self, word):
        """
        :type word: str
        :rtype: int
        """
        def distance(a, b):
            return abs(a//6 - b//6) + abs(a%6 - b%6)
        # dp[i] stores the cost of char i to its next char in string. max(dp) is where to change finger after that char.
        # All previous savings from changing hands are accumulated.
        dp = [0]*26
        for i in range(len(word)-1):
            b, c = ord(word[i])-ord('A'), ord(word[i+1])-ord('A')
            # the selected 'a' should just before 'c' for optimal path. If a same as c, means c is beginning of 2nd finger.
            dp[b] = max(dp[a] - distance(a, c) + distance(b, c) for a in range(26))
        seq = sum(distance(ord(word[i])-ord('A'), ord(word[i+1])-ord('A')) for i in range(len(word)-1))
        return seq - max(dp)

    # This solution is wrong. This is one hand, then another hand.
    def minimumDistance_wrong(self, word: str) -> int:
        ans = []
        c1 = word[0]
        x1, y1 = divmod(ord(c1)-ord('A'), 6)
        x2, y2 = None, None
        for c2 in word[1:]:
            x2, y2 = divmod(ord(c2)-ord('A'), 6)
            ans.append(abs(x1-x2)+abs(y1-y2))
            x1, y1 = x2, y2
        return sum(ans)-max(ans)

print(Solution().minimumDistance("CAKE")) # 3: 0 (f1 on C) + 2 (f1 on A) + 0 (f2 on K) + 1 (f2 on E)
# algorithm2: 2+5+1-max(dp {'A':5, 'C':2, 'K':1})
print(Solution().minimumDistance("HAPPY")) # 6: 0 (f1 on H) + 2 (f1 on A) + 0 (f2 on P) + 0 (f2 on P) + 4 (f1 on Y)
# algorithm2: 2+5+0+5-max(dp {'A':5, 'H':2, 'P':6})
print(Solution().minimumDistance("NEW")) # 3. algorithm2: 5+3-max(dp={'E':4, 'N':5})
print(Solution().minimumDistance("YEAR")) # 7. algorithm2: 8+4+7-max(dp={'A':12, 'E':8, 'Y':8})


import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
import tensorflow as tf
#tf.executing_eagerly()
import pickle
import sys
import time
import datetime
import numpy as np
import os

data = np.load("Data/Data0619--O.npz",allow_pickle=True)
x = data['x']
y = data['y']
evaX = np.expand_dims(np.array(x[1][:,-85:-3]), axis=0) # Female_Short_Run_Medium_R
evaY = np.expand_dims(np.array(y[1]), axis=0)

model = tf.keras.models.load_model('ClothNet+')
model.evaluate(evaX, evaY)

result = model(evaX)

savePath = 'Result/0621_2/'
os.mkdir(savePath)
print(result.shape)
cloth = result.numpy().reshape( result.shape[1], -1,3)
face = np.load("face.npy")
for i in range(cloth.shape[0]):
	now = cloth[i]
	print(now.shape)
	f = open(savePath + str(i).zfill(4) + '.obj' , "w")
	for v in now:
		f.write('v %f %f %f\n' % (v[0], v[1], v[2]+i*0.4))
	for fa in face:
		f.write('f %d %d %d\n' % (fa[0], fa[1], fa[2]))
	f.close()


#!/usr/bin/env python3
import tweepy
from datetime import datetime, timedelta

class TweetBot():
    def __init__(self):
        ###deletion settings
        #minimum for likes required to keep
        self.keep_liked = 1
        #tweets containing these strings will not be deleted
        self.strings_to_keep = []
        #how old are tweets before deleting
        self.days_old = 2

    def getKeys(self, filename):
        try:
            self.keys = {}
            with open(filename, 'r') as f:
                for line in f:
                    line = line.rstrip().split(" ")
                    self.keys[line[0][:-1]] = line[1]
            return (True, "success")
        except Exception as e:
            return (False, str(e))

    def auth(self):
        try:
            auth = tweepy.OAuthHandler(self.keys["CONSUMER_KEY"],
                                       self.keys["CONSUMER_SECRET"])
            auth.set_access_token(self.keys["ACCESS_KEY"],
                                  self.keys["ACCESS_SECRET"])
            self.api = tweepy.API(auth)
            return (True, "success")
        except Exception as e:
            return (False, str(e))

    def tweet(self, message):
        try:
            self.api.update_status(message)
            return (True, "success")
        except Exception as e:
            print(e)
            print("Failed to tweet:", message)
            return (False, str(e) + "\nFailed to tweet: " + message)

    def delete_tweets(self):
        try:
            timeline = tweepy.Cursor(self.api.user_timeline).items()
            for tweet in timeline:
                #delete all tweets that dont pass check
                if (not self.keep_tweet(tweet)):
                    self.api.destroy_status(tweet.id)
            return (True, "success")
        except Exception as e:
            return (False, str(e))

    # check if we want to keep tweet
    def keep_tweet(self, tweet):
        cutoff_date = datetime.utcnow() - timedelta(self.days_old)

        if tweet.favorite_count >= self.keep_liked:
            return True

        #if tweet has string in save list, keep
        for string in self.strings_to_keep:
            if tweet.text.find(string) > -1:
                return True

        #dont delete tweets younger than cutoff
        if tweet.created_at >= cutoff_date:
            return True

        return False


import telebot
from flask import Flask, request
from telebot import TeleBot
from telebot.types import Update

app = Flask(__name__)

@app.route('/tg/')
def tg():
    update = Update.de_json(request.stream.read().decode('utf-8'))
    bot.process_update([update])
    return 'ok', 200

bot = telebot.TeleBot('1667764364:AAHfD7JMybA28m_MJwrkWutgd8Y_EzKXS5s', threaded=False)

@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, f'Я бот. Приятно познакомиться, {message.from_user.first_name}')

@bot.message_handler(content_types=['text'])
def get_text_messages(message):
    if message.text == 'Привет':
        bot.send_message(message.from_user.id, 'Привет, как ты себя чувствуешь?')
    elif message.text == 'Плохо':
        bot.send_message(message.from_user.id, 'Надеюсь, тебе станет лучше')
    elif message.text == 'Хорошо':
        bot.send_message(message.from_user.id, 'Это хорошо :)')
    else:
        bot.send_message(message.from_user.id, 'Я тебя не понимаю :(')

bot.polling(none_stop=True)


#This code was tested using Python 3.6.4, GPAW 1.3.0, and ASE 3.16.0

from ase.io import read,write
from ase.visualize import view
import numpy as np
from ase.build import *
from copy import deepcopy
from ase.constraints import FixAtoms
import subprocess
import os.path
from ase.io.trajectory import PickleTrajectory
from matplotlib import pylab as plt
from ase import Atoms

def Junc(Mol, path, A, D1, D2, Alkyne):

	#Sulfur and Nitrogen(NH2) are used interchangeably
	mol = Mol

	##Define vacuum indices
	#Sulfur_1
	Me1_ind = 0
	S1_ind = 4
	C1_ind = 5
	Si1_ind = 6

	#Sulfur_2
	Me2_ind = len(mol)-7
	S2_ind = len(mol)-3
	C2_ind = len(mol)-2
	Si2_ind = len(mol)-1

	###basic setup###
	#make slab
	SH_dist = 1.75 #Use 1.5 for NH2
	HH_dist = 0.75

	#allign S-C with y-axis
	CCvec = mol[C1_ind].position - mol[C2_ind].position
	mol.rotate(CCvec,'z')

	a = A
	d1 = D1

	H1a = Atoms(['H'],[mol[S1_ind].position+[0,0,SH_dist]])
	H1b = Atoms(['H'],[mol[S1_ind].position+[0,0,SH_dist+HH_dist]])
	mol = mol + H1a + H1b
	mol.set_angle(C1_ind,S1_ind,-2,A)
	mol.set_angle(C1_ind,S1_ind,-1,A)
	if Alkyne is False:
		mol.set_dihedral(Si1_ind,C1_ind,S1_ind,-2, d1)
		mol.set_dihedral(Si1_ind,C1_ind,S1_ind,-1, d1)
	else:
		for n in np.arange(0,360,0.1):
			old1 = mol.get_distance(h1a,-1)
			old2 = mol.get_distance(h1b,-1)
			mol.set_dihedral(Si1_ind,C1_ind,S1_ind,-2, n)
			mol.set_dihedral(Si1_ind,C1_ind,S1_ind,-1, n)

			if mol.get_distance(h1a,-1) > mol.get_distance(h1b,-1) and old1 < old2:
				break
			print('dihedral is ', n)

	d2 = D2

	H2a = Atoms(['H'],[mol[S2_ind].position+[0,0,SH_dist]])
	H2b = Atoms(['H'],[mol[S2_ind].position+[0,0,SH_dist+HH_dist]])
	mol = mol + H2a + H2b
	mol.set_angle(C2_ind,S2_ind,-2,A)
	mol.set_angle(C2_ind,S2_ind,-1,A)
	if Alkyne is False:
		mol.set_dihedral(Si2_ind,C2_ind,S2_ind,-2, d2)
		mol.set_dihedral(Si2_ind,C2_ind,S2_ind,-1, d2)
	else:
		for n in np.arange(0,360,0.1):
			old1 = mol.get_distance(h2a,-1)
			old2 = mol.get_distance(h2b,-1)
			mol.set_dihedral(Si2_ind,C2_ind,S2_ind,-2, n)
			mol.set_dihedral(Si2_ind,C2_ind,S2_ind,-1, n)

			if mol.get_distance(h2a,-1) > mol.get_distance(h2b,-1) and old1 < old2:
				break
			print('dihedral is ', n)

	#set cell og periodic boundary conditions
	mol.center(vacuum=4.0)

	path2 = os.getcwd()
	folder = path
	write('%s/hh_junc.traj'%(folder),mol)#

	return mol


# -*- coding:utf-8 -*-
import json
from collections import OrderedDict

from core import comparator, utils, reportor
from core.command import CommonCommand
from core.reportor import test_result
from core.reportor.test_result import CommandResult

__author__ = 'chengchao'

class AssertCommand(CommonCommand):
    def __init__(self, expect):
        CommonCommand.__init__(self, expect)

    def do_run(self, pre_response=None):
        reportor.log("[assert][start] expect:%s, pre_response:%s" % (json.dumps(self.value), pre_response))
        # 如果期望的body是一个string，那么不需要转换response的类型，否则使用json.loads加载response body
        pre_response['body'] = pre_response['body'] if isinstance(self.value['body'], str) \
                                                       or pre_response['body'] is None \
            else json.loads(pre_response['body'], object_pairs_hook=OrderedDict)
        diff = comparator.json_compare(self.value, pre_response)
        diff = comparator.to_easy_read(diff)
        reportor.log("[assert][end] diff: %s" % json.dumps(diff))
        result = test_result.RESULT_SUCCESS if not diff else test_result.RESULT_FAIL
        return result, diff


"""
lskDB Class
"""

import pylisk.lskutils

class lskDB:
    """

    """

    def __init__(self, config_file):
        """

        """
        self.config_file = config_file
        self.del_addr_sql = '''
            SELECT m."username", m."isDelegate", m."u_isDelegate",
            m."secondSignature", m."u_secondSignature",
            m."u_username", m."address", m."balance",
            m."u_balance", m."vote", m."rate",
            m."delegates", m."u_delegates", m."address",
            m."multisignatures", m."u_multisignatures",
            m."multimin", m."u_multimin", m."multilifetime",
            m."u_multilifetime", m."blockId", m."nameexist",
            m."u_nameexist", m."producedblocks", m."missedblocks",
            m."fees", m."rewards", m."virgin",
            ENCODE(m."publicKey", \'hex\') AS public_key,
            ENCODE(m."secondPublicKey", \'hex\') AS second_public_key
            FROM mem_accounts as m'''
        self.transaction_sql = '''
            SELECT t."t_id", t."b_height", t."t_blockId",
            t."t_type", t."t_timestamp", t."t_senderId",
            t."t_recipientId", t."t_amount", t."t_fee",
            t."t_signature", t."t_SignSignature", t."t_signatures",
            t."confirmations",
            ENCODE(t."t_senderPublicKey", \'hex\') AS public_key
            FROM trs_list AS t'''

    def peers(self, rtype):
        """

        """

        if rtype == 'peers':

            sql = 'SELECT ip, port, state, os, version, height, clock FROM peers'

        return pylisk.lskutils.db_select(sql, None, self.config_file)

    def transactions(self, rtype, transaction_id=None, transactions=None):
        """

        """

        sql = self.transaction_sql
        sql_args = None

        if rtype == 'transaction':

            if not transaction_id: return {'success': False,
                                     'message': 'Missing --transaction <transaction>'}

            sql = sql + ' WHERE t_id = %(transaction_id)s'
            sql_args = {'transaction_id': transaction_id}

        elif rtype == 'transactions':

            if not transactions: return {'success': False,
                                     'message': 'Missing --transactions <txid> <txid'}

            sql = sql + ' WHERE t_id IN %(transactions)s'
            sql_args = {'transactions': tuple(transactions)}

        return pylisk.lskutils.db_select(sql, sql_args, self.config_file)

    def blocks(self, rtype, block_id=None, blocks=None):
        """

        """

        sql = ''
        sql_args = None

        if rtype == 'block':

            if not block_id: return {'success': False,
                                     'message': 'Missing --block <block_id>'}

            sql = '''
                SELECT * FROM full_blocks_list WHERE b_id = %(block_id)s'''
            sql_args = {'block_id': block_id}

        elif rtype == 'blocks':

            if not blocks: return {'success': False,
                                   'message': 'Missing --blocks <block_id> <block_id>'}

            sql = '''
                SELECT * FROM full_blocks_list WHERE b_id IN %(block_id)s'''
            sql_args = {'block_id': tuple(blocks)}

        return pylisk.lskutils.db_select(sql, sql_args, self.config_file)

    def delegates(self, rtype, delegate_name=None):
        """

        """

        sql = self.del_addr_sql
        sql_args = None

        if rtype == 'delegates':

            sql = sql + ''' WHERE m."username" IS NOT NULL'''

        elif rtype == 'delegate':

            sql = sql + ''' WHERE m."username" = %(delegate)s'''

            sql_args = {'delegate': delegate_name}

        return pylisk.lskutils.db_select(sql, sql_args, self.config_file)

    def addresses(self, rtype, address=None, addresses=None):
        """

        """

        sql = self.del_addr_sql
        sql_args = None

        if rtype == 'address':

            if not address: return {'success': False,
                                    'message': 'Missing --address <address>'}

            sql = sql + ' WHERE m."address" = %(address)s'
            sql_args = {'address': address}

        elif rtype == 'addresses':

            if not addresses: return {'success': False,
                                      'message': 'Missing --addresses <address> <address>'}

            sql = sql + ' WHERE m."address" IN  %(addresses)s'
            sql_args = {'addresses': tuple(addresses)}

        return pylisk.lskutils.db_select(sql, sql_args, self.config_file)

    def custom(self, rtype, public_key=None, block=None):
        """

        """

        sql = ''
        sql_args = None
        vote_sql = """
            SELECT t."t_id", t."b_height", t."t_blockId",
            t."t_type", t."t_timestamp", t."t_senderId",
            t."t_recipientId", t."t_amount", t."t_fee",
            t."t_signature", t."t_SignSignature", t."t_signatures",
            t."confirmations",
            ENCODE(t."t_senderPublicKey", \'hex\') AS public_key
            FROM votes AS v
            JOIN trs_list AS t ON (t."t_id" = v."transactionId")
            WHERE v."votes" LIKE %(public_key)s;"""

        fork_query = """
            SELECT f."blockTimestamp", f."blockId", f."blockHeight",
            f."previousBlock", f."cause", f."delegatePublicKey"
            FROM forks_stat AS f
            """

        if rtype == 'downvotes' or rtype == 'upvotes':

            if not public_key: return {'success': False,
                                       'message': 'Missing --public-key <pKey>'}

            sql = vote_sql

            if rtype == 'upvotes':
                sql_args = {'public_key': '%+' + public_key + '%'}
            elif rtype == 'downvotes':
                sql_args = {'public_key': '%-' + public_key + '%'}

        elif rtype == 'fork':

            if not block: return {'success': False,
                                  'message': 'Missing --block <blockid>'}

            sql = fork_query + ' WHERE f."blockId" = %(block)s'
            sql_args = {'block': block}

        elif rtype == 'forks':

            sql = fork_query

        return pylisk.lskutils.db_select(sql, sql_args, self.config_file)


import json
import logging
from datetime import datetime, timedelta

from django.core.management.base import BaseCommand

from apps.TA.management.commands.TA_worker import get_subscriber_classes
from apps.TA.storages.abstract.timeseries_storage import TimeseriesStorage
from settings.redis_db import database

logger = logging.getLogger(__name__)

class Command(BaseCommand):
    help = 'Run Redis Indicator wipe and restore'

    def add_arguments(self, parser):
        parser.add_argument('arg', nargs='?', default='some_arg', type=str)

    def handle(self, *args, **options):
        logger.info("Starting wipe and restore...")

        arg = options['arg']

        wipe_all_indicators()

        start_score = TimeseriesStorage.score_from_timestamp(datetime.now().timestamp())
        end_score = TimeseriesStorage.score_from_timestamp((datetime.now()-timedelta(days=2)).timestamp())
        restore_indicators(start_score, end_score)

def wipe_all_indicators():
    for key in database.keys("*Storage*"):
        storage_class = key.decode("utf-8").split(":")[2]

        if "Price" in storage_class or "Volume" in storage_class:
            continue
        else:
            logger.debug("deleting key: " + key.decode("utf-8"))
            # database.delete(key)

def restore_indicators(start_score, end_score, only_these_tickers=None):

    subscribers = []
    for subsrciber_class in get_subscriber_classes():
        subscribers.append(subsrciber_class())

    for key in database.keys("*PriceStorage*close_price*"):
        [ticker, exchange, storage_class, index] = key.decode("utf-8").split(":")
        if only_these_tickers and ticker not in only_these_tickers:
            continue
        logging.critical(f'Restoring {ticker}...')

        for score in range(int(start_score), int(end_score)+1):
            if int(score) % 10000 == 0:
                logging.critical(f'    ... score {score}')
            for subscriber in subscribers:
                subscriber(data_event=forge_data_event(
                    ticker, exchange, storage_class, index, value="doesntmatter", score=score
                ))
        logging.critical(f'{ticker} done')

def parallel_restore(start_score, end_score, only_these_tickers=None):
    from apps.backtesting.utils import parallel_run
    subscribers = []
    for subsrciber_class in get_subscriber_classes():
        subscribers.append(subsrciber_class())

    for key in database.keys("*PriceStorage*close_price*"):
        [ticker, exchange, storage_class, index] = key.decode("utf-8").split(":")
        if only_these_tickers is not None and not ticker in only_these_tickers:
            logging.critical(f'Skipping {ticker}...')
            continue

        logging.critical(f'Restoring {ticker}...')
        import time

        start = time.time()

        params = []
        for score in range(int(start_score), int(end_score)+1):
            if score % 10000 == 0:
                logging.critical(f'    ... score {score}')
            data_event = forge_data_event(
                ticker, exchange, storage_class, index, "123ABC", score
            )
            params += [(subscriber, data_event) for subscriber in subscribers]

        parallel_run(run_subscriber, params, pool_size=10, enable_tqdm=False)

        end = time.time()
        logging.critical(f'{ticker} done in {(start-end)/60:.2f} minutes')

def run_subscriber(params):
    subscriber, data_event = params
    subscriber(data_event)

def forge_data_event(ticker, exchange, storage_class, index, value, score):

    data = {
        "key": f"{ticker}:{exchange}:{storage_class}:{index}",
        "name": f"{value}:{score}",
        "score": f"{score}"
    }

    return {
        'type': 'message',
        'pattern': None,
        'channel': bytes(str(storage_class), "utf-8"),
        'data': bytes(json.dumps(data), "utf-8")
    }

if __name__ == '__main__':
    parallel_restore(227222, 259056, ['ETH_BTC'])


#Problem 1
def get_rainfall():
    rainfall_stats = []
    for i in range(12):
        rainfall = float(input("How much rain in month %d:\n" % i))
        rainfall_stats.append(rainfall)
    return rainfall_stats

def display_rainfall(rainfall_stats):
    total_rainfall = 0
    for stat in rainfall_stats:
        total_rainfall += stat
    avg_rainfall = total_rainfall / len(rainfall_stats)
    max_rainfall = max(rainfall_stats)
    min_rainfall = min(rainfall_stats)
    print("\nTotal rainfall for the year: %0.2f" % total_rainfall)
    print("Average rainfall for each month: %0.2f" % avg_rainfall)
    print("Most rainfall in a month: %0.2f" % max_rainfall)
    print("Least rainfall in a month: %0.2f" % min_rainfall)

def rainfall():
   display_rainfall(get_rainfall())

#Problem 2
def show_off_list():
    totally_not_a_list = []
    usr_str = input("Please enter a sequence of integers separated by a comma for this demonstration:\n")
    usr_str = usr_str.strip()
    totally_not_a_list = usr_str.split(',')
    for value in totally_not_a_list:
        totally_not_a_list[totally_not_a_list.index(value)] = int(value)
    print("This is a non-formatted list:\n%s" % totally_not_a_list)
    print("\nThis is a sorted list:\n%s" % sorted(totally_not_a_list))
    print("\nThis is a reversely sorted list:\n%s" % sorted(totally_not_a_list, reverse=True))
    print("\nThis is a list printing out each value separately:")
    for totally_not_an_object in totally_not_a_list:
        print(totally_not_an_object, end=' ')
    print()
    print("\nThis is the first half of that unsorted list:\n%s" % totally_not_a_list[:len(totally_not_a_list) // 2])
    print("\nThis is the second half of that same list\n%s" % totally_not_a_list[len(totally_not_a_list) // 2:])
    print("\nBut as you can see, I didn't change the actual list itself:\n%s" % totally_not_a_list)
    popped_value = totally_not_a_list.pop(len(totally_not_a_list) // 2)
    print("\nLet's take out the middle value which is: %s\n%s" % (popped_value, totally_not_a_list))
    insert_pos = (len(totally_not_a_list)  // 3)
    totally_not_a_list.insert(insert_pos - 1, popped_value)
    print("\nAnd let's add it back in somewhere like at position %d in the list:\n%s" % (insert_pos, totally_not_a_list))
    totally_not_a_list.clear()
    print("\nAnd lastly, let's wipe the slate clean and start over:\n%s" % totally_not_a_list)

#Problem 3
def encrypt(codes):
    usr_str = input("Enter a message to encrypt:\n")
    encrypted_str = ''
    for ch in usr_str:
        if ch in codes:
            encrypted_str += codes[ch]
    print("Encrypted message:\n%s" % encrypted_str)
    return encrypted_str

def decrypt(codes):
    usr_str = input("Enter a message to decrypt:\n")
    decrypted_str = ''
    keys = []
    values = []
    for key, value in codes.items():
        keys.append(key)
        values.append(value)
    for ch in usr_str:
        if ch in values:
            decrypted_str += keys[values.index(ch)]
    print("Encrypted message:\n%s" % decrypted_str)
    return decrypted_str

#Problem 4
def show_off_dict(totally_not_a_dict):
    print("\nThis is a non-formatted dictionary:\n%s" % totally_not_a_dict)
    print("\nThis is all the keys from the dictionary:\n%s" % totally_not_a_dict.keys())
    print("\nThis is all the values from the dictionary:\n%s" % totally_not_a_dict.values())
    totally_not_a_dict['sandwich'] = 'food'
    print("\nLet's add a new element called 'sandwich' with the value 'food':\n%s" % totally_not_a_dict)
    totally_not_a_dict.pop('3')
    print("\nLet's remove the key '3' now:\n%s" % totally_not_a_dict)
    totally_not_a_dict.clear()
    print("Let's wipe the slate clean and restart the dictionary now:\n%s" % totally_not_a_dict)

#Running all dis
if __name__ == '__main__':
    rainfall()
    codes = {'A': '1', 'a': '♫', 'B': '2', 'b': '@', 'C': '3', 'c': '#', 'D': '4', 'd': '$', 'E': '5', 'e': '%',
             'F': '6', 'f': '^', 'G': '7', 'g': '&', 'H': '8', 'h': '*', 'I': '9', 'i': '▓', 'J': '9', 'j': ')',
             'K': '[', 'k': '{', 'L': ']', 'l': '}', 'M': '≥', 'm': '|', 'N': ';', 'n': ':', 'O': "'", 'o': '♪',
             'P': ',', 'p': '<', 'Q': '.', 'q': '>', 'R': '/', 'r': '?', 'S': '`', 's': '~', 'T': '☺', 't': '▬',
             'U': '♦', 'u': '♣', 'V': '♠', 'v': '♂', 'W': '╝', 'w': '☼', 'X': '!', 'x': '(', 'Y': '±', 'y': '►',
             'Z': '√', 'z': '⌂', ' ': 'î', '0': 'ê', '1': 'Æ', '2': '╣', '3': '¥', '4': 'µ', '5': '╠', '6': '¿',
             '7': 'ç', '8': '└', '9': '◘', '!': '§', '*': 'δ', '+': '╧', '-': 'Σ', '/': 'ⁿ', ',': 'Ü', '.': '╕',
             '?': '╫', ':': '▀', ';': '█', '"': '├', "'": '╚', '(': '¡', ')': '╔', '_': 'Ω', '[': '╜', ']': '"',
             '{': '₧', '}': '╓'}
    encrypt(codes)
    list_to_show = [1, 423, 234235, 123, 23, 632, 123, 0.2, 32]
    show_off_list()
    dict_to_show = {'apple': 'fruit', 'red': 'color', '3': 'number'}
    show_off_dict(dict_to_show)


from cart.cart import Cart
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.urls import reverse
from django.views import View

from core.order.forms import OrderForm
from core.models import Product, Category, Order, SelectedProduct, IdOrder
from core.cart.views import get_total_cart, cart_clear, update_cart_items

@login_required()
def home(request):
    return redirect(reverse('customer:profile'))

@login_required()
def ouazzane_page(request):

    if "next_category" in request.GET:
        next_category = request.GET["next_category"]
        products = list(Product.objects.filter(category=Category.objects.get(name=next_category)))

    else:
        next_category = ""
        products = list(Product.objects.all())

    extra_context = {"products": products,"next_category": next_category }
    return render(request, 'ouazzane/ouazzane.html', extra_context)

@login_required()
def order(request):

    form = OrderForm(initial={'first_name': request.user.first_name, 'last_name': request.user.last_name})
    current_user = request.user

    defaut_firstname = current_user.first_name
    defaut_lastname = current_user.last_name

    extra_context = {
        "form": form,
        "defaut_firstname": defaut_firstname,
        "defaut_lastname": defaut_lastname,
    }

    return render(request, 'order/order.html', extra_context)

@login_required()
def order_preparation(request):
    extra_context = {}
    return render(request, 'order/order_preparation.html', extra_context)

@login_required()
def get_selected_articles(request, new_order_id):

    cart = Cart(request)
    nb_articles = 0
    list_selected_products = []

    for curr_dict_val in cart.cart.values():
        curr_quantity = int(curr_dict_val.get('quantity'))

        if curr_quantity > 0:
            curr_product_id = curr_dict_val.get('product_id')
            curr_product = Product.objects.get(id=curr_product_id)

            selected_product = SelectedProduct(
                user = request.user,
                name = curr_product.name,
                category = curr_product.category,
                price = float(curr_product.price),
                quantity = int(curr_dict_val.get('quantity')),
                order_id = new_order_id,
            )

            selected_product.save()
            list_selected_products.append(selected_product)

    return list_selected_products

class AjaxOrderView(View):

    def get(self, request):
        if request.is_ajax():
            action = request.GET.get('action')

            if action == "confirm_order":
                order_id = int(request.GET.get('order_id'))
                orders = Order.objects.filter(order_id=order_id)

                for order in orders:
                    order.is_confirmed = True
                    order.save()

                #On vide la panier
                cart_clear(request)
                return  JsonResponse({}, status=200)

            elif action == 'new_order' :
                last_name  = request.GET.get('last_name')
                first_name  = request.GET.get('first_name')
                adresse  = request.GET.get('adresse')
                phone_number  = request.GET.get('phone_number')

                new_id_order = IdOrder(user=request.user)
                new_id_order.save()
                list_selected_products = get_selected_articles(request, new_id_order.id)

                for selected_product in list_selected_products:
                    new_order = Order(last_name=last_name,
                                      first_name = first_name,
                                      adresse = adresse,
                                      phone_number = phone_number,
                                      user = request.user,
                                      selected_product = selected_product,
                                      order_id = new_id_order.id,
                                      price = float(selected_product.price) * float(selected_product.quantity),
                                      )
                    new_order.save()

                return JsonResponse({'order_id': str(new_id_order.id)}, status=200)

            elif action == 'change_order' :
                last_name  = request.GET.get('last_name')
                first_name  = request.GET.get('first_name')
                adresse  = request.GET.get('adresse')
                phone_number  = request.GET.get('phone_number')
                order_id  = request.GET.get('order_id')

                list_selected_products = SelectedProduct.objects.filter(order_id=order_id)
                list_order = Order.objects.filter(order_id=order_id)

                for order in list_order:
                    order.last_name = last_name
                    order.first_name = first_name
                    order.phone_number = phone_number
                    order.adresse = adresse
                    order.save()

                return JsonResponse({'order_id': order_id}, status=200)

        return render(request, 'order/order.html')


#!/usr/bin/env python
import time
import sys
import logging
import threading
import queue
import enum
from fileparser import import_files, get_filenames
import library
# import the MUD server class
from mudserver import MudServer, Event, EventType
from location import Location, Exit
import control

# Setup the logger
logging.basicConfig(format='%(asctime)s [%(threadName)s] [%(levelname)s] %(message)s',
    level=logging.INFO,
    handlers=[
        logging.FileHandler("muddyswamp.log"),
        logging.StreamHandler(sys.stdout)
    ])

#prints to stderr
def err_print(*args, **kwargs):
	print(*args, file=sys.stderr, **kwargs)

VERBOSE_PRINT = False
def v_print(*args, **kwargs):
	if VERBOSE_PRINT:
		err_print(*args, **kwargs)

# defining a set of paths
# by default, we import every json in chars and locations
import_paths = {
    "locations" : get_filenames("./locations/", ".json"),
    "chars" : get_filenames("./chars/", ".json")
}

# Basic enum for the type of server command
class ServerCommandEnum(enum.Enum):
    BROADCAST_MESSAGE=0
    GET_PLAYERS=1

# Simple wrapper class for a server-side command
class ServerComand:
    def __init__(self, command_type, params):
        self.command_type = command_type
        self.params = params

class MudServerWorker(threading.Thread):
    def __init__(self, q, *args, **kwargs):
        self.keep_running = True
        imported_lib = import_files(**import_paths)
        library.store_lib(imported_lib)
        self.start_location = Location("Starting Location",
                            "This is the default starting location.")
        if "Marston Basement" in library.locations:
            self.start_location = library.locations["Marston Basement"]
        super().__init__(*args, **kwargs)

    # Cannot call mud.shutdown() here because it will try to call the sockets in run on the final go through
    def shutdown(self):
        self.keep_running = False

    def run(self):
        logging.info("Starting server.")
        self.mud = MudServer()
        library.store_server(self.mud)
        logging.info("Server started successfully.")
        # main game loop. We loop forever (i.e. until the program is terminated)
        while self.keep_running:
            try:
                server_command = self.q.get(block=False)
                if server_command is not None:
                    if server_command.command_type == ServerCommandEnum.BROADCAST_MESSAGE:
                        self.mud.send_message_to_all(server_command.params)
                    elif server_command.command_type == ServerCommandEnum.GET_PLAYERS:
                        logging.info("Players: ")
                        for player in control.Player.player_ids.values():
                            logging.info(str(player))

            except Exception:
                pass

            # 'update' must be called in the loop to keep the game running and give
            # us up-to-date information
            self.mud.update()

            # handle events on the server_queue
            while (len(self.mud.server_queue) > 0):
                event = self.mud.server_queue.popleft()
                logging.info(event)
                id = event.id
                if event.type is EventType.PLAYER_JOIN:
                    logging.info("Player %s joined." % event.id)
                    # notifying the player of their class, creating the character
                    self.mud.send_message(id, "Welcome to MuddySwamp!")
                    PlayerClass = library.random_class.get()
                    self.mud.send_message(id, "You are a(n) %s" % PlayerClass)
                    self.mud.send_message(id, "What is your name?")
                    # creating a controler (a 'Player'), then giving that Player control of a new character
                    # of whatever class the player is
                    new_player = control.Player(event.id)
                    new_character = PlayerClass()
                    new_player.assume_control(new_character)

                elif event.type is EventType.MESSAGE_RECEIVED:
                    # log the message
                    logging.debug("Event message: " + event.message)
                    control.Player.send_command(id, event.message)

                elif event.type is EventType.PLAYER_DISCONNECT:
                    # logging data of the player
                    player = control.Player.player_ids[id]
                    logging.info("%s left" % player)
                    if player.receiver is not None:
                        pass
                        #self.mud.send_message_to_all("%s quit the game" % player.receiver)
                    control.Player.remove_player(id)

            # temporary: move this to a better place later
            for id, msg in control.Player.receive_messages():
                self.mud.send_message(id, msg)

        # Shut down the mud instance after the while loop finishes
        self.mud.shutdown()

# Create a threadsafe queue for commands entered on the server side
q = queue.Queue()
# Create an instance of the thread and start it
thread = MudServerWorker(q)
thread.setName("MudServerThread")
thread.start()

# Look for input on the server and send it to the thread
while True:
    try:
        command, params = (input("").split(" ", 1) + ["", ""])[:2]
        if command == "broadcast":
            q.put(ServerComand(ServerCommandEnum.BROADCAST_MESSAGE, u"\u001b[32m" + "[Server] " + params + u"\u001b[0m"))
        elif command == "players":
            q.put(ServerComand(ServerCommandEnum.GET_PLAYERS, ""))
        elif command == "stop":
            q.put(ServerComand(ServerCommandEnum.BROADCAST_MESSAGE, u"\u001b[32m" + "[Server] " + "Server shutting down..." + u"\u001b[0m"))
            break
        elif command == "help":
            logging.info("Server commands are: \n" \
            " broadcast [message] - Broadcasts a message to the entire server\n"\
            " players - Prints a list of all players\n" \
            " stop - Stops the server")
        else:
            logging.info("Command not recognized. Type help for a list of commands.")
    except KeyboardInterrupt:
        logging.info("Keyboard interrupt detected. Shutting down.")
        q.put(ServerComand(ServerCommandEnum.BROADCAST_MESSAGE, u"\u001b[32m" + "[Server] " + "Server shutting down..." + u"\u001b[0m"))
        break

# Shut down the server gracefully
logging.info("Shutting down server")
thread.shutdown()
thread.join()
logging.info("Server shutdown. Good bye!!")