from __future__ import absolute_import, division, print_function
import time
import logging
from collections import OrderedDict
from yokolibs import Transport
from yokolibs.Exceptions import Error, ErrorBadArgument, ErrorBadResponse

# This makes sure all classes are the new-style classes by default.
__metaclass__ = type # pylint: disable=invalid-name

_LOG = logging.getLogger("_yokobase")

# Special return value from a command function idicating that raw command should be executed upon
# function exit.
_CMD_CONTINUE = object

# The data items supported by all power meters.
_DATA_ITEMS = OrderedDict([
    ("V", "voltage"),
    ("I", "current"),
    ("P", "active power"),
    ("S", "apparent power"),
    ("Q", "reactive power"),
    ("Lambda", "power factor (λ)"),
    ("Phi", "phase difference (Φ)"),
    ("Fv", "voltage frequency"),
    ("Fi", "current frequency"),
    ("Wh", "watt-hours"),
    ("Whp", "positive watt-hours"),
    ("Whm", "negative watt-hours"),
    ("Ah", "ampere-hours"),
    ("Ahp", "positive ampere hours"),
    ("Ahm", "negative ampere hours"),
    ("Vmax", "maximum voltage"),
    ("Imax", "maximum current"),
    ("Time", "integration time"),
    ("Math", "value computed during integration"),
])

# Virtual data items are are generated on-the-fly in software.
_VDATA_ITEMS = OrderedDict([
    ("T", "time stamp at the end of the measurement interval"),
    ("J", "Joules (calculated as Power * Interval)"),
])

# Power meter math function names and description.
_MATH_NAMES = OrderedDict([
    ("cfv", "voltage crest factor"),
    ("cfi", "current crest factor"),
    ("add", "A+B"),
    ("sub", "A-B"),
    ("mul", "A*B"),
    ("div", "A/B"),
    ("diva", "A/B^2"),
    ("divb", "A^2/B"),
    ("avw", "Average active power"),
])

# The power meter commands common for all power meters.
# * property - whether this command just reads or changes a power meter configuration option or a
#              property. Can be 'None'.
# * property-descr - if the command is about reading/changing a property, this is a short human
#                    readable string describing the the property the command deals with. Can be
#                    'None'.
# * descr - human-readable description for the command.
#
# The following keys are added dynamically when the power meter object is initialized:
# * choices - list of all the possible values accepted or return by the command. Can be 'None'.
# * choices-set - same as choices, but of the 'set' type. Can be 'None'.
# * value-descr - human-readable text description of the possible values the command returns or
#                 accepts. Can be 'None'.
COMMANDS = OrderedDict([
    ("get-id", {
        "property-descr" : "device ID",
        "descr" : "get the device identification string",
    }),
    ("get-current-auto-range", {
        "property-descr" : "current auto range status",
        "descr" : "check whether the automatic current range feature is enabled",
    }),
    ("set-current-auto-range", {
        "property-descr" : "current auto range status",
        "descr" : "enable or disable the automatic current range feature",
    }),
    ("get-current-range", {
        "property-descr" : "current range (amperes)",
        "descr" : "get current range in amperes",
    }),
    ("set-current-range", {
        "property-descr" : "current range (amperes)",
        "descr" : "set current range in amperse",
    }),
    ("get-voltage-auto-range", {
        "property-descr" : "voltage auto range status",
        "descr" : "check whether the automatic voltage range feature is enabled",
    }),
    ("set-voltage-auto-range", {
        "property-descr" : "voltage auto range status",
        "descr" : "enable or disable the automatic voltage range feature",
    }),
    ("get-voltage-range", {
        "property-descr" : "voltage range (volts)",
        "descr" : "get voltage range in volts",
    }),
    ("set-voltage-range", {
        "property-descr" : "voltage range (volts)",
        "descr" : "set current range in volts",
    }),
    ("get-interval", {
        "property-descr" : "data update interval (seconds)",
        "descr" : "get the data update interval in seconds",
    }),
    ("set-interval", {
        "property-descr" : "data update interval (seconds)",
        "descr" : "set the data update interval in seconds",
    }),
    ("configure-data-items", {
        "property-descr" : None,
        "descr" : "set data items to read",
    }),
    ("wait-data-update", {
        "property-descr" : None,
        "descr" : "wait for data update",
    }),
    ("read-data", {
        "property-descr" : None,
        "descr" : "read power meter data",
    }),
    ("get-crest-factor", {
        "property-descr" : "crest factor",
        "descr" : "get crest factor",
    }),
    ("set-crest-factor", {
        "property-descr" : "crest factor",
        "descr" : "set crest factor",
    }),
    ("get-smoothing-status", {
        "property-descr" : "smoothing feature status",
        "descr" : "check whether the smoothing feature is enabled or disabled",
    }),
    ("set-smoothing-status", {
        "property-descr" : "smoothing feature status",
        "descr" : "enable or disable the smoothing feature",
    }),
    ("get-smoothing-type", {
        "property-descr" : "smoothing type",
        "descr" : "get smoothing type",
    }),
    ("set-smoothing-type", {
        "property-descr" : "smoothing type",
        "descr" : "set smoothing type",
    }),
    ("get-smoothing-factor", {
        "property-descr" : "smoothing factor",
        "descr" : "get the configured smoothing factor",
    }),
    ("set-smoothing-factor", {
        "property-descr" : "smoothing factor",
        "descr" : "set smoothing factor",
    }),
    ("get-integration-mode", {
        "property-descr" : "integration mode",
        "descr" : "get integration mode",
    }),
    ("set-integration-mode", {
        "property-descr" : "integration mode",
        "descr" : "set integration mode",
    }),
    ("get-integration-state", {
        "property-descr" : "integration state",
        "descr" : "get integration state",
    }),
    ("get-integration-timer", {
        "property-descr" : "integration timer value",
        "descr" : "get the integration timer value value",
    }),
    ("set-integration-timer", {
        "property-descr" : "integration timer value",
        "descr" : "get the integration timer value",
    }),
    ("start-integration", {
        "property-descr" : None,
        "descr" : "start integration",
    }),
    ("stop-integration", {
        "property-descr" : None,
        "descr" : "stop integration",
    }),
    ("reset-integration", {
        "property-descr" : None,
        "descr" : "reset integration",
    }),
    ("get-math", {
        "property-descr" : "computation function",
        "descr" : "get the currently configured computation function",
    }),
    ("set-math", {
        "property-descr" : "computation function",
        "descr" : "set the computation function",
    }),
    ("get-remote-mode", {
        "property-descr" : "remote mode status",
        "descr" : "check whether the remote mode is enabled or disabled",
    }),
    ("set-remote-mode", {
        "property-descr" : "remote mode status",
        "descr" : "enable or disable the remote mode",
    }),
    ("get-local-mode", {
        "property-descr" : "local mode status",
        "descr" : "check whether the local mode is enabled or disabled",
    }),
    ("set-local-mode", {
        "property-descr" : "local mode status",
        "descr" : "enable or disable the local mode",
    }),
    ("get-wiring-system", {
        "property-descr" : "wiring system type",
        "descr" : "get the wiring system type",
    }),
    ("factory-reset", {
        "property-descr" : None,
        "descr" : "reset to the factory default settings",
    }),
    ("calibrate", {
        "property-descr" : None,
        "descr" : "execute zero-level compensation",
    }),
    ("clear", {
        "property-descr" : None,
        "descr" : "clear the device output queue"
    }),
    ("get-installed-opts", {
        "property-descr" : "installed device options",
        "descr" : "get information about the installed device options",
    }),
    ("get-measurement-mode", {
        "property-descr" : "measurement mode",
        "descr" : "get the measurement mode",
    }),
    ("set-measurement-mode", {
        "property-descr" : "measurement mode",
        "descr" : "set the measurement mode",
    }),
    ("get-sync-source", {
        "property-descr"  : "synchronization source",
        "descr"  : "the information about the synchronization source",
    }),
    ("set-sync-source", {
        "property-descr"  : "synchronization source",
        "descr"  : "set the synchronization source",
    }),
    ("get-hold", {
        "property-descr" : "the 'hold' feature status",
        "descr"  : "check whether the 'hold' feture is on or off",
    }),
    ("set-hold", {
        "property-descr" : "the 'hold' feature status",
        "descr" : "switch the 'hold' feture is on or off",
    }),
    ("get-max-hold", {
        "property-descr" : "the 'max hold' feature status",
        "descr" : "check whether the 'max hold' feture is on or off",
    }),
    # WT210 says no help text for max hold on ./yokotool wt210 set max-hold
    ("set-max-hold", {
        "property-descr" : "the 'max hold' feature status",
        "descr" : "switch the 'max hold' feture is on or off",
    }),
    ("get-line-filter", {
        "property-descr" : "line filter status",
        "descr" : "check if the line filter is enabled or disabled",
    }),
    ("set-line-filter", {
        "property-descr" : "line filter status",
        "descr" : "enable or disable the line filter",
    }),
    ("get-freq-filter", {
        "property-descr" : "frequency filter status",
        "descr" : "check if the frequency filter is enabled or disabled",
    }),
    ("set-freq-filter", {
        "property-descr" : "frequency filter status",
        "descr" : "enable or disable the frequency filter",
    }),
])

_RAW_COMMANDS = (
    ("get-id", "*IDN?"),
    ("get-installed-opts", "*OPT?"),
    ("get-interval", ":SAMP:RATE?"),
    ("set-interval", ":SAMP:RATE"),
    ("get-hold", ":SAMP:HOLD?"),
    ("set-hold", ":SAMP:HOLD"),
    ("get-integration-mode", ":INTEG:MODE?"),
    ("set-integration-mode", ":INTEG:MODE"),
    ("get-integration-timer", ":INTEG:TIM?"),
    ("set-integration-timer", ":INTEG:TIM"),
    ("start-integration", ":INTEG:STAR"),
    ("stop-integration", ":INTEG:STOP"),
    ("reset-integration", ":INTEG:RES"),
    ("get-math", ":MATH?"),
    ("get-remote-mode", ":COMM:REM?"),
    ("set-remote-mode", ":COMM:REM"),
    ("get-local-mode", ":COMM:LOCK?"),
    ("set-local-mode", ":COMM:LOCK"),
    ("factory-reset", "*RST"),
    ("calibrate", "*CAL?"),
    ("get-error-status", ":STAT:ERR?"),
    ("clear", "\n*CLS"),
    ("set-verbose-errors", ":STAT:QMES"),
    ("set-headers", ":COMM:HEAD"),
    ("set-verbose-mode", ":COMM:VERB"),
    ("get-eesr", ":STAT:EESR?"),
)

# Valid arguments for the "enable/disable" type of commands.
ON_OFF_CHOICE = ("on", "off")

# The valid arguments for various commands.
_CHOICES = (
    {
        "commands" : ("get-current-range", "set-current-range"),
        # Note: the allowed values also depend on the crest-factor.
        "choices" : ("auto", "0.0025", "0.005", "0.01", "0.02", "0.05", "0.1", "0.2", "0.5", "1",
                     "2", "5", "10", "20"),
    },
    {
        "commands" : ("get-voltage-range", "set-voltage-range"),
        # Note: the allowed values also depend on the crest-factor.
        "choices" : ("7.5", "15", "30", "60", "75", "150", "300", "600"),
    },
    {
        "commands" : ("get-current-auto-range", "set-current-auto-range"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-voltage-auto-range", "set-voltage-auto-range"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-crest-factor", "set-crest-factor"),
        "choices" : ("3", "6"),
    },
    {
        "commands" : ("get-interval", "set-interval"),
        "choices" : ("0.1", "0.25", "0.5", "1", "2", "5"),
    },
    {
        "commands" : ("get-line-filter", "set-line-filter"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-freq-filter", "set-freq-filter"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-smoothing-status", "set-smoothing-status"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-smoothing-type", "set-smoothing-type"),
        "choices" : ("linear", "exponent"),
    },
    {
        "commands" : ("get-smoothing-factor", "set-smoothing-factor"),
        "choices" : ("8", "16", "32", "64"),
    },
    {
        "commands" : ("get-integration-mode", "set-integration-mode"),
        "choices" : ("normal", "continuous"),
    },
    {
        "commands" : ("get-measurement-mode", "set-measurement-mode"),
        "choices" : ("rms", "vmean", "dc"),
    },
    {
        "commands" : ("get-display-digits", "set-display-digits"),
        "choices" : ("4", "5"),
    },
    {
        "commands" : ("get-remote-mode", "set-remote-mode"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-local-mode", "set-local-mode"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-verbose-errors", "set-verbose-errors"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-verbose-mode", "set-verbose-mode"),
        "choices" : ON_OFF_CHOICE,
    },
    {
        "commands" : ("get-headers", "set-headers"),
        "choices" : ON_OFF_CHOICE,
    },
)

# The EESR register bits. It is important to keep this list ordered correctly.
_EESR_BITS = {
    "upd":  0,  # Measurement data is being updated.
    "itg":  1,  # Integration started.
    "itm":  2,  # Integration timer started.
    "ovrs": 3,  # Computation result overflow.
    "fov":  4,  # Frequency is out of range.
    "str":  5,  # 'storage' is ongoing.
    "ovr1": 6,  # Voltage or current on the 1st element is out of range.
    "pov1": 7,  # Peak voltage on the 1st element is out of range.
    "poa1": 8,  # Peak current on the 1st element is out of range.
    "ovr2": 9,  # Voltage or current on the 2nd element is out of range.
    "pov2": 10, # Peak voltage on the 2nd element is out of range.
    "poa2": 11, # Peak current on the 2nd element is out of range.
    "ovr3": 12, # Voltage or current on the 3rd element is out of range.
    "pov3": 13, # Peak voltage on the 3rd element is out of range.
    "poa3": 14, # Peak current on the 3rd element is out of range.
}

#
# Power meter's input and output values are not always very human-friendly. Below set of functions,
# referred to as 'tweaks', transform these values into a human-friendly format, and vice-versa, they
# also transform human-friendly notations into power meter's format.
#

def on_off_tweak(_, value):
    """Translate '0' and non-zero strings to 'off' and 'on' strings."""

    if value == "0":
        return "off"
    return "on"

def to_lower_tweak(_, value):
    """Translate 'value' to lowercase."""
    return value.lower()

def _to_lower_capitalize_tweak(_, value):
    """Translate 'value' to lowercase and capitalize it."""
    return value.lower().capitalize()

def _float_to_str_tweak(_, value):
    """Translate a float to string dropping superfluous zeros."""
    return "%g" % float(value)

def _success_failure_tweak(_, value):
    """Translate '0' and non-zero strings to 'success' and 'failure' strings."""

    if value == "0":
        return "success"
    return "failure"

def _csv_to_seconds_tweak(_, value):
    """Convert time from 'h,m,s' CSV format to seconds."""

    seconds = 0
    for item in value.split(','):
        seconds = seconds * 60 + int(item)
    return str(seconds)

def _seconds_to_csv_tweak(_, value):
    """Convert time from seconds to 'h,m,s' CSV format."""

    minutes, seconds = divmod(int(value), 60)
    hours, minutes = divmod(minutes, 60)
    return "%d,%d,%d" % (hours, minutes, seconds)

def _first_data_element_tweak(_, value):
    """Remove the ',1' ending from a data item."""

    if value.endswith(",1"):
        return value[:-2]
    return value

# The tweaks.
_TWEAKS = {
    "get-voltage-auto-range" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-current-auto-range" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-hold" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-max-hold" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-line-filter" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-freq-filter" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-smoothing-status" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-sync-source" : {
        "response-tweaks" : (to_lower_tweak,),
    },
    "get-measurement-mode" : {
        "response-tweaks" : (to_lower_tweak,),
    },
    "get-remote-mode" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-local-mode" : {
        "response-tweaks" : (on_off_tweak,),
    },
    "get-voltage-range" : {
        "response-tweaks" : (_float_to_str_tweak,),
    },
    "get-current-range" : {
        "response-tweaks" : (_float_to_str_tweak,),
    },
    "get-interval" : {
        "response-tweaks" : (_float_to_str_tweak,),
    },
    "set-interval" : {
        "input-tweaks" : (_float_to_str_tweak,),
    },
    "calibrate" : {
        "response-tweaks" : (_success_failure_tweak,),
    },
    "get-integration-mode" : {
        "response-tweaks" : (to_lower_tweak,),
    },
    "get-integration-timer" : {
        "response-tweaks" : (_csv_to_seconds_tweak,),
    },
    "set-integration-timer" : {
        "input-tweaks" : (_seconds_to_csv_tweak,),
    },
}

# Map a power meter error code into a human-readable message. We do not cover all codes here so far.
_ERROR_CODES_MAP = {
    813 : {"msg" : "operation is not allowed during integration, please reset integration first"},
}

def is_in_range(value, start=0, stop=0):
    """Verify whether or not a string 'value' contains an integer in the [min, max] range."""

    try:
        value = int(value)
    except (ValueError, TypeError):
        return False
    if value < start or value > stop:
        return False
    return True

def _verify_integration_time(value):
    """
    Verify whether or not the input value for integration time is an integer representing seconds,
    and if it is lower or equal to 10000 hours.
    """
    return is_in_range(value, 0, 10000 * 60 * 60)

def _cmd_to_str(cmd, arg):
    """Convert command 'cmd' with argument 'arg' to a string for printing."""

    if arg is not None:
        return "%s %s" % (cmd, arg)
    return cmd

class YokoBase():
    """
    This is the base class for all power meters. Each specific type of power meter should be derived
    from this class.
    """

    def _htop_tweak(self, _, value):
        """Translate data item in human notation to the protocol notation."""
        return self._ditt["htop"].get(value, value)

    def _ptoh_tweak(self, _, value):
        """Translate data item in protocol notation to the human notation."""
        return self._ditt["ptoh"].get(value, value)

    def _add_choices_from_dict(self, cmd, choices_dict):
        """
        Add "choices" and "value-descr" for command 'cmd' from the the 'choices_dict' dictionary.
        """

        self.commands[cmd]["choices"] = tuple(choices_dict)

        lines = []
        for name, descr in choices_dict.items():
            lines.append("%s - %s" % (name, descr))
        self.commands[cmd]["value-descr"] = "\n".join(lines)

    def _iter_data_item_commands(self):
        """
        Yield the (cmd_part, get_cmd, set_cmd) tuples for each possible data item command. Must be
        implemented by the child class.
        """

    def _populate_choices(self, choices):
        """Populate the valid values for various WT310 commands to 'self.commands'."""

        cmds = self.commands
        for info in _CHOICES:
            for cmd in info["commands"]:
                if cmd in cmds:
                    cmds[cmd]["choices"] = info["choices"]

        for info in choices:
            for cmd in info["commands"]:
                if cmd in cmds:
                    cmds[cmd]["choices"] = info["choices"]

        self._add_choices_from_dict("read-data", self._data_items)
        self._add_choices_from_dict("configure-data-items", self._data_items)
        self._add_choices_from_dict("get-math", _MATH_NAMES)
        self._add_choices_from_dict("set-math", _MATH_NAMES)

        descr = "integer amount of seconds (0-10000 hours)"
        cmds["get-integration-timer"]["value-descr"] = descr
        cmds["set-integration-timer"]["value-descr"] = descr

        for info in cmds.values():
            if "choices" not in info:
                info["choices"] = None
                info["choices-set"] = None
            if "choices-set" not in info:
                info["choices-set"] = set(info["choices"])
            if "value-descr" not in info:
                info["value-descr"] = None

    def _populate_data_items(self, items, pairs):
        """
        Initialize data items dictionary and build the data items translation tables which is needed
        because often human name for the data item is different to the protocol name and we
        translate the name. This helper creates and returns the data item translation table, which
        is just a dictionary that can be used to quickly get human name by the protocol name and
        vice versa.  The 'pairs' input argument is an iterable containing the (human name, protocol
        name) pairs.
        """

        self._data_items = _DATA_ITEMS
        for name, descr in items.items():
            self._data_items[name] = descr
        for name, descr in _VDATA_ITEMS.items():
            self._data_items[name] = descr

        self._ditt = {}
        self._ditt["htop"] = {}
        self._ditt["ptoh"] = {}
        for hname, pname in pairs:
            self._ditt["htop"][hname] = pname
            self._ditt["ptoh"][pname] = hname

    def _populate_raw_commands(self, raw_commands):
        """Populate the raw (wire) power meter commands to 'self._commands'."""

        for cmd, raw_cmd in _RAW_COMMANDS:
            self._commands[cmd] = {}
            self._commands[cmd]["raw-cmd"] = raw_cmd

        for cmd, raw_cmd in raw_commands:
            self._commands[cmd] = {}
            self._commands[cmd]["raw-cmd"] = raw_cmd

    def _populate_tweaks(self, tweaks):
        """
        Pupulate the tweaks to 'self._commands'. The tweaks are functions applied to command
        arguments before running the command or to the results of a command before returning the
        results to the end user.
        """

        for cmd, info in _TWEAKS.items():
            for key, value in info.items():
                self._commands[cmd][key] = value

        for cmd, info in tweaks.items():
            for key, value in info.items():
                self._commands[cmd][key] = value

        self._commands["read-data"]["response-tweaks"] = (self._get_data_tweak,)

        # Cover the data item get/set commands as well.
        response_tweaks = (_first_data_element_tweak, _to_lower_capitalize_tweak, self._ptoh_tweak)
        input_tweaks = (_to_lower_capitalize_tweak, self._htop_tweak)
        for _, get_cmd, set_cmd in self._iter_data_item_commands():
            self._commands[get_cmd]["response-tweaks"] = response_tweaks
            self._commands[set_cmd]["input-tweaks"] = input_tweaks

    def _populate_arg_verify_funcs(self):
        """Populate arugment verification functions. They are executed before the command is run."""

        self._commands["set-integration-timer"]["verify-arg"] = _verify_integration_time

    def _add_command_func(self, cmd, func):
        """
        Some commands require a handler function, this helpers adds one to the internal
        'self._commands' dictionary.
        """

        if cmd not in self._commands:
            self._commands[cmd] = {}
        if "raw-cmd" not in self._commands[cmd]:
            self._commands[cmd]["raw-cmd"] = None
        self._commands[cmd]["func"] = func

    def _populate_raw_commands_post(self):
        """Add post process and add common raw commands."""

        # Cover the EESR-related commands (one command per a EESR bit).
        for name, bit in self._eesr_bits.items():
            cmd = "set-eesr-filter-%s" % name
            self._commands[cmd] = {}
            self._commands[cmd]["raw-cmd"] = ":STAT:FILT%d" % (bit + 1)
            cmd = "eesr-wait-%s" % name
            self._commands[cmd] = {}
            self._commands[cmd]["raw-cmd"] = ":COMM:WAIT %d" % (bit + 1)

        self._add_command_func("wait-data-update", self._wait_data_update_cmd)
        self._add_command_func("get-current-range", self._get_range_cmd)
        self._add_command_func("set-current-range", self._set_range_cmd)
        self._add_command_func("get-voltage-range", self._get_range_cmd)
        self._add_command_func("set-voltage-range", self._set_range_cmd)
        self._add_command_func("start-integration", self._start_integration_cmd)

        if hasattr(self._transport, "set_timeout"):
            self._add_command_func("set-interval", self._set_interval_timeout_cmd)

        for cmd, info in self._commands.items():
            if cmd.startswith("get-") or (info["raw-cmd"] and info["raw-cmd"].endswith("?")):
                info["has-response"] = True
                info["has-argument"] = False
            else:
                info["has-response"] = False
                info["has-argument"] = True

    def _populate_errors_map_map(self):
        """
        Error codes map mapes power meter error code number either to a human-readable message or to
        an error handler that may either generate a human-readable message or handle the error
        condition.
        """

        self._errors_map = _ERROR_CODES_MAP
        self._errors_map[842] = self._errors_map[844] = self._errors_map[845] = \
                {"func" : self._integration_error_handler}

    @staticmethod
    def _integration_error_handler(cmd, arg, code, rawmsg): # pylint: disable=unused-argument
        """This function implements error handler for the integration commands."""

        if code == 845:
            # start -> reset
            return "current integration state is 'start' and it cannot be changed to 'reset', " \
                   "please stop it first"
        if code == 842:
            # start -> start
            return "integration is already in the 'start' state"
        if code == 844:
            # This is either 'reset->stop' or 'stop->stop'.
            return "cannot stop integration because it is not in the 'start' state, please " \
                   "start it first"

        return ""

    def _prepare_data_items_to_read(self, items):
        """
        The input 'items' list is a mix of pyisical and vitual data items. The former are provided
        by the power meter and the latter are computed in software. This function constructs and
        returns a list of physical data items from 'items'. We also avoid reading the same data item
        more than once with help of this function.
        """

        result = []
        self._item_indexes = {}

        idx = 0
        for item in items:
            # If users request to read the 'Joules' virtual data item, we read the and will use
            # this value to later compute the Joules.
            if item == "J":
                item = "P"
            if item not in _VDATA_ITEMS and item not in self._item_indexes:
                result.append(item)
                self._item_indexes[item] = idx
                idx += 1

        return result

    def _get_data_tweak(self, _, response):
        """Inject the virtual data items into power meter read response."""

        timestamp = time.time()
        items = []

        for item in self._items_to_read:
            if item not in _VDATA_ITEMS:
                items.append(response[self._item_indexes[item]])
            elif item == "T":
                items.append(str(timestamp))
            elif item == "J":
                items.append(str(float(response[self._item_indexes["P"]]) * self._interval))

        return items

    def _configure_data_items_cmd(self, _, items):
        """Set the data items that will be read by next "get-data" command."""

        self._items_to_read = items

        if len(items) > self.max_data_items:
            raise Error("too many data items, please, specify at most %s" % self.max_data_items)

        for item in items:
            if item not in self._data_items:
                msg = "bad data item '%s'" % item
                raise ErrorBadArgument(None, None, msg=msg)

        # The interval is needed to compute the Joules virtual data item.
        self._interval = float(self._command("get-interval"))
        items = self._prepare_data_items_to_read(items)
        _LOG.debug("data items to read from power meter: %s", ",".join(items))

        # Configure a trigger for the "UPD" bit changing from 1 to 0, which happens when data update
        # finishes.
        self._command("set-eesr-filter-upd", "fall")
        return items

    def _wait_data_update_cmd(self, _, __):
        """Wait until WT210 updates the data."""

        # Note, we use 'check_status=False' in this function because the status check commands may
        # take take long time in case of a low baud rate serial connection and we may be late when
        # the update interval is short.

        # Clear EESR by reading it.
        self._command("get-eesr", check_status=False)
        # Wait for the event.
        self._command("eesr-wait-upd", check_status=False)

    def _set_interval_timeout_cmd(self, _, arg):
        """Make sure transport device's timeout is larger than the interval."""

        # Set the timeout to 2x interval length as a margin of safty.
        timeout = int(float(arg) * 1000) * 2
        self._transport.set_timeout(timeout)

        return _CMD_CONTINUE

    def _get_range_cmd(self, cmd, _):
        """Implements the 'get-current-range' and 'get-voltage-range' commands."""

        result = self._command(cmd, func=False)
        auto = self._command(cmd.replace("-range", "-auto-range"))

        if auto == "on":
            result += " (auto)"
        return result

    def _set_range_cmd(self, cmd, arg):
        """Implements the 'set-current-range' and 'set-voltage-range' commands."""

        auto_range_cmd = cmd.replace("-range", "-auto-range")
        if arg == "auto":
            self._command(auto_range_cmd, "on")
            return

        self._command(auto_range_cmd, "off")
        choices = self.commands[cmd]["choices"]
        if arg in (choices[1], choices[-1]):
            # The first and the last current/voltage range availability depends on the crest factor.
            what = cmd.split("-")[1]
            crest = self._command("get-crest-factor")
            crest_needed = None
            if crest == "3" and arg == choices[1]:
                crest_needed = "6"
            elif crest == "6" and arg == choices[-1]:
                crest_needed = "3"
            if crest_needed:
                raise Error("%s range %s is only available when crest factor is %s, but currently "
                            "it is %s" % (what, arg, crest_needed, crest))

        self._command(cmd, arg, func=False)

    def _start_integration_cmd(self, cmd, _):
        """
        Adds a delay after the 'start' integration command. The delay is necessary because some of
        the subsequent commands may fail if executed right after integration had been started. There
        is some sort of the internal integrator busy period which we let pass by introducing a short
        delay.
        """

        self._command(cmd, func=False)
        time.sleep(0.2)

    def _apply_response_tweaks(self, cmd, response):
        """
        Tweak 'response' as defined within a specific type of power meter, then return the tweaked
        argument.
        """

        if "response-tweaks" in self._commands[cmd]:
            for tweak_func in self._commands[cmd]["response-tweaks"]:
                response = tweak_func(cmd, response)
        return response

    def _apply_input_tweaks(self, cmd, arg):
        """
        Tweak 'input' as defined within a specific type of power meter, then return the tweaked
        argument.
        """

        if "input-tweaks" in self._commands[cmd]:
            for tweak_func in self._commands[cmd]["input-tweaks"]:
                arg = tweak_func(cmd, arg)
        return arg

    def _verify_argument(self, cmd, arg):
        """Verify whether or not 'arg' argument is valid for 'cmd' command."""

        choices = self.commands[cmd]["choices-set"]
        if choices:
            # 'arg' may be a list, in which case we check every element of the list.
            if isinstance(arg, (list, tuple)):
                for elt in arg:
                    tweaked_elt = self._apply_input_tweaks(cmd, elt)
                    if tweaked_elt not in choices:
                        raise ErrorBadArgument(cmd, elt)
            else:
                tweaked_arg = self._apply_input_tweaks(cmd, arg)
                if tweaked_arg not in choices:
                    raise ErrorBadArgument(cmd, arg)

        if "verify-arg" in self._commands[cmd]:
            func = self._commands[cmd]["verify-arg"]
            if not func(arg):
                raise ErrorBadArgument(cmd, arg)

        return True

    def _check_error_status(self, cmd, arg):
        """
        Check whether the power meter error status and possibly apply the error handlers. Returns
        'None' if there were no errors (or the error was handled) and the error message otherwise.
        """

        status_cmd = self._commands["get-error-status"]["raw-cmd"]
        try:
            response = self._transport.queryline(status_cmd)
        except Transport.Error as err:
            raise type(err)("failed to check error status of command '%s':\n%s\nRaw command was "
                            "'%s'" % (_cmd_to_str(cmd, arg), err, status_cmd))

        try:
            code, rawmsg = response.split(',', 1)
            code = int(code)
        except ValueError as err:
            raise ErrorBadResponse(raw_cmd=status_cmd, response=response)

        if code == 0:
            return None

        if code in self._errors_map:
            if "func" in self._errors_map[code]:
                msg = self._errors_map[code]["func"](cmd, arg, code, rawmsg)
                if not msg:
                    return None
                if msg == "":
                    # Empty string means that the error handler could generate a customized error
                    # message and the default one should be used.
                    msg = response
            else:
                msg = self._errors_map[code]["msg"]
        else:
            msg = response

        return "command '%s' failed:\n%s" % (_cmd_to_str(cmd, arg), msg)

    def _command(self, cmd, arg=None, check_status=True, func=True):
        """
        Actually execute the command, the tweaks, and the status checks, unless 'check_status' is
        'False'. Some commands have both the "raw-cmd" and "func" keys in their 'self._command'
        description, and the 'func' argument whether the function should be executed or the raw
        command should be executed.
        """

        _LOG.debug(_cmd_to_str(cmd, arg))

        if func and "func" in self._commands[cmd]:
            retval = self._commands[cmd]["func"](cmd, arg)
            if retval is not _CMD_CONTINUE:
                return retval

        if arg is not None:
            arg = self._apply_input_tweaks(cmd, arg)

        raw_cmd = self._commands[cmd]["raw-cmd"]
        if arg is not None:
            raw_cmd += " %s" % arg

        try:
            self._transport.writeline(raw_cmd)
        except Transport.Error as err:
            raise type(err)("failed to write command '%s' to the power meter:\n%s\nRaw command "
                            "was '%s'" % (cmd, err, raw_cmd))
        response = None
        if self._commands[cmd]["has-response"]:
            try:
                response = self._transport.readline()
            except Transport.Error as err:
                raise type(err)("failed to read power meter response to '%s':\n%s\nRaw command was "
                                "'%s'" % (_cmd_to_str(cmd, arg), err, raw_cmd))
            response = self._apply_response_tweaks(cmd, response)

        if check_status:
            msg = self._check_error_status(cmd, arg)
            if msg:
                raise Error(msg)

        return response

    def command(self, cmd, arg=None):
        """
        Execute the power meter command 'cmd' with argument 'arg' if it is not null. Return the
        command response or 'None' if the command has no response. 'cmd' should be a string, 'arg'
        can be of any type since 'command()' handles the typecast to string.
        """

        if not isinstance(cmd, str) or cmd not in self.commands:
            raise Error("bad command '%s'" % cmd)

        # We allow 'arg' to be of different types and convert it into a string
        if arg is not None:
            if isinstance(arg, list):
                for idx, item in enumerate(arg):
                    if not isinstance(item, str):
                        arg[idx] = str(item)
            elif not isinstance(arg, str):
                arg = str(arg)

        # Sanity checks.
        if self._commands[cmd]["has-argument"]:
            self._verify_argument(cmd, arg)
        elif arg is not None:
            raise Error("command '%s' accepts no arguments, but '%s' was provided" % (cmd, arg))

        return self._command(cmd, arg)

    def reset(self, configure=True):
        """
        Reset the power meter and if 'configure' is 'True', also configure with reasonable defaults.
        """

        # Reset to factory settings.
        self.command("clear")
        self.command("factory-reset")
        if not configure:
            return

        # Set crest factor to 3 for better measurement precision.
        self.command("set-crest-factor", "3")
        # We are measuring AC, so need the RMS mode.
        self.command("set-measurement-mode", "rms")
        # Autmatically find the suitable voltage and current ranges.
        self.command("set-voltage-auto-range", "on")
        self.command("set-current-auto-range", "on")
        # Set the measurement interval to 1 second.
        self.command("set-interval", 1)
        # Disable line filer to inclue all the frequencies into the measurements.
        self.command("set-line-filter", "off")
        # Enable the frequency filter. It only affects frequency measurements and generally
        # recommended to be enabled.
        self.command("set-freq-filter", "on")

    def _init_pmeter(self):
        """Initialize the power meter."""

        # Clear the output and error queues of the power meter. The first command may fail with the
        # "interrupted" error if the power meter is currently expencting the results of the previous
        # command to be read, so clear 2 times.
        try:
            self._command("clear")
        except Error:
            self._command("clear")

        # Make sure that in case of error the device sends verbose error strings, not just the
        # status code.
        self._command("set-verbose-errors", "on")
        # Disable headers in responses.
        self._command("set-headers", "off")

        # Clear all the EESR trigger conditions.
        for name in self._eesr_bits:
            self._command("set-eesr-filter-%s" % name, "never")

    def __init__(self, transport):
        """The class constructor. The 'transport' argument is the power meter transport object."""

        self._transport = transport
        self._eesr_bits = _EESR_BITS

        # The data items translation table.
        self._ditt = None
        # Create the user-visible commands dictionary.
        self.commands = COMMANDS
        # The private commands dictionary.
        self._commands = {}
        # List of items configured to be read by 'configure-data-items'.
        self._items_to_read = []
        # Indexes of the data items that we are reading.
        self._item_indexes = None
        # All the supported data items, including the virtual ones.
        self._data_items = None
        # Virtual data items.
        self._vdata_items = _VDATA_ITEMS
        # Maximum count of data items that can be read at the same time.
        self.max_data_items = None
        # Saved value of the power meter data update interval.
        self._interval = None
        # Messages and actions in case power meter reports and error.
        self._errors_map = None

    def __del__(self):
        """The class destructor."""

        try:
            self.close()
        except Exception:
            pass

    def close(self):
        """Close the communication interface with the power meter."""

        if getattr(self, "_transport", None):
            self._transport.close()
            self._transport = None


# Author: Karl Zylinski, Uppsala University

# Goes through the ouput from the find_comoving_stars* scripts and prints
# a list of clusters inside, how many there are of each cluster size etc.

import sys
import os
import utils_str
import utils_dict

def verify_arguments():
    if len(sys.argv) != 3:
        return False

    if not os.path.isfile(sys.argv[1]):
        return False

    if not utils_str.to_int(sys.argv[2]):
        return False

    return True

assert verify_arguments(), "Usage: found_groups_get_group_id.py file gaia_source_id"
input_filename = sys.argv[1]
cg = utils_dict.read(input_filename)
i_source_id = cg["columns"].index("source_id")
sid = int(sys.argv[2])

groups = cg["groups"]

for g in groups:
    for s in g["stars"]:
        if s[i_source_id] == sid:
            print(g["id"])
            break


# encoding:utf-8
'''
Create on 2018-05-03
@author Zheng Huaiguo
'''

import socket
import time
import struct

s=struct.Struct('!I4sf')

def client(ip, port, message):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((ip, port))
        sock.sendall(message)
        print(message)
        response = str(sock.recv(1024))
        print(response)

HOST, PORT = "192.168.10.99", 8081
values=[1,b'good',1.22]
for i in range(10000):
    values[0]=i
    values[2]=i*1.2234
    print(values)
    packed_data=s.pack(*values)
    client(HOST, PORT, packed_data)
    time.sleep(1)


# Write a function called mySqrt that will approximate the square root of a number, call it n, by using Newton’s algorithm.
# Newton’s approach is an iterative guessing algorithm where the initial guess is n/2 and
# each subsequent guess is computed using the formula: newguess = (1/2) * (oldguess + (n/oldguess))

### I've changed it to return guess once the sqrt is perfect. It will fail to stop on recurring numbers, not sure how to fix that.

def perfect_mySqrt(n):
  guess = n / 2
  while n / guess != guess:
    newguess = (1/2) * (guess + (n/guess))
    guess = newguess
  return guess

print("%0.2f" % (perfect_mySqrt(100)))

HTTLACS 6.13 Ex 14 Perfect Square Extra.py


import datetime
import numpy as np

from src.algorithms import utilities

def general(all_contexts, all_rewards, max_num_observations, s_o_max_general):
    time_horizon = all_rewards.shape[0]
    number_of_actions = all_rewards.shape[1]
    context_dimensionality = all_contexts.shape[1]

    all_perms = utilities.perm_construct(context_dimensionality, max_num_observations)
    number_of_perms_general = all_perms.shape[0]

    selected_context_general = np.zeros((time_horizon, context_dimensionality))
    selected_action_general = np.zeros(time_horizon)
    all_gain_general = np.zeros(time_horizon + 1)

    number_of_unique_state_s_when_applying_perm_i = np.zeros((number_of_perms_general, s_o_max_general))

    # d_os = np.zeros((number_of_perms_general, s_o_max_general)) #Definition: N_os / N_o
    true_prob_so = np.zeros((number_of_perms_general,
                             s_o_max_general))  # Definition: number_of_unique_state_s_when_applying_perm_i / time_horizon

    S_Size = np.zeros(number_of_perms_general)

    true_average_reward = np.zeros((number_of_perms_general, s_o_max_general, number_of_actions))

    number_of_visits_for_average_reward = np.zeros((number_of_perms_general, s_o_max_general, number_of_actions))

    sum_of_rewards = np.zeros((number_of_perms_general, s_o_max_general, number_of_actions))

    for i in range(number_of_perms_general):

        one_perm = all_perms[i]

        O_temp = np.tile(one_perm, [time_horizon, 1])

        all_contexts_temp = all_contexts * O_temp  # a*b element.wise multiplication, np.multiply(a,b) is also correct

        # S_i is the matrix whose rows are the unique(between already existing contexts) state realizations of all of the contexts with observation action one_perm[i]
        S_i = np.unique(all_contexts_temp, axis=0)

        # number of unique state realizations for each domain
        # it has a subtle difference with s_o[i] = number of different states(realizations) with the same observation action all_perms[i]
        S_Size[i] = S_i.shape[0]

        for j in range(int(S_Size[i])):

            all_unique_state_s_when_applying_perm_i = (all_contexts_temp == S_i[j, :]).all(1)
            number_of_unique_state_s_when_applying_perm_i[i, j] = number_of_unique_state_s_when_applying_perm_i[
                                                                      i, j] + np.sum(
                all_unique_state_s_when_applying_perm_i)

            true_prob_so[i, j] = number_of_unique_state_s_when_applying_perm_i[i, j] / time_horizon

            all_rewards_temp = all_rewards[all_unique_state_s_when_applying_perm_i, :]

            for k in range(number_of_actions):
                number_of_visits_for_average_reward[i, j, k] = all_rewards_temp[:, k].shape[0]
                sum_of_rewards[i, j, k] = np.sum(all_rewards_temp[:, k])

                true_average_reward[i, j, k] = sum_of_rewards[i, j, k] / number_of_visits_for_average_reward[i, j, k]

    return [true_prob_so, true_average_reward, S_Size]

class SimOOS_Oracle:
    """Fixed-I oracle policy, as defined in SimOOS paper
    "Data-Driven Online Recommender Systems with Costly Information Acquisition"
    Atan et al. 2021

    Different from SimOOS algorithm in that it has access to true probabilites of observing partial state vectors,
    has true expected rewards for a given partial vector and arm.
    Also for this oracle best observation is chosen and fixed for the whole time horizon.
    """
    def __init__(self,
                 all_contexts: np.array,
                 all_rewards: np.array,
                 cost_vector: np.array,
                 number_of_actions: int,
                 max_num_observations: int,
                 beta: float,
                 ):

        self.name = f"SimOOS-Oracle (beta={beta})"

        self.time_horizon = all_contexts.shape[0]
        self.context_dimensionality = all_contexts.shape[1]
        self.max_num_observations = max_num_observations
        self.number_of_actions = number_of_actions
        self.beta = beta

        # All possible subsets of features (I in paper)
        self.all_perms = utilities.perm_construct(self.context_dimensionality, self.max_num_observations)
        self.perm_to_index = {}
        for i, perm in enumerate(self.all_perms):
            self.perm_to_index[tuple(perm)] = i

        self.number_of_perms = self.all_perms.shape[0]
        self.s_o = np.zeros(self.number_of_perms)

        self.selected_context = np.zeros((self.time_horizon, self.context_dimensionality))
        self.selected_action = np.zeros(self.time_horizon)
        self.all_gain = np.zeros(self.time_horizon + 1)

        self.collected_gains = np.zeros(self.time_horizon)
        self.collected_rewards = np.zeros(self.time_horizon)
        self.collected_costs = np.zeros(self.time_horizon)

        # debug variables
        self.states = np.zeros(self.time_horizon)
        self.true_average_rewards = np.zeros((self.time_horizon, self.number_of_actions))

        ########################################################################################
        self.feature_values, self.all_feature_counts = utilities.save_feature_values(all_contexts)

        for i in range(self.number_of_perms):
            # psi[i] = number of different partial vectors(realizations) with given observation action self.all_perms[i]
            # How many partial vectors with support given by self.all_perms[i].
            # Equal to cardinality of Psi(I) in the paper. Used to determine Psi_total, for confidence bounds.

            # s_o[i] - size of state array for a given observation action. It is bigger than psi[i] because
            # it also includes states which have None for observed features (although they are unreachable).
            self.s_o[i] = utilities.state_construct(self.all_feature_counts, all_contexts, self.all_perms[i])

        # s_o_max - the largest state vector for all observations, needed to create arrays.
        self.s_o_max = int(np.amax(self.s_o))
        self.Psi_total = int(np.sum(self.s_o))

        # Oracle variables (not present in SimOOS)
        self.true_prob_so, self.true_average_reward, self.S_Size = general(
            all_contexts, all_rewards, self.max_num_observations, self.s_o_max
        )

        self.r_star = np.zeros((self.number_of_perms, self.s_o_max))
        self.action_star = np.zeros((self.number_of_perms, self.s_o_max))

        for i in range(self.number_of_perms):

            for j in range(int(self.S_Size[i])):
                self.r_star[i, j] = np.max(self.true_average_reward[i, j, :])

                self.action_star[i, j] = np.argmax(self.true_average_reward[i, j, :])

        self.value_o = np.zeros(self.number_of_perms)

        for i in range(self.number_of_perms):
            self.value_o[i] = self.beta * np.dot(self.true_prob_so[i, :], self.r_star[i, :]) - np.dot(self.all_perms[i],
                                                                                cost_vector)

        self.index_of_observation_action_star = np.argmax(self.value_o)

        self.selected_observation_action_at_t = self.all_perms[self.index_of_observation_action_star]

    def choose_features_to_observe(self, t, feature_indices, cost_vector):
        self.observation_action_at_t = self.selected_observation_action_at_t
        return [ind for ind, value in enumerate(self.observation_action_at_t) if value]

    def choose_arm(self, t: int, context_at_t: np.array, pool_indices: list):
        """Return best arm's index relative to the pool of available arms.

        Args:
            t: number of trial
            context_at_t: user context at time t. One for each trial, arms don't have contexts.
            pool_indices: indices of arms available at time t.
        """
        s_t = utilities.state_extract(self.feature_values, self.all_feature_counts, context_at_t, self.observation_action_at_t)
        self.states[t] = s_t
        self.true_average_rewards[t, :] = self.true_average_reward[self.index_of_observation_action_star, s_t]

        self.action_at_t = int(self.action_star[self.index_of_observation_action_star, s_t])
        return pool_indices.index(self.action_at_t)

    def update(self, t, action_index_at_t, reward_at_t, cost_vector_at_t, context_at_t, pool_indices):
        if t % 500 == 0:
            print(f"Trial {t}, time {datetime.datetime.now()}")

        cost_at_t = np.dot(cost_vector_at_t, self.observation_action_at_t)

        action_at_t = pool_indices[action_index_at_t]

        self.selected_context[t, :] = self.selected_observation_action_at_t

        self.all_gain[t + 1] = self.all_gain[t] + reward_at_t - cost_at_t

        self.selected_action[t] = action_at_t

        self.collected_gains[t] = reward_at_t - cost_at_t
        self.collected_rewards[t] = reward_at_t
        self.collected_costs[t] = cost_at_t


import os

import numpy as np
import tensorflow as tf

from card import Suit, Rank
from card import Card, POINT_CARDS, CLUBS_T, SPADES_Q

from nn_utils import transform_game_info_to_nn, v2card

SORTED_CARDS = sorted(list(POINT_CARDS))
SORTED_CARDS = SORTED_CARDS[2:] + SORTED_CARDS[:2]

IS_DEBUG = False

class PolicyValueNet(object):
    def __init__(self, model_file=None):
        padding = "same"
        n_channel, n_suit, n_rank, n_player = 21, 4 ,13, 4

        activation_fn = tf.nn.relu

        # 1. inputs:
        self.inputs = tf.placeholder(tf.float32, shape=[None, n_channel, n_player, n_suit, n_rank], name="inputs")
        input_state = tf.transpose(self.inputs, [0, 2, 3, 4, 1], name="transpose_inputs")

        self.probs = tf.placeholder(tf.float32, shape=[None, 52], name="probs")

        self.score_1 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_2")
        self.score_2 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_3")
        self.score_3 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_4")
        self.score_4 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_5")
        self.score_5 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_6")
        self.score_6 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_7")
        self.score_7 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_8")
        self.score_8 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_9")
        self.score_9 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_10")
        self.score_10 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_11")
        self.score_11 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_12")
        self.score_12 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_13")
        self.score_13 = tf.placeholder(tf.int32, shape=[None, 4], name="hearts_ace")
        self.score_14 = tf.placeholder(tf.int32, shape=[None, 4], name="spades_queen")
        self.score_15 = tf.placeholder(tf.int32, shape=[None, 4], name="clubs_ten")

        # Define the optimizer we use for training
        self.learning_rate = tf.placeholder(tf.float32, name="learning_rate")

        conv1 = tf.layers.conv3d(inputs=input_state,
                                 filters=32,
                                 kernel_size=[4, 4, 13],
                                 padding=padding,
                                 activation=activation_fn)

        conv2 = tf.layers.conv3d(inputs=conv1,
                                 filters=64,
                                 kernel_size=[4, 4, 13],
                                 padding=padding,
                                 activation=activation_fn)

        conv3 = tf.layers.conv3d(inputs=conv2,
                                 filters=128,
                                 kernel_size=[4, 4, 13],
                                 padding=padding,
                                 activation=activation_fn)

        # 3. Policy Networks
        action_conv = tf.layers.conv3d(inputs=conv3,
                                       filters=32,
                                       kernel_size=[1, 1, 1],
                                       padding=padding,
                                       activation=activation_fn)

        action_conv_flat = tf.reshape(action_conv, [-1, 32 * n_player * n_suit * n_rank])
        action_fc1 = tf.layers.dense(inputs=action_conv_flat, units=4096, activation=activation_fn)
        action_fc2 = tf.layers.dense(inputs=action_fc1, units=1024, activation=activation_fn)
        action_fc3 = tf.layers.dense(inputs=action_fc2, units=256, activation=activation_fn)
        self.action_fc = tf.layers.dense(inputs=action_fc3, units=52, activation=tf.nn.softmax)
        self.policy_loss = tf.reduce_mean(tf.reduce_sum(tf.multiply(self.probs, self.action_fc), 1))

        # 4. Value Networks
        evaluation_conv = tf.layers.conv3d(inputs=conv3,
                                           filters=4,
                                           kernel_size=[1, 1, 1],
                                           padding=padding,
                                           activation=activation_fn)

        evaluation_conv_flat = tf.reshape(evaluation_conv, [-1, 4 * n_player * n_suit * n_rank])
        evaluation_fc1 = tf.layers.dense(inputs=evaluation_conv_flat, units=128, activation=activation_fn)
        evaluation_fc2 = tf.layers.dense(inputs=evaluation_fc1, units=32, activation=activation_fn)

        def get_loss(labels, logits, name=None):
            return tf.losses.softmax_cross_entropy(labels, logits)

        self.score_evaluation_fc1 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_1 = get_loss(self.score_1, self.score_evaluation_fc1)

        self.score_evaluation_fc2 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_2 = get_loss(self.score_2, self.score_evaluation_fc2)

        self.score_evaluation_fc3 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_3 = get_loss(self.score_3, self.score_evaluation_fc3)

        self.score_evaluation_fc4 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_4 = get_loss(self.score_4, self.score_evaluation_fc4)

        self.score_evaluation_fc5 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_5 = get_loss(self.score_5, self.score_evaluation_fc5)

        self.score_evaluation_fc6 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_6 = get_loss(self.score_6, self.score_evaluation_fc6)

        self.score_evaluation_fc7 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_7 = get_loss(self.score_7, self.score_evaluation_fc7)

        self.score_evaluation_fc8 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_8 = get_loss(self.score_8, self.score_evaluation_fc8)

        self.score_evaluation_fc9 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_hearts_ten = get_loss(self.score_9, self.score_evaluation_fc9)

        self.score_evaluation_fc10 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_hearts_jack = get_loss(self.score_10, self.score_evaluation_fc10)

        self.score_evaluation_fc11 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_hearts_queen = get_loss(self.score_11, self.score_evaluation_fc11)

        self.score_evaluation_fc12 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_hearts_king = get_loss(self.score_12, self.score_evaluation_fc12)

        self.score_evaluation_fc13 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_hearts_ace = get_loss(self.score_13, self.score_evaluation_fc13)

        self.score_evaluation_fc14 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_clubs_ten = get_loss(self.score_14, self.score_evaluation_fc14)

        self.score_evaluation_fc15 = tf.layers.dense(inputs=evaluation_fc2, units=4, activation=tf.nn.tanh, reuse=False)
        self.loss_spades_queen = get_loss(self.score_15, self.score_evaluation_fc15)

        self.value_loss = self.loss_1 + self.loss_2 + self.loss_3 + self.loss_4 + self.loss_5 + \
                          self.loss_6 + self.loss_7 + self.loss_8 + \
                          self.loss_hearts_ten + self.loss_hearts_jack + self.loss_hearts_queen + \
                          self.loss_hearts_king + self.loss_spades_queen + self.loss_clubs_ten

        # 3-3. L2 penalty (regularization)
        l2_penalty_beta = 1e-4
        vars = tf.trainable_variables()
        l2_penalty = l2_penalty_beta * tf.add_n([tf.nn.l2_loss(v) for v in vars if 'bias' not in v.name.lower()])

        # 3-4 Add up to be the Loss function
        self.loss = l2_penalty + self.policy_loss + self.value_loss

        self.optimizer = tf.train.AdamOptimizer(learning_rate=self.learning_rate).minimize(self.loss)

        # calc policy entropy, for monitoring only
        self.entropy = tf.negative(tf.reduce_mean(tf.reduce_sum(tf.log(self.action_fc) * self.action_fc, 1)))

        # Make a session
        self.session = tf.Session()

        # Initialize variables
        init = tf.global_variables_initializer()
        self.session.run(init)

        # For saving and restoring
        self.saver = tf.train.Saver()
        if model_file is not None and os.path.exists(model_file):
            print("start to restore model from {}".format(model_file),)
            self.restore_model(model_file)
            print("done")

    def policy_value(self, trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards):
        if IS_DEBUG:
            print("     trick_cards:", np.array(trick_cards).shape)
            print("     score_cards:", np.array(score_cards).shape)
            print("  possible_cards:", np.array(possible_cards).shape)
            print("this_trick_cards:", np.array(this_trick_cards).shape)
            print("     valid_cards:", np.array(valid_cards).shape)
            print("   leading_cards:", np.array(leading_cards).shape)
            print("    expose_cards:", np.array(expose_cards).shape)

        inputs = np.concatenate((trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards), \
                                axis=1)

        if IS_DEBUG:
            print("shape of inputs: {}".format(inputs.shape))

        results = self.session.run([self.action_fc, self.score_evaluation_fc1, self.score_evaluation_fc2,
                                    self.score_evaluation_fc3, self.score_evaluation_fc4, self.score_evaluation_fc5,
                                    self.score_evaluation_fc6, self.score_evaluation_fc7, self.score_evaluation_fc8,
                                    self.score_evaluation_fc9, self.score_evaluation_fc10, self.score_evaluation_fc11,
                                    self.score_evaluation_fc12, self.score_evaluation_fc13, self.score_evaluation_fc14,
                                    self.score_evaluation_fc15],
                                   feed_dict={self.inputs: inputs})
        return results

    def transform_results(self, all_player_idx, all_valid_cards, all_expose_cards, all_results, is_need_card=True):
        global SORTED_CARDS

        probs_batch, score_cards_batch = [], []
        for current_player_idx, valid_cards, expose_cards, results in zip(all_player_idx, all_valid_cards, all_expose_cards, all_results):
            is_expose = (np.max(expose_cards) == 2)

            scores, double_player_idx = [0, 0, 0, 0], None
            for card, sub_results in zip(SORTED_CARDS, results[1:]):
                player_idx = np.argmax(sub_results)

                if card.suit == Suit.hearts:
                    scores[player_idx] += (2 if is_expose else 1)
                elif card == CLUBS_T:
                    double_player_idx = player_idx
                elif card == SPADES_Q:
                    scores[player_idx] += 13

            scores[double_player_idx] <<= 1

            probs = []
            if is_need_card:
                where = np.where(valid_cards[current_player_idx] == 1)
                for pos_x, pos_y in zip(where[0], where[1]):
                    probs.append(((pos_x, 1<<pos_y), results[0][0][pos_x*13+pos_y]))
                    #probs.append(((pos_x, 1<<pos_y), np.exp(results[0][0][pos_x*13+pos_y])))

                #print("results", results)
                #print("-->", valid_cards[current_player_idx])
                #print("probs", probs)

            else:
                probs = []
                where = np.where(valid_cards[0, current_player_idx] != 99999999)
                for pos_x, pos_y in zip(where[0], where[1]):
                    probs.append(results[0][pos_x*13+pos_y])
                    #probs.append(np.exp(results[0][pos_x*13+pos_y]))

            probs_batch.append(probs)
            score_cards_batch.append(scores)

        #print("      probs_batch:", probs_batch)
        #print("score_cards_batch:", score_cards_batch)
        return probs_batch, score_cards_batch

    def predict(self, trick_nr, state):
        trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards = \
            transform_game_info_to_nn(state, trick_nr)

        results = self.policy_value(np.array([trick_cards]), np.array([score_cards]), np.array([possible_cards]), \
                                    np.array([this_trick_cards]), np.array([valid_cards]), \
                                    np.array([leading_cards]), np.array([expose_cards]))

        all_results = [[]]
        for idx in range(16):
            all_results[-1].append(results[idx])

        probs, scores = self.transform_results([state.start_pos], valid_cards, expose_cards, all_results)

        return probs[0], scores[0]

    def policy_value_fn(self, current_player_idx, trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards):
        results = self.policy_value(trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards)

        all_results = []
        for idx in range(len(trick_cards)):
            all_results.append([])

            for sub_idx in range(16):
                all_results[-1].append(results[sub_idx][idx])

        return self.transform_results(current_player_idx, valid_cards, expose_cards, all_results, is_need_card=False)

    def get_card_owner(self, trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards, scores):
        inputs = np.concatenate((trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards), \
                                axis=1)

        scores = np.array(scores)

        card_owner = self.session.run([self.score_evaluation_fc1, self.score_evaluation_fc2, self.score_evaluation_fc3,
                                       self.score_evaluation_fc4, self.score_evaluation_fc5, self.score_evaluation_fc6,
                                       self.score_evaluation_fc7, self.score_evaluation_fc8, self.score_evaluation_fc9,
                                       self.score_evaluation_fc10, self.score_evaluation_fc11, self.score_evaluation_fc12,
                                       self.score_evaluation_fc13, self.score_evaluation_fc14, self.score_evaluation_fc15],
                                       feed_dict={self.inputs: inputs,
                                                  self.score_1: scores[:,0],
                                                  self.score_2: scores[:,1],
                                                  self.score_3: scores[:,2],
                                                  self.score_4: scores[:,3],
                                                  self.score_5: scores[:,4],
                                                  self.score_6: scores[:,5],
                                                  self.score_7: scores[:,6],
                                                  self.score_8: scores[:,7],
                                                  self.score_9: scores[:,8],
                                                  self.score_10: scores[:,9],
                                                  self.score_11: scores[:,10],
                                                  self.score_12: scores[:,11],
                                                  self.score_13: scores[:,12],
                                                  self.score_14: scores[:,13],
                                                  self.score_15: scores[:,14],})

        return card_owner

    def train_step(self, \
                   trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards, \
                   probs, scores, learning_rate):
        inputs = np.concatenate((trick_cards, score_cards, possible_cards, this_trick_cards, valid_cards, leading_cards, expose_cards), \
                                axis=1)

        scores = np.array(scores)

        loss, policy_loss, value_loss, entropy, _ = self.session.run(
                [self.loss, self.policy_loss, self.value_loss, self.entropy, self.optimizer],
                feed_dict={self.inputs: inputs,
                           self.probs: probs,
                           self.score_1: scores[:,0],
                           self.score_2: scores[:,1],
                           self.score_3: scores[:,2],
                           self.score_4: scores[:,3],
                           self.score_5: scores[:,4],
                           self.score_6: scores[:,5],
                           self.score_7: scores[:,6],
                           self.score_8: scores[:,7],
                           self.score_9: scores[:,8],
                           self.score_10: scores[:,9],
                           self.score_11: scores[:,10],
                           self.score_12: scores[:,11],
                           self.score_13: scores[:,12],
                           self.score_14: scores[:,13],
                           self.score_15: scores[:,14],
                           self.learning_rate: learning_rate})

        return loss, policy_loss, value_loss, entropy

    def save_model(self, model_path):
        self.saver.save(self.session, model_path)
        print("save model in {}".format(model_path))

    def restore_model(self, model_path):
        self.saver.restore(self.session, model_path)
        print("restore model from {}".format(model_path))

    def close(self):
        self.session.close()


# Chapter 4 Lab Question 2
# Programmer: Jean Claude Hasrouty
# Instructor: Zare Agazaryan
# CSIS 151
# Date Created: 3/6/18

current_pay = 0.01
total_pay = 0

num_days = int(input("Please enter the number of worked days:\n"))
while (num_days < 1) or (num_days > 60):
    print("Invalid number of days.")
    num_days = int(input("Enter the number of days again:\n"))

for x in range(0, num_days):
    if x == 0:
        current_pay = 0.01
        print("Day: ", x + 1, ","," Payment: $", format(current_pay, "2.2f"), sep='')
        total_pay += current_pay
    else:
        current_pay *= 2
        print("Day: ", x + 1, ","," Payment: $", format(current_pay, "2.2f"), sep='')
        total_pay += current_pay

print("Total: $", format(total_pay, "2.2f"), sep='')


from tensorflow.keras.datasets import mnist
from sklearn.decomposition import PCA
import numpy as np
from sklearn.svm import SVC

def reshaping(x:np.ndarray):
    return x.reshape(x.shape[0],-1)

(x_train,y_train),(x_test,y_test)=mnist.load_data()
x=reshaping(np.concatenate((x_train,x_test),axis=0))
pca=PCA(n_components=x.shape[1])
pca.fit(x)
evr=np.cumsum(pca.explained_variance_ratio_)
print(f'0.95:{len(np.argwhere(evr>=0.95))}')
print(f'0.99:{len(np.argwhere(evr>=0.99))}')
print(f'0.999:{len(np.argwhere(evr>=0.999))}')
print(f'1.0:{len(np.argwhere(evr>=1.0))}')


#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import argparse as ap
import textwrap

import pickle as pkl
import gzip

import keras
from keras.models import load_model
import numpy as np

description = '''\
Ceci est un programme qui cherche à identifier la relation binaire
reliant deux noms dans le contexte d'une phrase.

--------------------------------------------------------------------------

Le résultat peut être l'une de ces relations binaires,
ainsi que leur symétries :
    - Cause-Effet(e1,e2) : relation de cause à effet entre deux mots
    - Outil-Agent(e1,e2) : agent utilisant un outil, un instrument
    - Produit-Fabricant(e1,e2) : produit conçu par un fabricant
    - Contenant-Contenu(e1,e2) : contenant contenant un contenu (oui)
    - Entité-Origine(e1,e2) : entité provenant d'une source, géographique
ou physique
    - Entité-Destination(e1,e2) : entité se dirigeant vers une destination
    - Composant-Catégorie(e1,e2) : composant d'une catégorie plus globale
    - Membre-Collection(e1,e2) : membre d'un groupe d'objet de même sorte
    - Message-Sujet(e1,e2) : message dont le thème est <e2>
    - Autre(e1,e2) (cette relation est symétrique)

--------------------------------------------------------------------------
'''

parser = ap.ArgumentParser(formatter_class=ap.RawDescriptionHelpFormatter,
description=textwrap.dedent(description),
epilog= "Matthieu RÉ, Yaohui WANG")
parser.add_argument("sentence",
                    help="La phrase dans laquelle on veut trouver une relation")
parser.add_argument("-e1","--first_term", type=int,
                    help="La position du premier terme")
parser.add_argument("-e2","--second_term", type=int,
                    help="La position de second terme")
parser.add_argument("-v","--verbose", action="store_true",
                    help="Affiche certaines informations supplémentaires")
args = vars(parser.parse_args())
pos1 = args["first_term"]
pos2 = args["second_term"]
sentence = args["sentence"]

################################################################################
######################### Preprocessing de la phrase ###########################
################################################################################

embeddingsPath = 'corpus/deps.words'

distanceMapping = {'PADDING': 0, 'LowerMin': 1, 'GreaterMax': 2}
minDistance = -30
maxDistance = 30
for dis in np.arange(minDistance,maxDistance+1):
    distanceMapping[dis] = len(distanceMapping)

labelsMapping = {'Other':0,
                 'Message-Topic(e1,e2)':1, 'Message-Topic(e2,e1)':2,
                 'Product-Producer(e1,e2)':3, 'Product-Producer(e2,e1)':4,
                 'Instrument-Agency(e1,e2)':5, 'Instrument-Agency(e2,e1)':6,
                 'Entity-Destination(e1,e2)':7, 'Entity-Destination(e2,e1)':8,
                 'Cause-Effect(e1,e2)':9, 'Cause-Effect(e2,e1)':10,
                 'Component-Whole(e1,e2)':11, 'Component-Whole(e2,e1)':12,
                 'Entity-Origin(e1,e2)':13, 'Entity-Origin(e2,e1)':14,
                 'Member-Collection(e1,e2)':15, 'Member-Collection(e2,e1)':16,
                 'Content-Container(e1,e2)':17, 'Content-Container(e2,e1)':18}
word2Idx = {}
words = {}
folder = 'files/'
files = [folder+'train.txt', folder+'test.txt']

# Create a dictionnary of words of the sentence
for fileIdx in np.arange(len(files)):
    file = files[fileIdx]
    for line in open(file):
        splits = line.strip().split('\t')

        sentence_ = splits[3]
        tokens = sentence_.split(" ")
        for token in tokens:
            words[token.lower()] = True

for token in sentence.split(" "):
    words[token.lower()] = True

# Create the word to index dictionary using 'deps.words'
for line in open(embeddingsPath):
    split = line.strip().split(" ")
    word = split[0]

    if len(word2Idx) == 0: #Add padding+unknown
        word2Idx["PADDING"] = len(word2Idx)
        vector = np.zeros(len(split)-1) #Zero vector vor 'PADDING' word

        word2Idx["UNKNOWN"] = len(word2Idx)
        vector = np.random.uniform(-0.25, 0.25, len(split)-1)

    if split[0].lower() in words:
        vector = np.array([float(num) for num in split[1:]])
        word2Idx[split[0]] = len(word2Idx)

def getWordIdx(token, word2Idx):
    """Returns from the word2Idex table the word index for a given token"""
    if token in word2Idx:
        return word2Idx[token]
    elif token.lower() in word2Idx:
        return word2Idx[token.lower()]

    return word2Idx["UNKNOWN"]

def createMatricesSentence(sentence, pos1, pos2, word2Idx, maxSentenceLen=100):
    """Creates matrices for the events and sentence for the given file"""
    positionMatrix1 = []
    positionMatrix2 = []
    tokenMatrix = []

    tokens = sentence.split(" ")

    tokenIds = np.zeros(maxSentenceLen)
    positionValues1 = np.zeros(maxSentenceLen)
    positionValues2 = np.zeros(maxSentenceLen)

    for idx in range(0, min(maxSentenceLen, len(tokens))):
        tokenIds[idx] = getWordIdx(tokens[idx], word2Idx)

        distance1 = idx - int(pos1)
        distance2 = idx - int(pos2)

        if distance1 in distanceMapping:
            positionValues1[idx] = distanceMapping[distance1]
        elif distance1 <= minDistance:
            positionValues1[idx] = distanceMapping['LowerMin']
        else:
            positionValues1[idx] = distanceMapping['GreaterMax']

        if distance2 in distanceMapping:
            positionValues2[idx] = distanceMapping[distance2]
        elif distance2 <= minDistance:
            positionValues2[idx] = distanceMapping['LowerMin']
        else:
            positionValues2[idx] = distanceMapping['GreaterMax']

    tokenMatrix.append(tokenIds)
    positionMatrix1.append(positionValues1)
    positionMatrix2.append(positionValues2)

    return [np.array(tokenMatrix, dtype='int32'),
           np.array(positionMatrix1, dtype='int32'),
           np.array(positionMatrix2, dtype='int32')]

################################################################################
########################## Prédiction de la relation ###########################
################################################################################

stcP, pos1P, pos2P = createMatricesSentence(sentence, pos1, pos2, word2Idx, 97)

if (args["verbose"]):
    print(stcP)
    print(pos1P)
    print(pos2P)

model = load_model('models/model1.h5')
pred = model.predict_classes([stcP,pos1P,pos2P],
                             verbose=args["verbose"])[0]

if (args["verbose"]):
    print("Valeur de la relation : "+ str(pred))

relation = [r for r in labelsMapping.keys() if (labelsMapping[r]==pred)][0]
relation = relation.split("(")[0]

if (pred%2==0):
    relation += "("+sentence.split(" ")[pos2]+", "+sentence.split(" ")[pos1]+")"
else:
    relation += "("+sentence.split(" ")[pos1]+", "+sentence.split(" ")[pos2]+")"

print("Relation trouvée : "+relation)

del model
import gc; gc.collect()


# pip install pygame

import pygame
import sys

FPS = 60
MAX_WIDTH = 600
MAX_HEIGHT = 400

pygame.init()       # pygame 초기화
clock = pygame.time.Clock()     # clock 설정
screen = pygame.display.set_mode((MAX_WIDTH, MAX_HEIGHT))       # 스크린 설정 600*400

class Player():     # Player Class 생성
    def __init__(self, x, y) :      # 객체 생성 시 초기화
        self.x = x
        self.y = y
        self.isJump = False
        self.jumpCount = 10

    def draw(self) :        # 파란색 네모 40*40 사이즈 생성
        return pygame.draw.rect(screen, (0, 0, 255), (self.x, self.y, 40, 40))

    def jump(self) :        # Player 점프 구현
        if self.isJump:
            if self.jumpCount >= -10 :
                neg = 1
                if self.jumpCount < 0 :
                    neg = -1
                self.y -= self.jumpCount**2 * 0.7 * neg
                self.jumpCount -= 1
            else :
                self.isJump = False
                self.jumpCount = 10

player = Player(50, MAX_HEIGHT - 40)        # player로 객체 생성

def main():
    while True:
        for event in pygame.event.get():        # pygame의 event 불러오기
            if event.type == pygame.QUIT:       # X 버튼을 누르면 종료
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    player.isJump = True        # spacebar를 누르면 player 점프

        clock.tick(FPS)     # 위에 설정된 FPS로 동작
        screen.fill((255, 255, 255))

        player_rect = player.draw()
        player.jump()

        print(player_rect)

        pygame.display.update()     # 적용된 함수들 업데이트

if __name__ == "__main__" :
    main()


"""
Part 2: This is the simplest version of viterbi that doesn't do anything special for unseen words
but it should do better than the baseline at words with multiple tags (because now you're using context
to predict the tag).
"""
# from typing import KeysView
import numpy as np
import math
def viterbi_1(train, test):
    '''
    input:  training data (list of sentences, with tags on the words). E.g.,  [[(word1, tag1), (word2, tag2)], [(word3, tag3), (word4, tag4)]]
        test data (list of sentences, no tags on the words). E.g.,  [[word1, word2], [word3, word4]]
    output: list of sentences, each sentence is a list of (word,tag) pairs.
        E.g., [[(word1, tag1), (word2, tag2)], [(word3, tag3), (word4, tag4)]]
    '''
    alphatag = .00001
    alphawords = .00001
    tagdic = {}
    tagwordict = {}
    # wordict = {}
    tagpairs = {}

    #getting tagpair counts
    for i in train:
        for b in range(1,len(i)):
            if(i[b-1][1] in tagpairs):
                tagpairs[i[b - 1][1]][i[b][1]] = tagpairs[i[b-1][1]].get(i[b][1], 0) + 1
            else:
                tagpairs[i[b - 1][1]] = {}
                tagpairs[i[b - 1][1]][i[b][1]] = 1
    for i in train:
        for b in i:
            # getting dict of words with tags
            # if b[0] not in wordict:
            #     wordict[b[0]] = {}
            #     wordict[b[0]][b[1]] = 1
            # else:
            #     wordict[b[0]][b[1]] = wordict[b[0]].get(b[1], 0) + 1

            #getting dic of tags MAY REMOVE LATER IF NOT USED
            tagdic[b[1]] = tagdic.get(b[1],0) + 1

            # getting dict of tags with words
            if b[1] not in tagwordict:
                tagwordict[b[1]] = {}
                tagwordict[b[1]][b[0]] = 1
            else:
                tagwordict[b[1]][b[0]] = tagwordict[b[1]].get(b[0], 0) + 1

    # turn tagpairs into log probabilities
    for key in tagpairs.keys():
        n = sum(tagpairs[key].values())
        v = len(tagpairs[key])
        for key2 in tagpairs[key].keys():
            count = tagpairs[key][key2]
            tagpairs[key][key2] =  math.log((alphatag + count)/(n + alphatag*(v + 1)))     #math.log(tagpairs[key][key2] / pairtot)
        tagpairs[key]['UNKNOWN'] = math.log(alphatag/(n + alphatag*(v + 1)))

    for key in tagwordict.keys():
        n = sum(tagwordict[key].values())
        v = len(tagwordict[key])
        for key2 in tagwordict[key].keys():
            count = tagwordict[key][key2]
            tagwordict[key][key2] =  math.log((alphawords + count)/(n + alphawords*(v + 1)))

        tagwordict[key]['UNKNOWN'] = math.log(alphawords/(n + alphawords*(v + 1)))

    tagmap = [i for i in tagdic.keys()]
    numTags = len(tagdic)
    del tagdic

    toReturn = []
    for sent in test:

        trellprob = np.zeros((len(sent),numTags))
        trellback = np.zeros((len(sent),numTags))

        for (idx,word) in enumerate(sent):
            if idx == 0: #start edge case
                for i in range(numTags):
                    trellprob[idx][i] += tagwordict[tagmap[i]][word] if word in tagwordict[tagmap[i]] else tagwordict[tagmap[i]]['UNKNOWN']
            else:
                for i in range(numTags):
                    toMax = np.zeros(numTags)
                    for b in range(numTags):
                        if(tagmap[b] == 'END'):
                             toMax[b] = -100000
                             continue
                        emission = tagwordict[tagmap[i]][word] if word in tagwordict[tagmap[i]] else tagwordict[tagmap[i]]['UNKNOWN']
                        transfer = tagpairs[tagmap[b]][tagmap[i]] if tagmap[i] in tagpairs[tagmap[b]] else tagpairs[tagmap[b]]['UNKNOWN']   #SUS LINE?
                        previous = trellprob[idx - 1][b]
                        toMax[b] = previous + transfer + emission
                    trellback[idx][i] = np.argmax(toMax)
                    trellprob[idx][i] = np.amax(toMax)

        reverseidx = []
        # print(trellprob)
        reverseidx.append(int(np.argmax(trellprob[len(sent) - 1][:])))
        for idx in range(len(sent) - 1, 0, -1):
            # temp = int(reverseidx[-1])
            reverseidx.append(int(trellback[idx][reverseidx[-1]]))

        toPush = [tagmap[reverseidx[b]] for b in range(len(reverseidx) - 1, -1, -1)]
        # toPush = toPush[::-1]
        for i in range(len(sent)):
            toPush[i] = tuple((sent[i], toPush[i]))

        toReturn.append(toPush)
    return toReturn


"""
API Router
"""
from fastapi import APIRouter

from app.apis.api_v1.book import create_book_router
from app.services.book_service import BookService

def v1_router(book_service: BookService) -> APIRouter:
    api_router = APIRouter()
    api_router.include_router(
        create_book_router(book_service),
        prefix="/books",
        tags=["books"],
    )
    return api_router


from dataclasses import dataclass
from datetime import datetime

def to_cypher_value(value) -> str:
    """Converts value to a valid openCypher type"""
    value_type = type(value)

    if value_type == str and value.lower() == "null":
        return value

    if value_type in [int, float, bool]:
        return str(value)

    if value_type in [list, set, tuple]:
        return f"[{', '.join(map(to_cypher_value, value))}]"

    if value_type == dict:
        lines = ", ".join(f"{k}: {to_cypher_value(v)}" for k, v in value.items())
        return f"{{{lines}}}"

    if value is None:
        return "null"

    if value.lower() in ["true", "false"]:
        return value

    return f"'{value}'"

@dataclass
class Track:
    LABEL = "Track"
    artist_name: str
    track_uri: str
    artist_uri: str
    track_name: str
    album_uri: str
    duration_ms: int
    album_name: str

    @staticmethod
    def create_from_data(data):
        return Track(
            data.properties["artist_name"],
            data.properties["track_uri"],
            data.properties["artist_uri"],
            data.properties["track_name"],
            data.properties["album_uri"],
            data.properties["duration_ms"],
            data.properties["album_name"],
        )

    def to_cypher(self):
        return (
            f"artist_name: {self.artist_name}, track_uri: {self.track_uri}, artist_uri:"
            f" {self.artist_uri}, track_name: {self.track_name}, album_uri: {self.album_uri},"
            f" duration_ms: {to_cypher_value(self.duration_ms)}, album_name: {self.album_name}"
        )

    @staticmethod
    def create_from_dict(data):
        return Track(
            data["artist_name"],
            data["track_uri"],
            data["artist_uri"],
            data["track_name"],
            data["album_uri"],
            data["duration_ms"],
            data["album_name"],
        )

@dataclass
class Playlist:
    LABEL = "Playlist"

    name: str
    collaborative: bool = False
    pid: int = 0
    modified_at: datetime = ""
    num_albums: int = 0
    num_tracks: int = 0
    num_followers: int = 0
    num_edits: int = 0
    duration_ms: int = 0
    num_artists: int = 0

    @staticmethod
    def create_from_data(data):
        return Playlist(
            data.properties["name"],
            data.properties["collaborative"],
            data.properties["pid"],
            data.properties["modified_at"],
            data.properties["num_albums"],
            data.properties["num_tracks"],
            data.properties["num_followers"],
            data.properties["num_edits"],
            data.properties["duration_ms"],
            data.properties["num_artists"],
        )

    @staticmethod
    def create_from_dict(data):
        return Playlist(
            data["name"],
            data["collaborative"],
            data["pid"],
            data["modified_at"],
            data["num_albums"],
            data["num_tracks"],
            data["num_followers"],
            data["num_edits"],
            data["duration_ms"],
            data["num_artists"],
        )

    def to_cypher(self):
        return (
            f"name: {self.name}, collaborative: {to_cypher_value(self.collaborative)},"
            f" pid: {to_cypher_value(self.pid)}, modified_at:"
            f" {to_cypher_value(self.modified_at)}, num_albums:"
            f" {to_cypher_value(self.num_albums)}, num_tracks:"
            f" {to_cypher_value(self.num_tracks)}, num_followers:"
            f" {to_cypher_value(self.num_followers)}, num_edits:"
            f" {to_cypher_value(self.num_edits)}, duration_ms:"
            f" {to_cypher_value(self.duration_ms)}, num_artists:"
            f" {to_cypher_value(self.num_artists)}"
        )

    def to_map(self):
        return self.__dict__


import streamlit as st
import pandas as pd
from analyzer import TableAnalyzerFactory
import os
from datetime import datetime as dt

# autogluon(TODO : 将来的には別ファイルに切り出す。UIページをautogluonと依存させたくないため)
import autogluon as ag

# scikit-learn
from sklearn.model_selection import train_test_split

def main():
    # set default config
    # TODO : enable to read config from json files
    config = {
        "output_base_dir": os.path.join("script", "output")
    }
    params = {
        "hp_tune"   : True,
        "xgboost"   : {},
        "autogluon" : {
            "hyperparameters": {
                "time_limits"    : 2*60,
                "num_trials"     : 5,
                "search_strategy": "skopt",
                "NN": { # specifies non-default hyperparameter values for neural network models
                    'num_epochs'   : 10, # number of training epochs (controls training time of NN models)
                    'learning_rate': ag.space.Real(1e-4, 1e-2, default=5e-4, log=True), # learning rate used in training (real-valued hyperparameter searched on log-scale)
                    'activation'   : ag.space.Categorical('relu', 'softrelu', 'tanh'), # activation function used in NN (categorical hyperparameter, default = first entry)
                    'layers'       : ag.space.Categorical([100],[1000],[200,100],[300,200,100]),
                    'dropout_prob' : ag.space.Real(0.0, 0.5, default=0.1), # dropout probability (real-valued hyperparameter)
                },
                "GBM": { # specifies non-default hyperparameter values for lightGBM gradient boosted trees
                    'num_boost_round': 100, # number of boosting rounds (controls training time of GBM models)
                    'num_leaves'     : ag.space.Int(lower=26, upper=66, default=36), # number of leaves in trees (integer hyperparameter)
                }
            }
        }
    }

    # set common sidebar
    page       = st.sidebar.radio("move page", ["train", "inference", "kaggle"])
    model_type = st.sidebar.selectbox("select model type", ["autogluon", "xgboost"])
    if page == "train":
        render_train_page(model_type, config, params)
    elif page == "inference":
        render_infer_page(model_type, config)
    elif page == "kaggle":
        render_kaggle_page(model_type, config)
    else:
        st.write("error page")

def render_train_page(model_type, config, params):
    st.title("Train Page")

    uploaded_file = st.file_uploader("Choose a csv file", type="csv")
    if uploaded_file is not None:
        # read csv file and display columns
        df = pd.read_csv(uploaded_file)

        # display sample data
        st.write("display sample data")
        st.write(df.head(10))

        # select columns
        label = st.radio("select label column", df.columns, index=0)
        params["label"] = label
        if st.button("Start Train"):
            analyzer = TableAnalyzerFactory.get_instance(model_type=model_type, config=config)
            start_train(analyzer, df, params)
            st.success("Model Training is done!")
        else:
            print("please push button")

def start_train(analyzer, df, params):
    train_data, val_data = train_test_split(df, test_size=0.2)
    analyzer.train(train_data=train_data, val_data=val_data, params=params)

def render_infer_page(model_type, config):
    st.title("Inference Page")

    uploaded_file = st.file_uploader("Choose a csv file", type="csv")
    if uploaded_file is not None:
        # read csv file and display columns
        df = pd.read_csv(uploaded_file)

        # display sample data
        st.write("display sample data")
        st.write(df.head(10))

        # get model list from predict result directory
        analyzer             = TableAnalyzerFactory.get_instance(model_type=model_type, config=config)
        train_folder         = analyzer.get_output_folders()[0]
        model_folder_name    = st.radio("select model", os.listdir(train_folder), index=0)
        config["model_path"] = os.path.join(train_folder, model_folder_name)
        if st.button("Start Predict"):
            analyzer.load(path=config["model_path"])
            result = analyzer.predict(data=df)

            # display result
            st.write("display result")
            label = analyzer.get_label_name()
            df[label] = result
            st.write(df)

            # save result
            predict_folder = analyzer.get_output_folders()[1]
            os.makedirs(predict_folder, exist_ok=True)
            csv_path = os.path.join(predict_folder, dt.now().strftime('%Y%m%d%H%M%S') + "_result.csv")
            df.to_csv(csv_path)
            st.success("Inference is done!")

def render_kaggle_page(model_type, config):
    st.title("Kaggle Page")

    from kaggle_wrapper import KaggleWrapper

    uploaded_file = st.file_uploader("Choose a result csv file", type="csv")
    if uploaded_file is not None:
        # read csv file and display columns
        df = pd.read_csv(uploaded_file)

        # display sample data
        st.write("display sample data")
        st.write(df.head(10))

        # select exported columns
        export_columns = st.multiselect("select the columns of export", df.columns)
        competition_id = st.text_input("Input competition_id of Kaggle")
        description    = st.text_input("Input competition description")
        if len(competition_id) > 0 and len(description) > 0 and st.button("Export result to Kaggle page"):
            # save csv file
            df = df.loc[:, export_columns].set_index(export_columns[0])
            #csv_dir  = os.path.dirname(uploaded_file)
            csv_path = os.path.join("submit.csv")
            df.to_csv(csv_path)

            # submit csv
            wrapper = KaggleWrapper()
            wrapper.submit_result(csv_path=csv_path, competition_id=competition_id, description=description)
            st.success("Success to submit result!")

            # delete submit file(TODO : 将来的にfile_uploaderからpathが変えるようになったら、submitファイルは残すようにする)
            os.remove(csv_path)

if __name__ == "__main__":
    main()


from django.db import models
from decouple import config

# Create your models here.

MEMBER_TYPE = (
        ('DIR', 'Director, NIT Raipur'),
        ('HCD', 'Head of Career development'),
        ('FCT','Faculty Incharge'),
        ('MNG', 'Manager'),
        ('HCO', 'Head Co-ordinator'),
        ('OCO', 'Overall Co-ordinator'),
        ('EXC', 'Executive'),
    )

class Member(models.Model):
    domain_choices = [
        ['tech']*2,
        ['spons']*2,
        ['pr']*2,
        ['doc']*2,
        ['design']*2,
        ['none']*2
    ]

    name = models.CharField(max_length=100)
    profile_url = models.URLField(blank=True, null=True)
    image = models.ImageField(upload_to='static/uploads/team', null=True, blank = True)
    member_type = models.CharField(max_length=3, choices= MEMBER_TYPE, default='EXEC')
    year = models.IntegerField(default=2019)
    domain = models.CharField(max_length=100, choices=domain_choices, default='pr')
    linkedin = models.URLField(blank=True, null=True)
    facebook = models.URLField(blank=True, null=True)

    @property
    def image_url(self):
        return config('HOST')+self.image.url

    def __str__(self):
        return self.member_type + '-' + self.name


#!/usr/bin/env python3

#
#
#	This was part of a process to migrate from Windows vSphere to VCSA in
#	a piece-by-piece manner.   This can be used to recreate the directory
#	structure on one vCenter to another
#
#	Uses a config file created by get-all-objects.py (or otherwise similar)
#

import sys
import os

#print(os.path.dirname(os.path.realpath(__file__)) + '/../lib/python3')
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + '/../lib/python3')

import pyVmomi
import vmwareutils
import loginutils

#
#----------------------------------------------------------------------
#

def check_folder(folder):
	obj = vmwareutils.get_named_obj(folder)

	if (obj is None):
		(base,ending) = folder.rsplit("/",1)

		check_folder(base)

		print("Creating",ending,"in",base)

		obj =  vmwareutils.get_named_obj(base)
		newobj = obj.CreateFolder(ending)

		vmwareutils.set_one_full_name(newobj,folder)

#
#----------------------------------------------------------------------
#

def main():
	really_do_it = False

	args = sys.argv[1:]   # Ignore the name

	if (len(args) != 2):
		print("Usage: <server> <file>")
		sys.exit(1)

	i = 0
	server = args[i]
	i += 1

	infile = open(args[i])
	i += 1

	context = loginutils.netlablogin(server)
	vmwareutils.get_all_roles(context)

	vmwareutils.get_all_objects(context)

	for line in infile:
		if (line.startswith("#")):
			continue

		line = line.rstrip()

		(shortname,fullname,type) = line.split("\t")

		if (type == "vim.Folder"):
			check_folder(fullname)

	sambautils.disable_user(ADMIN_SVC_ACCT)

main()


from cgitb import grey, text
from itertools import count
from tokenize import Number
import cv2
import imutils
import pytesseract

pytesseract.pytesseract.tesseract_cmd=r"C:\Program Files\Tesseract-OCR\tesseract.exe"

image = cv2.imread('car2.jpg')

image = imutils.resize(image, width=400)

cv2.imshow("original Image",image)
cv2.waitKey(0)

gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow("Gray Scale Image",gray)
cv2.waitKey(0)

gray = cv2.bilateralFilter(gray,11,17,17)
cv2.imshow("Smoother Image",gray)
cv2.waitKey(0)

edged = cv2.Canny(gray,170,200)
cv2.imshow("Canny edge",edged)
cv2.waitKey(0)

cnts, new = cv2.findContours(edged.copy(), cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

image1 = image.copy()
cv2.drawContours(image1 , cnts,-1,(0,255,0),3)
cv2.imshow("Canny after contouring", image1)
cv2.waitKey(0)

cnts = sorted(cnts, key=cv2.contourArea, reverse= True)[:30]
NumberPlateCount = None

image2 = image.copy()
cv2.drawContours(image2, cnts,-1,(0,255,0),3)
cv2.waitKey(0)

count = 0
name =1
for i in cnts:
    perimeter =  cv2.arcLength(i, True)
    approx = cv2.approxPolyDP(i,0.02*perimeter,True)

    if(len(approx)==4):
        NumberPlateCount= approx
        x,y,w,h = cv2.boundingRect(i)
        crp_img = image[y:y*h, x:x*w]

        cv2.imwrite(str(name)+ '.png',crp_img)
        name += 1
        break

cv2.drawContours(image,[NumberPlateCount],-1,(0,255,0),3)
cv2.imshow("Final Image",image)
cv2.waitKey(0)

crop_img_loc ='1.png'
cv2.imshow("Cropped Image",cv2.imread(crop_img_loc))

text = pytesseract.image_to_string(crop_img_loc,lang='eng')
print("Number is :",text)
cv2.waitKey(0)