"""A group of score reels."""
from collections import deque
from mpf.core.system_wide_device import SystemWideDevice
from mpf.devices.score_reel_controller import ScoreReelController

class ScoreReelGroup(SystemWideDevice):

    """Represents a logical grouping of score reels in a pinball machine.

    Multiple individual ScoreReel object make up the individual digits of this
    group. This group also has support for the blank zero "inserts" that some
    machines use. This is a subclass of mpf.core.device.Device.
    """

    config_section = 'score_reel_groups'
    collection = 'score_reel_groups'
    class_label = 'score_reel_group'

    @classmethod
    def device_class_init(cls, machine):
        """If we have at least one score reel group, we need a ScoreReelController."""
        machine.score_reel_controller = ScoreReelController(machine)

    def __init__(self, machine, name):
        """Initialise score reel group."""
        super().__init__(machine, name)

        self.wait_for_valid_queue = None
        self.valid = True  # Confirmed reels are showing the right values
        self.unlight_on_resync_key = None
        self.light_on_valid_key = None

        self.reels = []
        # A list of individual ScoreReel objects that make up this
        # ScoreReelGroup. The number of items in the list correspondis to the
        # number of digits that can be displayed. A value of `None` indicates a
        # position that is not controlled by a moving reel (like a fake ones
        # digit).

        # Note that this is "backwards," with element 0 representing the ones
        # digit, element 1 representing the tens, etc..

        self.desired_value_list = []
        # A list of what values the machine desires to have the score reel
        # group set to.

        self.advance_queue = deque()
        # Holds a list of the next reels that for step advances.

        self.jump_in_progress = False
        # Boolean attribute that is True when a jump advance is in progress.

        self._tick_task = None

    def _initialize(self):
        self.reels = self.config['reels']
        self.reels.reverse()  # We want our smallest digit in the 0th element

        # ---- temp chimes code. todo move this --------------------
        self.config['chimes'].reverse()

        for i in range(len(self.config['chimes'])):

            if self.config['chimes'][i]:
                self.machine.events.add_handler(event='reel_' +
                                                      self.reels[
                                                          i].name + '_advance',
                                                handler=self.chime,
                                                chime=self.config['chimes'][i])
        # ---- temp chimes code end --------------------------------

        # register for events
        self.machine.events.add_handler('init_phase_4',
                                        self.initialize)

        self._tick_task = self.machine.clock.schedule_interval(self.tick, 0.01)

        # Need to hook this in case reels aren't done when ball ends
        self.machine.events.add_handler('ball_ending', self._ball_ending, 900)

    # ----- temp method for chime ------------------------------------
    @classmethod
    def chime(cls, chime, **kwargs):
        """Pulse chime."""
        del kwargs
        chime.pulse()

    # ---- temp chimes code end --------------------------------------

    @property
    def assumed_value_list(self):
        """Return list that holds the values of the reels in the group."""
        value_list = []
        for reel in self.reels:
            if reel:
                value_list.append(reel.assumed_value)
                # Used lambda above so this list will always lookup the latest
            else:
                value_list.append(None)
        return value_list

    @property
    def assumed_value_int(self):
        """Return integer representation of the value we assume is shown on this ScoreReelGroup.

        A value of -999 means the value is unknown.
        """
        return self.reel_list_to_int(self.assumed_value_list)

    def initialize(self, **kwargs):
        """Initialize the score reels by reading their current physical values and setting each reel's rollover reel.

        This is a separate method since it can't run int __iniit__() because all the other reels have to be setup first.
        """
        del kwargs
        self.get_physical_value_list()
        self.set_rollover_reels()

    def set_rollover_reels(self):
        """Call each reel's `set_rollover_reel` method and passes it a pointer to the next higher up reel.

        This is how we know whether we're able to advance the next higher up reel when a particular reel rolls
        over during a step advance.
        """
        for reel in range(len(self.reels)):
            if self.reels[reel] and (reel < len(self.reels) - 1):
                self.reels[reel].set_rollover_reel(self.reels[reel + 1])

    def tick(self):
        """Automatically called once per machine tick and checks to see if there are any jumps or advances in progress.

        If so, calls those methods.
        """
        if self.jump_in_progress:
            self._jump_advance_step()
        elif self.advance_queue:
            self._step_advance_step()
        elif not self.valid:
            self.validate()

    def is_desired_valid(self, notify_event=False):
        """Test to see whether the machine thinks the ScoreReelGroup is currently showing the desired value.

        In other words, is the ScoreReelGroup "done" moving? Note this ignores placeholder non-controllable digits.

        Returns: True or False
        """
        for i in range(len(self.reels)):
            if self.reels[i]:
                if self.assumed_value_list[i] != self.desired_value_list[i]:
                    if notify_event:
                        self.machine.events.post('reel_' +
                                                 self.reels[i].name +
                                                 '_resync')
                    return False

        '''event: reel_(name)_resync
        desc: The score reel (name) is not valid and will be resyncing.
        '''

        return True

    def get_physical_value_list(self):
        """Query all the reels in the group and builds a list of their actual current physical state.

        This is either the value of the current switch or -999 if no switch is active. This method also updates each
        reel's physical value.

        Returns: List of physical reel values.
        """
        output_list = []
        for reel in self.reels:
            if reel:
                output_list.append(reel.check_hw_switches())

        return output_list

    def validate(self, value=None):
        """Validate that this score reel group is in the position the machine wants it to be in.

        If lazy or strict confirm is enabled, this method will also make sure
        the reels are in their proper physical positions.

        Args:
            value (ignored): This method takes an argument of `value`, but
                it's not used. It's only there because when reels post their
                events after they're done moving, they include a parameter of
                `value` which is the position they're in. So we just need to
                have this argument listed so we can use this method as an event
                handler for those events.
        """
        del value

        self.debug_log("Checking to see if score reels are valid.")

        # Can't validate until the reels are done moving. This shouldn't happen
        # but we look for it just in case.
        if self.jump_in_progress or self.advance_queue:
            return False

        # If any reels are set to lazy or strict confirm, we're only going to
        # validate if they've hw_confirmed
        for reel in self.reels:

            if reel and (reel.config['confirm'] == 'lazy' or reel.config['confirm'] == 'strict') and not reel.hw_sync:
                return False  # need hw_sync to proceed

        self.debug_log("Desired list: %s", self.desired_value_list)
        self.debug_log("Assumed list: %s", self.assumed_value_list)
        self.debug_log("Assumed integer: %s", self.assumed_value_int)

        try:
            self.debug_log("Player's Score: %s", self.machine.game.player.score)
        except AttributeError:
            pass

        # todo if confirm is set to none, should we at least wait until the
        # coils are not energized to validate?

        if not self.is_desired_valid(notify_event=True):
            # FYI each reel will hw check during hw_sync, so if there's a
            # misfire that we can know about then it will be caught here
            self.machine.events.post('scorereelgroup_' + self.name + '_resync')
            '''event: scorereelgroup_(name)_resync
            desc: The score reel group (name) is not valid and will be
            resyncing.
            '''
            self.set_value(value_list=self.desired_value_list)
            return False

        self.valid = True
        self.machine.events.post('scorereelgroup_' + self.name + '_valid',
                                 value=self.assumed_value_int)
        '''event: scorereelgroup_(name)_valid
        desc: The score reall group (name) is valid.
        args:
        value: The integer value this score reel group is assumed to be at.
        '''

        if self.wait_for_valid_queue:
            self.debug_log("Found a wait queue. Clearing now.")
            self.wait_for_valid_queue.clear()
            self.wait_for_valid_queue = None

        return True

    def add_value(self, value, jump=False, target=None):
        """Add value to a ScoreReelGroup.

        You can also pass a negative value to subtract points.

        You can control the logistics of how these pulses are applied via the
        `jump` parameter. If jump is False (default), then this method will
        respect the proper "sequencing" of reel advances. For example, if the
        current value is 1700 and the new value is 2200, this method will fire
        the hundreds reel twice (to go to 1800 then 1900), then on the third
        pulse it will fire the thousands and hundreds (to go to 2000), then do
        the final two pulses to land at 2200.

        Args:
            value: The integer value you'd like to add to (or subtract
                from) the current value

            jump: Optional boolean value which controls whether the reels should
                "count up" to the new value in the classic EM way (jump=False)
                or whether they should just jump there as fast as they can
                (jump=True). Default is False.
            target: Optional integer that's the target for where this reel group
                should end up after it's done advancing. If this is not
                specified then the target value will be calculated based on the
                current reel positions, though sometimes this get's wonky if the
                reel is jumping or moving, so it's best to specify the target if
                you can.
        """
        self.debug_log("Adding '%s' to the displayed value. Jump=%s", value,
                       jump)

        # As a starting point, we'll base our assumed current value of the reels
        # based on whatever the machine thinks they are. This is subject to
        # change, which is why we use our own variable here.
        current_reel_value = self.assumed_value_int

        if self.jump_in_progress:
            self.debug_log("There's a jump in progress, so we'll just change "
                           "the target of the jump to include our values.")
            # We'll base our desired value off whatever the reel is advancing
            # plus our value, because since there's a jump in progress we have
            # no idea where the reels are at this exact moment
            current_reel_value = self.reel_list_to_int(self.desired_value_list)
            jump = True

        if current_reel_value == - 999:
            self.debug_log("Current displayed value is unkown, "
                           "so we're jumping to the new value.")
            current_reel_value = 0
            jump = True

        # If we have a target, yay! (And thank you to whatever called this!!)
        # If not we have to use our current_reel_value as the baseline which is
        # fine, but it makes a lot of assumptions
        if target is None:
            target = current_reel_value + value

        elif value < 0:
            self.debug_log("add_value is negative, so we're subtracting this "
                           "value. We will do this via a jump.")
            jump = True

        # If we have to jump to this new value (for whatever reason), go for it
        if jump:
            self.set_value(target)

        # Otherwise we can do the cool step-wise advance
        else:
            self.desired_value_list = self.int_to_reel_list(target)
            self._step_advance_add_steps(value)

    def set_value(self, value=None, value_list=None):
        """Reset the score reel group to display the value passed.

        This method will "jump" the score reel group to display the value
        that's passed as an it. (Note this "jump" technique means it will just
        move the reels as fast as it can, and nonsensical values might show up
        on the reel while the movement is in progress.)

        This method is used to "reset" a reel group to all zeros at the
        beginning of a game, and can also be used to reset a reel group that is
        confused or to switch a reel to the new player's score if multiple
        players a sharing the same reel group.

        Note you can choose to pass either an integer representation of the
        value, or a value list.

        Args:
            value: An integer value of what the new displayed value (i.e. score)
                should be. This is the default option if you only pass a single
                positional argument, e.g. `set_value(2100)`.
            value_list: A list of the value you'd like the reel group to
                display.
        """
        if value is None and value_list is None:
            return  # we can't do anything here if we don't get a new value

        if value_list is None:
            value_list = self.int_to_reel_list(value)

        self.debug_log("Jumping to %s.", value_list)

        # set the new desired value which we'll use to verify the reels land
        # where we want them to.
        self.desired_value_list = value_list
        self.debug_log("set_value() just set DVL to: %s",
                       self.desired_value_list)

        self._jump_advance_step()

    def _jump_advance_step(self):
        # Checks the assumed values of the reels in the group, and if they're
        # off will automatically correct them.

        self.jump_in_progress = True
        self.valid = False

        if self.is_desired_valid():
            self.debug_log("They match! Jump is done.")
            self._jump_advance_complete()
            return

        reels_needing_advance = []  # reels that need to be advanced
        num_energized = 0  # count of the number of coils currently energized
        current_time = self.machine.clock.get_time()  # local reference for speed
        # loop through the reels one by one
        for i in range(len(self.reels)):
            this_reel = self.reels[i]  # local reference for speed
            if this_reel:

                # While we're in here let's get a count of the total number
                # of reels that are energized
                if this_reel.config['coil_inc'].time_when_done > current_time:
                    num_energized += 1

                # Does this reel want to be advanced, and is it ready?
                if self.desired_value_list[i] != self.assumed_value_list[i] and this_reel.ready:
                    # Do we need (and have) hw_sync to advance this reel?

                    if self.assumed_value_list[i] == -999 or this_reel.config['confirm'] == 'strict':

                        if this_reel.hw_sync:
                            reels_needing_advance.append(this_reel)

                    elif this_reel.ready:
                        reels_needing_advance.append(this_reel)

        # How many reels can we advance now?
        coils_this_round = (self.config['max_simultaneous_coils'] -
                            num_energized)

        # sort by last firing time, oldest first (so those are fired first)
        reels_needing_advance.sort(key=lambda x: x.next_pulse_time)

        if len(reels_needing_advance) < coils_this_round:
            coils_this_round = len(reels_needing_advance)

        for i in range(coils_this_round):
            reels_needing_advance[i].advance()

            # Any leftover reels that don't get fired this time will get picked up
            # whenever the next reel changes state and this method is called again.

    def _jump_advance_complete(self):
        # Called when a jump advance routine is complete and the score reel
        # group has been validated.

        self.debug_log("Jump complete")
        self.debug_log("Assumed values: %s", self.assumed_value_list)
        self.debug_log("Desired values: %s", self.desired_value_list)

        self.jump_in_progress = False

    def _step_advance_add_steps(self, value):
        # Receives an integer value, converts it to steps, adds them to the
        # step queue, and kicks off the step advance process. For example,
        # adding a value of 210 would result the following items added to the
        # advance queue: [coil_10, coil_100, coil_100]

        value_list = self.int_to_reel_list(value)

        self.debug_log("Will add '%s' to this reel group", value)

        for position, value in enumerate(value_list):
            if value:
                for dummy_num in range(value):
                    self.advance_queue.append(self.reels[position])

        # if there's a jump in progress we don't want to step on it, so we'll
        # just do nothing more here and _step_advance_step will be called when
        # the jump is done since we have entries in the advance queue
        if not self.jump_in_progress:
            self._step_advance_step()

    def _step_advance_step(self):
        # Attempts to kick off any advances that are in the advance_queue, but
        # that's not also possible. (For example, all the reels might be busy.)

        # todo if reel status is bad, do something

        if not self.advance_queue:
            self.validate()
            return

        self.valid = False

        # set our working reel to be the next one in the queue
        reel = self.advance_queue[0]

        # Check to see if this reel is ready. "Ready" depends on whether we're
        # using strict confirmation or not.

        # todo what if the hw is -999. Then we should return if we don't have
        # hw_sync also, right?

        if reel.config['confirm'] == 'strict' and not reel.hw_sync:
            return
        elif not reel.ready:
            return

        # is this real going to need a buddy pulse?
        self.debug_log("Reel: %s, Limit: %s, Current assumed value: %s",
                       reel.name, reel.config['limit_hi'], reel.assumed_value)
        if (reel.config['limit_hi'] == reel.assumed_value and
                not reel.rollover_reel_advanced):
            buddy_pulse = True
            # track that we've already ordered the buddy pulse so it doesn't
            # happen twice if this reel can't fire now for some reason
            reel.rollover_reel_advanced = True
            self.debug_log("Setting buddy pulse")
        else:
            buddy_pulse = False

        # todo we may not need the rollover_reel_advanced tracker anymore since
        # we wrapped the reel.advance below in an if block.

        # remove this reel from our queue from the queue
        self.advance_queue.popleft()

        # try to advance the reel, We use `if` here so this code block only runs
        # if the reel accepted our advance request
        if reel.advance():
            self.debug_log("Reel '%s' accepted advance", reel.name)
            self.debug_log("Reels (assumed): %s", self.assumed_value_int)
            try:
                self.debug_log("Score: %s",
                               self.machine.game.player.score)
            except AttributeError:
                pass
            self.machine.events.post('reel_' + reel.name + "_advance")
            # todo should this advance event be posted here? Or by the reel?
            '''event: reel_(name)_advance
            desc: The score reel (name) is advancing.
            '''

            # Add the reel's buddy to the advance queue
            if buddy_pulse:
                # insert the rollover reel
                if reel.rollover_reel:
                    self.advance_queue.appendleft(reel.rollover_reel)
                    # run through this again now so we pulse the buddy reel
                    # immediately (assuming we don't have too many pulsing
                    # currently, etc.)
                    self._step_advance_step()
                else:
                    # whoops, we don't have a rollover reel. Yay for player!
                    self.machine.events.post('scorereelgroup_' + self.name +
                                             '_rollover')
                    '''event: scorereelgroup_(name)_rollover
                    desc: The score reel group (name) has just rolled over,
                    meaning it exceeded its mechanical limit and rolled over
                    past zero.'''

        else:  # the reel did not accept the advance. Put it back in the queue
            self.advance_queue.appendleft(reel)
            self.debug_log("Reel '%s' rejected advance. We'll try again.",
                           reel.name)

    def int_to_reel_list(self, value):
        """Convert an integer to a list of integers that represent each positional digit in this ScoreReelGroup.

        The list returned is in reverse order. (See the example below.)

        The list returned is customized for this ScoreReelGroup both in terms
        of number of elements and values of `None` used to represent blank
        plastic zero inserts that are not controlled by a score reel unit.

        For example, if you have a 5-digit score reel group that has 4
        phyiscial reels in the tens through ten-thousands position and a fake
        plastic "0" insert for the ones position, if you pass this method a
        value of `12300`, it will return `[None, 0, 3, 2, 1]`

        This method will pad shorter ints with zeros, and it will chop off
        leading digits for ints that are too long. (For example, if you pass a
        value of 10000 to a ScoreReelGroup which only has 4 digits, the
        returns list would correspond to 0000, since your score reel unit has
        rolled over.)

        Args:
            value: The interger value you'd like to convert.

        Returns:
            A list containing the values for each corresponding score reel,
            with the lowest reel digit position in list position 0.

        """
        if value == -999:
            value = 0
            # todo hack

        output_list = []

        # convert our number to a string
        str_value = str(value)

        # pad the string with leading zeros
        str_value = str_value.zfill(len(self.reels))

        # slice off excess characters if the value is longer than num of reels

        # how many digits do we have to slice?
        trim = len(str_value) - len(self.reels)
        # and... slice!
        str_value = str_value[trim:]

        # todo if we don't do the above trim then it will just show the highest
        # digits, effective "shifting" the score by one. Might be a fun feature?

        # generate our list with one digit per item
        for digit in str_value:
            output_list.append(int(digit))

        # reverse the list so the least significant is first
        output_list.reverse()

        # replace fake position digits with `None`
        for i, dummy_output in enumerate(output_list):
            if not self.reels[i]:
                output_list[i] = None

        return output_list

    @classmethod
    def reel_list_to_int(cls, reel_list):
        """Convert an list of integers to a single integer.

        This method is like `int_to_reel_list` except that it works in the
        opposite direction.

        The list inputted is expected to be in "reverse" order, with the ones
        digit in the [0] index position. Values of `None` are converted to
        zeros. For example, if you pass `[None, 0, 3, 2, 1]`, this method will
        return an integer value of `12300`.

        Note this method does not take into consideration how many reel
        positions are in this ScoreReelGroup. It just converts whatever you
        pass it.

        Args:
            reel_list: The list containing the values for each score reel
                position.

        Returns:
            The resultant integer based on the list passed.
        """
        # reverse the list so it's in normal order
        reel_list.reverse()
        output = ""

        for item in reel_list:
            if isinstance(item, int):
                if item == -999:  # if any reels are unknown, then our int
                    return -999  # is unkown too.
                else:
                    output += str(item)
            elif isinstance(item, str) and item.isdigit():
                # Just in case we have an number that's a string
                output += str(int(item))  # ensure no leading zeros
            else:
                output += "0"
        return int(output)

    def light(self, relight_on_valid=False, **kwargs):
        """Light up this ScoreReelGroup based on the 'light_tag' in its config."""
        del kwargs
        self.debug_log("Turning on Lights")
        for light in self.machine.lights.items_tagged(
                self.config['lights_tag']):
            light.on()

        # Watch for these reels going out of sync so we can turn off the lights
        # while they're resyncing

        if self.unlight_on_resync_key:
            self.machine.events.remove_handler_by_key(self.unlight_on_resync_key)

        self.unlight_on_resync_key = self.machine.events.add_handler(
            'scorereelgroup_' + self.name + '_resync',
            self.unlight,
            relight_on_valid=True)

        if relight_on_valid:
            self.machine.events.remove_handler_by_key(self.light_on_valid_key)

    def unlight(self, relight_on_valid=False, **kwargs):
        """Turn off the lights for this ScoreReelGroup based on the 'light_tag' in its config."""
        del kwargs
        self.debug_log("Turning off Lights")
        for light in self.machine.lights.items_tagged(
                self.config['lights_tag']):
            light.off()

        if relight_on_valid:
            if self.light_on_valid_key:
                self.machine.events.remove_handler_by_key(self.light_on_valid_key)
            self.light_on_valid_key = self.machine.events.add_handler(
                'scorereelgroup_' + self.name + '_valid',
                self.light,
                relight_on_valid=True)
        elif self.unlight_on_resync_key:
            self.machine.events.remove_handler_by_key(
                self.unlight_on_resync_key)

    def _ball_ending(self, queue=None, **kwargs):
        del kwargs
        # We need to hook the ball_ending event in case the ball ends while the
        # score reel is still catching up.

        # only do this if this is the active group
        if self.machine.score_reel_controller.active_scorereelgroup != self:
            return

        if not self.valid:
            self.debug_log("Score reel group is not valid. Setting a queue")
            self.wait_for_valid_queue = queue
            self.wait_for_valid_queue.wait()
        else:
            self.debug_log("Score reel group is valid. No queue needed.")


#!/usr/bin/env python3
import functools
import sys

def compare(x, y):
    if x['difference'] > y['difference']:
        return -1
    elif x['difference'] < y['difference']:
        return 1
    elif x['weight'] > y['weight']:
        return -1
    return 1

def main():
    with open(sys.argv[1]) as f:
        num = int(next(f))
        data = []
        for l in f:
            weight, length = l.split(' ')
            weight = int(weight.strip())
            length = int(length.strip())
            data.append({
                'weight': weight,
                'length': length,
                'difference': weight - length
            })
    data = sorted(data, key=functools.cmp_to_key(compare))

    completion = 0
    time = 0
    for item in data:
        time += item['length']
        completion += time * item['weight']
    print('ans = {}'.format(completion))

if __name__ == '__main__':
    main()


#! /usr/bin/env python
# encoding: utf-8

######################
###### options #######
######################
def options (opt):
	opt.add_option ("--with-sip", action="store_true",
			dest="WITH_SIP", help = "Use Semi-infinite programming plugin")

	opt.plugins["sip"] = "WITH_SIP"

######################
##### configure ######
######################
def configure (conf):
	conf.env.WITH_SIP = conf.options.WITH_SIP

	conf.start_msg ("Semi-infinite programming plugin")
	if not conf.env.WITH_SIP:
		conf.end_msg ("not used")
		return

	conf.end_msg ("enabled")

	conf.env.append_unique ("IBEX_PLUGIN_USE_LIST", "SIP")

	# Add information in ibex_Setting
	conf.setting_define ("WITH_SIP", 1)

	# add SIP plugin include directory
	for f in conf.path.ant_glob ("src/** src", dir = True, src = False):
		conf.env.append_unique("INCLUDES_SIP", f.abspath())

	# The build and install steps will be run from the main src/wscript script so
	# we need to give path relative to the main src directory
	mainsrc = conf.srcnode.make_node ("src")

	# add SIP headers
	for f in conf.path.ant_glob ("src/**/ibex_*.h"):
		conf.env.append_unique ("IBEX_HDR", f.path_from (mainsrc))

	# add SIP source files
	for f in conf.path.ant_glob ("src/**/ibex_*.cpp"):
		conf.env.append_unique ("IBEX_SRC", f.path_from (mainsrc))

	# The utest step will be run from the main tests/wscript script so we need to
	# give path relative to the main tests directory
	maintests = conf.srcnode.make_node ("tests")

	# add SIP test files
	for f in conf.path.ant_glob ("tests/**/*.cpp"):
		conf.env.append_unique ('TEST_SRC', f.path_from (maintests))

	# Add sip/tests directory to list of INCLUDES for TESTS
	testsnode = conf.path.make_node ("tests")
	conf.env.append_unique ("INCLUDES_TESTS", testsnode.abspath ())

######################
####### build ########
######################
def build (bld):

	if bld.env.WITH_SIP:
		# build solver binary
		bld.program (
		target = "ibexsip",
		use = [ "ibex" ], # add dependency on ibex library
		source = bld.path.ant_glob ("main/ibexsip.cpp"),
		install_path = bld.env.BINDIR,
		)
		bld.program (
		target = "ibexopt-sip",
		use = [ "ibex" ], # add dependency on ibex library
		source = bld.path.ant_glob ("main/optimizer.cpp"),
		install_path = bld.env.BINDIR,
		)
		bld.program (
		target = "ibexsolve-sip",
		use = [ "ibex" ], # add dependency on ibex library
		source = bld.path.ant_glob ("main/solver.cpp"),
		install_path = bld.env.BINDIR,
		)


""" A collection of functions for game evolving population"""

import random as rd
import string
import numpy
import array
import pandas
from matplotlib import pyplot as plt

game_results = numpy.array([[[2, 2], [3, 0]], [[0, 3], [1, 1]]]) #an array of outcomes/payoffs of the games

decision_list = ['Cooperate', 'Compete']

payoff_matrix = pandas.DataFrame([[[2, 2], [3, 0]], [[0, 3], [1, 1]]], decision_list, decision_list) #payoff matrix for visual appeal in the notebook, no functional purpose

class Agent():
    """A class which stores all the unique instances of agents in our population, each with their own attributes which can then be called forth to allow for game play and descriptive statistics of the population"""

    start_range = 0
    end_range = 100

    #attributes unique to each instance, determine the probability of the agent to cooperat
    def __init__(self, start_range=0, end_range=100, strat_val=50):
        self.start_range = start_range
        self.end_range = end_range
        self.strat_val = strat_val #percent chance (out of 100) that the agent will cooperate

    #method which produces a new outcome each time it is called. The outcome in particular is the decision an agent makes in a game whether to cooperate or compete. It is determined by the strat_val
    def make_decision(self):
        strategy = rd.randrange(self.start_range, self.end_range)
        if strategy < self.strat_val:
            return 0 #"Cooperate"
        elif strategy >= self.strat_val:
            return 1 #"Compete"

#population = {}

def generate_initial_population(n=2, strat_val=50):
    """adds n agents with a default strat_val to the population."""
    population = {}
    for i in range(0, n):

        population['Ag{0}'.format(i)] = Agent(strat_val=strat_val)

    return population

def game_play(agent1, agent2):
    """uses the decision of two agents to return an outcome of a game. The outcome is constructed by indexing from possible outcomes in game_results"""
    ag1 = agent1.make_decision()
    ag2 = agent2.make_decision()

    outcome = game_results[ag1, ag2]

    return outcome

def replicate(agent1, agent2, outcome, population):
    """ Function which adds new agents to the population who inherit the probability of cooperating from their parents, as well as becoming slightly more or less cooperative based on the decision their parents made """

    #the parents are the two agents who played the game and produced an outcome
    parents = (agent1, agent2)
    for agent in parents:

        if outcome[parents.index(agent)]%2 == 0:  #check if the agent cooperated(even result) or competed(odd result) to determine how whether or not the offspring would be more or less cooperative

            for i in range(0, outcome[parents.index(agent)]): #take the index of the parent to determine what the corresponding outcome was, so if the first indivdidual won 3, that will be the end of the range for the for-loop

                population['Ag{0}'.format(len(population)+1)] = Agent(strat_val=agent1.strat_val + 2) #add new agent to population

        elif outcome[parents.index(agent)]%2 == 1: #same as above but for outcomes where parent agent competed

             for i in range(0, outcome[parents.index(agent)]):

                population['Ag{0}'.format(len(population)+1)] = Agent(strat_val=agent1.strat_val - 2)

    return population

def design_game(population, max_generation):
    """ This function is what causes the population to grow, replicating all agents in the population """

    current_generation = 0
    while current_generation < max_generation: #while loop ensures that the requested number of new generations are created

        pop = population.copy() #make a copy of the population because we are appending to our old population, and don't want parents to play games with their newborns

        # for loop which takes each agent in the population, assigns them to play a game against a random agent within the population

        for agent in pop:

            another_agent = rd.choice(list(pop)) #choose random agent from the population

            a = ''.join(another_agent) #removes the quotation marks from our choice so we're left with just the string object

            replicate(population[agent], population[a], game_play(population[agent], population[a]), population) #produce offspring using the two agents and the outcome of a game they played

        print(current_generation)

        current_generation += 1

    return population
def make_histogram(population):
    """constructs a histogram of all the strat_val's of each agent, to see the distribution of cooperative to competitive agents"""
    population_outputs = []

    #for loop which adds the strat_val's to a list
    for agent in population:

        population_outputs.append(population[agent].strat_val)

    #makes a histogram
    plt.hist(population_outputs)
    plt.xlabel('Percent Chance to Cooperate')
    plt.ylabel('Number of Agents')
    plt.title('Population Cooperativeness')
    plt.show(population_outputs)

    #descriptive statistics
    print('The average is = %f'  %numpy.mean(population_outputs))

    print('The median is = %d' %numpy.median(population_outputs))

    print('The standard deviation is = %f' %numpy.std(population_outputs))


# coding=utf-8
# @author:bryan
"""
使用全量数据提取特征，点击数，交叉点击数，占比
"""
import pandas as pd

def full_count_feature(org,name):
    cols=['user_id', 'item_id', 'item_brand_id', 'shop_id', 'item_category_list', 'item_city_id', 'cate', 'top10',
           'predict_category_property', 'context_page_id', 'query1', 'query']
    train=org[org.day==7][['instance_id'] + cols]
    if name=='day6':
        data = org[org.day==6][cols]
    elif name=='days7':
        data=org[org.day<7][cols]
    elif name == 'day7':
        data = org[org.day == 7][cols]
    elif name=='full':
        data=org[cols]

    for col in cols:
        print(col)
        train=pd.merge(train, data.groupby(col, as_index=False)['user_id'].agg({'_'.join([name, col, 'cnt']): 'count'}), on=col, how='left')

    for cross_col in range(len(cols)):
        for j in range(cross_col + 1, len(cols)):
            con_col=[cols[cross_col], cols[j]]
            print(con_col)
            tmp = data.groupby(con_col, as_index=False)['user_id'].agg({'_'.join([name, cols[cross_col], cols[j], 'cnt']): 'count'})
            train = pd.merge(train, tmp, on=con_col, how='left')

    cross_cols=[['user_id','query'],
               ['user_id','query1'],
               ['user_id','shop_id'],
               ['user_id','item_id'],
               ['item_id','shop_id'],
               ['item_id', 'item_brand_id'],
               ['item_brand_id', 'shop_id'],
               ['item_id','item_category_list'],
               ['item_id','query'],
               [ 'item_id','item_city_id'],
               ['item_id','cate'],
               ['item_id','top10'],
               ['item_id','context_page_id'],
               ['item_id','query1'],
               ['item_brand_id', 'shop_id'],
               ['shop_id','item_city_id'],
               [ 'shop_id','context_page_id']
              ]

    for cross_col in cross_cols:
        print(cross_col)
        train['_'.join(cross_col + ['cross'])]= train['_'.join([name, cross_col[0], cross_col[1], 'cnt'])] / train['_'.join([name, cross_col[1], 'cnt'])]

    train=train.drop(cols, axis=1)
    train.to_csv('../data/'+name+'_count_feature.csv',index=False)
    # return train

if __name__ == '__main__':
    org=pd.read_csv('../data/origion_concat.csv')
    full_count_feature(org, 'day6')
    full_count_feature(org, 'days7')
    full_count_feature(org, 'full')


import numpy as np

def second_sorting_func(inp):
    numbers_array = np.array(inp, int)
    max_value = numbers_array[0]  # переменная для хранения максимального числа для определения количества разрядов
    global_digits_amount = 0  # переменная для числа разрядов
    swap_index = 0  # переменная для индекса свопа
    d = []  # массив для хранения начальных чисел
    for i in range(1, numbers_array.size):  # определяем максимально большое число для нахождения чмсла разрядов
        if max_value < numbers_array[i]:
            max_value = numbers_array[i]
    while max_value != 0:  # записываем сколько разрядов в максимальном числе
        max_value = max_value // 10  # находим последнюю цифру числа
        global_digits_amount += 1
    for i in range(
            numbers_array.size):  # добавляем недостающие разряды для каждого элемента массива если это необходимо
        max_value = int(numbers_array[i])
        digits_amount = 0
        while max_value != 0:
            max_value = max_value // 10
            digits_amount += 1
        if digits_amount != global_digits_amount:  # сравниваем отличается ли количество разрядов,
            last_digit = int(numbers_array[i]) % 10  # если да, то находим последнюю цифру
            d[i] = numbers_array[i]
            for j in range(digits_amount + 1, global_digits_amount + 1):  # и добавляем её в конец нужное количество раз
                numbers_array[i] = numbers_array[i] * 10 + last_digit
        else:
            d[i] = numbers_array[i]
    while swap_index != numbers_array.size:  # делаем сортировку. Находим максимальное значение и ставим его на
        max_value = numbers_array[swap_index]  # первую позицию. После этого сдвигаем позицию.
        max_value_id = swap_index
        for i in range(swap_index, numbers_array.size):
            if max_value < numbers_array[i]:
                max_value = numbers_array[i]
                max_value_id = i
        buf = numbers_array[swap_index]
        numbers_array[swap_index] = numbers_array[max_value_id]
        numbers_array[max_value_id] = buf
        buf = d[swap_index]
        d[swap_index] = d[max_value_id]
        d[max_value_id] = buf
        swap_index += 1
    for i in range(numbers_array.size):  # выводим значения вспомогательного массива
        print(d[i], end="")

def main_sorting_func(inp):
    return 0  # пока не готово
    np.set_printoptions(threshold=np.nan)  # Для полного отображения массива

    numbers_array = np.array(inp, int)
    current_number = 9
    swap_amount = 0
    swap_position = 0  # Переменная для указания места куда пойдёт своп
    action_id = 0

    while swap_position != numbers_array.size:
        for i in range(swap_position, numbers_array.size):
            pass

    print(numbers_array)
    print("End")

if __name__ == "__main__":
    # print("Inert numbers divided by space: ")
    # second_sorting_func(np.array(input().split()).astype(int))
    second_sorting_func(np.array([6, 5, 4, 3, 2, 1]))


import json

class User(dict):
    id: int
    email: str
    firstname: str
    lastname: str

    def __init__(self, jpayload: bytes):
        super().__init__()
        if jpayload is None:
            self.id = 0
            self.email = ""
            self.firstname = ""
            self.lastname = ""
            return
        userdict = json.loads(str(jpayload, 'utf8'))
        self.id = userdict['id']
        self.email = userdict['email']
        self.firstname = userdict['firstname']
        self.lastname = userdict['lastname']

    def jsonify(self):
        self['id'] = self.id
        self['email'] = self.email
        self['firstname'] = self.firstname
        self['lastname'] = self.lastname
        return self


import rospy
from mavros_msgs.msg import GlobalPositionTarget, State, PositionTarget
from mavros_msgs.srv import CommandBool, CommandTOL, SetMode
from geometry_msgs.msg import PoseStamped, Twist, TwistStamped
from sensor_msgs.msg import Imu, NavSatFix
from std_msgs.msg import Float32, String
import time
import math

def velocityPositionCallback(velocityPositionCallback):
    global vx
    global vy
    vx = velocityPositionCallback.vx
    vy = velocityPositionCallback.vy

class ardupilot_controller:
    def __init__(self):
        #service
        self.flightModeService = rospy.ServiceProxy('/mavros/set_mode', SetMode)
        self.armService = rospy.ServiceProxy('/mavros/cmd/arming', CommandBool)
        self.takeoffService = rospy.ServiceProxy('/mavros/cmd/takeoff', CommandTOL)
        #sub
        rospy.Subscriber("/mavros/local_position/velocity", TwistStamped, velocityPositionCallback)
    def mode(self):
        if self.flightModeService(custom_mode='GUIDED'):
            return True
        else:
            return False

    def land(self):
        if self.flightModeService(custom_mode='LAND'):
            return True
        else:
            return False

    def arm(self):
        if self.armService(True):
            return True
        else:
            return False
    def takeoff(self):
        if self.takeoffService(altitude = 3):
            return True
        else:
            return False

    def velocity_location(self, vx, vy):
        rospy.init_node('anadolu_kartali')
        guided_waypoint_pub = rospy.Publisher('/mavros/setpoint_raw/local', PositionTarget, queue_size=1)
        while guided_waypoint_pub.get_num_connections() == 0:
            time.sleep(.1)
        g = PositionTarget()

        g.velocity.x = vx
        g.velocity.y = vy

        g.type_mask = int('110111000111', 2)
        g.coordinate_frame= 9

        global velocity

        guided_waypoint_pub.publish(g)

###################################################
if __name__ == '__main__':
    con = ardupilot_controller()
    con.mode()
    con.arm()
    con.takeoff()
    time.sleep(15)

    con.velocity_location(5,0)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 19 21:58:32 2017

@author: PeterTsai
"""
import os
import scipy.io
import numpy as np

def read(datadir, fileName):
    #print(os.path.join(os.path.sep,os.getcwd(),datadir,fileName))

    #print(os.path.exists(os.path.join(os.path.sep,os.getcwd(),datadir,fileName)))
    mat = scipy.io.loadmat(os.path.join(os.path.sep,os.getcwd(),datadir,fileName))

    #print(mat['bags'].shape)
    #print(mat['bags']['instance'].shape)
    #print(mat['bags']['instance'].dtype)
    #print(mat['bags']['instance'][0][0].shape)
    bags = mat['bags']

    #strHello = "the length of (%s) is %d" %('Hello World',len('Hello World'))
    #print(strHello)

#    strBagShape = "the shape of bags is ({0},{1})".format(bags.shape[0],bags.shape[1])
#    print(strBagShape)
    #print(bags.shape)

    bagNum = len(bags['instance'][0])
    instNum, featDim = (bags['instance'][0][0]).shape
    X = np.zeros([bagNum,instNum,featDim])
    #print(len(bags['instance'][0]))
    #for b in range(len(bags['instance'][0])):
    #    X = bags['instance'][0,b]
    #    print(np.sum(X,axis=1))
    #    Bag1 = np.array(bags['instance'][0][0])
    #    print(np.sum(Bag1,axis=1))
    #X = np.array(bags['instance'])
    for b in range(len(bags['instance'][0])):
        X[b,:,:] = bags['instance'][0,b]

    #print(len(bags['inst_label'][0]))
    Y = np.zeros((len(bags['label'][0]),1))
    for b in range(len(bags['label'][0])):
        Y[b] = int(bags['label'][0][b])

    labels = np.zeros([bagNum,instNum])
    for i in range(len(bags['inst_label'][0,:])):
        labels[i,:] = np.squeeze(bags['inst_label'][0][i][0])
        #print(label.shape)
        #print(label.dtype)
        #print(label)
        #print(np.sum(label,axis=1))

    #print(Y)
    return X,Y,labels

def multi_class_read(datadir,file_str,num_inst,dataset):
    instIdx = np.insert(np.cumsum(num_inst),0,0)
    newIdx = 0
    for k in range(len(dataset.k)):
        for c in range(len(dataset.C5k_CLASS[k])):
            tactic = dataset.tacticName[dataset.C5k_CLASS[k][c]]
            fileName= file_str.format(tactic,dataset.k[k])
            data_X, data_Y, data_KIlabel = read(datadir,fileName)
            data_KPlabel = Inst2Player(data_KIlabel,dataset.playerMap[k])
            if k == 0 and c == 0:
                multi_X = np.zeros([data_X.shape[0],np.sum(num_inst),data_X.shape[2]])
                multi_Y = np.zeros([data_Y.shape[0],len(dataset.tacticName)])
                multi_KPlabel = np.zeros([len(data_KIlabel),5])

            if c == 0:
                multi_X[:,instIdx[k]:instIdx[k+1],:] = data_X

            # change original tactic order to multi-mi-Net order
            multi_Y[:,newIdx:newIdx+1] = data_Y
            #KP outside positive bag is 0, so we can use addition to replace concatenate
            multi_KPlabel = multi_KPlabel + data_KPlabel
            newIdx = newIdx+1
            #multi_KPlabel
    return multi_X, multi_Y, multi_KPlabel

def Inst2Player(KIlabel,playerMap):
    KPlabel = np.zeros([len(KIlabel),5])
    vid, inst = np.nonzero(KIlabel)
    for v in range(len(vid)):
        KPlabel[vid[v],:] = playerMap[inst[v]]

    return KPlabel

if __name__ == "__main__":
    datadir = 'dataGood/multiPlayers/syncLargeZoneVelocitySoftAssign(R=16,s=10)'
    fileName = 'EVZoneVelocitySoftAssign(R=16,s=10)3.mat'

    X_batch, Y_batch = read(datadir,fileName)
    #print(X_batch[:,1])
    #print(type(X_batch))
    #print(type(Y_batch))


'''
immutable.py

'''

spam = [1,2,3,4,5]
eggs = spam
eggs[0] = 'Hello'
print(eggs)
print(spam)

spam1 = [1,2,3,4,5,6]
eggs1 = spam1[:]
eggs1[0] = 'yoyoyo'

print(eggs1)
print(spam1)

def change(value):
    value = value[:]
    value.append('yoy')
    return value

new = change(spam1)

print(spam1)
print(new)


"""
Add coreference information to the GENIA data set.

Also remove blacklisted documents, for which the merge didn't go correctly and off-by-one-errors
were introduced.
"""

from collections import defaultdict

from os import path
import os
import glob
import re
import json
from bs4 import BeautifulSoup as BS
import pandas as pd
import argparse

import shared
import copy

from stanfordcorenlp import StanfordCoreNLP
from tqdm import tqdm

genia_base = "./data/genia"
genia_raw = f"{genia_base}/raw-data"
genia_processed = f"{genia_base}/processed-data"

json_dir = f"{genia_processed}/json-ner"
tree_dir = f"{genia_raw}/GENIA_treebank_v1"
coref_dir = f"{genia_raw}/GENIA_MedCo_coreference_corpus_1.0"
alignment_file = f"{genia_raw}/align/alignment.csv"

# output_directory = "json-treebank"
# output_directory = "json-matched"
# output_directory = "json-tf"
output_directory = "json-dep"
only_match = False
use_tree_feature = False
MAX_DEPTH = 3
MAX_PATH = 5

use_dep = True
use_tree = False

alignment = pd.read_csv(alignment_file).set_index("ner")

class Coref(object):
    """Represents a single coreference."""

    def __init__(self, xml, soup_text, sents):
        "Get the text, id, referrent, and text span."
        self.xml = xml
        self.text = xml.text
        self.tokens = [tok for tok in re.split('([ -/,.+])', self.text)
                       if tok not in ["", " "]]
        self.id = xml.attrs["id"]
        # A very small number of corefs have two parents. I'm going to just take the first parent.
        # TODO(dwadden) If time, go back and fix this.
        self.ref = xml.attrs["ref"].split(" ")[0] if "ref" in xml.attrs else None
        self.span = self._get_span(sents, soup_text)
        self.type = xml.attrs["type"] if "type" in xml.attrs else None

    def _get_span(self, sents, soup_text):
        """Get text span of coref. We have inclusive endpoints."""

        spans = shared.find_sub_lists(self.tokens, sents)
        n_matches = len(spans)
        # Case 1: If can't match the span, record and return. This doesn't happen
        # much.
        if n_matches == 0:
            stats["no_matches"] += 1
            return None
        # Case 2: IF there are multiple span matches, go back and look the original
        # XML tag to determine which match we want.
        elif n_matches > 1:
            xml_tag = self.xml.__repr__()
            tmp_ixs = shared.find_sub_lists(list(self.text), list(soup_text))
            text_ixs = []
            # Last character of the match must be a dash or char after must be an
            # escape, else we're not at end of token.
            text_ixs = [ixs for ixs in tmp_ixs if
                        soup_text[ixs[1] + 1] in '([ -/,.+])<' or soup_text[ixs[1]] == "-"]
            if len(text_ixs) != n_matches:
                # If the number of xml tag matches doesn't equal the number of span
                # matches, record and return.
                stats["different_num_matches"] += 1
                return None
            tag_ix = shared.find_sub_lists(list(xml_tag), list(soup_text))
            assert len(tag_ix) == 1
            tag_ix = tag_ix[0]
            text_inside = [x[0] >= tag_ix[0] and x[1] <= tag_ix[1] for x in text_ixs]
            assert sum(text_inside) == 1
            match_ix = text_inside.index(True)
        else:
            match_ix = 0
        stats["successful_matches"] += 1
        span = spans[match_ix]
        return span

class Corefs(object):
    """Holds all corefs and represents relations between them."""

    def __init__(self, soup, sents_flat, coref_types):
        self.coref_types = coref_types
        coref_items = soup.find_all("coref")
        corefs = [Coref(item, soup.__repr__(), sents_flat) for item in coref_items]
        # Put the cluster exemplars first.
        corefs = sorted(corefs, key=lambda coref: coref.ref is None, reverse=True)
        coref_ids = [coref.id for coref in corefs]
        corefs = self._assign_parent_indices(corefs, coref_ids)
        clusters = self._get_coref_clusters(corefs)
        clusters = self._cleanup_coref_clusters(corefs, clusters)
        cluster_spans = self._make_cluster_spans(clusters)
        self.corefs = corefs
        self.clusters = clusters
        self.cluster_spans = cluster_spans

    @staticmethod
    def _assign_parent_indices(corefs, coref_ids):
        """Give each coref the index of it parent in the list of corefs."""
        for coref in corefs:
            if coref.ref is None:
                coref.parent_ix = None
            else:
                coref.parent_ix = coref_ids.index(coref.ref)
        return corefs

    @staticmethod
    def _get_coref_clusters(corefs):
        def get_cluster_assignment(coref):
            ids_so_far = set()
            this_coref = coref
            while this_coref.ref is not None:
                # Condition to prevent self-loops.
                if this_coref.id in ids_so_far or this_coref.id == this_coref.ref:
                    return None
                ids_so_far.add(this_coref.id)
                parent = corefs[this_coref.parent_ix]
                this_coref = parent
            return this_coref.id

        clusters = {None: set()}
        for coref in corefs:
            if coref.ref is None:
                # It's a cluster exemplar
                coref.cluster_assignment = coref.id
                clusters[coref.id] = set([coref])
            else:
                cluster_assignment = get_cluster_assignment(coref)
                coref.cluster_assignment = cluster_assignment
                clusters[cluster_assignment].add(coref)
        return clusters

    def _cleanup_coref_clusters(self, corefs, clusters):
        """
        Remove items that didn't get spans, don't have an allowed coref type, or
        weren't assigned a cluster
        """
        # Remove unassigned corefs.
        _ = clusters.pop(None)
        for coref in corefs:
            # If the referent entity didn't get a span match, remove the cluster.
            if coref.ref is None:
                if coref.span is None:
                    _ = clusters.pop(coref.id)
            # If a referring coref didn't have a span or isn't the right coref type, remove it.
            else:
                if coref.type not in self.coref_types or coref.span is None:
                    # Check to make sure the cluster wasn't already removed.
                    if coref.cluster_assignment in clusters:
                        clusters[coref.cluster_assignment].remove(coref)
        # Now remove singleton clusters.
        # Need to make it a list to avoid `dictionary size changed iteration` error."
        for key in list(clusters.keys()):
            if len(clusters[key]) == 1:
                _ = clusters.pop(key)
        return clusters

    @staticmethod
    def _make_cluster_spans(clusters):
        """Convert to nested list of cluster spans, as in scierc data."""
        res = []
        for key, cluster in clusters.items():
            cluster_spans = []
            for coref in cluster:
                cluster_spans.append(list(coref.span))
            res.append(sorted(cluster_spans))
        return res

class Tree(object):
    def __init__(self, nodes):
        self.nodes = nodes
        self.match = True

        self.leaf_nodes = []
        self.leaf_nodes_idx = []
        for idx, node in enumerate(self.nodes):
            # if node.data != "":
            if len(node.children) == 0 and node.data != "":  # some leaf nodes don't correspond to tokens
                self.leaf_nodes.append(node)
                self.leaf_nodes_idx.append(idx)

    def get_span_for_leaf_node(self, sentence):
        if len(self.leaf_nodes) != len(sentence):
            self.match = False
            for idx, node in enumerate(self.leaf_nodes):
                node.span = [idx, idx]  # inclusive endpoints
        else:
            for idx, (node, text) in enumerate(zip(self.leaf_nodes, sentence)):
                if node.data != text:
                    self.match = False
                node.span = [idx, idx]  # inclusive endpoints

    def get_span_for_node(self, sentence):

        # assert (len(sentence) == len(self.leaf_nodes))
        # for idx, (node, text) in enumerate(zip(self.leaf_nodes, sentence)):
        #     assert (node.data == text)
        #     node.span = [idx, idx]  # inclusive endpoints

        sentence_start, sentence_end = Tree.get_span_for_node_(self.nodes, 0)
        # assert(sentence_start==0)
        # assert(sentence_end==len(sentence)-1)

        for node in self.nodes:
            if node.span[1] == -1: # update the span for Null constituent
                node.span[0] = -1

    def show_leaf_node(self):
        ret = [n.data for n in self.leaf_nodes]
        return ret

    @staticmethod
    def get_span_for_node_(nodes, node_idx):
        node = nodes[node_idx]
        if len(node.children) == 0:
            if node.data != "":
                return node.span[0], node.span[1]
            else:
                node.span = [999, -1]
                return 999, -1
        else:
            span_start = 999
            span_end = -1
            for child_idx in node.children:
                child_span_start, child_span_end = Tree.get_span_for_node_(nodes, child_idx)
                span_start = child_span_start if child_span_start < span_start else span_start
                span_end = child_span_end if child_span_end > span_end else span_end

            # assert(span_start<=span_end)
            node.span = [span_start, span_end]
            return span_start, span_end

    def print_tree(self):
        return Tree._print_node(self.nodes, 0, "", 0)

    @staticmethod
    def _print_node(nodes, node_idx, ret, level):
        node = nodes[node_idx]
        indent = '  '*level
        ret += '\n'+indent+'('+node.cat if node.data == '' else ' ('+node.cat+' '+node.data
        for child_idx in node.children:
            ret = Tree._print_node(nodes, child_idx, ret, level+1)
        ret += ')'
        return ret

    def to_json(self):
        nodes = []
        ret = {'match':self.match, 'nodes': nodes}
        for node in self.nodes:
            nodes.append(node.to_json())
        return ret

class Node(object):
    def __init__(self, parent, cat, data):
        self.parent = parent
        self.cat = cat
        self.data = data
        self.children = []

    def __str__(self):
        return self.cat+"|"+self.data+"|"+str(self.parent)

    def to_json(self):
        return [self.parent, self.children, self.cat, self.data, self.span]

def get_node(input, nodes, parent_idx, tokenized):
    for child in input.children:
        if child.name == 'cons':
            # if "null" in child.attrs:
            #     continue # ignore Null constituent
            node = Node(parent_idx, child.attrs["cat"], "")
            nodes.append(node)
            if parent_idx >= 0:
                nodes[parent_idx].children.append(len(nodes)-1)
            get_node(child, nodes, len(nodes)-1, tokenized)
        elif child.name == 'tok':
            if tokenized:
                tokens = [tok for tok in re.split('([ -/,.+])', child.text)
                           if tok not in ["", " "]]
                for token in tokens:
                    node = Node(parent_idx, child.attrs["cat"], token)
                    nodes.append(node)
                    nodes[parent_idx].children.append(len(nodes) - 1)
            else:
                node = Node(parent_idx, child.attrs["cat"], child.text)
                nodes.append(node)
                nodes[parent_idx].children.append(len(nodes)-1)

def matched(tree, sentence):
    if len(sentence) >= 3 and len(tree.leaf_nodes) >= 3:
        if tree.leaf_nodes[0].data == sentence[0] and tree.leaf_nodes[1].data == sentence[1] and tree.leaf_nodes[2].data == sentence[2] and \
            tree.leaf_nodes[-1].data == sentence[-1] and tree.leaf_nodes[-2].data == sentence[-2] and tree.leaf_nodes[-3].data == sentence[-3]:
            return True
        else:
            return False
    else:
        if tree.leaf_nodes[0].data == sentence[0] and tree.leaf_nodes[1].data == sentence[1] and \
            tree.leaf_nodes[-1].data == sentence[-1] and tree.leaf_nodes[-2].data == sentence[-2]:
            return True
        else:
            return False

def getPathToRoot(token, token_idx, tree):
    tmp = token
    # path_to_root = [token_idx]
    path_to_root = []
    while tmp.parent != -1:
        path_to_root.append(tmp.parent)
        tmp = tree.nodes[tmp.parent]
    return path_to_root

def getLowestCommonAncestor(token_i_path, token_j_path):
    lca = -1
    for i, node_idx_i in enumerate(token_i_path):
        for j, node_idx_j in enumerate(token_j_path):
            if node_idx_i == node_idx_j:
                lca = node_idx_i
                break
        if lca != -1:
            break
    assert lca != -1
    return i, j, lca

def getTreeFeature_Path(token_i, token_i_idx, token_j, token_j_idx, tree):
    token_i_path = getPathToRoot(token_i, token_i_idx, tree)
    token_j_path = getPathToRoot(token_j, token_j_idx, tree)
    i, j, lca = getLowestCommonAncestor(token_i_path, token_j_path)

    # ret = []
    # ii = 0
    # while ii < i:
    #     ret.append(tree.nodes[token_i_path[ii]].cat)
    #     ii += 1
    # ret.append(tree.nodes[lca].cat)
    # jj = j - 1
    # while jj >= 0:
    #     ret.append(tree.nodes[token_j_path[jj]].cat)
    #     jj -= 1
    # ret = '-'.join(ret)
    # return ret

    ret = []
    ii = 0
    jj = 0
    i_exhaust = False
    j_exhaust = False
    while (not i_exhaust) or (not j_exhaust):

        if ii < i:
            ret.append(tree.nodes[token_i_path[ii]].cat)
            ii += 1
        else:
            i_exhaust = True

        if len(ret) >= MAX_PATH:
            break

        if jj < j:
            ret.append(tree.nodes[token_j_path[jj]].cat)
            jj += 1
        else:
            j_exhaust = True

        if len(ret) >= MAX_PATH:
            break

    if len(ret) < MAX_PATH:
        ret.append(tree.nodes[lca].cat)

    ret = '-'.join(ret)
    return ret

def getTreeFeature_DirectionalPath1(token_i, token_i_idx, token_j, token_j_idx, tree):
    token_i_path = getPathToRoot(token_i, token_i_idx, tree)
    token_j_path = getPathToRoot(token_j, token_j_idx, tree)
    i, j, lca = getLowestCommonAncestor(token_i_path, token_j_path)

    ret = ''
    steps = []
    ii = 0
    while ii < i:
        if len(steps) >= MAX_PATH:
            break
        ret += tree.nodes[token_i_path[ii]].cat if len(steps) == 0 else ">"+tree.nodes[token_i_path[ii]].cat
        steps.append(tree.nodes[token_i_path[ii]].cat)
        ii += 1
    if len(steps) < MAX_PATH:
        ret += tree.nodes[lca].cat if len(steps) == 0 else ">"+tree.nodes[lca].cat
        steps.append(tree.nodes[lca].cat)
    jj = j - 1
    while jj >= 0:
        if len(steps) >= MAX_PATH:
            break
        ret += tree.nodes[token_j_path[jj]].cat if len(steps) == 0 else "<"+tree.nodes[token_j_path[jj]].cat
        steps.append(tree.nodes[token_j_path[jj]].cat)
        jj -= 1

    return ret

def getTreeFeature_DirectionalPath2(token_i, token_i_idx, token_j, token_j_idx, tree):
    token_i_path = getPathToRoot(token_i, token_i_idx, tree)
    token_j_path = getPathToRoot(token_j, token_j_idx, tree)
    i, j, lca = getLowestCommonAncestor(token_i_path, token_j_path)

    ret = ''
    ii = 0
    while ii < i:
        ret += tree.nodes[token_i_path[ii]].cat if len(ret) == 0 else ">"+tree.nodes[token_i_path[ii]].cat
        ii += 1
    ret += tree.nodes[lca].cat if len(ret) == 0 else ">"+tree.nodes[lca].cat
    jj = j - 1
    while jj >= 0:
        ret += tree.nodes[token_j_path[jj]].cat if len(ret) == 0 else "<"+tree.nodes[token_j_path[jj]].cat
        jj -= 1

    return ret

def getTreeFeature_LcaRootSyntax(token_i, token_i_idx, token_j, token_j_idx, tree):
    token_i_path = getPathToRoot(token_i, token_i_idx, tree)
    token_j_path = getPathToRoot(token_j, token_j_idx, tree)
    i, j, lca = getLowestCommonAncestor(token_i_path, token_j_path)

    return tree.nodes[lca].cat

def getTreeFeature_LcaLeftDepth(token_i, token_i_idx, token_j, token_j_idx, tree):
    token_i_path = getPathToRoot(token_i, token_i_idx, tree)
    token_j_path = getPathToRoot(token_j, token_j_idx, tree)
    i, j, lca = getLowestCommonAncestor(token_i_path, token_j_path)

    if i > MAX_DEPTH:
        i = MAX_DEPTH
    return str(i)

def getTreeFeature_LcaRightDepth(token_i, token_i_idx, token_j, token_j_idx, tree):
    token_i_path = getPathToRoot(token_i, token_i_idx, tree)
    token_j_path = getPathToRoot(token_j, token_j_idx, tree)
    i, j, lca = getLowestCommonAncestor(token_i_path, token_j_path)

    if j > MAX_DEPTH:
        j = MAX_DEPTH
    return str(j)

# i is the idx in tree.leaf_nodes, while token_i_idx is the idx in tree.nodes
def getTreeFeature_LcaMatch(token_i_leaf_idx, token_i, token_i_idx, token_j_leaf_idx, token_j, token_j_idx, tree):
    token_i_path = getPathToRoot(token_i, token_i_idx, tree)
    token_j_path = getPathToRoot(token_j, token_j_idx, tree)
    i, j, lca = getLowestCommonAncestor(token_i_path, token_j_path)

    span_left_token_idx = tree.nodes[lca].span[0]
    span_right_token_idx = tree.nodes[lca].span[1]

    left_leaf_idx = token_j_leaf_idx if token_i_leaf_idx > token_j_leaf_idx else token_i_leaf_idx
    right_leaf_idx = token_i_leaf_idx if token_i_leaf_idx > token_j_leaf_idx else token_j_leaf_idx

    if span_left_token_idx == left_leaf_idx and span_right_token_idx == right_leaf_idx:
        return 'm' # match
    elif span_left_token_idx == left_leaf_idx and span_right_token_idx != right_leaf_idx:
        return 'lm' # left match
    elif span_left_token_idx != left_leaf_idx and span_right_token_idx == right_leaf_idx:
        return 'rm' # right match
    else:
        return 'nm' # not match

def getTreeFeatures(tree):
    tree_features = {}
    if not tree.match:
        return tree_features
    # list_list, denotes the relation between token_i and token_j
    # e.g., given a sentence t1 t2 t3, return [[t1_t1, t1_t2, t1_t3],[t2_t1, t2_t2, t2_t3],[t3 ...]]
    tree_features['F1'] = []
    # tree_features['F2'] = []
    # tree_features['F3'] = []
    # tree_features['F4'] = []
    # tree_features['F5'] = []
    # tree_features['F6'] = []
    # tree_features['F7'] = []
    for i, (token_i, token_i_idx) in enumerate(zip(tree.leaf_nodes, tree.leaf_nodes_idx)):
        # f1, f2, f3, f4, f5, f6, f7 = [], [], [], [], [], [], []
        f1 = []
        for j, (token_j, token_j_idx) in enumerate(zip(tree.leaf_nodes, tree.leaf_nodes_idx)):
            if i == j:
                f1.append('self')
                # f2.append('self')
                # f3.append('self')
                # f4.append('self')
                # f5.append('self')
                # f6.append('self')
                # f7.append('self')
            else:
                f1.append(getTreeFeature_Path(token_i, token_i_idx, token_j, token_j_idx, tree))
                # f2.append(getTreeFeature_LcaRootSyntax(token_i, token_i_idx, token_j, token_j_idx, tree)) # lowest common ancestor
                # f3.append(getTreeFeature_LcaLeftDepth(token_i, token_i_idx, token_j, token_j_idx, tree))
                # f4.append(getTreeFeature_LcaRightDepth(token_i, token_i_idx, token_j, token_j_idx, tree))
                # f5.append(getTreeFeature_LcaMatch(i, token_i, token_i_idx, j, token_j, token_j_idx, tree))
                # f6.append(getTreeFeature_DirectionalPath1(token_i, token_i_idx, token_j, token_j_idx, tree))
                # f7.append(getTreeFeature_DirectionalPath2(token_i, token_i_idx, token_j, token_j_idx, tree))
        tree_features['F1'].append(f1)
        # tree_features['F2'].append(f2)
        # tree_features['F3'].append(f3)
        # tree_features['F4'].append(f4)
        # tree_features['F5'].append(f5)
        # tree_features['F6'].append(f6)
        # tree_features['F7'].append(f7)

    return tree_features

def getDepTree1(tokens, edges_list):
    nodes = [[] for token in tokens]
    nodes_dict = {"nodes":nodes}

    for edge in edges_list:
        if edge['dep'] == 'ROOT':
            continue
        if edge['dependent']-1 not in nodes[edge['governor']-1]:
            nodes[edge['governor']-1].append(edge['dependent']-1)
        if edge['governor']-1 not in nodes[edge['dependent']-1]:
            nodes[edge['dependent']-1].append(edge['governor']-1)

    return nodes_dict

def build_tree(soup, doc, tokenized, pmid, medline_id, nlp):
    tree_sentences = soup.find_all("sentence")

    # assert(len(tree_sentences)==len(sentences))
    if len(tree_sentences) != len(doc['sentences']):
        # print("doc mismatch, term doc: {}, doc len {}, treebank doc: {}, doc len {}".format(pmid, len(doc['sentences']), medline_id, len(tree_sentences)))
        stats_treebank['doc_mismatches'] += 1
    else:
        stats_treebank['doc_matches'] += 1

    trees = [] if use_tree else None
    if use_tree_feature:
        tf = []
    else:
        tf = None
    if use_dep:
        dep = []
    else:
        dep = None
    start = 0
    for sentence in doc['sentences']:
        b_match = False
        for idx, tree_sentence in enumerate(tree_sentences[start:]):
            nodes = []
            get_node(tree_sentence, nodes, -1, tokenized)
            tree = Tree(nodes)
            if matched(tree, sentence):
                b_match = True
                break
        if b_match:
            tree.get_span_for_leaf_node(sentence)
            if not tree.match:
                # print(
                #     "sent mismatch, term doc: {}, term sentence: {}, treebank doc: {}, treebank sentence {}".format(
                #         pmid, sentence, medline_id, tree.show_leaf_node()))
                stats_treebank['sent_mismatches'] += 1
            else:
                stats_treebank['sent_matches'] += 1
            tree.get_span_for_node(sentence)
            if use_tree:
                trees.append(tree.to_json())
            if use_tree_feature:
                tree_features = getTreeFeatures(tree)
                tf.append(tree_features)
            if use_dep:
                try:
                    nlp_res_raw = nlp.annotate(' '.join(sentence), properties={'annotators': 'tokenize,ssplit,pos,parse'})
                    nlp_res = json.loads(nlp_res_raw)
                    if len(nlp_res['sentences']) >= 2:
                        print("tokenization mismatch: {}".format(sentence))
                        dep.append({})
                    else:
                        dep_nodes = getDepTree1(nlp_res['sentences'][0]['tokens'],
                                                nlp_res['sentences'][0]['basicDependencies'])
                        dep.append(dep_nodes)
                except Exception as e:
                    print("nlp timeout: {}".format(sentence))
                    dep.append({})

            start = start + idx + 1
        else:
            # print(
            #     "sent not find tree, term doc: {}, term sentence: {}, treebank doc: {}".format(
            #         pmid, sentence, medline_id))
            stats_treebank['sent_notree'] += 1
            if use_tree:
                trees.append({})
            if use_tree_feature:
                tf.append({})
            if use_dep:
                dep.append({})

    # for tree_sentence, sentence in zip(tree_sentences, doc['sentences']):
    #     nodes = []
    #     get_node(tree_sentence, nodes, -1, tokenized)
    #     tree = Tree(nodes)
    #     # print(tree.print_tree())
    #     tree.get_span_for_leaf_node(sentence)
    #     if not tree.match:
    #         print("sent mismatch, term doc: {}, term sentence: {}, treebank doc: {}, treebank sentence {}".format(pmid, sentence, medline_id, tree.show_leaf_node()))
    #         stats_treebank['sent_mismatches'] += 1
    #     else:
    #         stats_treebank['sent_matches'] += 1
    #     tree.get_span_for_node(sentence)
    #     trees.append(tree.to_json())

    return trees, tf, dep

def get_excluded():
    "Get list of files that had random off-by-1-errors and will be excluded."
    current_path = os.path.dirname(os.path.realpath(__file__))
    excluded = pd.read_table(f"{current_path}/exclude.txt", header=None, squeeze=True).values
    return excluded

from collections import Counter

def is_span_overlapped(start, end, other_start, other_end):
    if other_start < start and other_end >= start:
        return True
    elif other_start <= end and other_end > end:
        return True
    elif other_start >= start and other_end <= end:
        return True
    else:
        return False

def one_fold(fold, coref_types, out_dir, keep_excluded, nlp):
    """Add coref field to json, one fold."""
    print("Running fold {0}.".format(fold))
    entity_length = Counter()
    entity_stat = dict(entity=0, entity_common=0)
    excluded = get_excluded()
    f_json = open(path.join(json_dir, "{0}.json".format(fold)))
    f_out = open(path.join(out_dir, "{0}.json".format(fold)), "w")

    lines = f_json.readlines()
    for line in tqdm(lines):
        doc = json.loads(line)

        for sentence, ner, relation_for_this_sentence in zip(doc['sentences'], doc['ner'], doc['relations']):
            for entity_idx, entity in enumerate(ner):
                entity_stat['entity'] += 1
                entity_length[entity[1]-entity[0]+1] += 1
                if entity[1] - entity[0] + 1 <= 8:
                    entity_stat['entity_common'] += 1
                for other_idx, other in enumerate(ner):
                    if other_idx == entity_idx:
                        continue
                    if entity[0] == other[0] and entity[1] == other[1]:
                        continue
                    if is_span_overlapped(entity[0], entity[1], other[0], other[1]):
                        relation_for_this_sentence.append(
                            [entity[0], entity[1], other[0],
                             other[1], "Overlap"])
            pass

        pmid = int(doc["doc_key"].split("_")[0])
        medline_id = alignment.loc[pmid][0]
        # xml_file = path.join(coref_dir, str(medline_id) + ".xml")
        # sents_flat = shared.flatten(doc["sentences"])
        xml_tree_file = path.join(tree_dir, str(medline_id) + ".xml")
        # with open(xml_file, "r") as f_xml:
        #     soup = BS(f_xml.read(), "lxml")
        #     corefs = Corefs(soup, sents_flat, coref_types)
        # doc["clusters"] = corefs.cluster_spans
        with open(xml_tree_file, 'r') as f_xml:
            soup = BS(f_xml.read(), "lxml")
            trees, tf, dep = build_tree(soup, doc, True, pmid, medline_id, nlp)
        if use_tree:
            doc["trees"] = trees
        if use_tree_feature:
            doc['tf'] = tf
        if use_dep:
            doc['dep'] = dep
        if only_match:
            good = True
            for tree in doc['trees']:
                if 'match' not in tree:
                    good = False
                    break
                if not tree['match']:
                    good = False
                    break
            if good:
                # Save unless it's bad and we're excluding bad documents.
                if keep_excluded or doc["doc_key"] not in excluded:
                    f_out.write(json.dumps(doc) + "\n")
            # else:
            #     a = 1
        else:
            # Save unless it's bad and we're excluding bad documents.
            if keep_excluded or doc["doc_key"] not in excluded:
                f_out.write(json.dumps(doc) + "\n")

    f_json.close()
    f_out.close()
    print(entity_length)
    print(entity_stat)

def get_clusters(coref_types, out_dir, keep_excluded, nlp):
    """Add coref to json, filtering to only keep coref roots and `coref_types`."""
    global stats
    stats = dict(no_matches=0, successful_matches=0, different_num_matches=0)
    global stats_treebank
    stats_treebank = dict(doc_mismatches=0, doc_matches=0, sent_mismatches=0, sent_matches=0, sent_notree=0)
    for fold in ["train", "dev", "test"]:
        one_fold(fold, coref_types, out_dir, keep_excluded, nlp)
    print(stats)
    print(stats_treebank)

def main():
    # get_coref_types()
    parser = argparse.ArgumentParser()
    parser.add_argument("--ident-only", action="store_true",
                        help="If true, only do `IDENT` coreferences.")
    parser.add_argument("--keep-excluded", action="store_true",
                        help="If true, keep training docs that were excluded due to off-by-1 errors.")
    args = parser.parse_args()
    if args.ident_only:
        coref_types = ["IDENT"]
    else:
        coref_types = [
            "IDENT",
            "NONE",
            "RELAT",
            "PRON",
            "APPOS",
            "OTHER",
            "PART-WHOLE",
            "WHOLE-PART"
        ]

    out_dir = f"{genia_processed}/{output_directory}"

    if not path.exists(out_dir):
        os.mkdir(out_dir)

    with StanfordCoreNLP('./files_for_discontinuous_ner/stanford-corenlp-full-2018-10-05', memory='8g', timeout=100000) as nlp:

        get_clusters(coref_types, out_dir, args.keep_excluded, nlp)

if __name__ == '__main__':
    main()


# Filepath variable will contain path to file
filepath = ''
# Separator will here be space, change it to comma(,) in case of csv
separator = ' '
# Mapping variable will contain all mappings
mapping = {}
with open(filepath, 'w', newline='') as file:
    for line in file:
        id_, name = line.split(separator)
        mapping[id_] = name
# Mapping variable has all data, do whatever you seek.
print(mapping)
# BYE


'''
Created on 5 Mar 2017

@author: Daniele
'''
import time
import matplotlib.pyplot as plt
from src.Stack_linkedList_implementation import *

running_times = []

# Increase size of n in increments.
for n in range (5, 50000, 183):
    s = Stack_linkedList(100000)
    # Add n elements to the set.
    for i in range(n):
        s.push(i)

    start = time.time()
    # the operation I will test is getElementAtRank(n // 2 (integer division)). I am expecting O(1) complexity
    for j in range(n//2):
        s.pop()
    x = s.peek()
    end = time.time()

    run_time = end - start
    print(n, run_time)
    running_times.append(run_time)
# Plot the running times
plt.plot(running_times, 'bx')
plt.xlabel('Size of N (x 1000)')
plt.ylabel('Time')
plt.show()


from collections import namedtuple

V2 = namedtuple('Point2', ['x', 'y'])

V3 = namedtuple('Point3', ['x', 'y', 'z'])

V4 = namedtuple('Point4', ['x', 'y', 'z','w'])
PI = 3.141592653589793

def deg2rad(degrees):
	radians = degrees * (PI/180)
	return radians

def substract(v0, v1):
    return V3(v0.x - v1.x, v0.y - v1.y, v0.z - v1.z)

def norm(v0):
    vLength = length(v0)
    if not vLength:
        return V3(0, 0, 0)

    return V3(v0.x/vLength, v0.y/vLength, v0.z/vLength)

def dot(v0, v1):
    return v0.x * v1.x + v0.y * v1.y + v0.z * v1.z

def length(v0):
    return (v0.x**2 + v0.y**2 + v0.z**2)**0.5

def cross(v0, v1):
    return V3(
        v0.y * v1.z - v0.z * v1.y,
        v0.z * v1.x - v0.x * v1.z,
        v0.x * v1.y - v0.y * v1.x,
    )
# La lógica par sacar la matriz inversa fue extraída de
# https://stackoverflow.com/a/39881366/11168233
def eliminate(r1, r2, col, target=0):
    fac = (r2[col]-target) / r1[col]
    for i in range(len(r2)):
        r2[i] -= fac * r1[i]

def gauss(a):
    for i in range(len(a)):
        if a[i][i] == 0:
            for j in range(i+1, len(a)):
                if a[i][j] != 0:
                    a[i], a[j] = a[j], a[i]
                    break
            else:
                print("It's not invertible :C")
                return -1
        for j in range(i+1, len(a)):
            eliminate(a[i], a[j], i)
    for i in range(len(a)-1, -1, -1):
        for j in range(i-1, -1, -1):
            eliminate(a[i], a[j], i)
    for i in range(len(a)):
        eliminate(a[i], a[i], i, target=1)
    return a

def inverse(a):
    tmp = [[] for _ in a]
    for i,row in enumerate(a):
        assert len(row) == len(a)
        tmp[i].extend(row + [0]*i + [1] + [0]*(len(a)-i-1))
    gauss(tmp)
    ret = []
    for i in range(len(tmp)):
        ret.append(tmp[i][len(tmp[i])//2:])
    return ret

# La lógica para operar matrices fue extraída de
# https://www.programiz.com/python-programming/examples/multiply-matrix

def multiplyMatrices(matrix0, matrix1):
	matrix = [[0 for x in range(len(matrix0))] for y in range(len(matrix1[0]))]
	for i in range(len(matrix0)):
		for j in range(len(matrix1[0])):
			for k in range(len(matrix1)):
				matrix[i][j] += matrix0[i][k] * matrix1[k][j]
	return matrix

def matrixDotVector(matrix0, v0):
	matrix = [[0 for x in range(len(matrix0))] for y in range(1)]
	for i in range(len(matrix0)):
		for j in range(1):
			for k in range(len(v0)):
				matrix[0][i] += matrix0[i][k] * v0[k]
	return matrix


from django.db import models

from django.db.models.signals import post_save ,pre_save , post_delete
from django.dispatch import receiver

# Create your models here.

from django.contrib.auth.models import AbstractUser
# from django.contrib.auth.models import User

class MyUser(AbstractUser):
	deceased_id = models.CharField(max_length=6,null=True,blank=True,editable=False)
	buyer_id = models.CharField(max_length=6,null=True,blank=True,editable=False)
	presenter_id = models.CharField(max_length=6,null=True,blank=True,editable=False)
	driver_id = models.CharField(max_length=6,null=True,blank=True,editable=False)
	national_number = models.CharField(max_length=10,null=True,blank=True)
	phone_number = models.CharField(max_length=11,null=True,blank=True)
	picture = models.ImageField(null=True,blank=True,verbose_name='تصویر ')

class New(models.Model):
	STATUS = {
		('Publish','publish'),
		('Draft','draft')
	}
	created = models.DateTimeField(auto_now_add=True)
	updated = models.DateTimeField(auto_now=True)
	title = models.CharField(max_length=128,verbose_name='موضوع ')
	content = models.TextField(verbose_name='محتوا ')
	picture = models.ImageField(upload_to='news-pic/',default='news-pic/default.png',null=True,blank=True ,verbose_name='تصویر ')
	status = models.CharField(max_length=32,choices=STATUS,default='Draft',verbose_name='وضعیت ')
	class Meta:
		verbose_name = 'اخبار'
		verbose_name_plural = 'اخبار'
	def __str__(self):
		return self.title +' '+self.status

class Hadith(models.Model):
	created = models.DateTimeField(auto_now_add=True)
	updated = models.DateTimeField(auto_now=True)
	name = models.CharField(max_length=64,verbose_name='نام شخصیت ')
	content = models.TextField(verbose_name='متن حدیث ')
	picture = models.ImageField(upload_to='Hadith-pic/',verbose_name='تصویر ')
	class Meta:
		verbose_name = 'احادیث'
		verbose_name_plural = 'احادیث'
	def __str__(self):
		return self.name + ' ' + self.content[:50]

class Slider(models.Model):
	STATUS = (
		('Inactive','غیر فعال'),
		('Active','فعال'),
	)
	created = models.DateTimeField(auto_now_add=True)
	updated = models.DateTimeField(auto_now=True)
	small_text = models.TextField(verbose_name='متن کوچکتر ')
	bold_text = models.TextField(verbose_name='متن بولد ')
	picture = models.ImageField(upload_to='slider-pic/',verbose_name='تصویر ')
	status = models.CharField(max_length=32,choices=STATUS , default='Inactive',verbose_name='وضعیت ')
	class Meta:
		verbose_name = 'اسلایدر'
		verbose_name_plural = 'اسلایدر'
	def __str__(self):
		return self.small_text[:32] + ' - ' + self.bold_text[:32]

class Message(models.Model):
	STATUS = (
		('Read', 'خوانده شد'),
		('UnRead', 'خوانده نشده'),
	)
	created = models.DateTimeField(auto_now_add=True)
	updated = models.DateTimeField(auto_now=True)
	email = models.EmailField()
	first_name = models.CharField(max_length=128)
	last_name = models.CharField(max_length=128)
	subject = models.CharField(max_length=128)
	content = models.TextField()
	status = models.CharField(max_length=32,choices=STATUS,default='UnRead')

	class Meta:
		verbose_name = 'درخواست ها'
		verbose_name_plural = 'درخواست ها'
	def __str__(self):
		return self.email + self.subject


samochody = ['syrena', 'polonez']
ilosc = [3 ,5]

for idx in range( len(samochody)):
    print("idx: " + str(idx) + ": " + samochody[idx])
    print(samochody[idx] + " ma ilosc drzwi " + str(ilosc[idx]))

media = ['woda', 'prad']
cena = [20, 10]

for idx in range( len(media)):
    print("idx: " + str(idx) + ": " + media[idx])
    print(media[idx] + " ma cene " + str(cena[idx]))

print('-----------------------')

koszyk = ['herbata', 'kawa']
cena = [2, 3]
suma = sum(cena)
print('Cena bez promocji= ' + str(suma))

if cena > 3:
    print('Promocja 20%')
    suma = suma - (suma * 20) / 100

elif cena > 500:
    print('Pomocja 15')
    suma = suma - (suma * 15) / 100
print('Do zaplacenia: ' + str(suma))

print('---------------')

produkty = ['mleko']
ceny = [120, 320, 22]

suma = 0

for c in ceny:
    suma = suma + c

if suma > 500:
    print('20 % off, >500!')
    suma = suma - (suma * 20.0)/100

if len(produkty) > 3:
    print('000 Udane zakupy!')
    suma = suma - (suma * 15.0) / 1000

print("Do zaplaty: {0}".format(suma))


# Coding Challenge
import bs4 as bs
import os
import json

"""
this function cleans the name. There were many similar names with little difference
The idea is that there should be one artist with that name, so to reduced redundancy
I have removed all extre caracters like - [. , (1550 - 1767), etc ]

Note: I have purposely kept artist name case sensitive as this did not effect my results.
      but ideally the name should be first lower and then tested
"""
def clean_artist_name(artist):

    i = 0
    ret = ''
    while(i < len(artist)):

        if (artist[i].isalpha() or artist[i] == ' ') and artist[i] != '.':
            ret += artist[i]
        i += 1

    return ret.strip()

"""
return the list of artists
"""
def questiom_1(all_soup):
    if not all_soup or len(all_soup) == 0:
        return

    artists = []

    for soup in all_soup:
        artist = soup.find_all('h3')[0].string
        artist = clean_artist_name(artist)
        artists.append(clean_artist_name(artist))

    """
        I don't want the duplicate in the list so first converting it to set.
        Then converting back to list for the desired result
    """
    return list(set(artists))

"""
Parse the HTML and return the soup obj
"""
def read_soup(file_names):
    all_file_soup1 = []
    for file in file_names:
            f=open(file, 'r')
            soup = bs.BeautifulSoup(f, 'html.parser')
            all_file_soup1.append(soup)
    return all_file_soup1

"""
    dump the data into the jason file
"""
def dump_json(obj_list):
    info = json.dumps(obj_list)
    loaded_info = json.loads(info)
    with open('problem1_soup2.json', 'w') as outfile:
        json.dump(loaded_info,outfile)

"""
remember to change the path if the html directory is not in the current folder
"""

file_names = os.listdir('./soup2')
file_names = ["./soup2/"+file for file in file_names if file[-4:] == 'html']

# caller
dump_json(questiom_1(read_soup(file_names)))


# -*- coding: utf-8 -*-
from PySide import QtGui,QtCore
from Noriter.UI.ModalWindow import ModalWindow
from Noriter.UI.Window import Window
from Noriter.utils.Settings import Settings
from Noriter.views.NoriterMainWindow import *

from controller.ComponentController import ComponentController
from controller.SceneListController import SceneListController

class LayerWindow(Window):
	def __init__(self,parent=None):
		super(LayerWindow,self).__init__(parent)
		self.setWindowTitle("layers")

		self.sceneCtrl = None
		self.objList = []

		self.sceneListCtrl = SceneListController.getInstance();
		self.sceneListCtrl.SceneOpen.connect(self.loadScene)

		self.list.changed.connect(self.changedSelected)
		ComponentController.getInstance().componentModify.connect(self.componentModify)

	@LayoutGUI
	def GUI(self):
		self.list = self.Layout.listbox(self.layerFactory,[])
		self.Layout.button("Add Object",self.AddObject)
		self.Layout.button("Remove Object",self.RemoveObject)

	def componentModify(self,objModel,idx,new,old):
		if objModel in self.objList:
			if "name" in new :
				objModel.components[idx].data["name"] = new["name"]
				self.updateList()

	def changedSelected(self,indices):
		s = []
		for v in indices:
			s.append( v.model )
		self.sceneCtrl.layerCtrl.SetSelectObjects( s )

	def layerFactory(self,model):
		transform = model.components[0].data
		self.Layout.label(transform['name'])
		self.Layout.widget.model = model
		return 30

	def updateList(self):
		self.list.data = self.objList

	def AddObject(self):
		self.sceneCtrl.layerCtrl.New()

	def RemoveObject(self):
		pass

	def OnAddObject(self,objModel):
		self.objList.append(objModel);
		self.updateList()

	def OnRemoveObject(self,objModel):
		self.updateList()

	def OnSelectObject(self,objModels):
		arr = []
		for v in objModels:
			arr.append( self.objList.index(v) )

		self.list.changed.disconnect(self.changedSelected)
		self.list.selectIndices(arr)
		self.list.changed.connect(self.changedSelected)

	def loadScene(self,path):
		if self.sceneCtrl :
			self.sceneCtrl.layerCtrl.objectAdded.disconnect(self.OnAddObject)
			self.sceneCtrl.layerCtrl.objectRemoved.disconnect(self.OnRemoveObject)
			self.sceneCtrl.layerCtrl.objectSelected.disconnect(self.OnSelectObject)

		self.sceneCtrl = self.sceneListCtrl.Now()
		self.sceneCtrl.layerCtrl.objectAdded.connect(self.OnAddObject)
		self.sceneCtrl.layerCtrl.objectRemoved.connect(self.OnRemoveObject)
		self.sceneCtrl.layerCtrl.objectSelected.connect(self.OnSelectObject)

		self.objList = self.sceneCtrl.layerCtrl.layer.children[:]
		self.updateList()

def start():
	m = NoriterMain()
	m.Dock(NoriterMain.DOCK_LEFT,LayerWindow(m))


def custom_split(t, gran):
    chasti = [] #сделает так, чтобы сплит вернулся с войны
    eta_chast = ''
    for bus in t:
        if bus not in gran:
            eta_chast += bus # будет относиться к куску текста, если не сплитить
        else:
            # заикнет результат в список частей
            chasti.append(eta_chast)
            # обнулит нужный кусок текста
            eta_chast = ''
    return chasti

with open("ozhegov.txt", "r", encoding='utf-8') as f:
    t = f.read()
    t = custom_split(t, '.!?')
    dictionar = {sent: sent.split() for sent in t}
    for key, value in dictionar.items():
        dictionar[key] = {word: len(word) for word in key.split()}
    print('Словарь:', dictionar, sep='\n')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File              : 25_find_path.py
# Author            : lryong <15816537946@163.com>
# Date              : 12.04.2019
# Last Modified Date: 08.06.2019
# Last Modified By  : lryong <15816537946@163.com>
# -*- coding:utf-8 -*-
'''
输入一颗二叉树的跟节点和一个整数，打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中，数组长度大的)
'''
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
# 返回二维列表，内部每个列表表示找到的路径
    def __init__(self):
        tmp, all_ret = [], []
    def dfs(self, tree, left):
        tmp.append(tree.val)
        if tree.val == 0 and not tree.left and not tree.right:
            all_ret.append(tmp)
        else:
            if tree.left:
                self.dfs(tree.left, left-tree.val)
            if tree.right:
                self.dfs(tree.right, left-tree.val)
        # 回退到上一个节点
        tmp.pop()

    def FindPath(self, root, expectNumber):
        if not root: return all_ret # 没有必要
        self.dfs(root,expectNumber)
        return all_ret

'''
# Solution 2
class Solution:
        # 返回二维列表，内部每个列表表示找到的路径
            def FindPath(self, root, expectNumber):
                        # write code here
                        if not root:
                            return []
                        if root and not root.left and not root.right and root.val == expectNumber:
                            return [[root.val]]

                        res = []
                        left = self.FindPath(root.left,expectNumber-root.val)
                        right = self.FindPath(root.right,expectNumber-root.val)

                        for i in left + right:
                            res.append([root.val]+i)
                        return res
'''


# 8.35.1. Tratando exceções com 'raise'
nomes = ["Ana", "Carlos", "Maria"]
for tentativa in range(3):
    try:
        i = int(input("Digite o índice que quer imprimir: "))
        print(nomes[i])
    except ValueError:
        print("Digite um número!")
        raise
    except IndexError:
        print("Valor inválido! Digite entre -3 e 3")
    finally:
        print("Sempre o finally é executado.")