from django.contrib.auth import get_user_model
from django.db.models import Q

from friendsservice.friendship.exceptions import FriendshipRequestDoesNotExistsError, HasActiveFriendship
from friendsservice.friendship.models import UserFriendship, FriendshipStatus

User = get_user_model()

class CheckFriendshipStatusService:

    def __init__(self, target_username: str):
        self.target_username = target_username

    def _get_user(self) -> User:
        try:
            return User.objects.get(username=self.target_username)
        except User.DoesNotExists as exc:
            raise FriendshipRequestDoesNotExistsError from exc

    def _check_status(self) -> None:
        target_user = self._get_user()
        friendship_with_user = (
            UserFriendship.objects.filter(Q(recipient=target_user) | Q(sender=target_user))
            .exclude(Q(status=FriendshipStatus.DECLINED.value))
            .first()
        )

        if not friendship_with_user:
            raise FriendshipRequestDoesNotExistsError

        if friendship_with_user.status == FriendshipStatus.CONFIRMED.value:
            message = 'In friends list'
        elif friendship_with_user.sender == target_user:
            message = f'You have active friends request from {self.target_username}'
        else:
            message = f'You have active friends request to {self.target_username}'

        raise HasActiveFriendship(friendship_status=message)

    def __call__(self) -> None:
        self._check_status()


from plyer.facades import notification
import requests
import json
from plyer import notification
import time

def notify(title, message):
    notification.notify(
        title = title,
        message = message,
        app_icon = "C:\\Users\\Aakash Garg\\Desktop\\Github\\Python Projects\\Covid-19 Cases Notificator\\favicon.ico",
        timeout = 2
    )
    time.sleep(5)

url = "https://data.covid19india.org/data.json"
r = requests.get(url).text
# print(r)
li = json.loads(r)
# print(li)
state = li["statewise"]
print(state)
for i in state[1:]:
    v1 = "State: " + i["state"] + " --- " + i["statecode"]
    v2 = "Confirmed Cases: " + i["confirmed"] + "\n" + "Deaths: " + i["deaths"] + "\n" + "Recovered Cases: " + i["recovered"] + "\n" + "Updated Till: " + i["lastupdatedtime"]
    notify(v1, v2)
    print(v1, v2)


import coverage
import os
from inspect import getmembers, ismodule

from django.conf import settings
from django.test.simple import run_tests as django_test_runner
from django.db.models import get_app, get_apps

from nodatabase import run_tests as nodatabase_run_tests

def get_coverage_modules(app_module):
    """
    Returns a list of modules to report coverage info for, given an
    application module.
    """
    app_path = app_module.__name__.split('.')[:-1]
    coverage_module = __import__('.'.join(app_path), {}, {}, app_path[-1])

    return [coverage_module] + [attr for name, attr in
        getmembers(coverage_module) if ismodule(attr) and name != 'tests']

def get_all_coverage_modules(app_module):
    """
    Returns all possible modules to report coverage on, even if they
    aren't loaded.
    """
    # We start off with the imported models.py, so we need to import
    # the parent app package to find the path.
    app_path = app_module.__name__.split('.')[:-1]
    app_package = __import__('.'.join(app_path), {}, {}, app_path[-1])
    app_dirpath = app_package.__path__[-1]

    mod_list = []
    for root, dirs, files in os.walk(app_dirpath):
        root_path = app_path + root[len(app_dirpath):].split(os.path.sep)[1:]
        excludes = getattr(settings, 'EXCLUDE_FROM_COVERAGE', [])
        if app_path[0] not in excludes:
            for file in files:
                if file.lower().endswith('.py'):
                    mod_name = file[:-3].lower()
                    try:
                        mod = __import__('.'.join(root_path + [mod_name]),
                            {}, {}, mod_name)
                    except ImportError:
                        pass
                    else:
                        mod_list.append(mod)

    return mod_list

def run_tests(test_labels, verbosity=1, interactive=True,
        extra_tests=[], nodatabase=False):
    """
    Test runner which displays a code coverage report at the end of the
    run.
    """
    coverage.use_cache(0)
    coverage.start()
    if nodatabase:
        results = nodatabase_run_tests(test_labels, verbosity, interactive,
            extra_tests)
    else:
        results = django_test_runner(test_labels, verbosity, interactive,
            extra_tests)
    coverage.stop()

    coverage_modules = []
    if test_labels:
        for label in test_labels:
            # Don't report coverage if you're only running a single
            # test case.
            if '.' not in label:
                app = get_app(label)
                coverage_modules.extend(get_all_coverage_modules(app))
    else:
        for app in get_apps():
            coverage_modules.extend(get_all_coverage_modules(app))

    if coverage_modules:
        coverage.report(coverage_modules, show_missing=1)

    return results


#Improved code usind WASD and JL
import tty, termios, sys
from serial import Serial
from time import sleep # Import the sleep function from the time module
import time
i = 0
while(1):
        time.sleep(1)
        try:
                # ser = Serial('COM'+str(i), 19200, timeout=.1) #PC
                ser = Serial('/dev/ttyACM'+str(i), 19200, timeout=.1) #UNIX
                # ser = Serial('/dev/ttyACM0', 19200, timeout=.1) #UNIX
                print('All Ok')
                break
        except:
                print('PORT '+str(i)+ ' ERROR')
                i = (i+1)%8

def getchar():
   #Returns a single character from standard input
   fd = sys.stdin.fileno()
   old_settings = termios.tcgetattr(fd)
   try:
      tty.setraw(sys.stdin.fileno())
      ch = sys.stdin.read(1)
   finally:
      termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
   return ch
time.sleep(2)
print("Enter options in WASD")
while 1:
    ch = getchar()
    if ch.strip() == '':
        print('bye!')
        break
    else:
        # print(ch)
        if ch=='w':
                print ("up")
                ser.write(b'w')
                sleep(0.5)
        elif ch=='s':
                print ("down")
                ser.write(b's')
                sleep(0.5)
        elif ch=='d':
                print ("right")
                ser.write(b'a')
                sleep(0.25)
        elif ch=='a':
                print ("left")
                ser.write(b'd')
                sleep(0.25)
        elif ch=='j':
                print ("rotateLeft")
                ser.write(b'i')
                sleep(0.25)
        elif ch=='l':
                print ("roteteRight")
                ser.write(b'p')
                sleep(0.25)
        elif ch=='t':
                print ("Trot")
                ser.write(b't')
                sleep(0.5)


import arcade

import enemyController
from component import Component
from eventManager import EventManager
from soundManager import SoundManager
from spriteRenderer import SpriteRenderer
from transform import Transform
from entity import Entity
from levelSectionLoader import LevelSectionLoader

# A component that handles input for a player
from gameManager import GameManager

# Amount the player is knocked back when they attack
KNOCK_BACK_ATTACK = 350

# Amount the player is knocked back when they take damage
KNOCK_BACK_DAMAGE = 2000

# Timer for attack animation taking precedence over walking animation
ATTACK_TIME = 0.1
ATTACK_COOL_DOWN = 0.2
ATTACK_ANIMATION = 0.25

# Constants for animation
RIGHT_FACING = 1
LEFT_FACING = 0
IDLE_TIME = 3

# DEFAULT SPEED VALUES
GRAVITY = -2000
MAX_SPEED = 500
MAX_JUMP = 2500

class PlayerController(Component):
    # Called when a key is pressed
    def on_key_press(self, key, modifiers):
        self.__keys_pressed[key] = True
        self.__idle = False
        self.__idle_timer = IDLE_TIME

        # Jump
        if key == arcade.key.W:
            self.__jump_requested = True
            self.__jump_timer = self.__jump_buffer_time
            self.__touching_floor = False
            self.current_texture = 0

        # Toggle debug
        if key == arcade.key.F:
            print("Toggling debug mode")
            GameManager.debug = not GameManager.debug

        # Pause/quit
        if key == arcade.key.ESCAPE:
            arcade.exit()

        # Attacking
        if key == arcade.key.SPACE:
            self.__is_attacking = True
            self.current_texture = 0

    # Change the value of the key_pressed dictionary when a key is released
    def on_key_release(self, key, modifiers):
        self.__keys_pressed[key] = False
        self.__idle_timer = IDLE_TIME
        self.__idle = False

    # Called every time physics get updated (currently every frame)
    # Deals with all player movement and collision
    def on_physics_update(self, dt):
        # Round velocity to 0 if we're close enough
        epsilon = 0.001
        if abs(self.__velocity[0]) < epsilon:
            self.__velocity = (0, self.__velocity[1])
        if abs(self.__velocity[1]) < epsilon:
            self.__velocity = (self.__velocity[0], 0)

        # Update timers
        self.__coyote_timer -= dt
        self.__jump_timer -= dt
        self.__invincibility_timer -= dt
        self.__attack_time -= dt
        self.__attack_timer -= dt
        self.__health_up_timer -= dt
        self.__jumping_timer -= dt
        self.__speed_timer -= dt
        self.__mad_timer -= dt
        self.__attack_animation_timer -= dt
        self.__idle_timer -= dt

        # If the player is in the air, determine if they've landed on the ground
        # If the player is on the ground, determine if they've jumped (or moved up/down a slope)
        # In both cases, determine if they've collided with a wall

        # On-the-ground case
        # Deal with whether the player should fall (they've stepped off the platform) and jumps
        if self.__touching_ground:
            # Give player slight downward movement so that the downward case below is run
            self.__velocity = (self.__velocity[0], -0.1)
            self.__touching_ground = False
            self.__coyote_timer = self.__coyote_time  # Start coyote timer

        if self.__transform.position[1] == 0:
            self.__touching_floor = True

        # Get some stuff we'll need
        all_colliders = GameManager.get_colliders()  # List of all colliders in scene
        player_collision_polygon = self.__collider.polygon  # Polygon of the player
        # CAN'T GET THIS OBJECT IN on_created() (CIRCULAR REFERENCE) (Need to create player first in screenView.setup())
        self.__sword_sprite_polygon = GameManager.get_entities_by_name("Sword")[0].get_component_by_name(
            "Collider").polygon

        # Disallow the player from moving past the edge of the screen
        if not self.__freeze_camera:
            if self.__transform.position[0] <= self.__camera_min + 50:
                self.__transform.position = (self.__camera_min + 51, self.__transform.position[1])
        else:
            if self.__transform.position[0] <= 100:
                self.__transform.position = (101, self.__transform.position[1])
            if self.__transform.position[0] >= 1820:
                self.__transform.position = (1819, self.__transform.position[1])

        # Player dies if they fall off the level edge
        if self.__transform.position[1] < -5:
            self.__health = self.__health - 1
            self.__invincibility_timer = 1.0
            SoundManager.play_sound("player", "damage")
            self.__taking_damage = True
            self.__velocity = (self.__velocity[0] * 490 / 500, self.__velocity[1])
            self.__is_falling = True
            self.__transform.position = (self.__camera_min + 50, 1500)

        # For when the player is attacking
        if self.__is_attacking and self.__attack_timer < 0:
            SoundManager.play_sound("player", "attack")
            # SoundManager.test_play_sound("assets/sounds/music/main_stage_music.mp3") """Used to test if sounds will stop playing on death"""
            self.__attack_time = ATTACK_TIME
            self.__attack_timer = ATTACK_COOL_DOWN
            self.__attack_animation_timer = ATTACK_ANIMATION
            self.__attack_animation = True
            self.__is_attacking = False
            # implement attacking knock back
            if self.__velocity[1] == 0:
                if (self.__velocity[0] >= KNOCK_BACK_ATTACK):
                    self.__velocity = (self.__velocity[0] - KNOCK_BACK_ATTACK, self.__velocity[1])
                elif self.__velocity[0] >= 0:
                    self.__velocity = (
                    self.__velocity[0] - (KNOCK_BACK_ATTACK - (self.__velocity[0] / 2)), self.__velocity[1])
                elif (self.__velocity[0] <= (-1 * KNOCK_BACK_ATTACK)):
                    self.__velocity = (self.__velocity[0] + KNOCK_BACK_ATTACK, self.__velocity[1])
                elif self.__velocity[0] < 0:
                    self.__velocity = (
                    self.__velocity[0] + (KNOCK_BACK_ATTACK - self.__velocity[0] / 2), self.__velocity[1])

            else:
                if (self.__velocity[0] >= KNOCK_BACK_ATTACK):
                    self.__velocity = (self.__velocity[0] - KNOCK_BACK_ATTACK / 2, self.__velocity[1])
                elif self.__velocity[0] >= 0:
                    self.__velocity = (
                    self.__velocity[0] - (KNOCK_BACK_ATTACK / 2 - (self.__velocity[0] / 2)), self.__velocity[1])
                elif (self.__velocity[0] <= (-1 * KNOCK_BACK_ATTACK)):
                    self.__velocity = (self.__velocity[0] + KNOCK_BACK_ATTACK / 2, self.__velocity[1])
                elif self.__velocity[0] < 0:
                    self.__velocity = (
                    self.__velocity[0] + (KNOCK_BACK_ATTACK / 2 - self.__velocity[0] / 2), self.__velocity[1])

            for collider in all_colliders:
                if collider.parent is self:
                    continue
                if "Enemy" in collider.parent.tags:
                    if arcade.are_polygons_intersecting(self.__sword_sprite_polygon, collider.polygon):
                        collider.parent.get_component_by_name("EnemyController").take_damage(self.__attack_power)
                elif "Boss" in collider.parent.tags:
                    if arcade.are_polygons_intersecting(self.__sword_sprite_polygon, collider.polygon):
                        collider.parent.get_component_by_name("BossController").take_damage(self.__attack_power)

        if self.__taking_damage and not self.__is_falling:
            # implement damage knock back
            if self.__velocity[0] >= 0:
                self.__velocity = (self.__velocity[0] - KNOCK_BACK_DAMAGE, self.__velocity[1])
            else:
                self.__velocity = (self.__velocity[0] + KNOCK_BACK_DAMAGE, self.__velocity[1])

        # For when the player is taking damage
        self.__taking_damage = False
        for collider in all_colliders:
            # Ignore the player's own collider
            if collider.parent is self:
                continue
            if "Enemy" in collider.parent.tags or "Boss" in collider.parent.tags:
                if arcade.are_polygons_intersecting(player_collision_polygon, collider.polygon):
                    if self.__invincibility_timer < 0:
                        if "Enemy" in collider.parent.tags:
                            self.__invincibility_timer = 1.0
                            self.__health = self.__health - 1
                            SoundManager.play_sound("player", "damage")
                            self.__taking_damage = True
                            self.__velocity = (self.__velocity[0] * 490 / 500, self.__velocity[1])
                        else:
                            if not collider.parent.get_component_by_name("BossController").dead:
                                damage_taken = collider.parent.get_component_by_name(
                                    "BossController").get_attack_power()
                                self.__invincibility_timer = 1.0
                                self.__health = self.__health - damage_taken
                                SoundManager.play_sound("player", "damage")
                                self.__taking_damage = True
                                self.__velocity = (self.__velocity[0] * 490 / 500, self.__velocity[1])

        if self.__invincibility_timer > 0:
            self.__sprite_renderer.sprite.color = (255, 100, 100)
        else:
            self.__is_falling = False

        if self.__invincibility_timer <= 0 and not self.__health_up and not self.__speed and not self.__jump and not self.__mad:
            self.__sprite_renderer.sprite.color = (255, 255, 255)

        if self.__attack_animation_timer < 0:
            self.__attack_animation = False

        # Two cases here: moving up and moving down
        # Both have different physics and check for different things
        # Deal with vertical movement first, same for both cases (collision checking comes later)
        self.__velocity = (arcade.clamp(self.__velocity[0], -self.__max_velocity[0], self.__max_velocity[0]),
                           arcade.clamp(self.__velocity[1], -self.__max_velocity[1], self.__max_velocity[1]))
        self.__transform.move((0, self.__velocity[1] * dt))

        # First case: moving up
        # Check for ground collision (with ceilings)
        # Deal with vertical deceleration
        if self.__velocity[1] > 0:
            # Ground collision (ceilings)
            largest_difference = float("inf")
            for collider in all_colliders:
                # Ignore the player's own collider
                if collider.parent is self:
                    continue
                # Ignore colliders that we're above (avoid colliding with floor we just left)
                # TODO: THIS IS A BODGE
                if self.__transform.position[1] > collider.transform.position[1]:
                    continue
                # Only checking for objects tagged with "Ground" (solid objects, not platforms)
                if "Ground" in collider.parent.tags:
                    if arcade.are_polygons_intersecting(player_collision_polygon, collider.polygon):
                        # Get how far we would have to move the player to get them out of the ceiling
                        difference = (collider.transform.position[1] - collider.height / 2) - (
                                self.__transform.position[1] + self.__collider.height / 2)
                        if difference < largest_difference:  # Largest negative amount
                            largest_difference = difference
                        # Stop the player's vertical movement
                        self.__velocity = (self.__velocity[0], 0)
            # Move the player out of the ceiling if they're in it
            if largest_difference != float("inf"):
                self.__transform.move((0, largest_difference))

            # Deal with vertical deceleration
            self.__velocity = (self.__velocity[0], self.__velocity[1] + (self.__gravity * dt))

        # Second case: moving down
        # Check for collision with ground and platforms
        # Deal with vertical acceleration
        else:
            # Ground collision (floors)
            largest_difference = float("-inf")
            for collider in all_colliders:
                # Ignore the player's own collider
                if collider.parent is self:
                    continue

                if "PowerUp" in collider.parent.tags:
                    if arcade.are_polygons_intersecting(player_collision_polygon, collider.polygon):
                        temp = collider.parent.on_collection()
                        if temp == "Health-Up":
                            self.__health_up_timer = 0.1
                            self.__sprite_renderer.sprite.color = arcade.color.PINK
                            self.__health_up = True

                        if temp == "Speed":
                            self.__sprite_renderer.sprite.color = (100, 100, 255)
                            self.__speed = True
                            self.__speed_timer = 5
                            # CHANGE
                            self.__max_velocity = (self.__max_velocity[0] + 350, self.__max_velocity[1] + 350)
                            self.__velocity = (self.__velocity[0] + 100, self.__velocity[1] + 100)

                            # Make player speed

                        if temp == "Jump":
                            self.__jumping_timer = 7
                            self.__jump = True
                            self.__jumping_timer = 7
                            self.__sprite_renderer.sprite.color = (100, 255, 100)
                            # CHANGE
                            self.__gravity = -1000
                            self.__max_velocity = (self.__max_velocity[0], self.__max_velocity[1] + 100)
                            self.__velocity = (self.__velocity[0], self.__velocity[1] + 100)
                            # make player jump high

                        if temp == "Attack":
                            self.__mad = True
                            self.__mad_timer = 5
                            self.__attack_power = 10

                # Only checking for objects tagged with "Ground" or "Platform" (solid objects and platforms)
                if "Ground" in collider.parent.tags or (
                        "Platform" in collider.parent.tags and self.__transform.position[1] > (
                        collider.transform.position[1] + collider.height / 4)):
                    if arcade.are_polygons_intersecting(player_collision_polygon, collider.polygon):
                        # Get how far we would have to move the player to get them out of the floor
                        difference = (collider.transform.position[1] + collider.height / 2) - \
                                     (self.__transform.position[1] - self.__collider.height / 2)

                        if difference > largest_difference:
                            largest_difference = difference
                        # Stop the player's vertical movement
                        self.__velocity = (self.__velocity[0], 0)
                        # Set the touching_ground flag
                        self.__touching_ground = True
                        self.__touching_floor = True

            # Move the player out of the floor if they're in it
            if largest_difference != float("-inf"):
                self.__transform.move((0, largest_difference))

            # Deal with vertical acceleration
            # Multiply vertical acceleration by a multiplier to get faster falling (less "floaty")
            self.__velocity = (
                self.__velocity[0], self.__velocity[1] + (self.__gravity * self.__falling_speed_multiplier * dt))

        # If we're on the ground (or in coyote time) and the player has pressed the jump button, let them jump
        if (self.__jump_requested or self.__jump_timer > 0) and (self.__touching_ground or self.__coyote_timer > 0):
            self.__velocity = (self.__velocity[0], self.__jump_speed)
            SoundManager.play_sound("player", "jump")
            # print(self.__velocity)
            self.__jump_requested = False
            self.__jump_timer = 0
            self.__touching_ground = False
            self.__touching_floor = False

        # Move the character based on which keys are pressed
        # Deal with wall collision
        # First, move the character horizontally

        self.__transform.move((self.__velocity[0] * dt, 0))
        if self.__keys_pressed[arcade.key.D]:
            self.__moving_left = False
            self.__holding_left = False
            self.__holding_right = True
            if self.__velocity[0] > 0:  # Moving right (accelerating)
                self.__velocity = (self.__velocity[0] + self.__horizontal_acceleration * dt, self.__velocity[1])
            else:  # Moving left (decelerating)
                self.__velocity = (
                self.__velocity[0] + self.__horizontal_turnaround_acceleration * dt, self.__velocity[1])
        elif self.__keys_pressed[arcade.key.A]:
            self.__moving_left = True
            self.__holding_left = True
            self.__holding_right = False
            if self.__velocity[0] > 0:  # Moving right (decelerating)
                self.__velocity = (
                self.__velocity[0] - self.__horizontal_turnaround_acceleration * dt, self.__velocity[1])
            else:  # Moving left (accelerating)
                self.__velocity = (self.__velocity[0] - self.__horizontal_acceleration * dt, self.__velocity[1])
        else:  # no keys pressed, default deceleration
            self.__velocity = (
            self.__velocity[0] * (1 - self.__horizontal_deceleration_multiplier * dt), self.__velocity[1])

        self.__jump_requested = False

        if self.__idle_timer < 0:
            self.__idle = True

        self.power_up_effects()

    # Gets called every frame
    # dt is the time taken since the last frame
    def on_update(self, dt):
        # Camera Movement Control:
        # 1) Camera does not move vertically
        # 2) Once the character reaches halfway across the screen, the camera moves forward with them again
        # 3) Camera never moves backwards

        # Can't just get them here again because that crashes for some reason
        width, height = self.__screen_width, self.__screen_height

        if self.__transform.position[0] > (self.__camera_min + width / 2):
            loader = self.get_level_section_loader()
            if loader.sections_gone_through < loader.sections_before_tower or \
                    self.get_transform_x() < (loader.current_offset + loader.tower_section[1] - width / 2):
                # if self.__transform.position[0] < 1920 * 9 - width / 2:
                self.__camera_min = self.__camera_min + (self.__transform.position[0] - (self.__camera_min + width / 2))

        if not self.__freeze_camera:
            GameManager.main_camera.move_to((self.__camera_min, 0), 5 * dt)

        # Animation update
        self.update_animation()

        # Health
        self.set_gui()

    def __init__(self):
        super().__init__("PlayerController")
        # Initialize the keys_pressed dictionary
        self.__keys_pressed = {
            arcade.key.A: False,
            arcade.key.D: False
        }

        # Get the screen width and height just once when the game starts
        self.__screen_width, self.__screen_height = arcade.window_commands.get_display_size()
        print("Screen resolution: " + str(self.__screen_width) + "x" + str(self.__screen_height))

        # Store some components here (set when the program starts), so we don't have to look for them each time
        self.__transform = None
        self.__collider = None
        self.__sprite_renderer = None
        self.__sword_sprite_polygon = None
        self.__level_section_loader = None

        # Private variables for player health
        self.__health = 6
        self.__max_health = 6
        self.__taking_damage = False
        self.__invincibility_timer = 0.0

        # Private variable for player attacking
        self.__is_attacking = False
        self.__attack_time = ATTACK_TIME
        self.__attack_timer = ATTACK_COOL_DOWN
        self.__attack_power = 1

        # Variable used for camera movement, stores the left most edge of the visable screen
        self.__camera_min = 0
        self.__freeze_camera = False

        # Variable used for sword positioning, stores the direction the player is facing
        self.__moving_left = False

        # Private variables for player movement
        self.__touching_ground = False
        self.__touching_floor = False  # this is a variable just for animation
        self.__jump_requested = False
        self.__velocity = (0, 0)
        self.__gravity = -2000
        self.__jump_speed = 1300
        self.__max_velocity = (500, 2500)
        self.__falling_speed_multiplier = 1.75  # Fall faster than you go up (makes jumps feel better)
        self.__coyote_time = 0.1  # Period after walking off a platform where you can still jump (another QOL feature)
        self.__coyote_timer = 0  # Temporary variable to keep track of the coyote time
        self.__is_falling = False  # variable changes to true once you fall off an edge and false once you respawn

        # Pressing jump within this amount of time before touching the ground
        # will make you jump when you land, avoiding missed inputs.
        self.__jump_buffer_time = 0.1
        self.__jump_timer = 0

        # Variables for the powerups
        self.__health_up = False
        self.__speed = False
        self.__jump = False
        self.__mad = False

        self.__power_up_type = None
        self.__health_up_timer = 0.5
        self.__speed_timer = 7
        self.__jumping_timer = 7
        self.__mad_timer = 5

        self.__flash_count = 0

        self.__horizontal_acceleration = 700  # How quickly you accelerate when moving sideways
        self.__horizontal_deceleration_multiplier = 10  # How quickly you decelerate when no button is pressed
        self.__horizontal_turnaround_acceleration = 4000  # How quickly you decelerate when changing direction

        self.__exit_sprite = arcade.Sprite("assets/sprites/exit.png", 1.0)

        # Animation
        # I USED THE FOLLOWING LINK AS REFERENCE: https://api.arcade.academy/en/latest/examples/platform_tutorial/step_12.html#platformer-part-twelve
        self.character_face_direction = RIGHT_FACING
        self.current_texture = 0

        self.__holding_left = False
        self.__holding_right = False

        self.__attack_animation_timer = 0
        self.__attack_animation = False

        self.__idle = True
        self.__idle_timer = IDLE_TIME

        idle_1 = (arcade.load_texture("assets/sprites/player/player_idle_1.png"),
                  arcade.load_texture("assets/sprites/player/player_idle_1.png"))
        idle_2 = (arcade.load_texture("assets/sprites/player/player_idle_2.png"),
                  arcade.load_texture("assets/sprites/player/player_idle_2.png"))
        self.idle_texture_pair = (idle_1, idle_2)

        idle_side_1 = (arcade.load_texture("assets/sprites/player/player_idle_L_1.png"),
                       arcade.load_texture("assets/sprites/player/player_idle_R_1.png"))
        idle_side_2 = (arcade.load_texture("assets/sprites/player/player_idle_L_2.png"),
                       arcade.load_texture("assets/sprites/player/player_idle_R_2.png"))
        self.idle_side_texture_pair = (idle_side_1, idle_side_2)

        attack_1 = (arcade.load_texture("assets/sprites/player/player_attack_L_1.png"),
                    arcade.load_texture("assets/sprites/player/player_attack_R_1.png"))
        attack_2 = (arcade.load_texture("assets/sprites/player/player_attack_L_2.png"),
                    arcade.load_texture("assets/sprites/player/player_attack_R_2.png"))
        self.attack_texture_pair = (attack_1, attack_2)

        jump_attack_1 = (arcade.load_texture("assets/sprites/player/player_jump_attack_L_1.png"),
                         arcade.load_texture("assets/sprites/player/player_jump_attack_R_1.png"))
        jump_attack_2 = (arcade.load_texture("assets/sprites/player/player_jump_attack_L_2.png"),
                         arcade.load_texture("assets/sprites/player/player_jump_attack_R_2.png"))
        self.jump_attack_texture_pair = (jump_attack_1, jump_attack_2)

        jump_1 = (arcade.load_texture("assets/sprites/player/player_jump_L.png"),
                  arcade.load_texture("assets/sprites/player/player_jump_R.png"))
        self.jump_texture_pair = (jump_1)

        walk_1 = (arcade.load_texture("assets/sprites/player/player_walk_L_1.png"),
                  arcade.load_texture("assets/sprites/player/player_walk_R_1.png"))
        walk_2 = (arcade.load_texture("assets/sprites/player/player_walk_L_2.png"),
                  arcade.load_texture("assets/sprites/player/player_walk_R_2.png"))
        walk_3 = (arcade.load_texture("assets/sprites/player/player_walk_L_3.png"),
                  arcade.load_texture("assets/sprites/player/player_walk_R_3.png"))
        walk_4 = (arcade.load_texture("assets/sprites/player/player_walk_L_4.png"),
                  arcade.load_texture("assets/sprites/player/player_walk_R_4.png"))
        self.walk_texture_pair = (walk_1, walk_2, walk_3, walk_4)

        self.texture = self.idle_texture_pair

        # Add listeners for all the events
        EventManager.add_listener("Update", self.on_update)  # calls on_update every frame
        EventManager.add_listener("KeyPress", self.on_key_press)  # calls on_key_press every time a key is pressed
        EventManager.add_listener("KeyRelease",
                                  self.on_key_release)  # calls on_key_release every time a key is released
        EventManager.add_listener("PhysicsUpdate", self.on_physics_update)  # calls physics_update every frame

        # UI entities
        self.__exit_entity = None
        self.__heart_entities = []
        print("Creating heart entities")
        for i in range(3):
            heart_sprite = arcade.Sprite("assets/sprites/heart_full.png")
            heart_sprite_renderer = SpriteRenderer(heart_sprite)
            heart_transform = Transform((i * (heart_sprite.width + 10) + 70, 980 + heart_sprite.height / 2), 0,
                                        1.0)
            heart_entity = Entity("Heart", ["HeartTag"], [heart_sprite_renderer, heart_transform])
            self.__heart_entities.append(heart_entity)
            GameManager.add_gui_entity(heart_entity)

        self.sprite_full = arcade.Sprite("assets/sprites/heart_full.png", 1.0)
        self.sprite_half = arcade.Sprite("assets/sprites/heart_half.png", 1.0)
        self.sprite_empty = arcade.Sprite("assets/sprites/heart_empty.png", 1.0)

        # Exit Button
        exit_sprite_renderer = SpriteRenderer(self.__exit_sprite)
        exit_transform = Transform((1860, 1020), 0, 1.0)
        exit_entity = Entity("Exit", ["ExitTag"], [exit_sprite_renderer, exit_transform])
        GameManager.add_gui_entity(exit_entity)

    # Called when the entity is removed
    # Remove listeners here
    def on_remove(self):
        print("Removing listeners for player controller")
        EventManager.remove_listener("Update", self.on_update)
        EventManager.remove_listener("KeyPress", self.on_key_press)
        EventManager.remove_listener("KeyRelease", self.on_key_release)
        EventManager.remove_listener("PhysicsUpdate", self.on_physics_update)

    def set_transform(self, pos):
        self.__transform.position = pos

    def get_transform_x(self):
        return self.__transform.position[0]

    def set_health(self, health):
        self.__health = health

    def set_power_up(self, power_up):
        self.__power_up_type = power_up

    def get_level_section_loader(self):
        return self.__level_section_loader

    # Called when parent entity is created
    def on_created(self):
        self.__collider = self.parent.get_component_by_name("Collider")
        self.__transform = self.parent.get_component_by_name("Transform")
        self.__sprite_renderer = self.parent.get_component_by_name("SpriteRenderer")
        self.__level_section_loader = self.parent.get_component_by_name("LevelSectionLoader")

    def set_gui(self):
        # GameManager.clear_gui_sprite()
        if self.__health <= 2:
            if self.__health == 1:
                self.make_heart_entity(0, "half")
            else:
                self.make_heart_entity(0, "full")
            self.make_heart_entity(1, "empty")
            self.make_heart_entity(2, "empty")
        elif self.__health <= 4:
            if self.__health == 3:
                self.make_heart_entity(1, "half")
            else:
                self.make_heart_entity(1, "full")
            self.make_heart_entity(0, "full")
            self.make_heart_entity(2, "empty")
        else:
            if self.__health == 5:
                self.make_heart_entity(2, "half")
            else:
                self.make_heart_entity(2, "full")
            self.make_heart_entity(0, "full")
            self.make_heart_entity(1, "full")

    def make_heart_entity(self, num_heart, state):
        if state == "full":
            heart_sprite = self.sprite_full
        elif state == "half":
            heart_sprite = self.sprite_half
        else:
            heart_sprite = self.sprite_empty
        self.__heart_entities[num_heart].get_component_by_name("SpriteRenderer").switch_sprite(heart_sprite)

    def get_exit_sprite(self):
        return self.__exit_sprite

    def set_exit_sprite(self, new_sprite):
        self.__exit_sprite = new_sprite

    def power_up_effects(self):
        # FLASHES PINK when you get HEALTH-UP
        if self.__health_up_timer < 0 and self.__flash_count == 0 and self.__health_up:
            self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__health_up_timer = 0.1
            self.__flash_count += 1

        if self.__health_up_timer < 0 and self.__flash_count == 1 and self.__health_up:
            self.__sprite_renderer.sprite.color = arcade.color.PINK
            self.__health_up_timer = 0.1
            self.__flash_count += 1

        if self.__health_up_timer < 0 and self.__flash_count == 2 and self.__health_up:
            self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__flash_count = 0
            self.__health_up = False

        # Undoes the effect of the speed-boost power-up
        if self.__speed_timer < 0 and self.__speed:
            self.__speed = False
            self.__flash_count = 0
            self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__max_velocity = (MAX_SPEED, MAX_JUMP)

        # Undoes the effect of the jump power-up
        if self.__jumping_timer < 0 and self.__jump:
            self.__jump = False
            self.__flash_count = 0
            self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__gravity = -1700
            self.__max_velocity = (self.__max_velocity[0], MAX_JUMP)

        # Undoes the effect of the attack power-up
        if self.__mad_timer < 0 and self.__mad:
            self.__mad = False
            self.__flash_count = 0
            self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__attack_power = 1

        # FLASHES BLUE when you get SPEED-BOOST
        if self.__speed:
            if self.__flash_count % 16 == 0:
                self.__sprite_renderer.sprite.color = (100, 100, 255)
            elif self.__flash_count % 8 == 0:
                self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__flash_count = (self.__flash_count + 1) % 80

        # FLASHES GREEN when you get JUMP-BOOST
        if self.__jump:
            if self.__flash_count % 16 == 0:
                self.__sprite_renderer.sprite.color = (100, 255, 100)
            elif self.__flash_count % 8 == 0:
                self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__flash_count = (self.__flash_count + 1) % 8e0

        # FLASHES PURPLE when you get ATTACK-BOOST
        if self.__mad:
            if self.__flash_count % 16 == 0:
                self.__sprite_renderer.sprite.color = (255, 100, 255)
            elif self.__flash_count % 8 == 0:
                self.__sprite_renderer.sprite.color = (255, 255, 255)
            self.__flash_count = (self.__flash_count + 1) % 80

    def toggle_camera_movement(self):
        self.__freeze_camera = not self.__freeze_camera

    # Update the player's animation
    # THE FOLLOWING LINK WAS USED AS REFERENCE: https://api.arcade.academy/en/latest/examples/platform_tutorial/step_12.html#platformer-part-twelve
    def update_animation(self, delta_time: float = 1 / 30):
        speed = 18
        if self.__velocity[0] > 100 or self.__velocity[0] < -100:
            speed = 13
        if self.__velocity[0] > 300 or self.__velocity[0] < -300:
            speed = 9
        if self.__velocity[0] > 500 or self.__velocity[0] < -500:
            speed = 7
        if self.__velocity[0] > 600 or self.__velocity[0] < -600:
            speed = 3

        # Determine if the character is facing right or left
        if self.__moving_left:
            self.character_face_direction = LEFT_FACING
        else:
            self.character_face_direction = RIGHT_FACING

        # If player is currently attacking
        if self.__attack_animation:
            # Update frame
            self.current_texture += 1
            if self.current_texture > (2 * 9) - 1:
                self.current_texture = 0
            frame = self.current_texture // 9
            if not self.__touching_floor:  # If you are attacking in air
                self.__sprite_renderer.set_texture(self.jump_attack_texture_pair[frame][self.character_face_direction])
                return
            else:
                self.__sprite_renderer.set_texture(self.attack_texture_pair[frame][self.character_face_direction])
                return

        # If the player is jumping
        if not self.__touching_floor:
            self.__sprite_renderer.set_texture(self.jump_texture_pair[self.character_face_direction])
            return

        # Idle animation:
        # Update frame
        if 0.1 > self.__velocity[0] > -0.1:
            if not self.__idle:
                # Side idle animation
                # Update frame
                self.current_texture += 1
                if self.current_texture > (2 * speed) - 1:
                    self.current_texture = 0
                frame = self.current_texture // speed
                self.__sprite_renderer.set_texture(self.idle_side_texture_pair[frame][self.character_face_direction])
                return

            self.current_texture += 1
            if self.current_texture > (2 * speed) - 1:
                self.current_texture = 0
            frame = self.current_texture // speed
            self.__sprite_renderer.set_texture(self.idle_texture_pair[frame][self.character_face_direction])
            return

        # Walking animation:
        # Update frame
        self.current_texture += 1
        if self.current_texture > (4 * speed) - 1:
            self.current_texture = 0
        frame = self.current_texture // speed
        self.__sprite_renderer.set_texture(self.walk_texture_pair[frame][self.character_face_direction])
        return

    @property
    def touching_ground(self):
        return self.__touching_ground

    @property
    def velocity(self):
        return self.__velocity

    @property
    def health(self):
        return self.__health

    @health.setter
    def health(self, new):
        self.__health = new

    @property
    def max_health(self):
        return self.__max_health

    @property
    def taking_damage(self):
        return self.__taking_damage

    @property
    def is_attacking(self):
        return self.__is_attacking

    @property
    def is_moving_left(self):
        return self.__moving_left

    @property
    def attack_power(self):
        return self.__attack_power


# coding: utf-8

# In[5]:

import urllib, sqlite3
import time, datetime
from bs4 import BeautifulSoup

# connect to the database
con = sqlite3.connect('C:\\NBA\\nba.db') # create database in the directory where the .py file is saved
cur = con.cursor()

boxscore_links = []
#yesterday = datetime.datetime.strptime('2016-11-15', '%Y-%m-%d')
yesterday = (datetime.date.today() + datetime.timedelta(days=-1))

url = 'http://www.basketball-reference.com/boxscores/index.cgi?month=' + str(yesterday.month) + '&day=' + str(yesterday.day) + '&year=' + str(yesterday.year)

html = urllib.urlopen(url).read()
soup = BeautifulSoup(html, "lxml")
for p in soup.findAll('p'):
    if p.a != None:
        if p.a.string == 'Box Score':
            boxscore_links.append('http://www.basketball-reference.com' + p.a.get('href', None))

# collect the current max game in the table
cur.execute('SELECT MAX(game_id) FROM games')
for g in cur:
    game_id = g[0]

for url in boxscore_links:
    game_id += 1

    html = urllib.urlopen(url).read()
    soup = BeautifulSoup(html, "lxml")

    # collect the game details
    titles = soup('title')

    for t in titles:
        if 'Box Score' in t.string:
            away = t.string.split(' at ')[0].strip()
            home = t.string.split(' at ')[1].split(' Box')[0].strip()
            date = t.string.split('Score, ')[1].split('|')[0].strip()
            year = date.split(', ')[1]
            month = date.split(' ')[0]
            day = date.split(' ')[1].split(',')[0].strip()
            day = '00' + day
            day = day[-2:]
            if month == 'January':
                month = '01'
            elif month == 'February':
                month = '02'
            elif month == 'March':
                month = '03'
            elif month == 'April':
                month = '04'
            elif month == 'May':
                month = '05'
            elif month == 'June':
                month = '06'
            elif month == 'July':
                month = '07'
            elif month == 'August':
                month = '08'
            elif month == 'September':
                month = '09'
            elif month == 'October':
                month = '10'
            elif month == 'November':
                month = '11'
            elif month == 'December':
                month = '12'
            date = year + '-' + month + '-' + day

            if int(month) > 9:
                season = int(year) + 1
            else:
                season = int(year)

    stats_input = [] # empty list to store the tuples that will be inserted into the stats table
    for i in range(0,3,2): # tables 0 and 2
        if i == 0:
            team = away
            home_flag = 0
        else:
            team = home
            home_flag = 1
        for tr in soup('table')[i].findAll('tr'):
            if tr.th.get('data-stat', None) == 'player':
                if tr.th.get('scope', None) == 'row':
                    if tr.th.string != 'Team Totals':
                        player_id = tr.th.get('data-append-csv',None)
                        for td in tr.findAll('td'):
                            if td.get('data-stat',None) == 'mp':
                                minutes_played = td.string
                            elif td.get('data-stat',None) == 'fg':
                                field_goals = td.string
                            elif td.get('data-stat',None) == 'fga':
                                field_goal_attempts = td.string
                            elif td.get('data-stat',None) == 'fg3':
                                three_pointers = td.string
                            elif td.get('data-stat',None) == 'fg3a':
                                three_point_attempts = td.string
                            elif td.get('data-stat',None) == 'ft':
                                free_throws = td.string
                            elif td.get('data-stat',None) == 'fta':
                                free_throw_attempts = td.string
                            elif td.get('data-stat',None) == 'orb':
                                offensive_rebounds = td.string
                            elif td.get('data-stat',None) == 'drb':
                                defensive_rebounds = td.string
                            elif td.get('data-stat',None) == 'trb':
                                total_rebounds = td.string
                            elif td.get('data-stat',None) == 'ast':
                                assists = td.string
                            elif td.get('data-stat',None) == 'stl':
                                steals = td.string
                            elif td.get('data-stat',None) == 'blk':
                                blocks = td.string
                            elif td.get('data-stat',None) == 'tov':
                                turnovers = td.string
                            elif td.get('data-stat',None) == 'pf':
                                personal_fouls = td.string
                            elif td.get('data-stat',None) == 'pts':
                                points = td.string
                        player_stats = (game_id,date,team,home_flag,season,player_id,minutes_played,field_goals,field_goal_attempts,three_pointers,three_point_attempts,free_throws,free_throw_attempts,offensive_rebounds,defensive_rebounds,total_rebounds,assists,steals,blocks,turnovers,personal_fouls,points)
                        stats_input.append(player_stats)

    # update the database
    for input_row in stats_input:
        cur.execute('INSERT INTO games VALUES(?' + ',?'*21 + ')',input_row)

    con.commit()    # commit inserted rows

con.close()

# In[ ]:


import theano
import theano.tensor as T
import sklearn
import sklearn.datasets
import numpy as np
import matplotlib.pyplot as plt
import timeit

theano.config.floatX = 'float32'

# Helper function to plot a decision boundary.
def plot_decision_boundary(pred_func):
    # Set min and max values and give it some padding
    x_min, x_max = train_X[:, 0].min() - .5, train_X[:, 0].max() + .5
    y_min, y_max = train_X[:, 1].min() - .5, train_X[:, 1].max() + .5
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole gid
    Z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.scatter(train_X[:, 0], train_X[:, 1], c=train_y, cmap=plt.cm.Spectral)

# Generate datasets
train_X, train_y = sklearn.datasets.make_moons(200, noise='0.2')
train_y_onehot = np.eye(2)[train_y]

# Size definitions
num_examples = len(train_X)  # training set size
nn_input_dim = 2  # input layer dimensionality
nn_output_dim = 2  # output layer dimensionality
nn_hdim = 100

epsilon = np.float32(0.01) # learning rate for gradient descent
reg_lambda = np.float32(0.01) # regularization strength

# These float32 values will be initialized on the GPU
X = theano.shared(train_X.astype('float32'), name='X')
y = theano.shared(train_y_onehot.astype('float32'), name='y')
W1 = theano.shared(np.random.randn(nn_input_dim, nn_hdim).astype('float32'), name='W1')
b1 = theano.shared(np.zeros(nn_hdim).astype('float32'), name='b1')
W2 = theano.shared(np.random.randn(nn_hdim, nn_output_dim).astype('float32'), name='W2')
b2 = theano.shared(np.zeros(nn_output_dim).astype('float32'), name='b2')

# Forward propagation
# Note: We are just defining the expressions, nothing is evaluated here!
z1 = X.dot(W1) + b1
a1 = T.tanh(z1)
z2 = a1.dot(W2) + b2
y_hat = T.nnet.softmax(z2)  # output probabilties

# The regularization term (optional)
loss_reg = 1./num_examples * reg_lambda/2 * (T.sum(T.sqr(W1)) + T.sum(T.sqr(W2)))
# the loss function we want to optimize
loss = T.nnet.categorical_crossentropy(y_hat, y).mean() + loss_reg

# Returns a class prediction
prediction = T.argmax(y_hat, axis=1)

# Theano functions that can be called from our Python code
forward_prop = theano.function([], y_hat)
calculate_loss = theano.function([], loss)
predict = theano.function([], prediction)

# Easy: Let Theano calculate the derivatives for us!
dW2 = T.grad(loss, W2)
db2 = T.grad(loss, b2)
dW1 = T.grad(loss, W1)
db1 = T.grad(loss, b1)

gradient_step = theano.function(
    [],
    updates=((W2, W2 - epsilon * dW2),
             (W1, W1 - epsilon * dW1),
             (b2, b2 - epsilon * db2),
             (b1, b1 - epsilon * db1)))

def build_model(num_passes=20000, print_loss=False):
    # Re-Initialize the parameters to random values. We need to learn these.
    np.random.seed(0)
    # GPU NOTE: Conversion to float32 to store them on the GPU!
    W1.set_value((np.random.randn(nn_input_dim, nn_hdim) / np.sqrt(nn_input_dim)).astype('float32'))
    b1.set_value(np.zeros(nn_hdim).astype('float32'))
    W2.set_value((np.random.randn(nn_hdim, nn_output_dim) / np.sqrt(nn_hdim)).astype('float32'))
    b2.set_value(np.zeros(nn_output_dim).astype('float32'))

    # Gradient descent. For each batch...
    for i in range(0, num_passes):
        # This will update our parameters W2, b2, W1 and b1!
        gradient_step()

        # Optionally print the loss.
        # This is expensive because it uses the whole dataset, so we don't want to do it too often.
        if print_loss and i % 1000 == 0:
            print("Loss after iteration %i: %f" %(i, calculate_loss()))

# Profiling
# theano.config.profile = True
# theano.config.profile_memory = True
# gradient_step()\
# theano.printing.debugprint(gradient_step)
# print gradient_step.profile.summary()

def plot_decision_boundary_gpu(pred_func):
    # Set min and max values and give it some padding
    x_min, x_max = train_X[:, 0].min() - .5, train_X[:, 0].max() + .5
    y_min, y_max = train_X[:, 1].min() - .5, train_X[:, 1].max() + .5
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

    X.set_value((np.c_[xx.ravel(), yy.ravel()]).astype('float32'))
    # Z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    Z = pred_func()
    Z = Z.reshape(xx.shape)

    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.scatter(train_X[:, 0], train_X[:, 1], c=train_y, cmap=plt.cm.Spectral)

build_model()
# print(timeit.timeit("build_model()", "from __main__ import build_model"))
# Plot the decision boundary

plot_decision_boundary(lambda x: predict(x))
plt.title("Decision Boundary for hidden layer size 3")
plt.show()


import cv2
import numpy as np
import mediapipe as mp

class ImageEditor:

    def __init__(self, img: str):
        self._mp_selfie_segmentation = mp.solutions.selfie_segmentation
        self._selfie_segmentation = self._mp_selfie_segmentation.SelfieSegmentation(model_selection=1)
        self._img = img

    def to_file(self, path: str):
        cv2.imwrite(path, self.img)

    @property
    def img(self):
        return self._img

    @classmethod
    def from_file(cls, image_file_path: str) -> "ImageEditor":
        img = cv2.imread(image_file_path)
        return cls(img)

    def segmentation_mask(self):
        RGB = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)

        # get the result
        results = self._selfie_segmentation.process(RGB)

        # extract segmented mask
        return results.segmentation_mask

    def without_background(self, new_background_color: int = 255):
        mask = self.segmentation_mask()
        condition = np.stack(
            (mask,) * 3, axis=-1) > 0.5
        # combine frame and background image using the condition
        return np.where(condition, self.img, 255)

    def as_cartoon(self, k: int = 8, remove_background: bool = True):
        """
        Turn the image into a cartoon.
        :param k: The number of clusters.
        :param remove_background: Whether to remove the background.
        :return: The cartoonized image.
        """
        img = self.img

        if remove_background:
            img = self.without_background()

        # Defining input data for clustering
        data = np.float32(img).reshape((-1, 3))

        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
        # Applying cv2.kmeans function
        _, label, center = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

        center = np.uint8(center)

        # Reshape the output data to the size of input image
        result = center[label.flatten()]
        result = result.reshape(img.shape)

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # Perform adaptive threshold
        edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 9, 8)
        blurred = cv2.medianBlur(result, 3)

        # Combine the result and edges to get final cartoon effect
        return cv2.bitwise_and(blurred, blurred, mask=edges)


import sys
from dataclasses import dataclass

data = int(sys.stdin.read().strip())

@dataclass
class Elf:
    number: int
    presents: int
    left: 'Elf'

    def __repr__(self):
        return f'<Elf {self.number} (w/{self.presents})>'

def play(n):
    elves = [Elf(i+1, 1, None) for i in range(n)]
    for elf, left in zip(elves, elves[1:] + [elves[0]]):
        elf.left = left
    current_elf = elves[0]
    del elves
    remaining = n
    while current_elf.left != current_elf:
        if remaining < 100 or remaining % 100_000 == 0:
            print(f'{current_elf} steals from {current_elf.left}. {remaining} remain.')
        current_elf.presents += current_elf.left.presents
        current_elf.left.presents = 0
        current_elf.left = current_elf.left.left
        current_elf = current_elf.left
        remaining -= 1
    print(f'{current_elf} remains.')
    return current_elf.number

assert play(5) == 3

#print(f'*** part 1: {play(data)}')
class ElfSkipList:
    def __init__(self, sequence):
        self._len = len(sequence)
        self._mid = len(sequence) // 2
        if self._mid < 100:
            self._left = sequence[:self._mid]
            self._right = sequence[self._mid:]
        else:
            self._left = ElfSkipList(sequence[:self._mid])
            self._right = ElfSkipList(sequence[self._mid:])

    def __len__(self):
        return self._len

    def __getitem__(self, n):
        #print(f'[{n}]', self._mid, self._len)
        if n < self._mid:
            return self._left[n]
        else:
            return self._right[n-self._mid]

    def __delitem__(self, n):
        #print(f'×{n}', self._mid, self._len)
        if n < self._mid:
            del self._left[n]
            self._mid -= 1
            self._len -= 1
        else:
            del self._right[n-self._mid]
            self._len -= 1

def play_right(n):
    elves = ElfSkipList([i+1 for i in range(n)])
    current_index = 0
    remaining = n
    while len(elves) > 1:
        current_elf = elves[current_index]
        target_index = (current_index + len(elves) // 2) % len(elves)
        target_elf = elves[target_index]
        if len(elves) < 1000 or len(elves) % 10_000 == 0:
            print(f'Elf {current_elf} steals from Elf {target_elf}. {len(elves)} remain.')
        del elves[target_index]
        if target_index > current_index:
            current_index += 1
        current_index %= len(elves)
    current_elf = elves[current_index]
    print(f'Elf {current_elf} remains.')
    return current_elf

assert play_right(5) == 2

assert play_right(6_561) == 6561
assert play_right(6_562) == 1
assert play_right(10_000) == 3439

print(f'*** part 2: {play_right(data)}')


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

#
#  Hotdog_def.py
#
#  Created on: 2020. 11. 25.
#      Author: Choi chan yeok
#

import os, sys
import time
import serial
import math
import dynamixel_sdk as dynamixel
from mpl_toolkits import mplot3d
import numpy as np
from math import *
import matplotlib.pyplot as plt
global Leg_thetaes

Leg_thetaes = []
grd_leg_theta = []

def setupView(limit):
    ax = plt.axes(projection="3d")
    ax.set_xlim(-limit, limit)
    ax.set_ylim(-limit, limit)
    ax.set_zlim(-limit, limit)
    ax.set_xlabel("X")
    ax.set_ylabel("Z")
    ax.set_zlabel("Y")
    return ax

setupView(200).view_init(elev=12., azim=28)

omega =  pi/4
phi =0
psi = 0

xm = 0
ym = 0
zm = 0

l1 = 70
l2 = 0
l3 = 220
l4 = 200

L = 350
W = 180

#FL,FR, RL, RR Leg Point
Lp=np.array([[100,-100,170,1],[100,-100,-170,1],[-100,-100,170,1],[-100,-100,-170,1]])

sHp=np.sin(pi/2)
cHp=np.cos(pi/2)

Lo=np.array([0,0,0,1])

if os.name == 'nt':
    import msvcrt
    def getch():
        return msvcrt.getch().decode()
else:
    import tty, termios
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    tty.setraw(sys.stdin.fileno())
    def getch():
        return sys.stdin.read(1)

# Control table address for Dynamixel XM-W350-R             # Control table address is different in Dynamixel model
ADDR_XM_TORQUE_ENABLE      = 64
ADDR_XM_Pgain      = 84
ADDR_XM_Igain      = 82
ADDR_XM_Dgain      = 80
ADDR_XM_FF2ND      = 88
ADDR_XM_FF1ST      = 90
ADDR_XM_GOAL_POSITION      = 116
ADDR_XM_PRESENT_POSITION   = 132
ADDR_XM_ProfileACC         = 108
ADDR_XM_ProfileVel         = 112
ADDR_XM_PRESENT_CURRENT    = 126

# Protocol version
PROTOCOL_VERSION1           = 1                             # See which protocol version is used in the Dynamixel
PROTOCOL_VERSION2           = 2

# Default setting
XM_ID = list(range(1,13))
FR1_ID                      = 1
FR2_ID                      = 2
FR3_ID                      = 3
FL4_ID                      = 4
FL5_ID                      = 5
FL6_ID                      = 6
RR7_ID                      = 7
RR8_ID                      = 8
RR9_ID                      = 9
RL10_ID                     = 10
RL11_ID                     = 11
RL12_ID                     = 12
IMU                         = 13

BAUDRATE                    = 3000000
DEVICENAME1                  = "COM17" #ID1,2,3,10,11,12
DEVICENAME2                  = "COM18" #ID4,5,6,7,8,9

#DEVICENAME1                  = "/dev/ttyUSB0".encode('utf-8')        # Check which port is being used on your controller
                                                                     # ex) Windows: "COM1"   Linux: "/dev/ttyUSB0"

TORQUE_ENABLE               = 1                             # Value for enabling the torque
TORQUE_DISABLE              = 0                             # Value for disabling the torque

MINIMUM_POSITION_VALUE       = 2000                         # Dynamixel will rotate between this value
MAXIMUM_POSITION_VALUE       = 2100                         # and this value (note that the Dynamixel would not move when the position value is out of movable range. Check e-manual about the range of the Dynamixel you use.)
MOVING_STATUS_THRESHOLD      = 20                           # Dynamixel moving status threshold

ESC_ASCII_VALUE             = 0x1b

COMM_SUCCESS                = 0                             # Communication Success result value
COMM_TX_FAIL                = -1001                         # Communication Tx Failed

# Initialize PortHandler1 Structs
# Set the port path
# Get methods and members of PortHandler1Linux or PortHandler1Windows
portHandler1 = dynamixel.PortHandler(DEVICENAME1)
portHandler2 = dynamixel.PortHandler(DEVICENAME2)

# Initialize PacketHandler1 Structs
packetHandler1 = dynamixel.PacketHandler(PROTOCOL_VERSION2)
packetHandler2 = dynamixel.PacketHandler(PROTOCOL_VERSION2)

index = 0
dxl_comm_result = COMM_TX_FAIL                                   # Communication result
goal_position = [MINIMUM_POSITION_VALUE, MAXIMUM_POSITION_VALUE] # Goal position of Dynamixel XM-W350-R
dxl_error = 0                                                    # Dynamixel error
present_position = 0                                             # Present position of Dynamixel XM-W350-R

# Open port 1
if portHandler1.openPort():
    print("Succeeded to open the port!")
else:
    print("Failed to open the port!")
    print("Press any key to terminate...")
    getch()
    quit()

# Open port 2
if portHandler2.openPort():
    print("Succeeded to open the port!")
else:
    print("Failed to open the port!")
    print("Press any key to terminate...")
    getch()
    quit()

# Set port baudrate 1
if portHandler1.setBaudRate(BAUDRATE):
    print("Succeeded to change the baudrate!")
else:
    print("Failed to change the baudrate!")
    print("Press any key to terminate...")
    getch()
    quit()

# Set port baudrate 2
if portHandler2.setBaudRate(BAUDRATE):
    print("Succeeded to change the baudrate!")
else:
    print("Failed to change the baudrate!")
    print("Press any key to terminate...")
    getch()
    quit()

# Enable Dynamixel torque 1
for ID in [1,2,3,10,11,12]:
    dxl_comm_result, dxl_error = packetHandler1.write1ByteTxRx(portHandler1, ID, ADDR_XM_TORQUE_ENABLE, TORQUE_ENABLE)
    if dxl_comm_result != COMM_SUCCESS:
        print("%s" % packetHandler1.getTxRxResult(dxl_comm_result))
    elif dxl_error != 0:
        print("%s" % packetHandler1.getRxPacketError(dxl_error))
    else:
        print("Dynamixel#%d has been successfully connected" % (ID))

# Enable Dynamixel torque 2
for ID in [4,5,6,7,8,9]:
    dxl_comm_result, dxl_error = packetHandler2.write1ByteTxRx(portHandler2, ID, ADDR_XM_TORQUE_ENABLE, TORQUE_ENABLE)
    if dxl_comm_result != COMM_SUCCESS:
        print("%s" % packetHandler2.getTxRxResult(dxl_comm_result))
    elif dxl_error != 0:
        print("%s" % packetHandler2.getRxPacketError(dxl_error))
    else:
        print("Dynamixel#%d has been successfully connected" % (ID))

vel = 200
acc = 200
packetHandler1.write4ByteTxRx(portHandler1, FR1_ID, ADDR_XM_ProfileVel, vel)
packetHandler1.write4ByteTxRx(portHandler1, FR2_ID, ADDR_XM_ProfileVel, vel)
packetHandler1.write4ByteTxRx(portHandler1, FR3_ID, ADDR_XM_ProfileVel, vel)
packetHandler1.write4ByteTxRx(portHandler1, FL4_ID, ADDR_XM_ProfileVel, vel)
packetHandler1.write4ByteTxRx(portHandler1, FL5_ID, ADDR_XM_ProfileVel, vel)
packetHandler1.write4ByteTxRx(portHandler1, FL6_ID, ADDR_XM_ProfileVel, vel)

packetHandler2.write4ByteTxRx(portHandler2, RR7_ID, ADDR_XM_ProfileVel, vel)
packetHandler2.write4ByteTxRx(portHandler2, RR8_ID, ADDR_XM_ProfileVel, vel)
packetHandler2.write4ByteTxRx(portHandler2, RR9_ID, ADDR_XM_ProfileVel, vel)
packetHandler2.write4ByteTxRx(portHandler2, RL10_ID, ADDR_XM_ProfileVel, vel)
packetHandler2.write4ByteTxRx(portHandler2, RL11_ID, ADDR_XM_ProfileVel, vel)
packetHandler2.write4ByteTxRx(portHandler2, RL12_ID, ADDR_XM_ProfileVel, vel)

packetHandler1.write4ByteTxRx(portHandler1, FR1_ID, ADDR_XM_ProfileACC, acc)
packetHandler1.write4ByteTxRx(portHandler1, FR2_ID, ADDR_XM_ProfileACC, acc)
packetHandler1.write4ByteTxRx(portHandler1, FR3_ID, ADDR_XM_ProfileACC, acc)
packetHandler1.write4ByteTxRx(portHandler1, FL4_ID, ADDR_XM_ProfileACC, acc)
packetHandler1.write4ByteTxRx(portHandler1, FL5_ID, ADDR_XM_ProfileACC, acc)
packetHandler1.write4ByteTxRx(portHandler1, FL6_ID, ADDR_XM_ProfileACC, acc)

packetHandler2.write4ByteTxRx(portHandler2, RR7_ID, ADDR_XM_ProfileACC, acc)
packetHandler2.write4ByteTxRx(portHandler2, RR8_ID, ADDR_XM_ProfileACC, acc)
packetHandler2.write4ByteTxRx(portHandler2, RR9_ID, ADDR_XM_ProfileACC, acc)
packetHandler2.write4ByteTxRx(portHandler2, RL10_ID, ADDR_XM_ProfileACC, acc)
packetHandler2.write4ByteTxRx(portHandler2, RL11_ID, ADDR_XM_ProfileACC, acc)
packetHandler2.write4ByteTxRx(portHandler2, RL12_ID, ADDR_XM_ProfileACC, acc)

# Initialize Groupsyncwrite instance
groupwrite_num1 = dynamixel.GroupSyncWrite(portHandler1, packetHandler1, ADDR_XM_GOAL_POSITION , 4)
groupread_num1 = dynamixel.GroupSyncRead(portHandler1, packetHandler1, ADDR_XM_PRESENT_CURRENT, 4)
Pwrite_num1 = dynamixel.GroupSyncWrite(portHandler1, packetHandler1, ADDR_XM_Pgain , 2)
Dwrite_num1 = dynamixel.GroupSyncWrite(portHandler1, packetHandler1, ADDR_XM_Dgain , 2)

groupwrite_num2 = dynamixel.GroupSyncWrite(portHandler2, packetHandler2, ADDR_XM_GOAL_POSITION , 4)
groupread_num2 = dynamixel.GroupSyncRead(portHandler2, packetHandler2, ADDR_XM_PRESENT_CURRENT, 4)
Pwrite_num2 = dynamixel.GroupSyncWrite(portHandler2, packetHandler2, ADDR_XM_Pgain , 2)
Dwrite_num2 = dynamixel.GroupSyncWrite(portHandler2, packetHandler2, ADDR_XM_Dgain , 2)

def p_data(Pgain):
    p_goalposition = [0,0]
    p_goalposition[0] = dynamixel.DXL_LOBYTE(dynamixel.DXL_LOWORD(Pgain))
    p_goalposition[1] = dynamixel.DXL_HIBYTE(dynamixel.DXL_LOWORD(Pgain))

    return p_goalposition

def P_write_1(ID1, ID2, ID3, Pgain1, Pgain2, Pgain3, times):
    Pwrite_num1.clearParam()
    Pwrite_num1.addParam(ID1, p_data(Pgain1))
    Pwrite_num1.addParam(ID2, p_data(Pgain2))
    Pwrite_num1.addParam(ID3, p_data(Pgain3))
    dxl_comm_result = Pwrite_num1.txPacket()

    if (dxl_comm_result != COMM_SUCCESS):
        print("%s" % packetHandler1.getTxRxResult(dxl_comm_result))
    #time.sleep(times)

    return 0

def P_write_2(ID1, ID2, ID3, Pgain1, Pgain2, Pgain3, times):
    Pwrite_num2.clearParam()
    Pwrite_num2.addParam(ID1, p_data(Pgain1))
    Pwrite_num2.addParam(ID2, p_data(Pgain2))
    Pwrite_num2.addParam(ID3, p_data(Pgain3))
    dxl_comm_result = Pwrite_num2.txPacket()

    if (dxl_comm_result != COMM_SUCCESS):
        print("%s" % packetHandler1.getTxRxResult(dxl_comm_result))
    #time.sleep(times)

    return 0

def position_data(position):
    param_goalposition = [0,0,0,0]
    param_goalposition[0] = dynamixel.DXL_LOBYTE(dynamixel.DXL_LOWORD(position))
    param_goalposition[1] = dynamixel.DXL_HIBYTE(dynamixel.DXL_LOWORD(position))
    param_goalposition[2] = dynamixel.DXL_LOBYTE(dynamixel.DXL_HIWORD(position))
    param_goalposition[3] = dynamixel.DXL_HIBYTE(dynamixel.DXL_HIWORD(position))

    return param_goalposition

def leg_position_write_1(ID1, ID2, ID3, position1, position2, position3, times):
    groupwrite_num1.clearParam()
    groupwrite_num1.addParam(ID1, position_data(position1))
    groupwrite_num1.addParam(ID2, position_data(position2))
    groupwrite_num1.addParam(ID3, position_data(position3))
    dxl_comm_result = groupwrite_num1.txPacket()

    if (dxl_comm_result != COMM_SUCCESS):
        print("%s" % packetHandler1.getTxRxResult(dxl_comm_result))
    #time.sleep(times)

    return 0

def leg_position_write_2(ID1, ID2, ID3, position1, position2, position3, times):
    groupwrite_num2.clearParam()
    groupwrite_num2.addParam(ID1, position_data(position1))
    groupwrite_num2.addParam(ID2, position_data(position2))
    groupwrite_num2.addParam(ID3, position_data(position3))
    dxl_comm_result = groupwrite_num2.txPacket()

    if (dxl_comm_result != COMM_SUCCESS):
        print("%s" % packetHandler2.getTxRxResult(dxl_comm_result))
    #time.sleep(times)

    return 0

def leg_position_bulk_write(ID1, ID2, ID3,
                            ID4, ID5, ID6,
                            ID7, ID8, ID9,
                            ID10, ID11, ID12,
                            position1, position2, position3,
                            position4, position5, position6,
                            position7, position8, position9,
                            position10, position11, position12):

    groupwrite_num1.clearParam()
    groupwrite_num2.clearParam()
    groupwrite_num1.addParam(ID1, position_data(position1))
    groupwrite_num1.addParam(ID2, position_data(position2))
    groupwrite_num1.addParam(ID3, position_data(position3))
    groupwrite_num2.addParam(ID4, position_data(position4))
    groupwrite_num2.addParam(ID5, position_data(position5))
    groupwrite_num2.addParam(ID6, position_data(position6))
    groupwrite_num2.addParam(ID7, position_data(position7))
    groupwrite_num2.addParam(ID8, position_data(position8))
    groupwrite_num2.addParam(ID9, position_data(position9))
    groupwrite_num1.addParam(ID10, position_data(position10))
    groupwrite_num1.addParam(ID11, position_data(position11))
    groupwrite_num1.addParam(ID12, position_data(position12))
    dxl_comm_result1 = groupwrite_num1.txPacket()
    dxl_comm_result2 = groupwrite_num2.txPacket()

    if (dxl_comm_result1 != COMM_SUCCESS):
        print("%s" % packetHandler1.getTxRxResult(dxl_comm_result1))

    if (dxl_comm_result2 != COMM_SUCCESS):
        print("%s" % packetHandler2.getTxRxResult(dxl_comm_result2))

    return 0

def leg_current_read():
    current = []
    groupread_num.clearParam()
    for ID in XM_ID:
        groupread_num.addParam(ID)
    dxl_comm_result = groupread_num.txRxPacket()
    if (dxl_comm_result != COMM_SUCCESS):
        print("%s" % packetHandler1.getTxRxResult(dxl_comm_result))
    for ID in XM_ID:
        addr_xm_present_current = groupread_num.getData(ID, ADDR_XM_PRESENT_CURRENT,2)
        if  addr_xm_present_current > 0x7fff:
            addr_xm_present_current = addr_xm_present_current- 65536
        current.append(addr_xm_present_current)

    print("Current "," :" , current)
    return current

def IMU_value(times):
    read_data = []
    IMU_x = []
    IMU_y = []
    IMU_z = []
    comma = 0
    if portHandler1.getBytesAvailable() > 0 :
        read_data = portHandler1.readPort(1024)
        read_data = read_data.decode('ascii')
        for i in range(len(read_data)):
            if read_data[i] == ',' and comma == 0:
                comma = comma + 1
                IMU_x = read_data[0:i]
                comma_first = i
            elif read_data[i] == ',' and comma == 1:
                comma = comma + 1
                IMU_y = read_data[comma_first+1:i]
                comma_first = i
            elif read_data[i] == ',' and comma == 2:
                IMU_z = read_data[comma_first+1:i]
                comma = 0
                break

    print("IMU_x:", IMU_x, "IMU_y:", IMU_y, "IMU_z:", IMU_z)
    #time.sleep(times)

    return read_data

def bodyIK(omega,phi,psi,xm,ym,zm):
    Rx = np.array([[1,0,0,0],
                   [0,np.cos(omega),-np.sin(omega),0],
                   [0,np.sin(omega),np.cos(omega),0],[0,0,0,1]])
    Ry = np.array([[np.cos(phi),0,np.sin(phi),0],
                   [0,1,0,0],
                   [-np.sin(phi),0,np.cos(phi),0],[0,0,0,1]])
    Rz = np.array([[np.cos(psi),-np.sin(psi),0,0],
                   [np.sin(psi),np.cos(psi),0,0],[0,0,1,0],[0,0,0,1]])
    Rxyz=Rx@Ry@Rz

    T = np.array([[0,0,0,xm],[0,0,0,ym],[0,0,0,zm],[0,0,0,0]])
    Tm = T+Rxyz

    return([Tm @ np.array([[cHp,0,sHp,L/2],[0,1,0,0],[-sHp,0,cHp,W/2],[0,0,0,1]]),
           Tm @ np.array([[cHp,0,sHp,L/2],[0,1,0,0],[-sHp,0,cHp,-W/2],[0,0,0,1]]),
           Tm @ np.array([[cHp,0,sHp,-L/2],[0,1,0,0],[-sHp,0,cHp,W/2],[0,0,0,1]]),
           Tm @ np.array([[cHp,0,sHp,-L/2],[0,1,0,0],[-sHp,0,cHp,-W/2],[0,0,0,1]])
           ])

def legIK(point):
    (x,y,z)=(point[0],point[1],point[2])
    F=sqrt(x**2+y**2-l1**2)
    G=F-l2
    H=sqrt(G**2+z**2)
    theta1=-atan2(y,x)-atan2(F,-l1)

    D=(H**2-l3**2-l4**2)/(2*l3*l4)
    theta3=acos(D)

    theta2=atan2(z,G)-atan2(l4*sin(theta3),l3+l4*cos(theta3))

    if len(Leg_thetaes) >= 12:
        Leg_thetaes.clear()

    Leg_thetaes.extend([theta1, theta2, theta3])
    return (theta1,theta2,theta3)

def calcLegPoints(angles):
    (theta1,theta2,theta3)=angles
    theta23=theta2+theta3

    T0=Lo
    T1=T0+np.array([-l1*cos(theta1),l1*sin(theta1),0,0])
    T2=T1+np.array([-l2*sin(theta1),-l2*cos(theta1),0,0])
    T3=T2+np.array([-l3*sin(theta1)*cos(theta2),-l3*cos(theta1)*cos(theta2),l3*sin(theta2),0])
    T4=T3+np.array([-l4*sin(theta1)*cos(theta23),-l4*cos(theta1)*cos(theta23),l4*sin(theta23),0])

    return np.array([T0,T1,T2,T3,T4])

def drawLegPoints(p):
    plt.plot([x[0] for x in p],[x[2] for x in p],[x[1] for x in p], 'k-', lw=3)
    plt.plot([p[0][0]],[p[0][2]],[p[0][1]],'bo',lw=2)
    plt.plot([p[4][0]],[p[4][2]],[p[4][1]],'ro',lw=2)

def drawLegPair(Tl,Tr,Ll,Lr):
    Ix=np.array([[-1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]])
    drawLegPoints([Tl@x for x in calcLegPoints(legIK(np.linalg.inv(Tl)@Ll))])
    drawLegPoints([Tr@Ix@x for x in calcLegPoints(legIK(Ix@np.linalg.inv(Tr)@Lr))])

def drawRobot(Lp,angles,center):
    (omega,phi,psi)=angles
    (xm,ym,zm)=center

    FP=[0,0,0,1]
    (Tlf,Trf,Tlb,Trb)= bodyIK(omega,phi,psi,xm,ym,zm)
    CP=[x@FP for x in [Tlf,Trf,Tlb,Trb]]

    CPs=[CP[x] for x in [0,1,3,2,0]]
    plt.plot([x[0] for x in CPs],[x[2] for x in CPs],[x[1] for x in CPs], 'bo-', lw=2)

    drawLegPair(Tlf,Trf,Lp[0],Lp[1])
    drawLegPair(Tlb,Trb,Lp[2],Lp[3])

def leg_theta(angles, center):
    drawRobot(Lp, angles, center)
    #plt.show()
    return Leg_thetaes

def four_leg_theta(angles, center):
    #radian
    grd_leg_theta = leg_theta(angles, center)

    #degree
    for i in range(len(grd_leg_theta)):
        grd_leg_theta[i] = math.degrees(grd_leg_theta[i])
        if i == 2 or i == 5 or i == 8 or i == 11:
            grd_leg_theta[i] = grd_leg_theta[i] - 180

    #DXL Unit
    for i in range(len(grd_leg_theta)):
        grd_leg_theta[i] = int(grd_leg_theta[i]*(4096//360) + 2048)

    return grd_leg_theta

P_write_1(1, 2, 3, 1200, 1200 ,1200,0.1)
P_write_1(4, 5, 6, 1200, 1200 ,1200,0.1)
P_write_2(7, 8, 9, 1200, 1200 ,1200,0.1)
P_write_2(10, 11, 12, 1200, 1200 ,1200,0.1)


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

from django.db import models, migrations
from django.conf import settings

class Migration(migrations.Migration):

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Contractor',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=128)),
                ('url', models.URLField()),
                ('bill_rate', models.IntegerField(default=0)),
                ('slug', models.SlugField(unique=True)),
            ],
            options={
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='Project',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('title', models.CharField(max_length=128)),
                ('slug', models.SlugField(unique=True)),
                ('contractor_hours', models.IntegerField(default=0)),
                ('client', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True)),
                ('contractor', models.ManyToManyField(to='keeper.Contractor')),
            ],
            options={
            },
            bases=(models.Model,),
        ),
        migrations.CreateModel(
            name='UserProfile',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
            ],
            options={
            },
            bases=(models.Model,),
        ),
    ]


import json
import logging

LOG = logging.getLogger(__name__)

def get_properties(properties_file='raw.properties.json', env=None, region=None):
    """Get contents of _properties_file_ for the _env_.

    Args:
        properties_file (str): File name of `create-configs` JSON output.
        env (str): Environment to read optionally.
        region (str): Region to get specific configs for.

    Returns:
        dict: JSON loaded Application properties for _env_.
        None: Given _env_ was not found in `create-configs` JSON output.

    """
    with open(properties_file, 'rt') as file_handle:
        properties = json.load(file_handle)

    env_properties = properties.get(env, properties)
    contents = env_properties.get(region, env_properties)
    LOG.debug('Found properties for %s:\n%s', env, contents)
    return contents


import json
import mimetypes
import uuid
import falcon
from tucluster import fmdb

class ModelCollection(object):
    '''List and create ``Model`` documents
    '''
    def __init__(self, data_store, model_document):
        # Instance supporting `save()` which will handle writing
        # incoming zip data streams to disk
        self._data_store = data_store

        # MongoEngine ``Document`` class which provides the data for this
        # resource
        self._document = model_document

    def on_get(self, req, resp):
        '''Retrieve a JSON representation of all ``Model`` documents.

        Broadly, a ``Model`` represents a geographical domain over which we will
        produce one or more flood models (called 'runs').
        A model has a name, description and a folder where input data files are stored.
        The JSON representation returned by this GET handler encodes the folder path as
        a URL-safe base64 string which can be used with the ``/file/tree/{fid}`` endpoint.

        A ``Model`` will typically have a 'baseline' where one of the runs is selected
        as the definitive or primary flood model.

        Example::

            http localhost:8000/models
        '''
        docs = self._document.objects.all()
        # Create a JSON representation of the resource
        resp.body = docs.to_json()
        resp.status = falcon.HTTP_OK

    def on_post(self, req, resp):
        '''Create a new ``Model`` by uploading a zip file containing the input data
        required to run the model using a supported flood modelling software.

        The zip file will be saved and unpacked to the data folder configured in the
        ``data_store`` instance. This folder path will be stored in the ``Model`` instance.

        The name of the model is generated automatically and can be overwritten with a PUT
        request.

        A JSON representation of the created model is returned in the response body and
        the GET URL in the response location header.

        Example::

            http post localhost:8000/models @/path/to/my/archive.zip
        '''
        if req.content_type == 'application/json':
            # Create a model without data.
            data = json.load(req.bounded_stream)
            model = self._document(
                name=data['name']
            )
            if 'description' in data:
                model.description = data['description']
            if 'email' in data:
                model.email = data['email']
            model.save()

            resp.status = falcon.HTTP_CREATED
            resp.location = '/models/{}'.format(model.name)
            resp.body = model.to_json()

        elif req.content_type == 'application/zip':
            directory, name = self._data_store.save_zip(req.stream, req.content_type)
            # Create the model
            model = self._document(
                name=name,
                folder=directory
            ).save()

            resp.status = falcon.HTTP_CREATED
            resp.location = '/models/{}'.format(model.name)
            resp.body = model.to_json()
        else:
            resp.status = falcon.HTTP_BAD_REQUEST
            resp.body = 'Content type must be zip or json'

class ModelItem(ModelCollection):
    '''Fetch or update a single ``Model`` document
    '''
    def get_object(self, name):
        try:
            return self._document.objects.get(name=name)
        except self._document.DoesNotExist:
            raise falcon.HTTPBadRequest(
                description="A model with the name {} does not exist".format(name)
            )

    def on_get(self, req, resp, name):
        '''Retrieve a JSON representation of a single ``Model`` based on its'
        name.

        Example::

            http localhost:8000/models/{name}
        '''
        model = self.get_object(name)
        resp.status = falcon.HTTP_OK
        resp.body = model.to_json()

    def on_patch(self, req, resp, name):
        '''Update a ``Model`` instance with new data.

        Data is submitted as a JSON object. Any of the following attributes are accepted:

        - ``description``: A new description of the model
        - ``name``: A new name for the model
        - ``email``: Email address of an existing user to transfer ownership
            of the model to.

        '''
        model = self.get_object(name)
        if req.content_type == 'application/json':
            data = json.load(req.bounded_stream)
            if 'description' in data:
                model.description = data['description']
            if 'name' in data:
                model.name = data['name']
            if 'email' in data:
                model.email = data['email']

            try:
                model.save()
                resp.status = falcon.HTTP_NO_CONTENT
            except fmdb.NotUniqueError:
                resp.status = falcon.HTTP_BAD_REQUEST
                resp.body = 'Name {} is already taken'.format(data['name'])

        else:
            if model.folder:
                folder = model.resolve_folder()
            else:
                folder = model.name

            if req.content_type == 'application/zip':
                # Extract any uploaded zip file into the model data folder
                root, name = self._data_store.save_zip(req.stream, req.content_type, folder)
            else:
                # Save a single uploaded file to the model folder.
                # If the filename is given, use that, otherwise
                # try to guess the file type and generate a name
                disp = req.get_header('content-disposition')
                result = disp.split('filename=')
                if len(result) == 2:
                    filename = result[1].replace('"', '').replace("'", '')
                else:
                    ext = mimetypes.guess_extension(req.content_type)
                    filename = '{}{}'.format(uuid.uuid4(), ext)
                root, fid = self._data_store.save(req.stream, folder, filename)
                resp.body = json.dumps({
                    'fid': fid
                })

            model.folder = root
            model.save()
            resp.status = falcon.HTTP_ACCEPTED


import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from jp_extractor import JapaneseMecabWordExtractor
from chainer import iterators

def make_vectorizer(texts, null_set=(0, ""), unknown_set=(1, "###"),
                    option=None):
    """
    """
    print("Making vectorizer.")
    vectorizer = CountVectorizer(max_df=1.0,
                                 min_df=10,
                                 max_features=10000,
                                 stop_words=[null_set[1], unknown_set[1]])
    vectorizer.tokenizer = JapaneseMecabWordExtractor(split_mode="unigram",
                                                      use_all=True,
                                                      tagger_option=option)
    vectorizer.fit(texts)
    max_id = max(vectorizer.vocabulary_.values())
    prev_char = vectorizer.get_feature_names()[null_set[0]]
    vectorizer.vocabulary_[null_set[1]] = null_set[0]
    vectorizer.vocabulary_[prev_char] = max_id + 1
    prev_char = vectorizer.get_feature_names()[unknown_set[0]]
    vectorizer.vocabulary_[unknown_set[1]] = unknown_set[0]
    vectorizer.vocabulary_[prev_char] = max_id + 2
    return vectorizer

def text_to_word_sequence(texts, tokenizer, vocabulary,
                          null_id, unknown_id, max_length=None):
    """
    """
    print("Converting text to index sequences")
    num_unknown = 0
    total_words = 0
    sequences = list()
    for text in texts:
        words = tokenizer(text)
        maxl = max_length if max_length else len(words)
        ids = np.ones(maxl, dtype="int32")*null_id
        offset = 0 if len(words) > maxl else maxl - len(words)
        for i, word in enumerate(words):
            if i >= maxl:
                break
            ids[i+offset] = vocabulary.get(word, unknown_id)
            total_words += 1
            if ids[i+offset] == unknown_id:
                num_unknown += 1
        sequences.append(ids)

    print("unknown/words : {}/{} = {:.4f}".format(
        num_unknown, total_words, num_unknown/total_words))
    print("unknown/sentence : {}/{} = {:.4f}".format(
        num_unknown, len(sequences), num_unknown/len(sequences)))

    return sequences

class SerialPaddingIterator(iterators.SerialIterator):
    """
    """
    def __next__(self):
        """
        """
        batch = super(SerialPaddingIterator, self).__next__()
        sequences = [batch[i][0] for i in range(len(batch))]
        sequences = pad_sequences(sequences)
        for i, sequence in enumerate(sequences):
            batch[i] = (np.expand_dims(sequence, 0), batch[i][1])
        return batch

    next = __next__

### keras function ###
def pad_sequences(sequences, maxlen=None, dtype='int32',
                  padding='pre', truncating='pre', value=0.):
    """Pads each sequence to the same length (length of the longest sequence).
    If maxlen is provided, any sequence longer
    than maxlen is truncated to maxlen.
    Truncation happens off either the beginning (default) or
    the end of the sequence.
    Supports post-padding and pre-padding (default).
    # Arguments
        sequences: list of lists where each element is a sequence
        maxlen: int, maximum length
        dtype: type to cast the resulting sequence.
        padding: 'pre' or 'post', pad either before or after each sequence.
        truncating: 'pre' or 'post', remove values from sequences larger than
            maxlen either in the beginning or in the end of the sequence
        value: float, value to pad the sequences to the desired value.
    # Returns
        x: numpy array with dimensions (number_of_sequences, maxlen)
    # Raises
        ValueError: in case of invalid values for `truncating` or `padding`,
            or in case of invalid shape for a `sequences` entry.
    """
    if not hasattr(sequences, '__len__'):
        raise ValueError('`sequences` must be iterable.')
    lengths = []
    for x in sequences:
        if not hasattr(x, '__len__'):
            raise ValueError('`sequences` must be a list of iterables. '
                             'Found non-iterable: ' + str(x))
        lengths.append(len(x))

    num_samples = len(sequences)
    if maxlen is None:
        maxlen = np.max(lengths)

    # take the sample shape from the first non empty sequence
    # checking for consistency in the main loop below.
    sample_shape = tuple()
    for s in sequences:
        if len(s) > 0:
            sample_shape = np.asarray(s).shape[1:]
            break

    x = (np.ones((num_samples, maxlen) + sample_shape) * value).astype(dtype)
    for idx, s in enumerate(sequences):
        if not len(s):
            continue  # empty list/array was found
        if truncating == 'pre':
            trunc = s[-maxlen:]
        elif truncating == 'post':
            trunc = s[:maxlen]
        else:
            raise ValueError('Truncating type "%s" not understood' % truncating)

        # check `trunc` has expected shape
        trunc = np.asarray(trunc, dtype=dtype)
        if trunc.shape[1:] != sample_shape:
            raise ValueError('Shape of sample %s of sequence at position %s is different from expected shape %s' %
                             (trunc.shape[1:], idx, sample_shape))

        if padding == 'post':
            x[idx, :len(trunc)] = trunc
        elif padding == 'pre':
            x[idx, -len(trunc):] = trunc
        else:
            raise ValueError('Padding type "%s" not understood' % padding)
    return x


from trytond.model import ModelView, ModelSQL, fields

class Lineaire(ModelSQL, ModelView):
    'Linear'
    __name__ = 'lineaire.lineaire'

    lin_dispositif = fields.Many2One(
            'dispositif.dispositif',
            string=u'Dispositif',
            required=True,
            help='Dispositif',
        )
    lin_cycle = fields.Many2One(
            'cycle.cycle',
            string=u'Cycle',
            ondelete='CASCADE',
            help=u'Cycle number on the extent of linear measure',
            required=True,
        )
    lin_placette = fields.Many2One(
            'placettes.placettes',
            string='Plot',
            required=True,
            select=True,
            help=u'Plot number',
        )
    lin_essence = fields.Many2One(
            'essence.essence',
            string=u'Species',
            required=True,
            help=u'Species',
        )
    lin_transect = fields.Integer(
            string=u'Num transect',
            help=u'Transect number',
        )
    lin_diam = fields.Integer(
            string=u'Diameter',
            help=u'Diameter',
        )
    lin_angle = fields.Integer(
            string=u'Angle',
            help=u'Angle between the soil and the wood piece',
        )
    lin_contact = fields.Boolean(
            string=u'Contact',
            help=u'Contact',
        )
    lin_chablis = fields.Boolean(
            string=u'Chablis',
            help=u'Chablis',
        )
    lin_stade = fields.Integer(
            string=u'Stage',
            help=u'Stage of decomposition',
        )
    lin_observation = fields.Text(
            string=u'Observation',
            help=u'Observation',
        )


from __future__ import annotations

from typing import Tuple

from pyspark.sql.dataframe import DataFrame

from pysparkdq.validator import DataFrameValidator
from pysparkdq.checks.base import BaseCheck
from pysparkdq.exceptions import (
    InvalidCheckTypeException,
    InvalidDataFrameException
)

class CheckOperator:
    def __init__(self, dataframe: DataFrame) -> None:
        if not isinstance(dataframe, DataFrame):
            raise InvalidDataFrameException(
                "Not a pyspark.sql.dataframe.DataFrame: {}".format(
                    dataframe
                )
            )
        self.dataframe = dataframe
        self.checks = []

    def add_check(self, check: BaseCheck) -> CheckOperator:
        if not isinstance(check, BaseCheck):
            raise InvalidCheckTypeException(
                "Not a child of pysparkdq.checks.base.BaseCheck: {}".format(
                    type(check)
                )
            )
        self.checks.append(check)
        return self

    def run(self) -> Tuple[DataFrame, DataFrame]:
        return DataFrameValidator(
            dataframe=self.dataframe,
            checks=self.checks
        ).validate()


import json
from django.http import HttpResponse
from django.utils.module_loading import import_string
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db.models import Q

from .api import imgur_uploader
from .settings import MARTOR_MARKDOWNIFY_FUNCTION
from .utils import LazyEncoder

def markdownfy_view(request):
    if request.method == 'POST':
        markdownify = import_string(MARTOR_MARKDOWNIFY_FUNCTION)
        return HttpResponse(markdownify(request.POST['content']))
    return HttpResponse(_('Invalid request!'))

@login_required
def markdown_imgur_uploader(request):
    """
    Makdown image upload for uploading to imgur.com
    and represent as json to markdown editor.
    """
    if request.method == 'POST' and request.is_ajax():
        if 'markdown-image-upload' in request.FILES:
            image = request.FILES['markdown-image-upload']
            data = imgur_uploader(image)
            return HttpResponse(data, content_type='application/json')
        return HttpResponse(_('Invalid request!'))
    return HttpResponse(_('Invalid request!'))

@login_required
def markdown_search_user(request):
    """
    Json usernames of the users registered & actived.

    url(method=get):
        /martor/search-user/?username={username}

    Response:
        error:
            - `status` is status code (204)
            - `error` is error message.
        success:
            - `status` is status code (204)
            - `data` is list dict of usernames.
                { 'status': 200,
                  'data': [
                    {'usernane': 'john'},
                    {'usernane': 'albert'}]
                }
    """
    data = {}
    username = request.GET.get('username')
    if username is not None \
            and username != '' \
            and ' ' not in username:
        users = User.objects.filter(
            Q(username__icontains=username)
        ).filter(is_active=True)
        if users.exists():
            data.update({
                'status': 200,
                'data': [{'username': u.username} for u in users]
            })
            return HttpResponse(
                json.dumps(data, cls=LazyEncoder),
                content_type='application/json')
        data.update({
            'status': 204,
            'error': _('No users registered as `%(username)s` '
                       'or user is unactived.') % {'username': username}
        })
    else:
        data.update({
            'status': 204,
            'error': _('Validation Failed for field `username`')
        })
    return HttpResponse(
        json.dumps(data, cls=LazyEncoder),
        content_type='application/json')


from datetime import datetime

from skytemple_dse.util import DseAutoString, dse_read_uintle, dse_write_uintle

class DseDate(DseAutoString):
    def __init__(self, year: int, month: int, day: int, hour: int, minute: int, second: int, centisecond: int):
        self.year = year
        self.month = month
        self.day = day
        self.hour = hour
        self.minute = minute
        self.second = second
        self.centisecond = centisecond

    @classmethod
    def from_bytes(cls, data: bytes):
        return cls(
            dse_read_uintle(data, 0x00, 2),
            dse_read_uintle(data, 0x02, 1),
            dse_read_uintle(data, 0x03, 1),
            dse_read_uintle(data, 0x04, 1),
            dse_read_uintle(data, 0x05, 1),
            dse_read_uintle(data, 0x06, 1),
            dse_read_uintle(data, 0x07, 1)
        )

    @classmethod
    def now(cls):
        date = datetime.now()
        return cls(
            date.year,
            date.month,
            date.day,
            date.hour,
            date.minute,
            date.second,
            0
        )

    def to_bytes(self):
        buffer = bytearray(8)
        dse_write_uintle(buffer, self.year, 0x00, 2),
        dse_write_uintle(buffer, self.month, 0x02, 1),
        dse_write_uintle(buffer, self.day, 0x03, 1),
        dse_write_uintle(buffer, self.hour, 0x04, 1),
        dse_write_uintle(buffer, self.minute, 0x05, 1),
        dse_write_uintle(buffer, self.second, 0x06, 1),
        dse_write_uintle(buffer, self.centisecond, 0x07, 1)
        return buffer

    def __eq__(self, other):
        if not isinstance(other, DseDate):
            return False
        return vars(self) == vars(other)