# validated: 2017-12-15 EN f9bece2ffbf7 edu/wpi/first/wpilibj/Counter.java
#----------------------------------------------------------------------------
# Copyright (c) FIRST 2008-2012. All Rights Reserved.
# Open Source Software - may be modified and shared by FRC teams. The code
# must be accompanied by the FIRST BSD license file in the root directory of
# the project.
#----------------------------------------------------------------------------

import hal
import weakref
from enum import IntEnum

from .interfaces.counterbase import CounterBase
from .interfaces.pidsource import PIDSource
from .analogtriggeroutput import AnalogTriggerOutput
from .digitalinput import DigitalInput
from .sensorbase import SensorBase
from ._impl.utils import match_arglist, HasAttribute

__all__ = ["Counter"]

def _freeCounter(counterObj):
    hal.setCounterUpdateWhenEmpty(counterObj._counter, True)

    counterObj.clearUpSource()
    counterObj.clearDownSource()

    hal.freeCounter(counterObj._counter)

    counterObj.upSource = None
    counterObj.downSource = None
    counterObj._counter = None

class Counter(SensorBase):
    """Counts the number of ticks on a :class:`.DigitalInput` channel.

    This is a general purpose class for counting repetitive events. It can return
    the number of counts, the period of the most recent cycle, and detect when
    the signal being counted has stopped by supplying a maximum cycle time.

    All counters will immediately start counting - :meth:`reset` them if you need
    them to be zeroed before use.

    .. not_implemented: initCounter
    """

    class Mode(IntEnum):
        """Mode determines how and what the counter counts"""

        #: two pulse mode
        kTwoPulse = 0

        #: semi period mode
        kSemiperiod = 1

        #: pulse length mode
        kPulseLength = 2

        #: external direction mode
        kExternalDirection = 3

    EncodingType = CounterBase.EncodingType
    PIDSourceType = PIDSource.PIDSourceType
    allocatedUpSource = False
    allocatedDownSource = False

    def __init__(self, *args, **kwargs):
        """Counter constructor.

        The counter will start counting immediately.

        Positional arguments may be either channel numbers, :class:`.DigitalSource`
        sources, or :class:`.AnalogTrigger` sources in the following order:

        A "source" is any valid single-argument input to :meth:`setUpSource` and :meth:`setDownSource`

        - (none)
        - upSource
        - upSource, down source
        - encodingType, up source, down source, inverted

        If the passed object has a
        `getPortHandleForRouting` function, it is assumed to be a DigitalSource.
        If the passed object has a `createOutput` function, it is assumed to
        be an AnalogTrigger.

        In addition, extra keyword parameters may be provided for mode, inverted,
        and encodingType.

        :param upSource: The source (channel num, DigitalInput, or AnalogTrigger)
            that should be used for up counting.
        :param downSource: The source (channel num, DigitalInput, or AnalogTrigger)
            that should be used for down counting or direction control.
        :param mode:
            How and what the counter counts (see :class:`.Mode`).  Defaults to
            `Mode.kTwoPulse` for zero or one source, and
            `Mode.kExternalDirection` for two sources.
        :param inverted:
            Flips the direction of counting.  Defaults to False if unspecified.
            Only used when two sources are specified.
        :param encodingType:
            Either k1X or k2X to indicate 1X or 2X decoding. 4X decoding
            is not supported by Counter; use `Encoder` instead.  Defaults
            to k1X if unspecified.  Only used when two sources are specified.
        :type encodingType: :class:`.Counter.EncodingType`
        """

        super().__init__()
        source_identifier = [int, HasAttribute("getPortHandleForRouting"), HasAttribute("createOutput")]

        argument_templates = [[],
                              [("upSource", source_identifier), ],
                              [("upSource", source_identifier), ("downSource", source_identifier)],
                              [("encodingType", None), ("upSource", source_identifier),
                               ("downSource", source_identifier), ("inverted", bool)], ]

        _, results = match_arglist('Counter.__init__',
                                   args, kwargs, argument_templates, allow_extra_kwargs=True)

        # extract arguments
        upSource = results.pop("upSource", None)
        downSource = results.pop("downSource", None)

        encodingType = results.pop("encodingType", None)
        inverted = results.pop("inverted", False)
        mode = results.pop("mode", None)

        if mode is None:
            #Get the mode
            if upSource is not None and downSource is not None:
                mode = self.Mode.kExternalDirection
            else:
                mode = self.Mode.kTwoPulse

        # save some variables
        self.distancePerPulse = 1.0 # distance of travel for each tick
        self.pidSource = self.PIDSourceType.kDisplacement

        # create counter
        self._counter, self.index = hal.initializeCounter(mode)
        self.__finalizer = \
            weakref.finalize(self, _freeCounter, self)

        self.setMaxPeriod(.5)

        hal.report(hal.UsageReporting.kResourceType_Counter, self.index, mode)
        self.setName("Counter", self.index)

        # Set sources
        if upSource is not None:
            self.setUpSource(upSource)
        else:
            self.upSource = None

        if downSource is not None:
            self.setDownSource(downSource)
        else:
            self.downSource = None

        # when given two sources, set edges
        if upSource is not None and downSource is not None:
            if encodingType == self.EncodingType.k1X:
                self.setUpSourceEdge(True, False)
                hal.setCounterAverageSize(self._counter, 1)
            else:
                self.setUpSourceEdge(True, True)
                hal.setCounterAverageSize(self._counter, 2)
            self.setDownSourceEdge(inverted, True)

    @property
    def counter(self):
        if not self.__finalizer.alive:
            raise ValueError("Cannot use counter after free() has been called")
        return self._counter

    def free(self):
        super().free()
        self.__finalizer()

    def getFPGAIndex(self):
        """
        :returns: The Counter's FPGA index.
        """
        return self.index

    def setUpSource(self, *args, **kwargs):
        """Set the up counting source for the counter.

        This function accepts either a digital channel index, a
        `DigitalSource`, or an `AnalogTrigger` as positional arguments:

        - source
        - channel
        - analogTrigger
        - analogTrigger, triggerType

        For positional arguments, if the passed object has a
        `getPortHandleForRouting` function, it is assumed to be a DigitalSource.
        If the passed object has a `createOutput` function, it is assumed to
        be an AnalogTrigger.

        Alternatively, sources and/or channels may be passed as keyword
        arguments.  The behavior of specifying both a source and a number
        for the same channel is undefined, as is passing both a positional
        and a keyword argument for the same channel.

        :param channel: the DIO channel to use as the up source. 0-9 are on-board, 10-25 are on the MXP
        :type channel: int
        :param source: The digital source to count
        :type source: DigitalInput
        :param analogTrigger:
            The analog trigger object that is used for the Up Source
        :type analogTrigger: AnalogTrigger
        :param triggerType:
            The analog trigger output that will trigger the counter.
            Defaults to kState if not specified.
        :type triggerType: AnalogTrigger.AnalogTriggerType
        """

        #TODO Both this and the java implementation should probably not allow setting a source if one is already set.

        argument_templates = [[("channel", int)],
                              [("source", HasAttribute("getPortHandleForRouting")), ],
                              [("analogTrigger", HasAttribute("createOutput"))],
                              [("analogTrigger", HasAttribute("createOutput")), ("triggerType", None)]]

        _, results = match_arglist('Counter.setUpSource',
                                   args, kwargs, argument_templates)

        # extract arguments
        source = results.pop("source", None)
        channel = results.pop("channel", None)
        analogTrigger = results.pop("analogTrigger", None)
        triggerType = results.pop("triggerType", AnalogTriggerOutput.AnalogTriggerType.kState)

        # If we don't have source, generate it from other arguments.
        if source is None:
            if channel is not None:
                source = DigitalInput(channel)
                self.allocatedUpSource = True
                self.addChild(source)
            elif analogTrigger is not None and triggerType is not None:
                source = analogTrigger.createOutput(triggerType)
            else:
                raise ValueError("No usable source.")

        # save and set
        self.upSource = source
        hal.setCounterUpSource(self.counter,
                               self.upSource.getPortHandleForRouting(),
                               self.upSource.getAnalogTriggerTypeForRouting())

    def setUpSourceEdge(self, risingEdge, fallingEdge):
        """Set the edge sensitivity on an up counting source. Set the up
        source to either detect rising edges or falling edges.

        :param risingEdge: True to count rising edge
        :type  risingEdge: bool
        :param fallingEdge: True to count falling edge
        :type  fallingEdge: bool
        """
        if self.upSource is None:
            raise ValueError("Up Source must be set before setting the edge")
        hal.setCounterUpSourceEdge(self.counter, risingEdge, fallingEdge)

    def clearUpSource(self):
        """Disable the up counting source to the counter."""
        if self.upSource is not None and self.allocatedUpSource:
            self.upSource.free()
            self.allocatedUpSource = False
        self.upSource = None
        hal.clearCounterUpSource(self._counter)

    def setDownSource(self, *args, **kwargs):
        """Set the down counting source for the counter.

        This function accepts either a digital channel index, a
        `DigitalSource`, or an `AnalogTrigger` as positional arguments:

        - source
        - channel
        - analogTrigger
        - analogTrigger, triggerType

        For positional arguments, if the passed object has a
        `getChannelForRouting` function, it is assumed to be a DigitalSource.
        If the passed object has a `createOutput` function, it is assumed to
        be an AnalogTrigger.

        Alternatively, sources and/or channels may be passed as keyword
        arguments.  The behavior of specifying both a source and a number
        for the same channel is undefined, as is passing both a positional
        and a keyword argument for the same channel.

        :param channel: the DIO channel to use as the down source. 0-9 are on-board, 10-25 are on the MXP
        :type channel: int
        :param source: The digital source to count
        :type source: DigitalInput
        :param analogTrigger:
            The analog trigger object that is used for the Up Source
        :type analogTrigger: AnalogTrigger
        :param triggerType:
            The analog trigger output that will trigger the counter.
            Defaults to kState if not specified.
        :type triggerType: AnalogTrigger.AnalogTriggerType
        """

        #TODO Both this and the java implementation should probably not allow setting a source if one is already set.

        argument_templates = [[("channel", int)],
                              [("source", HasAttribute("getPortHandleForRouting")), ],
                              [("analogTrigger", HasAttribute("createOutput")), ],
                              [("analogTrigger", HasAttribute("createOutput")), ("triggerType", None)]]

        _, results = match_arglist('Counter.setDownSource',
                                   args, kwargs, argument_templates)

        # extract arguments
        source = results.pop("source", None)
        channel = results.pop("channel", None)
        analogTrigger = results.pop("analogTrigger", None)
        triggerType = results.pop("triggerType", AnalogTriggerOutput.AnalogTriggerType.kState)

        # If we don't have source, generate it from other arguments.
        if source is None:
            if channel is not None:
                source = DigitalInput(channel)
                self.allocatedDownSource = True
                self.addChild(source)
            elif analogTrigger is not None and triggerType is not None:
                source = analogTrigger.createOutput(triggerType)
            else:
                raise ValueError("No usable source.")

        # save and set
        self.downSource = source
        hal.setCounterDownSource(self.counter,
                                 self.downSource.getPortHandleForRouting(),
                                 self.downSource.getAnalogTriggerTypeForRouting())

    def setDownSourceEdge(self, risingEdge, fallingEdge):
        """Set the edge sensitivity on an down counting source. Set the down
        source to either detect rising edges or falling edges.

        :param risingEdge: True to count rising edge
        :type  risingEdge: bool
        :param fallingEdge: True to count falling edge
        :type  fallingEdge: bool
        """
        if self.downSource is None:
            raise ValueError("Down Source must be set before setting the edge")

        hal.setCounterDownSourceEdge(self.counter, risingEdge, fallingEdge)

    def clearDownSource(self):
        """Disable the down counting source to the counter.
        """
        if self.downSource is not None and self.allocatedDownSource:
            self.downSource.free()
            self.allocatedDownSource = False
        self.downSource = None

        hal.clearCounterDownSource(self._counter)

    def setUpDownCounterMode(self):
        """Set standard up / down counting mode on this counter. Up and down
        counts are sourced independently from two inputs.
        """
        hal.setCounterUpDownMode(self.counter)

    def setExternalDirectionMode(self):
        """Set external direction mode on this counter. Counts are sourced on
        the Up counter input. The Down counter input represents the direction
        to count.
        """
        hal.setCounterExternalDirectionMode(self.counter)

    def setSemiPeriodMode(self, highSemiPeriod):
        """Set Semi-period mode on this counter. Counts up on both rising and
        falling edges.

        :param highSemiPeriod: True to count up on both rising and falling
        :type  highSemiPeriod: bool
        """
        hal.setCounterSemiPeriodMode(self.counter, highSemiPeriod)

    def setPulseLengthMode(self, threshold):
        """Configure the counter to count in up or down based on the length
        of the input pulse. This mode is most useful for direction sensitive
        gear tooth sensors.

        :param threshold: The pulse length beyond which the counter counts the
            opposite direction. Units are seconds.
        :type  threshold: float, int
        """
        hal.setCounterPulseLengthMode(self.counter, float(threshold))

    def get(self):
        """Read the current counter value. Read the value at this instant. It
        may still be running, so it reflects the current value. Next time it
        is read, it might have a different value.
        """
        return hal.getCounter(self.counter)

    def getDistance(self):
        """Read the current scaled counter value. Read the value at this
        instant, scaled by the distance per pulse (defaults to 1).

        :returns: Scaled value
        :rtype: float
        """
        return self.get() * self.distancePerPulse

    def reset(self):
        """Reset the Counter to zero. Set the counter value to zero. This
        doesn't effect the running state of the counter, just sets the
        current value to zero.
        """
        hal.resetCounter(self.counter)

    def setMaxPeriod(self, maxPeriod):
        """Set the maximum period where the device is still considered
        "moving".  Sets the maximum period where the device is considered
        moving. This value is used to determine the "stopped" state of the
        counter using the :func:`getStopped` method.

        :param maxPeriod: The maximum period where the counted device is
            considered moving in seconds.
        :type maxPeriod: float or int
        """
        hal.setCounterMaxPeriod(self.counter, float(maxPeriod))

    def setUpdateWhenEmpty(self, enabled):
        """Select whether you want to continue updating the event timer
        output when there are no samples captured. The output of the event
        timer has a buffer of periods that are averaged and posted to a
        register on the FPGA. When the timer detects that the event source
        has stopped (based on the MaxPeriod) the buffer of samples to be
        averaged is emptied. If you enable update when empty, you will be
        notified of the stopped source and the event time will report 0
        samples. If you disable update when empty, the most recent average
        will remain on the output until a new sample is acquired. You will
        never see 0 samples output (except when there have been no events
        since an FPGA reset) and you will likely not see the stopped bit
        become true (since it is updated at the end of an average and
        there are no samples to average).

        :param enabled: True to continue updating
        :type  enabled: bool
        """
        hal.setCounterUpdateWhenEmpty(self.counter, enabled)

    def getStopped(self):
        """Determine if the clock is stopped. Determine if the clocked input
        is stopped based on the MaxPeriod value set using the
        :func:`setMaxPeriod` method.  If the clock exceeds the MaxPeriod,
        then the device (and counter) are assumed to be stopped and it
        returns True.

        :returns: Returns True if the most recent counter period exceeds the
            MaxPeriod value set by SetMaxPeriod.
        :rtype: bool
        """
        return hal.getCounterStopped(self.counter)

    def getDirection(self):
        """The last direction the counter value changed.

        :returns: The last direction the counter value changed.
        :rtype: bool
        """
        return hal.getCounterDirection(self.counter)

    def setReverseDirection(self, reverseDirection):
        """Set the Counter to return reversed sensing on the direction. This
        allows counters to change the direction they are counting in the case
        of 1X and 2X quadrature encoding only. Any other counter mode isn't
        supported.

        :param reverseDirection: True if the value counted should be negated.
        :type  reverseDirection: bool
        """
        hal.setCounterReverseDirection(self.counter, reverseDirection)

    def getPeriod(self):
        """Get the Period of the most recent count. Returns the time interval
        of the most recent count. This can be used for velocity calculations
        to determine shaft speed.

        :returns: The period of the last two pulses in units of seconds.
        :rtype: float
        """
        return hal.getCounterPeriod(self.counter)

    def getRate(self):
        """Get the current rate of the Counter. Read the current rate of the
        counter accounting for the distance per pulse value. The default
        value for distance per pulse (1) yields units of pulses per second.

        :returns: The rate in units/sec
        :rtype: float
        """
        return self.distancePerPulse / self.getPeriod()

    def setSamplesToAverage(self, samplesToAverage):
        """Set the Samples to Average which specifies the number of samples
        of the timer to average when calculating the period. Perform averaging
        to account for mechanical imperfections or as oversampling to increase
        resolution.

        :param samplesToAverage: The number of samples to average from 1 to 127.
        :type  samplesToAverage: int
        """
        hal.setCounterSamplesToAverage(self.counter, samplesToAverage)

    def getSamplesToAverage(self):
        """Get the Samples to Average which specifies the number of samples
        of the timer to average when calculating the period. Perform averaging
        to account for mechanical imperfections or as oversampling to increase
        resolution.

        :returns: The number of samples being averaged (from 1 to 127)
        :rtype: int
        """
        return hal.getCounterSamplesToAverage(self.counter)

    def setDistancePerPulse(self, distancePerPulse):
        """Set the distance per pulse for this counter. This sets the
        multiplier used to determine the distance driven based on the count
        value from the encoder. Set this value based on the Pulses per
        Revolution and factor in any gearing reductions. This distance can be
        in any units you like, linear or angular.

        :param distancePerPulse:
            The scale factor that will be used to convert pulses to useful
            units.
        :type  distancePerPulse: float
        """
        self.distancePerPulse = distancePerPulse

    def setPIDSourceType(self, pidSource):
        """Set which parameter of the encoder you are using as a process
        control variable. The counter class supports the rate and distance
        parameters.

        :param pidSource: An enum to select the parameter.
        :type  pidSource: :class:`Counter.PIDSourceType`
        """
        if pidSource not in (self.PIDSourceType.kDisplacement,
                             self.PIDSourceType.kRate):
            raise ValueError("Invalid pidSource argument '%s'" % pidSource)
        self.pidSource = pidSource

    def getPIDSourceType(self):
        return self.pidSource

    def pidGet(self):
        if self.pidSource == self.PIDSourceType.kDisplacement:
            return self.getDistance()
        elif self.pidSource == self.PIDSourceType.kRate:
            return self.getRate()
        else:
            return 0.0

    def initSendable(self, builder):
        builder.setSmartDashboardType("Counter")
        builder.addDoubleProperty("Value", self.get, None)


global sum_ofAllLuckyNumbers
sum_ofAllLuckyNumbers = 0

class Person:
    name = "John"
    lastname = "Doe"
    age = 35
    gender = "male"
    lucky_numbers = [ 7, 11, 13, 17]

class Person_2:
    name = "Jane"
    lastname = "Doe"
    age = 38
    gender = "female"
    lucky_numbers = [ 2, 4, 6, 8]

class Family:
    lastname = "Doe"
    members = [Person, Person_2]       #Array of objects, don't forget to add Jimmy

# STEP 1 Change the fourth lucky number of John Doe to 33
# Your code here
del Person.lucky_numbers[-1]
Person.lucky_numbers.append(33)
print (Person.lucky_numbers)

# STEP 2 Create Little Jimmy's object and then add it to the family object
# Your code here
class Person_3:
    name = "Jimmy"
    lastname = "Doe"
    age = 13
    lucky_numbers = [1,2,3,4]

Family.members.append(Person_3)

def add_allFamilyLuckyNumbers(an_array):
    sum_ofAllLuckyNumbers = 0 # sum_ofAllLuckyNumbers is a number, the sum of all lucky numbers.

    # STEP 3 Loop through all the family members to get all the lucky numbers
    # Your code here

    #### COLBY I AM stuck here!!!
    # cannot get any variation of sum(array) to work?

    sum_ofAllLuckyNumbers = array_sum1() + array_sum2() + array_sum3()
    sum = 0

    return sum_ofAllLuckyNumbers

# STEP 4 Print the sum of all the lucky numbers of the Doe's family
# Your code here

print(sum_ofAllLuckyNumbers)


from pathlib import Path
from typing import Any, Dict

import tensorflow as tf

from yeahml.build.build_layers import build_hidden_block
from yeahml.build.layers.config import NOTPRESENT
from yeahml.information.write_info import write_build_information

# from yeahml.build.get_components import get_logits_and_preds
from yeahml.log.yf_logging import config_logger

# Helper to make the output "consistent"
def reset_graph_deterministic(seed: int = 42) -> None:
    # logger = logging.getLogger("build_logger")
    # logger.info("reset_graph_deterministic")
    # there is no option for deterministic behavior yet...
    # > tf issue https://github.com/tensorflow/tensorflow/issues/18096
    # os.environ["TF_CUDNN_USE_AUTOTUNE"] = "0"
    tf.random.set_seed(seed)
    tf.keras.backend.clear_session()
    # np.random.seed(seed)

def reset_graph(seed: int = 42) -> None:
    # logger = logging.getLogger("build_logger")
    # logger.info("reset_graph")
    # tf.reset_default_graph()
    tf.random.set_seed(seed)
    tf.keras.backend.clear_session()

def _configure_input(cur_name, cur_config):

    # TODO: this section should be redone to match the layer API. but for now
    # I'm going to continue on with this minimal approach
    dtype = cur_config["dtype"]
    shape = cur_config["shape"]
    if cur_config["startpoint"]:
        out = tf.keras.layers.Input(shape=shape, dtype=dtype, name=cur_name)
    else:
        # all data layers should be a startpoint
        raise ValueError(f"current data layer config:{cur_config} is not a startpoint")

    return out

def _configure_layer(cur_name, cur_config):

    # 'layer_base', 'options', 'layer_in_name'
    layer_base = cur_config["layer_base"]

    # default layer function
    layer_fn = layer_base["func"]

    # assemble layer with user values (or default if not specified)
    # another way to do this could be just overwrite the values the user
    # specifies, but I want the ability to set defaults for each layer
    # eventually (in case we would want to change them)
    layer_args = layer_base["func_args"]
    layer_defaults = layer_base["func_defaults"]
    user_values = cur_config["options"]["user_vals"]

    param_dict = {}
    for i, param_name in enumerate(layer_args):
        if user_values:
            user_val = user_values[i]
        else:
            # TODO: this logic will need to be rethought, since it's possible
            # that a user argument could be `None` (I think?). I think a
            # potential solution would be to use a custom class sentinel value
            user_val = None

        # NOTE: `if user_val`: does not work because `user_val` could be False
        # TODO: this function will need to be tested
        if user_val is not None:
            param_dict[param_name] = user_val
        else:
            def_val = layer_defaults[i]
            if isinstance(def_val, NOTPRESENT):
                raise ValueError(
                    f"param {param_name} for layer {cur_name} not specified, but is required"
                )
            else:
                param_dict[param_name] = def_val

                # overwrite name with layer name if not exist
                if param_name == "name":
                    if not def_val:
                        param_dict[param_name] = cur_name
    configured_layer = layer_fn(**param_dict)

    return configured_layer

###############################################

def _is_tensor_or_list_of_tensors(obj):
    if isinstance(obj, tf.Tensor):
        return True
    elif isinstance(obj, list):
        for v in obj:
            if isinstance(v, tf.Tensor):
                pass
            else:
                return False
        return True
    else:
        raise ValueError(f"prev_out is neither a tensor or list. is type: {type(obj)}")

def _build_branch_from_pure_node_list(branch_seq, built_nodes):
    prev_out = None
    for sub_seq in branch_seq:
        tensors = []
        if isinstance(sub_seq, str):
            sub_seq = [sub_seq]
        elif isinstance(sub_seq, TupleOut):
            sub_seq = sub_seq.vals
        for node_name in sub_seq:
            try:
                cur_built_node = built_nodes[node_name]
            except KeyError:
                # TODO: this message will have to be expanded for huge graphs
                raise KeyError(
                    f"node ({node_name}) not found in built nodes {built_nodes.keys()}"
                )

            # get output of node
            if isinstance(cur_built_node["out"], tf.Tensor):
                # output already exists
                out = cur_built_node["out"]
            else:
                # output does not exist (func hasn't been called), get prev_out
                # to use as input
                if _is_tensor_or_list_of_tensors(prev_out):
                    try:
                        cur_func = cur_built_node["func"]
                    except KeyError:
                        raise KeyError(
                            f"node ({node_name}) function has not been built yet"
                        )

                    out = cur_func(prev_out)
                    cur_built_node["out"] = out
                else:
                    raise ValueError(
                        f"node ({node_name}) does not have an output yet and there is not previous out to use as an input"
                    )
            tensors.append(out)
        if len(tensors) == 1:
            tensors = tensors[0]
        prev_out = tensors

def _unpack_and_build_tuple(tuple_seq, built_nodes):

    # ((2, [[((2, [['n_a', ...], ['n_a', ...]]), 'ct_1'), 'ct_1', 'out'], ['n_a', 'd_1', ...]]), 'c3')
    branch_tuple = tuple_seq[0]
    num_branches = branch_tuple[0]
    branch_seqs = branch_tuple[1]
    name = tuple_seq[1]
    outer_seq_to_build = TupleOut()

    for branch_seq in branch_seqs:
        if isinstance(branch_seq, tuple):
            final_node = _unpack_and_build_tuple(branch_seq, built_nodes)
            outer_seq_to_build.vals.append(final_node)
        else:
            out_seq = _build_sequence(branch_seq, built_nodes)
            _build_sequence(out_seq, built_nodes)
            outer_seq_to_build.vals.append(out_seq[-1])

    return outer_seq_to_build

def _is_pure_node_list(seq):
    # a node list may be a list of strings or a list of strings with a list of
    # strings
    for v in seq:
        if isinstance(v, str):
            pass
        elif isinstance(v, TupleOut):
            pass
        else:
            return False
    return True

class TupleOut:
    def __init__(self, vals=None):
        if vals:
            self.vals = vals
        else:
            self.vals = []

    def __str__(self):
        return str(self.__class__) + f" @ {hex(id(self))}" + ": " + str(self.__dict__)

    def __call__(self):
        return self.vals

def _build_sequence(seq_info, built_nodes):

    outer_seq_to_build = []
    if _is_pure_node_list(seq_info):
        _build_branch_from_pure_node_list(seq_info, built_nodes)
        outer_seq_to_build.append(seq_info[-1])
    else:
        # may contain sublists or tuples
        for sub_seq in seq_info:
            if isinstance(sub_seq, str):
                outer_seq_to_build.append(sub_seq)
            elif isinstance(sub_seq, TupleOut):
                outer_seq_to_build.append(sub_seq)
            elif _is_pure_node_list(sub_seq):
                _build_branch_from_pure_node_list(sub_seq, built_nodes)
                outer_seq_to_build.append(sub_seq)
            else:
                if isinstance(sub_seq, list):
                    outer_seq = _build_sequence(sub_seq, built_nodes)
                    _build_sequence(outer_seq, built_nodes)
                    if not outer_seq:
                        outer_seq_to_build.append(sub_seq[-1])
                elif isinstance(sub_seq, tuple):
                    outer_seq = _unpack_and_build_tuple(sub_seq, built_nodes)
                    outer_seq_to_build.append(outer_seq)

    return outer_seq_to_build

def build_model(config_dict: Dict[str, Dict[str, Any]]) -> Any:

    # unpack configuration
    model_cdict: Dict[str, Any] = config_dict["model"]
    meta_cdict: Dict[str, Any] = config_dict["meta"]
    log_cdict: Dict[str, Any] = config_dict["logging"]
    data_cdict: Dict[str, Any] = config_dict["data"]
    static_cdict: Dict[str, Any] = config_dict["static"]
    subgraphs_cdict: Dict[str, Any] = config_dict["subgraphs"]
    model_io_cdict: Dict[str, Any] = config_dict["model_io"]

    full_exp_path = (
        Path(meta_cdict["yeahml_dir"])
        .joinpath(meta_cdict["data_name"])
        .joinpath(meta_cdict["experiment_name"])
    )
    logger = config_logger(full_exp_path, log_cdict, "build")
    logger.info("-> START building graph")

    try:
        reset_graph_deterministic(meta_cdict["seed"])
    except KeyError:
        reset_graph()

    full_exp_path = (
        Path(meta_cdict["yeahml_dir"])
        .joinpath(meta_cdict["data_name"])
        .joinpath(meta_cdict["experiment_name"])
    )
    g_logger = config_logger(full_exp_path, log_cdict, "graph")

    # configure/build all layers and save in lookup table
    built_nodes = {}
    for name, node in static_cdict.items():
        if node.config_location == "model":
            blueprint = model_cdict["layers"][node.name]
        elif node.config_location == "data":
            blueprint = data_cdict["in"][node.name]
        else:
            raise ValueError(f"layer {name} can't be found in {node.config_location}")

        if node.startpoint:
            if node.label:
                pass
            else:
                func = None
                out = _configure_input(name, blueprint)
        else:
            func = _configure_layer(name, blueprint)
            out = None

        # TODO: this is a quick fix. the issue is that a node that is a label,
        # does not need to be built as a layer in the graph -- it is only used
        # as a target during training and therefore does not need to be included
        # here
        if not node.label:
            built_nodes[name] = {"out": out, "func": func}

    # connect the subgraphs
    for end_name, seq_dict in subgraphs_cdict.items():

        seq_info = seq_dict["sequence"]
        out_seq = _build_sequence(seq_info, built_nodes)
        if out_seq:
            _build_branch_from_pure_node_list(out_seq, built_nodes)

    model_input_tensors = []
    for name in model_io_cdict["inputs"]:
        try:
            node_d = built_nodes[name]
        except KeyError:
            raise KeyError(f"{name} not found in built nodes when creating inputs")

        try:
            out = node_d["out"]
        except KeyError:
            raise KeyError(
                f"out was not created for {name} when creating tensor inputs"
            )
        model_input_tensors.append(out)
    if not model_input_tensors:
        raise ValueError(f"not model inputs are available")

    model_output_tensors = []
    for name in model_io_cdict["outputs"]:
        try:
            node_d = built_nodes[name]
        except KeyError:
            raise KeyError(f"{name} not found in built nodes when creating outputs")

        try:
            out = node_d["out"]
        except KeyError:
            raise KeyError(
                f"out was not created for {name} when creating tensor outputs"
            )
        model_output_tensors.append(out)
    if not model_output_tensors:
        raise ValueError(f"not model outputs are available")

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

    # TODO: inputs may be more complex than an ordered list
    # TODO: outputs could be a list
    # TODO: right now it is assumed that the last layer defined in the config is the
    # output layer -- this may not be true. named outputs would be better.
    model = tf.keras.Model(inputs=model_input_tensors, outputs=model_output_tensors)

    # write meta.json including model hash
    if write_build_information(model_cdict, meta_cdict):
        logger.info("information json file created")

    return model


'''
Convert images to numpy array, stack with labels.
Recursively search directory tree to find images to convert.
Create output directory tree as required.
'''

import pandas as pd
import numpy as np
from PIL import Image
from convobot.util.TreeUtil import TreeUtil
from convobot.util.FilenameManager import FilenameManager
from convobot.imageprocessor.ImageCounter import ImageCounter
import os

class ImageToNumpy(object):
    def __init__(self, src_root, dst_root, grayscale, size):
        '''
        Args:
            src_root: Source root directory
            dst_root: Target root directory.   This will always be created.
            resize: tuple of the new x and y size.
        '''
        self.tree_util = TreeUtil(src_root, dst_root)

        converter = ImageCounter(src_root, src_root)
        converter.process()
        img_cnt = converter.get_count()

        self._size = size
        self._grayscale = grayscale

        self._color_layers = 1
        if not self._grayscale:
            self._color_layers = 3

        self._img = np.zeros([img_cnt, size[0]*size[1]*self._color_layers], dtype=np.uint8)
        self._label = np.zeros([img_cnt, 3], dtype=np.float32)
        self._idx = 0
        self._filename_manager = FilenameManager()

    def process(self):
        '''
        Get image, convert to numpy array, store in list.
        '''
        def loader(src_path, dest_path, filename):
            img = Image.open(os.path.join(src_path, filename))
            img_np = np.array(img)

            img_np = img_np.reshape(self._size[0]*self._size[1]*self._color_layers,)
            self._img[self._idx] = img_np.tolist()

            theta, radius, alpha = self._filename_manager.filename_to_labels(filename)
            label = [theta, radius, alpha]

            for i in range(len(label)):
                self._label[self._idx][i] = label[i]

            self._idx += 1
            print('Storing: {}, {}'.format(os.path.join(src_path, filename),
                            os.path.join(dest_path, filename)))

        self.tree_util.apply_files(loader, '*.png')

    def get_data(self):
        if self._grayscale:
            return self._label, self._img.reshape(len(self._img), self._size[0], self._size[1])
        else:
            return self._label, self._img.reshape(len(self._img), self._size[0], self._size[1], self._color_layers)


import os
import re
from setuptools import setup, find_packages

here = os.path.abspath(os.path.dirname(__file__))
REQUIREMENTS = open(os.path.join(here, 'requirements.txt')).readlines()

compiled = re.compile('([^=><]*).*')

def parse_req(req):
    return compiled.search(req).group(1).strip()

requires = [_f for _f in map(parse_req, REQUIREMENTS) if _f]

setup(name='channelstream',
      version='0.6.1',
      description='Websocket server supporting channels/users communication',
      classifiers=[
          'Intended Audience :: Developers'
      ],
      author='Marcin Lulek',
      author_email='info@webreactor.eu',
      license='BSD',
      zip_safe=True,
      packages=find_packages(),
      include_package_data=True,
      install_requires=requires,
      entry_points={
          'console_scripts': [
              'channelstream = channelstream.cli:cli_start',
          ],
      })


import glob, os

def has_numbers(inputString):
	return any(char.isdigit() for char in inputString)

os.chdir("/Users/Chrsitine/Downloads/US_Faculty_Bio_txt")

compiled_file_name = ""
compiled_file = None
for file_name in glob.glob("*.txt"):
	data_file = open(file_name, "r")
	index = file_name.rfind("(")
	new_name = "/Users/Chrsitine/Downloads/compiled_files/" + file_name[:index] + ".csv"
	if new_name != compiled_file_name:
		compiled_file = open(new_name, "w")
		compiled_file_name = new_name
	lines = data_file.readlines()

	name = ""
	info = ""
	for line in lines:
		line = line.replace(";", ".")
		if line.strip() == "<pre>" or line.strip() == "ALPHABETICAL LIST OF TEACHERS" or line.strip() == "WITH BIOGRAPHICAL MATTER":
			if name != "":
				compiled_file.write(";".join([name, info, "\n"]).replace("- ", ""))
				name = ""
				info = ""
			continue
		splitted = line.strip().split(",")
		if len(splitted) > 2 and not has_numbers(splitted[0]) and splitted[0].isupper() and not has_numbers(splitted[1]) and splitted[1].isupper():
			if name != "":
				compiled_file.write(";".join([name, info, "\n"]).replace("- ", ""))
				name = ""
				info = ""
			if splitted[2] == "JR.":
				name = ",".join(splitted[0:3])
				info = " ".join([info] + splitted[3:])
			else:
				name = ",".join(splitted[0:2])
				info = " ".join([info] + splitted[2:])
		elif name != "" and line != "":
			info = " ".join([info, line.strip()])


import re
import sys

argv = sys.argv
if len(argv) != 3:
    print(argv)
    exit(1)

src_pid = argv[1]
dst_pid = argv[2]

src_maps_file = open("/proc/{}/maps".format(src_pid), 'r')
src_mem_file = open("/proc/{}/mem".format(src_pid), 'rb')
dst_maps_file = open("/proc/{}/maps".format(dst_pid), 'r')
dst_mem_file = open("/proc/{}/mem".format(dst_pid), 'wb')

for line in src_maps_file.readlines():
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
    # print(m.group(1), m.group(2), m.group(3))
    if line.find("vsyscall") != -1 or line.find("vdso") != -1 or line.find("vvar") != -1:
        continue
    if m.group(3) == 'r':
        start = int(m.group(1), 16)
        end = int(m.group(2), 16)
        # print(m.group(1), m.group(2))
        src_mem_file.seek(start)
        dst_mem_file.seek(start)
        chunk = src_mem_file.read(end - start)
        bytes_written = dst_mem_file.write(chunk)
        # print(end-start, bytes_written)

src_maps_file.close()
src_mem_file.close()
dst_maps_file.close()
dst_mem_file.close()


#!/usr/bin/python
import tkinter as tk
import tkinter.font as font
from enum import Enum

import RPi.GPIO as GPIO
from time import sleep
from threading import Thread

enaLF = 4
enaLB = 19
enaRF = 16
enaRB = 26

dirLF = 27
dirLB = 20
dirRF = 6
dirRB = 13

pulLF = 23
pulLB = 12
pulRF = 5
pulRB = 21

class Status(Enum):
    FORWARD = 1
    STOP = 2
    BACKWARD = 3

class Window(tk.Frame):

    def __init__(self, parent):
        super(Window, self).__init__(parent)
        self.direction = Status.STOP
        self.buttonFont = font.Font(family='Helvetica', size=12, weight='bold')
        self.forwardB = tk.Button(self, text="  Forward  ", font=self.buttonFont, command=self.forward)
        self.backwardB = tk.Button(self, text="  Backward  ", font=self.buttonFont, command=self.backward)
        self.stopB = tk.Button(self, text="   Stop   ", font=self.buttonFont, command=self.stop)
        self.fastB = tk.Button(self, text="   fast   ", font=self.buttonFont, command=self.set_fast, state=tk.DISABLED)
        self.slowB = tk.Button(self, text="   slow   ", font=self.buttonFont, command=self.set_slow)
        self.statusL = tk.Label(self, text="Status: ", font=self.buttonFont)
        self.speedL = tk.Label(self, text="Speed", font=self.buttonFont)

        self.statusL.grid(row=0, column=0, columnspan=2)
        self.forwardB.grid(row=1, column=0)
        self.stopB.grid(row=1, column=1)
        self.backwardB.grid(row=1, column=2)
        self.speedL.grid(row=2, column=0)
        self.fastB.grid(row=2, column=1)
        self.slowB.grid(row=2, column=2)

        self.fast = 0.0025
        self.slow = 0.0050
        self.speed = self.fast
        self.init()

    def init(self):
        # init GPIO pins
        GPIO.setmode(GPIO.BCM)

        GPIO.setup(enaLF, GPIO.OUT)
        GPIO.setup(dirLF, GPIO.OUT)
        GPIO.setup(pulLF, GPIO.OUT)
        GPIO.setup(enaLB, GPIO.OUT)
        GPIO.setup(dirLB, GPIO.OUT)
        GPIO.setup(pulLB, GPIO.OUT)
        GPIO.setup(enaRF, GPIO.OUT)
        GPIO.setup(dirRF, GPIO.OUT)
        GPIO.setup(pulRF, GPIO.OUT)
        GPIO.setup(enaRB, GPIO.OUT)
        GPIO.setup(dirRB, GPIO.OUT)
        GPIO.setup(pulRB, GPIO.OUT)

        GPIO.output(enaLF, GPIO.LOW)
        GPIO.output(dirLF, GPIO.LOW)
        GPIO.output(pulLF, GPIO.LOW)
        GPIO.output(enaLB, GPIO.LOW)
        GPIO.output(dirLB, GPIO.LOW)
        GPIO.output(pulLB, GPIO.LOW)
        GPIO.output(enaRF, GPIO.LOW)
        GPIO.output(dirRF, GPIO.LOW)
        GPIO.output(pulRF, GPIO.LOW)
        GPIO.output(enaRB, GPIO.LOW)
        GPIO.output(dirRB, GPIO.LOW)
        GPIO.output(pulRB, GPIO.LOW)

    def __del__(self):
        GPIO.cleanup()

    def set_fast(self):
        self.speed = self.fast
        self.fastB.configure(state=tk.DISABLED)
        self.slowB.configure(state=tk.NORMAL)

    def set_slow(self):
        self.speed = self.slow
        self.fastB.configure(state=tk.NORMAL)
        self.slowB.configure(state=tk.DISABLED)

    def forward(self):
        print("move forward")

    def backward(self):
        print("move backward")

    def stop(self):
        print("move stop")

class SideWalkMotor(Window):
    def __init__(self, parent):
        super(SideWalkMotor, self).__init__(parent)
        # self.thread = Thread(target=self.move)
        # self.thread.start()

    def forward(self):
        self.set_direction(Status.FORWARD)
        self.statusL.configure(text="Status: moving forward ")
        print("forward")
        thread = Thread(target=self.move).start()

    def backward(self):
        self.set_direction(Status.BACKWARD)
        self.statusL.configure(text="Status: moving backward")
        print("backward")
        thread = Thread(target=self.move).start()

    def stop(self):
        self.direction = Status.STOP
        self.statusL.configure(text="Status: stopped")
        print("stop")
        self.disableMotor()

    def move(self):
        while(self.direction != Status.STOP):
            GPIO.output(pulLF, GPIO.HIGH)
            GPIO.output(pulLB, GPIO.HIGH)
            GPIO.output(pulRF, GPIO.HIGH)
            GPIO.output(pulRB, GPIO.HIGH)
            sleep(self.speed)
            GPIO.output(pulLF, GPIO.LOW)
            GPIO.output(pulLB, GPIO.LOW)
            GPIO.output(pulRF, GPIO.LOW)
            GPIO.output(pulRB, GPIO.LOW)
            sleep(self.speed)

    def set_direction(self, direction):
        self.direction = direction
        self.enableMotor()
        if(direction == Status.FORWARD):
            GPIO.output(dirLF, GPIO.HIGH)
            GPIO.output(dirLB, GPIO.HIGH)
            GPIO.output(dirRF, GPIO.LOW)
            GPIO.output(dirRB, GPIO.LOW)
        else:
            GPIO.output(dirLF, GPIO.LOW)
            GPIO.output(dirLB, GPIO.LOW)
            GPIO.output(dirRF, GPIO.HIGH)
            GPIO.output(dirRB, GPIO.HIGH)

    def enableMotor(self):
        GPIO.output(enaLF, GPIO.HIGH)
        GPIO.output(enaLB, GPIO.HIGH)
        GPIO.output(enaRF, GPIO.HIGH)
        GPIO.output(enaRB, GPIO.HIGH)

    def disableMotor(self):
        GPIO.output(enaLF, GPIO.LOW)
        GPIO.output(enaLB, GPIO.LOW)
        GPIO.output(enaRF, GPIO.LOW)
        GPIO.output(enaRB, GPIO.LOW)

if __name__ == "__main__":
    root = tk.Tk()
    root.title("Bureau Of Engineering - Sidewalk Slope Monitoring Motor Move")
    root.geometry("350x200")
    main = SideWalkMotor(root)
    main.pack(fill="both", expand=True)
    root.mainloop()


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations

def negate_log_fc(apps, schema_editor):
    PeakDtComparison = apps.get_model('data', 'PeakDtComparison')
    for pdtc in PeakDtComparison.objects.all():
        pdtc.logFC = -pdtc.logFC
        pdtc.save()

class Migration(migrations.Migration):

    dependencies = [
        ('data', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(negate_log_fc),
    ]


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 20 11:51:35 2018

@author: AlokRai
"""

end = 10

total = 0
for i in range(0, end+1):
    total += i
print(total)


from connection import Database
from autobahn.asyncio.wamp import ApplicationSession
from asyncio import coroutine
from autobahn.asyncio.wamp import ApplicationRunner

class PoloniexComponent(ApplicationSession):
    url="wss://api.poloniex.com:443"
    feed="ticker"
    realm_name="realm1"

    def onConnect(self):
        self.join(self.config.realm)

    @coroutine
    def onJoin(self, details):
        print("session started")

        def onEvent(*args):
            event = list(args)
            #event_handler(event)
            event_handler(event)

        try:
            yield from self.subscribe(onEvent, self.feed)
        except Exception as e:
            print("Could not subscribe to topic: {0}\n".format(self.feed), e)

    def start(self):
        runner = ApplicationRunner(self.url, self.realm_name)
        runner.run(PoloniexComponent)

def event_handler(event):
    # currencyPair, last, lowestAsk, highestBid, percentChange, baseVolume, quoteVolume, isFrozen, 24hrHigh, 24hrLow
    print(event)
    query = ("INSERT INTO poloniex_ticker "
                                 "(currencyPair, last, lowestAsk, highestBid, percentChange, baseVolume, quoteVolume, isFrozen, 24hrHigh, 24hrLow)"
                                 "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)")
    db.insert(query, event)

if __name__ == '__main__':
    db = Database()
    poloniex_api = PoloniexComponent()
    poloniex_api.start()


from django.shortcuts import render

from django.http import JsonResponse

from django.core.paginator import Paginator

from django.conf import settings

from django.views.generic import DetailView

import json

import datetime

from .models import *

from .filters import *

from .utils import *

# Create your views here.

def store(request):
    context = {}

    data = cart_data(request)

    products = Product.objects.all().order_by('name')

    product_filter = ProductFilter(request.GET, queryset=products)
    # context['athlete_list'] = athlete_list
    context['product_filter'] = product_filter

    paginated_product_filter = Paginator(product_filter.qs, 4)
    page_number = request.GET.get('page')
    product_page_obj = paginated_product_filter.get_page(page_number)

    # context['products'] = products
    context['product_page_obj'] = product_page_obj
    context['total_quantity'] = data['total_quantity']

    return render(request, 'store/store.html', context=context)

def cart(request):
    context = cart_data(request)

    return render(request, 'store/cart.html', context=context)

def checkout(request):
    context = cart_data(request)

    context['barikoi_autocomplete_api_key'] = settings.BARIKOI_AUTOCOMPLETE_API_KEY

    return render(request, 'store/checkout.html', context=context)

def update_item(request):
    data = json.loads(request.body)
    product_id = data['productId']
    action = data['action']

    print('action: ', action)
    print('product_id: ', product_id)

    customer = request.user.customer
    product = Product.objects.get(id=product_id)

    order, created = Order.objects.get_or_create(customer=customer, complete=False)
    orderitem, created = OrderItem.objects.get_or_create(order=order, product=product)

    if action == 'add':
        orderitem.quantity += 1
    elif action == 'remove':
        orderitem.quantity -= 1

    orderitem.save()

    if orderitem.quantity <= 0:
        orderitem.delete()

    return JsonResponse('Item was added.', safe=False)

def process_order(request):
    transaction_id = datetime.datetime.now().timestamp()
    data = json.loads(request.body)

    if request.user.is_authenticated:
        customer = request.user.customer
        order, created = Order.objects.get_or_create(customer=customer, complete=False)
    else:
        customer, order = guest_order(request, data)

    total = float(data['form']['total'])
    order.transaction_id = transaction_id

    # validate against actual price from the Order model
    # also check if cart is empty
    if (total == order.total_price) and (len(order.orderitem_set.all()) > 0):
        order.complete = True
    order.save()

    if order.shipping == True:
        ShippingAddress.objects.create(
            customer=customer,
            order=order,
            address=data['shipping']['address'],
            city=data['shipping']['city'],
            zipcode=data['shipping']['zipcode'],
        )

    print('total: ', total)
    print('order.total_price: ', order.total_price)
    print('total == order.total_price: ', total == order.total_price)

    return JsonResponse('Payment complete.', safe=False)

class ProductDetailView(DetailView):
    model = Product
    template_name = 'store/product_detail.html'

    def get(self, request, pk) :
        context = {}
        product = Product.objects.get(id=pk)
        data = cart_data(request)
        context['total_quantity'] = data['total_quantity']
        context['product'] = product
        return render(request, self.template_name, context)


# python -m virtualenv -p /usr/bin/python3.8 venv
# source venv/bin/activate
# pip install ipykernel
# python -m ipykernel install --user --name=venv

# %%

import pandas as pd
import numpy as np
import tensortrade.env.default as default

import matplotlib
matplotlib.use('Agg')

from tensortrade.data.cdd import CryptoDataDownload
from tensortrade.feed.core import Stream, DataFeed
from tensortrade.oms.exchanges import Exchange
from tensortrade.oms.services.execution.simulated import execute_order
from tensortrade.oms.instruments import EUR, BTC, ETH, EUR
from tensortrade.oms.wallets import Wallet, Portfolio
from tensortrade.agents import DQNAgent
from statsmodels.tsa.stattools import adfuller

cdd = CryptoDataDownload()

data = cdd.fetch("Bitstamp", "EUR", "BTC", "1h")

# data = pd.read_csv('./data/backtest/15m.csv')
# data.columns =['unix', 'open', 'high', 'low', 'close', 'volume', 'Close time', 'Quote asset volume', 'Number of trades', 'Taker buy base asset volume', 'Taker buy quote asset volume', 'Ignore']

# data['date'] = pd.to_datetime(data["unix"], unit='ms').dt.strftime('%Y-%m-%d %H:%M:%S')

# data = data[['date', 'unix', 'open', 'high', 'low', 'close', 'volume']]
# data['unix'] = data['unix'].div(1000).astype('int64')

# data['diffed'] = data['close'] - data['close'].shift(1)
# data['logged_and_diffed'] = np.log(data['close']) - np.log(data['close'].shift(1))
# print(data)

# data['logged_and_diffed'] = np.log(data['close']) - np.log(data['close']).shift(1)
# result = adfuller(data['logged_and_diffed'].values[1:], autolag="AIC")
# print('p-value: %f' % result[1])

def rsi(price: Stream[float], period: float) -> Stream[float]:
    r = price.diff()
    upside = r.clamp_min(0).abs()
    downside = r.clamp_max(0).abs()
    rs = upside.ewm(alpha=1 / period).mean() / downside.ewm(alpha=1 / period).mean()
    return 100*(1 - (1 + rs) ** -1)

def macd(price: Stream[float], fast: float, slow: float, signal: float) -> Stream[float]:
    fm = price.ewm(span=fast, adjust=False).mean()
    sm = price.ewm(span=slow, adjust=False).mean()
    md = fm - sm
    signal = md - md.ewm(span=signal, adjust=False).mean()
    return signal

features = []
for c in data.columns[1:]:
    s = Stream.source(list(data[c]), dtype="float").rename(data[c].name)
    features += [s]

cp = Stream.select(features, lambda s: s.name == "close")

features = [
    cp.log().diff().rename("lr"),
    rsi(cp, period=20).rename("rsi"),
    # macd(cp, fast=10, slow=50, signal=5).rename("macd")
]

feed = DataFeed(features)
feed.compile()

for i in range(5):
    print(feed.next())

bitstamp = Exchange("bitstamp", service=execute_order)(
    Stream.source(list(data["close"]), dtype="float").rename("EUR-BTC")
)

portfolio = Portfolio(EUR, [
    Wallet(bitstamp, 1000 * EUR),
    Wallet(bitstamp, 0.0025 * BTC)
])

renderer_feed = DataFeed([
    Stream.source(list(data["date"])).rename("date"),
    Stream.source(list(data["open"]), dtype="float").rename("open"),
    Stream.source(list(data["high"]), dtype="float").rename("high"),
    Stream.source(list(data["low"]), dtype="float").rename("low"),
    Stream.source(list(data["close"]), dtype="float").rename("close"),
    Stream.source(list(data["volume"]), dtype="float").rename("volume")
])

env = default.create(
    portfolio=portfolio,
    action_scheme="managed-risk",
    reward_scheme="risk-adjusted",
    feed=feed,
    renderer_feed=renderer_feed,
    renderer=default.renderers.PlotlyTradingChart(),
    window_size=20
)

env.observer.feed.next()

agent = DQNAgent(env)

agent.train(n_steps=10000, n_episodes=1,
            save_path="agents/", render_interval=10000)

print('Success')


from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QPushButton, QGraphicsSceneMouseEvent, QGraphicsTextItem, QLabel
from PyQt5.QtGui import QBrush, QColor, QFont
from PyQt5.QtCore import QTimer

from enemy_graphics_item import EnemyGraphicsItem
from tower_graphics_item import TowerGraphicsItem
from missile_graphics_item import MissileGraphicsItem
from explosion_graphics_item import ExplosionGraphicsItem
from board_graphics_item import BoardGraphicsItem
from menu_graphics_item import MenuGraphicsItem
from text_item import TextItem
from player_name import PlayerName
from load_high_scores import LoadHighScores
from build_tower_graphics_item import BuildTowerGraphicsItem
from building_slot_graphics_item import BuildingSlotGraphicsItem

from add_board_graphics import add_board_graphics
from add_high_score import add_high_score

from PyQt5.QtWidgets import QWidget, QLineEdit, QApplication

class GUI(QtWidgets.QMainWindow):

	def __init__(self, game, high_scores, high_scores_data):
		super().__init__()
		self.scene = QtWidgets.QGraphicsScene()
		self.window_size = [1900, 1200]

		self.scene.setSceneRect(0, 0, self.window_size[0], self.window_size[1])

		self.view = QtWidgets.QGraphicsView(self.scene, self)
		self.view.setBackgroundBrush(QBrush(QColor("Black")))	# Set background to black
		self.view.adjustSize()
		#self.view.show()

		self.setCentralWidget(self.view)

		#self.setCentralWidget(QtWidgets.QWidget()) 			# QMainWindown must have a centralWidget to be able to add layouts

		self.showFullScreen()
		self.showMaximized()
		self.setWindowTitle("Defence")
		#self.show()

		self.play_text_items			=	[]
		self.high_scores_text_items 	=	[]
		self.board_graphics_items 		=	[]
		self.enemy_graphics_items 		=	[]
		self.tower_base_graphics_items 	= 	[]
		self.tower_graphics_items 		=	[]
		self.missile_graphics_items 	=	[]
		self.explosion_graphics_items 	= 	[]
		self.menu_graphics_items 		=	[]
		self.buildable_graphics_items 	= 	[]
		self.building_slots 			= 	[]

		self.game = game
		self.high_scores = high_scores
		self.high_scores_data = high_scores_data
		self.square_size = game.get_board().get_square_size()
		self.main_menu_item = MenuGraphicsItem(self, "images/main_menu.png", self.window_size[0] / 10 * 9, self.window_size[1] / 10 * 9, "Main Menu")

		self.next_wave_timer = QTimer()

		self.main_menu()

		#self.init_buttons()

		#self.play()

	def get_game(self):
		return self.game

	def add_all_graphics(self):
		squares = self.game.get_board().get_squares()
		self.board_graphics_items = add_board_graphics(self.game.get_board().get_difficulty(), squares, self.square_size, self.scene)

		self.add_text_graphics_items()
		self.add_buildable_tower_graphics_items()

	def add_enemies(self):
		self.enemies_to_be_added = self.game.next_wave()

		if self.game.get_board().get_current_wave() % 10 == 0:
			current_interval = self.game.get_enemy_spawn_interval()
			new_interval = int(current_interval / 2)
			self.game.set_enemy_spawn_interval(new_interval)

	def add_enemy_graphics_item(self):
		enemy = self.enemies_to_be_added[0]
		self.enemies_to_be_added.remove(enemy)
		if self.enemies_to_be_added == []:					# If all enemies have been added, indicate that new ones can be added
			self.game.get_board().set_enemies_added()

		enemy = self.game.get_board().add_enemy(enemy, self.game.get_board().get_enemy_start_location())
		enemy_graphics_item = EnemyGraphicsItem(enemy, self.square_size)
		if enemy_graphics_item.has_shadow():
			self.scene.addItem(enemy_graphics_item.get_shadow())
		self.enemy_graphics_items.append(enemy_graphics_item)
		self.scene.addItem(enemy_graphics_item)
		self.new_enemy_timer.setSingleShot(True)
		self.new_enemy_timer.start(self.game.get_enemy_spawn_interval())

	def add_tower_base_graphics_item(self, tower):
		for item in self.buildable_graphics_items:
			item.set_building(False)

		tower_base_graphics_item = TowerGraphicsItem(tower, self.square_size)
		self.tower_base_graphics_items.append(tower_base_graphics_item)
		self.scene.addItem(tower_base_graphics_item)

		for item in self.building_slots:
			self.scene.removeItem(item)
		self.building_slots = []

	def add_explosion_graphics_item(self, location, explosion_type, time):
		explosion_graphics_item = ExplosionGraphicsItem(location, explosion_type, time, self.square_size)
		self.explosion_graphics_items.append(explosion_graphics_item)
		self.scene.addItem(explosion_graphics_item)

	def add_text_graphics_items(self):
		self.qLabel = QLabel(self)
		self.qLabel.setStyleSheet("QLabel {color : white; }")
		self.qLabel.setText("Hover over an object to receive information about it")
		self.qLabel.move(1600, 1150)
		self.qLabel.setFixedWidth(1000)
		self.qLabel.show()

		font_size = 15
		level = TextItem("Level: " + str(self.game.get_board().get_current_wave()), font_size, 20, 800)
		#time = TextItem("Time until next wave: 0", font_size, 20, 900)
		points = TextItem("Points: \n" + str(self.game.get_points()), font_size, 20, 1000)
		money = TextItem("Money: \n" + str(self.game.get_money()), font_size, 200, 1000)
		lives = TextItem("Lives: \n" + str(self.game.get_lives()), font_size, 380, 1000)
		tower_building_information = TextItem("Build a tower:", font_size, 700, 800)

		text_items = [level, points, money, lives, tower_building_information]

		for item in text_items:
			self.scene.addItem(item)
			self.play_text_items.append(item)

	def add_buildable_tower_graphics_items(self):
		cannon = BuildTowerGraphicsItem(self.game.get_tower_types()["Cannon"], 700, 900, self.square_size, self)
		machine_gun = BuildTowerGraphicsItem(self.game.get_tower_types()["MachineGun"], 900, 900, self.square_size, self)
		rocket_launcher = BuildTowerGraphicsItem(self.game.get_tower_types()["RocketLauncher"], 1100, 900, self.square_size, self)
		double_rocket_launcher = BuildTowerGraphicsItem(self.game.get_tower_types()["DoubleRocketLauncher"], 700, 1000, self.square_size, self)
		tank = BuildTowerGraphicsItem(self.game.get_tower_types()["Tank"], 900, 1000, self.square_size, self)
		leopard = BuildTowerGraphicsItem(self.game.get_tower_types()["Leopard"], 1100, 1000, self.square_size, self)

		tower_graphics_items = [cannon, machine_gun, rocket_launcher, double_rocket_launcher, tank, leopard]

		for item in tower_graphics_items:
			self.scene.addItem(item)
			self.buildable_graphics_items.append(item)

	def add_building_slots(self, tower_type):
		for item in self.buildable_graphics_items:
			item.set_building(True)

		squares = self.game.get_board().get_squares()
		for squares_list in squares:
			i = squares.index(squares_list)
			for square in squares_list:
				j = squares_list.index(square)
				if square.contains() == 0:
					slot = BuildingSlotGraphicsItem(tower_type, i, j, self.square_size, "Building_slot.png", self)
					self.scene.addItem(slot)
					self.building_slots.append(slot)

	def update_all(self):
		self.is_game_over()
		self.update_enemies()										# Firstly the enemies move
		self.update_towers(self.game.get_board().get_towers())		# Then  the towers shoot according to their targets
		self.update_missiles(self.game.get_board().get_missiles())	# Lastly the missiles that were created as well as the previously created ones move
		self.update_explosions()									# Update explosion effects
		self.update_text_graphics_items()							# Update text's that indicate game information

	def update_enemies(self):
		if self.enemies_to_be_added != []:
			if self.new_enemy_timer.remainingTime() < 0:
				self.add_enemy_graphics_item()

		enemies = self.game.get_board().get_enemies()

		if enemies == []:
			if not self.game.get_board().is_adding_enemies():		# Do not add new enemies if enemies are currently being added
				self.game.get_board().set_adding_enemies()
				self.next_wave_timer.singleShot(self.game.get_time_between_waves(), self.add_enemies)
		else:
			enemies[:] = [enemy for enemy in enemies if not enemy.is_dead()] 	# Check which enemies are dead
			enemies[:] = [enemy for enemy in enemies if not enemy.move()]		# Move the enemies

			enemy_graphics_items_to_be_removed = []

			for enemy_graphics_item in self.enemy_graphics_items:
				if enemy_graphics_item.get_enemy() in enemies:
					enemy_graphics_item.update_graphics()
				else:
					self.scene.removeItem(enemy_graphics_item)
					if enemy_graphics_item.has_shadow():
						self.scene.removeItem(enemy_graphics_item.get_shadow())
					enemy_graphics_items_to_be_removed.append(enemy_graphics_item)

			for item in enemy_graphics_items_to_be_removed:
				self.enemy_graphics_items.remove(item)

	def update_towers(self, towers):
		for tower in towers:							# Iterate through towers
			missile = tower.shoot()						# Tower shoots and creates a missile
			if missile != None:
				missile_graphics_item = MissileGraphicsItem(missile, self.square_size)			# Create graphics item for missile
				self.missile_graphics_items.append(missile_graphics_item)
				self.scene.addItem(missile_graphics_item)

		for tower_base_graphics_item in self.tower_base_graphics_items:
			tower_base_graphics_item.update_graphics()
			if tower_base_graphics_item.build():
				tower_graphics_item = TowerGraphicsItem(tower_base_graphics_item.get_tower(), self.square_size)
				self.tower_graphics_items.append(tower_graphics_item)
				self.scene.addItem(tower_graphics_item)

		for tower_graphics_item in self.tower_graphics_items:
			tower_graphics_item.update_graphics()

	def update_missiles(self, missiles):
		# Move missiles and remove those, which have reached their target or whose target has reached goal
		missiles[:] = [missile for missile in missiles if not missile.move(self.game.get_board().get_enemies(), self)]

		new_missile_graphics_items = []

		for missile_graphics_item in self.missile_graphics_items:
			if missile_graphics_item.get_missile() in missiles:
				missile_graphics_item.update_graphics()
				new_missile_graphics_items.append(missile_graphics_item)
			else:
				self.scene.removeItem(missile_graphics_item)

		self.missile_graphics_items = new_missile_graphics_items

	def update_explosions(self):
		items_to_be_removed = []
		for item in self.explosion_graphics_items:
			if item.time_passed() <= 0:
				items_to_be_removed.append(item)

		for item in items_to_be_removed:
			self.scene.removeItem(item)
			self.explosion_graphics_items.remove(item)

	def update_text_graphics_items(self):
		for item in self.buildable_graphics_items:
			if item.isUnderMouse():
				tower = item.get_tower()
				information = "Costs: " + str(tower[5]) + ", Range: " + str(tower[2]) + ", Damage: " + str(tower[1]) \
					+ ", Builds in: " + str(tower[4] / 1000) + " s" + ", Reloads in: " + str(tower[3] / 1000) + " s"
				self.qLabel.setText(information)

		for item in self.enemy_graphics_items:
			if item.isUnderMouse():
				enemy = item.get_enemy()
				information = "Type: " + str(enemy.get_type()) + ", Hitpoints: " + str(enemy.get_hitpoints()) + ", Speed: " \
					+ str(enemy.get_speed()) + ", Worth: " + str(enemy.get_worth())
				self.qLabel.setText(information)

		for item in self.tower_graphics_items:
			if item.isUnderMouse():
				target_type = item.get_tower().get_target_type()
				if target_type == 0:
					target = "first"
				elif target_type == 1:
					target = "closest"
				elif target_type == 2:
					target = "strongest"
				else:
					target = "weakest"
				information = "Tower has been set to shoot the " + target + " enemy"
				self.qLabel.setText(information)

		self.qLabel.show()

		updated_texts = ["Level: " + str(self.game.get_board().get_current_wave()), "Points: \n" + str(self.game.get_points()),
		"Money: \n" + str(self.game.get_money()), "Lives: \n" + str(self.game.get_lives()), "Build a tower:"]

		for item in self.play_text_items:
			item.set_text(updated_texts[self.play_text_items.index(item)])

	def is_game_over(self):
		if self.game.get_lives() <= 0:
			self.timer.stop()

			self.qLabel.setText("")

			for item in self.play_text_items:
				self.scene.removeItem(item)
			self.play_text_items = []
			for item in self.board_graphics_items:
				self.scene.removeItem(item)
			self.board_graphics_items = []
			for item in self.enemy_graphics_items:
				self.scene.removeItem(item)
			self.enemy_graphics_items = []
			for item in self.tower_graphics_items:
				self.scene.removeItem(item)
			self.tower_graphics_items = []
			for item in self.missile_graphics_items:
				self.scene.removeItem(item)
			self.missile_graphics_items = []
			for item in self.tower_base_graphics_items:
				self.scene.removeItem(item)
			self.tower_base_graphics_items = []
			for item in self.explosion_graphics_items:
				self.scene.removeItem(item)
			self.explosion_graphics_items = []
			for item in self.menu_graphics_items:
				self.scene.removeItem(item)
			self.menu_graphics_items = []
			for item in self.buildable_graphics_items:
				self.scene.removeItem(item)
			self.buildable_graphics_items = []
			for item in self.building_slots:
				self.scene.removeItem(item)
			self.building_slots = []

			self.level = self.game.get_board().get_current_wave()
			self.points = self.game.get_points()

			self.qLineEdit = PlayerName(self)
			text = "Game over, enter username and hit Enter. Maximum 15 charactes, whitespace not allowed"
			text_item = TextItem(text, 40, 200, 200)
			self.scene.addItem(text_item)
			self.menu_graphics_items.append(text_item)

	def check_points(self):
		name = self.qLineEdit.get_text()
		name = "".join(name.split())
		if len(name) < 1:
			name = "Nameless"
		add_high_score(self.high_scores_data, "#" + self.game.get_board().get_difficulty(), name, self.level, self.points)
		self.qLineEdit.setParent(None)
		self.game.initialize()

		self.show_high_scores()

	def main_menu(self):
		# If high scores have been viewed, remove them from the scene
		for item in self.high_scores_text_items:
			self.scene.removeItem(item)
		self.high_scores_items = []
		if self.scene.items() != []:
			self.scene.removeItem(self.main_menu_item)

		font = QFont("Comic Sans", 40)					# Set font for menu instructions
		color = QColor("White")							# Set font color
		text = "Click one of the icons to proceed"		# Set the instruction text
		menu_text = QGraphicsTextItem(text)				# Create the actual text item
		menu_text.setFont(font)
		menu_text.setDefaultTextColor(color)
		menu_text.setPos(200, 900)
		self.scene.addItem(menu_text)

		play_item = MenuGraphicsItem(self, "images/play.png", self.window_size[0] / 4, self.window_size[1] / 2, "Play")
		high_scores_item = MenuGraphicsItem(self, "images/high_scores.png", self.window_size[0] / 4 * 3, self.window_size[1] / 2, "High Scores")
		self.scene.addItem(play_item)
		self.scene.addItem(high_scores_item)

		self.menu_graphics_items.append(menu_text)
		self.menu_graphics_items.append(play_item)
		self.menu_graphics_items.append(high_scores_item)

	def choose_difficulty(self):
		# Remove menu items from scene
		for item in self.menu_graphics_items:
			self.scene.removeItem(item)
		self.menu_graphics_items = []

		easy = MenuGraphicsItem(self, "images/Easy.png", self.window_size[0] / 10, self.window_size[1] / 2, "Easy")
		medium = MenuGraphicsItem(self, "images/Medium.png", self.window_size[0] / 10 * 5, self.window_size[1] / 2, "Medium")
		hard = MenuGraphicsItem(self, "images/Hard.png", self.window_size[0] / 10 * 9, self.window_size[1] / 2, "Hard")
		self.menu_graphics_items.append(easy)
		self.menu_graphics_items.append(medium)
		self.menu_graphics_items.append(hard)

		size = 30
		instructions = ["Choose difficulty:", 50, 400, 10]
		text_for_easy = ["Easy", size, easy.pos().x(), easy.pos().y() + easy.height()]
		text_for_medium	= ["Medium", size, medium.pos().x(), medium.pos().y() + medium.height()]
		text_for_hard = ["Hard", size, hard.pos().x(), hard.pos().y() + hard.height()]
		texts = [instructions, text_for_easy, text_for_medium, text_for_hard]

		for text in texts:
			text_item = TextItem(text[0], text[1], text[2], text[3])
			self.menu_graphics_items.append(text_item)

		for item in self.menu_graphics_items:
			self.scene.addItem(item)

	def play(self):
		for item in self.menu_graphics_items:
			self.scene.removeItem(item)
		self.menu_graphics_items = []

		self.enemies_to_be_added = []
		self.new_enemy_timer = QTimer()

		self.add_all_graphics()
		self.update_all()

		# Set a timer to call the update function periodically
		self.timer = QTimer()
		self.timer.start(self.game.get_fps()) 				# Milliseconds
		self.timer.timeout.connect(self.update_all)

	def show_high_scores(self):
		for item in self.menu_graphics_items:
			self.scene.removeItem(item)

		headers = ["Easy", "Medium", "Hard"]
		x = 20

		for header in headers:
			text_item = TextItem(header, 30, x, 200)
			self.high_scores_text_items.append(text_item)
			self.scene.addItem(text_item)
			x += 600

		self.high_scores = LoadHighScores().load(self.high_scores_data)

		font_size = 12
		y = 300
		x_increment = 0

		for header in headers:
			for scores in self.high_scores[header]:
				x = 20 + x_increment
				for text in scores:
					text_item = TextItem(text, font_size, x, y)
					self.high_scores_text_items.append(text_item)
					self.scene.addItem(text_item)
					if scores.index(text) == 0:
						x += 225
					elif scores.index(text) == 1:
						x += 120
				y += font_size + 30
			x_increment += 600
			y = 300

		self.scene.addItem(self.main_menu_item)


from unittest import TestCase
from monitor.api import minerapi

class MinerAPITestCase(TestCase):
    # Tests for the script used to query the api of
    # running instances of mining software (cg/bfg miner, etc)

    def test_running_miner_api(self):
        # This test will fail if there IS NOT
        # miner running/listening at host:port
        host = 'miner'
        port = 4028
        # 'hello' is not valid command for the miners
        # but the miner should respond with json with
        # a 'STATUS' value
        q = minerapi.query(host, port, 'hello')
        self.assertTrue('STATUS' in q)

    def test_no_miner_timeout(self):
        # This test will fail if there IS a
        # miner running/listening at host:port
        host = 'miner'
        port = 5000
        timedOut = False
        # This api should timeout and throw an exception
        # after 10 seconds with no reply from miner
        try:
            minerapi.query(host, port, 'hello')
        except:
            timedOut = True
        self.assertTrue(timedOut)


import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import sys
import pandas as pd
import pytraj as pt
import matplotlib.mlab as mlab
import matplotlib.cm as cm
import os

# python program_name ncp peng ngen filename
#python plot_scores.py 5 5 10000 100 scores1.dat

ncp = sys.argv[1] #number of chromosome print
peng = sys.argv[2] # print every n generation
ngen = sys.argv[3] #number of generation
max_x = sys.argv[4] # maxiumum number of generation u want to plot

filename = np.genfromtxt(sys.argv[5])
scores = np.genfromtxt(sys.argv[5], usecols=2) # get the scores
# but scores are printed based on ncp

# need to split  scores to give an array with ncp for each peng
scores = np.split(scores, (len(scores))/int(peng))

def plot_avg_score(scores, ncp, peng, ngen, max_x):
  Avg = [];Std = []
  for i in scores:
    sum = np.sum(i)
    std = np.std(i)
    Std.append(std)
    avg = float(sum) / int(ncp)
    Avg.append(avg)
  Avg = np.array(Avg)
  Std = np.array(Std)
  import seaborn as sns; sns.set(style="ticks")
  plt.figure()
  Yarray = Avg

  #plot my data, +ncp, because of initial scores (-1)
  x=np.arange(0, (int(ngen) + int(ncp)), int(peng))
  plt.plot(x, Yarray, 'k-', color="blue")
  plt.fill_between(x, Yarray-Std, Yarray+Std)
  plt.scatter(x, Yarray, s=15, color="black")
  #plt.axhline(y=2, color="black", linewidth=1)

  plt.ylabel("Score (AAE) ", fontsize=24)
  plt.xlabel('# of Generation', fontsize=24)
  plt.ylim(0, max(Yarray))
  #plt.yticks(np.arange(23,31,1))
  #plt.xlim(0,max(x))
  plt.xlim(0, int(max_x))
  plt.grid(b=True, which='both', color='gray', linewidth=0.13, linestyle='--')
  plt.savefig('Average_score_vs_ngen.png')

plot_avg_score(scores, ncp, peng, ngen, max_x)
#print (scores)


def laceStrings(s1, s2):
    """
    s1 and s2 are strings.

    Returns a new str with elements of s1 and s2 interlaced,
    beginning with s1. If strings are not of same length,
    then the extra elements should appear at the end.
    """
    # Your Code Here
    lace = ''
    if s1 == '':
        lace = s2
    elif s2 == '':
        lace = s1
    elif len(s1) < len(s2):
        for i in range(len(s1)):
            lace += s1[i] + s2[i]
        lace += s2[i + 1:]
    elif len(s2) < len(s1):
        for i in range(len(s2)):
            lace += s1[i] + s2[i]
        lace += s1[i + 1:]
    else:
        for i in range(len(s1)):
            lace += s1[i] + s2[i]
    return lace


import requests
import logging

class BranchClient(object):

    base_url = "https://api.branch.io/v1"

    def __init__(self,
                 branch_key,
                 branch_secret,
                 upside_url='https://upsideappbeta.app.link',  # default to alpha
                 session_factory=requests.session):
        self.branch_key = branch_key
        self.branch_secret = branch_secret
        self.upside_url = upside_url

        self.session = session_factory()

        self.session.mount('http://', requests.adapters.HTTPAdapter(max_retries=3))
        self.session.mount('https://', requests.adapters.HTTPAdapter(max_retries=3))

    def get_deep_link(self, deep_link):
        # $ curl 'https://api.branch.io/v1/url?url=https%3A%2F%2Fupside.app.link/THOMAS688&branch_key=xxx' | jq

        url = '{branchUrl}/url'.format(branchUrl=self.base_url)
        query_params = {
            'url': '{upsideUrl}/{deepLink}'.format(upsideUrl=self.upside_url, deepLink=deep_link),
            'branch_key': self.branch_key
        }

        logging.info('Sending to url {} query params: {}'.format(url, query_params))

        response = self.session.get(
            url=url,
            params=query_params
        )

        logging.info('url = {}'.format(response.url))

        return response.json()

    def update_deep_link(self, deep_link, **data_map):
        """
        :param deep_link: The 'deep_link' to update data for.  In Upside lingo, this is a 'promoCode' like 'THOMAS688'
        :param kwargs: The dataMap we want to update the deep_link with.  Note that the default branch.io data that
        exists on the deep link will remain intact after an update, but any and all non-branch.io data will be
        replaced with the contents of the
        :return: The response from the server
        """
        # e.g. https://api.branch.io/v1/url?url=https%3A%2F%2Fupside.app.link/THOMAS688
        branch_url = '{branchUrl}/url?url={upsideUrl}/{deepLink}'.format(branchUrl=self.base_url,
                                                                         upsideUrl=self.upside_url,
                                                                         deepLink=deep_link)

        payload = {
            'branch_key': self.branch_key,
            'branch_secret': self.branch_secret,
            'data': data_map
        }

        logging.info('sending payload {}'.format(payload))

        response = self.session.put(
            url=branch_url,
            json=payload
        )

        logging.info('url = {}'.format(response.url))

        return response.json()


#!/usr/bin/env python
# Copyright 2020-2023 OpenDR European Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse

# EAGERx imports
from eagerx import Object, Bridge, Node, initialize, log
from eagerx.core.graph import Graph
import eagerx.bridges.openai_gym as eagerx_gym
import eagerx_examples  # noqa: F401

# Import stable-baselines
import stable_baselines3 as sb

def example_pid_only(name, eps, eval_eps, device, render=False):
    # Start roscore & initialize main thread as node
    initialize("eagerx", anonymous=True, log_level=log.INFO)

    # Define object
    sensors = ["observation", "reward", "done"]
    if render:
        sensors.append("image")
    pendulum = Object.make("GymObject", "pendulum", sensors=sensors, env_id="Pendulum-v0", rate=20)

    # Define PID controller & classifier
    pid = Node.make("PidController", "pid", rate=20, gains=[8, 1, 0], y_range=[-4, 4])

    # Define graph (agnostic) & connect nodes
    graph = Graph.create(nodes=[pid], objects=[pendulum])
    graph.connect(source=pendulum.sensors.reward, observation="reward")
    graph.connect(source=pendulum.sensors.done, observation="done")
    graph.connect(source=pendulum.sensors.observation, observation="state")
    # Connect PID
    graph.connect(source=pendulum.sensors.observation, target=pid.inputs.y)
    graph.connect(action="yref", target=pid.inputs.yref)
    graph.connect(source=pid.outputs.u, target=pendulum.actuators.action)
    if render:
        graph.render(source=pendulum.sensors.image, rate=10, display=False)

    # Define bridge
    bridge = Bridge.make("GymBridge", rate=20)

    # Initialize Environment (agnostic graph +  bridge)
    env = eagerx_gym.EagerxGym(name=name, rate=20, graph=graph, bridge=bridge)
    if render:
        env.render(mode="human")

    # Initialize and train stable-baselines model
    model = sb.SAC("MlpPolicy", env, verbose=1, device=device)
    model.learn(total_timesteps=int(eps * 200))

    # Evaluate trained policy
    for i in range(eval_eps):
        obs, done = env.reset(), False
        while not done:
            action, _ = model.predict(obs, deterministic=True)
            obs, reward, done, info = env.step(action)
    env.shutdown()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cpu", choices=["cuda", "cpu"])
    parser.add_argument("--name", help="Name of the environment", type=str, default="example")
    parser.add_argument("--eps", help="Number of training episodes", type=int, default=200)
    parser.add_argument("--eval_eps", help="Number of evaluation episodes", type=int, default=20)
    parser.add_argument("--render", help="Toggle rendering", action="store_true")

    args = parser.parse_args()

    example_pid_only(name=args.name, eps=args.eps, eval_eps=args.eval_eps, device=args.device, render=args.render)


import json
import os
import sys
import random

from kbEndPoint.utils.sparql import sparqlUtils
from preprocessing import metricUtils
import pandas as pd

import nltk
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer # will do for now?

import codecs
import numpy as np
from scipy import stats

#PREFIX = "/Users/funke/Documents/ComplexWebQuestions_preprocess"
PREFIX = "/media/nbhutani/Data/textray_workspace/TextRay/datasets/ComplexWebQuestions_preprocess"

INPUT_PATH = os.path.join(PREFIX, "annotated/train.json")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_PATH = os.path.join(PREFIX, "cands/train/main_with_constraints")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_PATH = os.path.join(PREFIX, "rewards/dedup/train")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_PATH = os.path.join(PREFIX, "rewards/labels/train")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_MAX_PATH = os.path.join(PREFIX, "rewards/rescaled_max/train")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_Z_SCORE_PATH = os.path.join(PREFIX, "rewards/rescaled_zscore/train")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_Z_SCORE_PRIORS_PATH = os.path.join(PREFIX, "rewards/rescaled_zscore_priors/train")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_MAX_PRIORS_PATH = os.path.join(PREFIX, "rewards/rescaled_max_priors/train")
#
# CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_MAX_PRIORS_DERIVED_1_PATH = os.path.join(PREFIX, "rewards/rescaled_max_priors_derived_0.1/train")
# CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_MAX_PRIORS_DERIVED_5_PATH = os.path.join(PREFIX, "rewards/rescaled_max_priors_derived_0.5/train")
# CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_MAX_DERIVED_1_PATH = os.path.join(PREFIX, "rewards/rescaled_max_derived_0.1/train")
CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_MAX_DERIVED_5_PATH = os.path.join(PREFIX, "rewards/rescaled_max_derived_0.5/train")
# TOPIC_PATH = os.path.join(PREFIX, "topic_entities/main/train_topic.csv")

def train_data_stats(input_path, src_dir):
    questions = json.load(codecs.open(input_path, 'r', encoding='utf-8'))
    positive_examples_ct = 0
    negative_examples_ct = 0
    for q in questions:
        ques_id = q["ID"]
        type = q["compositionality_type"]
        if type == "conjunction" or type == "composition":
            ques_path = os.path.join(src_dir, ques_id + ".json")
            if not os.path.exists(ques_path):
                continue

            #print(ques_id)
            main_entity_paths = json.load(codecs.open(ques_path, 'r', encoding='utf-8'))
            for topic in main_entity_paths:
                for path in main_entity_paths[topic]:
                    if path["derived_label"] == 0:
                        negative_examples_ct += 1
                    elif path["derived_label"] == 1:
                        positive_examples_ct += 1
    print(positive_examples_ct)
    print(negative_examples_ct)

if __name__ == '__main__':
    train_data_stats(INPUT_PATH, CANDIDATE_MAIN_WITH_CONSTRAINTS_DEST_REWARDS_DEDUP_LABEL_RESCALED_MAX_DERIVED_5_PATH)


"""Spider_Stretched_Maps.

Author:         Benjamin Yvernault
contact:        b.yvernault@ucl.ac.uk
Spider name:    Stretched_Maps
Spider version: 1.0.0
Creation date:  2017-02-23 14:25:45
Purpose:        Calculate DDC maps and a maps using the DW Head and Neck data
"""

# Python packages import
import os
import sys

from dax import spiders, ScanSpider, XnatUtils

__author__ = "Benjamin Yvernault"
__email__ = "b.yvernault@ucl.ac.uk"
__purpose__ = "Calculate DDC maps and a maps using the DW Head and Neck data"
__spider_name__ = "Stretched_Maps"
__version__ = "1.0.0"
__modifications__ = """2017-02-23 14:25:45 - Original write"""

def parse_args():
    """Argument parser for the spider input variables.

    by default (set in get_session_argparser):
        -p       : proj_label
        -s       : subj_label
        -e       : sess_label
        -c       : scan_label
        -d       : temp_dir
        --suffix : suffix (suffix for assessor proctype on XNAT)
        --host : host for XNAT (default: XNAT_HOST env variable)
        --user : user on XNAT (default: XNAT_USER env variable)
    your arguments:
        ...

    :return: argument parser object created by parse_args()
    """
    ap = spiders.get_scan_argparser("Stretched_Maps", __purpose__)
    _h = "Matlab code folder containing XNAT_StretchedMaps_final.m"
    ap.add_argument("--mc", dest="matlab_code", default=None, required=True,
                    help=_h)
    return ap.parse_args()

class Spider_Stretched_Maps(ScanSpider):
    """Scan Spider: Spider_Stretched_Maps

    :param spider_path: spider file path
    :param jobdir: directory for temporary files
    :param xnat_project: project ID on XNAT
    :param xnat_subject: subject label on XNAT
    :param xnat_session: experiment label on XNAT
    :param xnat_scan: scan label on XNAT
    :param matlab_code: matlab path to the code
    :param xnat_host: host for XNAT if not set in environment variables
    :param xnat_user: user for XNAT if not set in environment variables
    :param xnat_pass: password for XNAT if not set in environment variables
    :param suffix: suffix to the assessor creation
    """
    def __init__(self, spider_path, jobdir,
                 xnat_project, xnat_subject, xnat_session, xnat_scan,
                 matlab_code,
                 xnat_host=None, xnat_user=None, xnat_pass=None,
                 suffix="", subdir=True, skip_finish=False):
        """Entry point for Spider_Stretched_Maps Class."""
        super(Spider_Stretched_Maps,
              self).__init__(spider_path, jobdir, xnat_project, xnat_subject,
                             xnat_session, xnat_scan, xnat_host, xnat_user,
                             xnat_pass, suffix, subdir, skip_finish)
        # Inputs to download from XNAT specified by:
        #   type: 'scan' or 'assessor' or 'session' or 'subject' or 'project'
        #   label: label on xnat for the object, e.g: '0002' for a scan
        #   resource: label of the resource on xnat, e.g: NIFTI
        #   dir (optional): directory where to download the data
        #   scan (optional): if using an scan assessor and giving just the
        #                    proctype to the label key, generate the
        #                    assessor_label string.
        self.inputs = [
            {'type': 'scan', 'label': xnat_scan, 'resource': 'DICOM'},
        ]
        _format = 'Report_Stretched_Maps_%s_%s.pdf'
        self.matlab_code = matlab_code
        self.pdf_final = os.path.join(
            self.jobdir, _format % (self.xnat_session, self.xnat_scan))

    def pre_run(self):
        """Method to download data from XNAT."""
        # Download inputs specified by self.inputs
        self.download_inputs()
        fname = os.path.basename(self.data[self.xnat_scan]['DICOM'][0])
        if fname == 'dicoms.zip':
            input_dir = os.path.dirname(self.data[self.xnat_scan]['DICOM'][0])
            XnatUtils.unzip_list(
                self.data[self.xnat_scan]['DICOM'][0], input_dir)

    def run(self):
        """Method running the process for the spider on the inputs data."""
        # Run command define by self.cmd_args
        matlab_template = """addpath('$mpath');
XNAT_StretchedMaps_final('$dcm_folder', '$ddc_maps', '$adc_maps', '$pdf');"""
        folder = os.path.dirname(self.data[self.xnat_scan]['DICOM'][0])
        maps_dir = os.path.join(self.jobdir, 'maps')
        os.makedirs(maps_dir)
        self.cmd_args = {
            'exe': 'matlab',
            'template': matlab_template,
            'args': {
                'dcm_folder': folder,
                'ddc_maps': maps_dir,
                'adc_maps': maps_dir,
                'mpath': self.matlab_code,
                'pdf': self.pdf_final,
            }
        }
        self.run_cmd_args()

    def finish(self):
        """Method to copy the results in dax.RESULTS_DIR."""
        maps_dir = os.path.join(self.jobdir, 'maps')
        results_dict = {
            'PDF': self.pdf_final,
            'OsiriX': maps_dir,
        }
        self.upload_dict(results_dict)
        self.end()

if __name__ == '__main__':
    args = parse_args()
    # generate spider object:
    spider_obj = Spider_Stretched_Maps(
                    spider_path=sys.argv[0],
                    jobdir=args.temp_dir,
                    xnat_project=args.proj_label,
                    xnat_subject=args.subj_label,
                    xnat_session=args.sess_label,
                    xnat_scan=args.scan_label,
                    matlab_code=args.matlab_code,
                    xnat_host=args.host,
                    xnat_user=args.user,
                    xnat_pass=None,
                    suffix=args.suffix,
                    subdir=args.subdir,
                    skip_finish=args.skipfinish)

    # print some information before starting
    spider_obj.print_init(args, "Benjamin Yvernault", "b.yvernault@ucl.ac.uk")

    # Pre-run method to download data from XNAT
    spider_obj.pre_run()

    # Run method
    spider_obj.run()

    # Finish method to copy results
    if not args.skipfinish:
        spider_obj.finish()


# -*- coding: utf-8 -*-
"""
Created on Wed Mar 14 14:40:38 2018

@author: Liaowei
"""

import pandas as pd
import numpy as np
import time
import datetime
import os

from utils import raw_data_path,feature_data_path,result_path,cache_pkl_path,dump_pickle,load_pickle,build_train_dataset,cal_log_loss,cal_single_log_loss
from smooth import BayesianSmoothing
import gen_smooth_features as smooth_features
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import minmax_scale
import xgboost as xgb
import operator
import matplotlib.pyplot as plt
params={
    'booster':'gbtree',
    'objective': 'binary:logistic',
    'eval_metric':'logloss',
    'max_depth':8,
    'colsample_bytree': 1,
#    'lambda':1,
#    'eta':0.2,
#    'silent':0,
#    'alpha':3,
#    'subsample':1,
}
n_round=20

if __name__ == '__main__':

    t0 = time.time()
    train_data = load_pickle(path=cache_pkl_path +'train_data_onehot')
    train_Y = load_pickle(path=cache_pkl_path +'train_Y')
    cv_data = load_pickle(path=cache_pkl_path +'cv_data_onehot')
    cv_Y = load_pickle(path=cache_pkl_path +'cv_Y')

    test_data = load_pickle(path=cache_pkl_path +'test_data_onehot')
    test_file = 'round1_ijcai_18_test_a_20180301.txt'
    test = pd.read_table(raw_data_path + test_file,delim_whitespace=True)
    test_id = test.instance_id

    drop_cols = ['is_trade','user_id','shop_id','item_id','item_brand_id']
    train_data.drop(drop_cols,axis=1,inplace=True)
    cv_data.drop(drop_cols,axis=1,inplace=True)
    test_data.drop(drop_cols,axis=1,inplace=True)

    print('train shap:',train_data.shape)
    print('cv shape', cv_data.shape)
    print('test shape', test_data.shape)

    clf = LogisticRegression(C=0.5, fit_intercept=True, max_iter=1000,class_weight={0:0.5, 1:0.5})
    clf.fit(X=train_data.values, y=np.squeeze(train_Y))

    predict_train_fir = clf.predict_proba(train_data.values)[:,1]
    predict_cv_fir = clf.predict_proba(cv_data.values)[:,1]
    predict_test_fir = clf.predict_proba(test_data.values)[:,1]

    print('训练损失:',cal_log_loss(predict_train_fir, train_Y))
    print('测试损失:',cal_log_loss(predict_cv_fir, cv_Y))

    #把全量数据拿过来训练
    train_data_all = pd.concat([train_data, cv_data],axis=0)
    train_Y_all = np.append(train_Y, cv_Y)
    clf.fit(X=train_data_all.values, y=np.squeeze(train_Y_all))
    print('训练损失:',cal_log_loss(clf.predict_proba(train_data_all.values)[:,1], train_Y_all))
    predict_test_fir = clf.predict_proba(test_data.values)[:,1]

    #保存结果
    submission = pd.DataFrame({'instance_id':test_id,'predicted_score':predict_test_fir})
    print('预测正样本比例:',len(submission.loc[submission.predicted_score>=0.5])/len(submission))
    submission.to_csv(r'../result/LR_{}.txt'.format(datetime.datetime.now().strftime('%Y%m%d_%H%M%S')),
                  index=False, sep=' ',line_terminator='\r')
    #%%
    '''
    粗筛后删除分数较低的那些样本
    '''
    #按一定比例抽取概率较低的数据，作为LR的结果
    precent_2 = 0.96
    LR_cv_len = int(len(cv_data)*precent_2)
    LR_test_len = int(len(test_data)*precent_2)

    #LR的较低的分数直接拼接到最后的结果中
    predict_cv_df = pd.DataFrame({'col_index':cv_data.index,'score':predict_cv_fir})
    predict_cv_df.sort_values(by='score',inplace=True)
    predict_test_df = pd.DataFrame({'col_index':test_data.index,'score':predict_test_fir})
    predict_test_df.sort_values(by='score',inplace=True)

    LR_cv_score = predict_cv_df.iloc[0:LR_cv_len]
    LR_test_score = predict_test_df.iloc[0:LR_test_len]

    XGB_cv_index = predict_cv_df.iloc[LR_cv_len:]['col_index'].values
    XGB_test_index = predict_test_df.iloc[LR_test_len:]['col_index'].values

    #较难训练的样本的index 采用XGBoost来训练
    precent_1 = 0.65
    drop_len = int(len(train_data)*precent_1)

    predict_train_df = pd.DataFrame({'col_index':train_data.index,'score':predict_train_fir})
    predict_train_df.sort_values(by='score',inplace=True)

    #概率排名较低的前drop_len个样本中，如果label是0，则删除
    drop_index = predict_train_df.col_index[0:drop_len].apply(lambda x:(train_Y[x]==0))
    drop_index = drop_index[drop_index==True].index

    LR_train_score = predict_train_df.loc[drop_index]
    #得到保留下来的，较难训练的样本
    predict_train_df.drop(drop_index, inplace=True)
    reserved_index  = predict_train_df.col_index.values

    #读取XGBoost特征，训练数据
    train_data = load_pickle(path=cache_pkl_path +'train_data')
    cv_data = load_pickle(path=cache_pkl_path +'cv_data')
    test_data = load_pickle(path=cache_pkl_path +'test_data')

    train_data_sec = train_data.loc[reserved_index,:]
    train_Y_sec = train_Y[reserved_index]

    train_feat = xgb.DMatrix(train_data_sec.values, label=train_Y_sec)
    cv_feat = xgb.DMatrix(cv_data.values)
    test_feat = xgb.DMatrix(test_data.values)
    clf = xgb.train(params=params, dtrain=train_feat,num_boost_round=n_round)

    #得到XGBoost训练的结果
    predict_train_sec = clf.predict(train_feat)
    predict_cv_sec = clf.predict(cv_feat)
    predict_test_sec = clf.predict(test_feat)

    #把全量数据拿过来训练
#    train_data_all = pd.concat([train_data_sec, cv_data],axis=0)
#    train_Y_all = np.append(train_Y_sec, cv_Y)
#    train_feat_all = xgb.DMatrix(train_data_all.values, label=train_Y_all)
#    clf = xgb.train(params=params, dtrain=train_feat,num_boost_round=n_round)
#    predict_test_sec= clf.predict(test_feat)

    XGB_train_score = pd.DataFrame({'col_index':train_data_sec.index,'score':predict_train_sec})
    XGB_cv_score = pd.DataFrame({'col_index':cv_data.index,'score':predict_cv_sec})
    XGB_cv_score = XGB_cv_score.loc[XGB_cv_index]
    XGB_test_score = pd.DataFrame({'col_index':test_data.index,'score':predict_test_sec})
    XGB_test_score = XGB_test_score.loc[XGB_test_index]

    #将LR和XGBoost的结果混合
    train_score_all = pd.concat([LR_train_score, XGB_train_score],axis=0)
    train_score_all.sort_values(by='col_index',inplace=True)
    cv_score_all = pd.concat([LR_cv_score, XGB_cv_score],axis=0)
    cv_score_all.sort_values(by='col_index',inplace=True)
    test_score_all = pd.concat([LR_test_score, XGB_test_score],axis=0)
    test_score_all.sort_values(by='col_index',inplace=True)

    print('训练损失:',cal_log_loss(train_score_all.score.values, train_Y))
    print('测试损失:',cal_log_loss(cv_score_all.score.values, cv_Y))
    t1 = time.time()
    print('训练用时：',t1-t0)

    submission = pd.DataFrame({'instance_id':test_id,'predicted_score':test_score_all.score.values})
    print('预测正样本比例:',len(submission.loc[submission.predicted_score>=0.5])/len(submission))
    submission.to_csv(r'../result/LR_XGB_{}.txt'.format(datetime.datetime.now().strftime('%Y%m%d_%H%M%S')),
                  index=False, sep=' ',line_terminator='\r')