"""drop history

Revision ID: 77b147fe0ee2
Revises: fe53ac970441
Create Date: 2021-08-14 19:14:07.617715

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '77b147fe0ee2'
down_revision = 'fe53ac970441'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('ticket_history')
    with op.batch_alter_table('user', schema=None) as batch_op:
        batch_op.create_unique_constraint(batch_op.f('uq_user_login'), ['login'])

    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('user', schema=None) as batch_op:
        batch_op.drop_constraint(batch_op.f('uq_user_login'), type_='unique')

    op.create_table('ticket_history',
    sa.Column('id', sa.INTEGER(), nullable=False),
    sa.Column('status', sa.INTEGER(), nullable=True),
    sa.Column('ticket', sa.INTEGER(), nullable=True),
    sa.Column('updated_at', sa.DATETIME(), nullable=True),
    sa.ForeignKeyConstraint(['status'], ['status.id'], ),
    sa.ForeignKeyConstraint(['ticket'], ['ticket.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###


# -*- coding: UTF-8 -*-
#brailleDisplayDrivers/seika.py
#A part of NonVisual Desktop Access (NVDA)
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
#Copyright (C) 2012 Ulf Beckmann <beckmann@flusoft.de>

# Parts of this code are inherited from the baum braille driver
# written by James Teh <jamie@jantrid.net>

# This file represents the braille display driver for
# Seika3 V2.00, Seika80, a product from Nippon Telesoft
# see www.seika-braille.com for more details
# 18.08.2012 13:54

import time
import wx
import serial
import braille
import inputCore
import hwPortUtils
from logHandler import log

TIMEOUT = 0.2
BAUDRATE = 9600
READ_INTERVAL = 50

class BrailleDisplayDriver(braille.BrailleDisplayDriver):
	name = "seika"
	# Translators: Names of braille displays.
	description = _("Seika braille displays")
	numCells = 0

	@classmethod
	def check(cls):
		return True

	def __init__(self):
		super(BrailleDisplayDriver, self).__init__()

		for portInfo in hwPortUtils.listComPorts(onlyAvailable=True):
			port = portInfo["port"]
			hwID = portInfo["hardwareID"]
			# log.info("Found port {port} with hardwareID {hwID}".format(port=port, hwID=hwID))
			if not hwID.upper().startswith(r"USB\VID_10C4&PID_EA60"): # Seika USB to Serial, in XP it is lowercase, in Win7 uppercase
				continue
			# At this point, a port bound to this display has been found.
			# Try talking to the display.
			try:
				self._ser = serial.Serial(port, baudrate=BAUDRATE, timeout=TIMEOUT, writeTimeout=TIMEOUT, parity=serial.PARITY_ODD, bytesize=serial.EIGHTBITS, stopbits=serial.STOPBITS_ONE)
			except serial.SerialException:
				continue
			log.debug("serial port open {port}".format(port=port))
			self._ser.write("\xFF\xFF\x1C")
			self._ser.flush()
			# Read out the input buffer
			versionS = self._ser.read(13)
			log.debug("receive {p}".format(p=versionS))
			if versionS.startswith("seika80"):
				log.info("Found Seika80 connected via {port} Version {versionS}".format(port=port, versionS=versionS))
				self.numCells = 80
				break
			if versionS.startswith("seika3"):
				log.info("Found Seika40 connected via {port} Version {versionS}".format(port=port, versionS=versionS))
				self.numCells = 40
				self.s40 = "\xFF\xFF\x73\x65\x69\x6B\x61\x00"
				break
			# is it a old Seika3?
			log.debug("test if it is a old Seika3")
			self._ser.write("\xFF\xFF\x0A")
			self._ser.flush()
			# Read out the input buffer
			versionS = self._ser.read(12)
			log.debug("receive {p}".format(p=versionS))
			if versionS.startswith("\x00\x05\x28\x08\x76\x35\x2E\x30\x01\x01\x01\x01") or versionS.startswith("\x00\x05\x28\x08\x73\x65\x69\x6b\x61\x00"):
				log.info("Found Seika3 old Version connected via {port} Version {versionS}".format(port=port, versionS=versionS))
				self.numCells = 40
				self.s40 = "\xFF\xFF\x04\x00\x63\x00\x50\x00"
				break
			self._ser.close()
		else:
			raise RuntimeError("No SEIKA40/80 display found")
		self._readTimer = wx.PyTimer(self.handleResponses)
		self._readTimer.Start(READ_INTERVAL)

	def terminate(self):
		try:
			super(BrailleDisplayDriver, self).terminate()
			self._readTimer.Stop()
			self._readTimer = None
		finally:
			self._ser.close()

	def display(self, cells):
		# every transmitted line consists of the preamble SEIKA_SENDHEADER and the Cells
		if self.numCells==80:
			line = "\xff\xff\x73\x38\x30\x00\x00\x00"+"".join(chr(cell) for cell in cells)
		else:
			line = self.s40+"".join("\0"+chr(cell) for cell in cells)
		self._ser.write(line)

	def handleResponses(self):
		if not self._ser.inWaiting():
			return
		chars = [0,0]
		key = 0
		keys= set()
		max = self.numCells / 4 # for 80 max is 20, for 40 cell max is 10
		chars[0] = ord(self._ser.read())
		chars[1] = ord(self._ser.read())
		keytyp=1
		if not chars[0] & 0x60: # a cursorrouting block is expected
			char = self._ser.read(max)
			chars = [ord(c) for c in char]
			keytyp=2
		# log.info("Seika K {c}".format(c=chars))
		if keytyp == 1: # normal key
			if chars[0] & 1: # LEFT
				keys.add("left")
			if chars[0] & 4: # RIGHT
				keys.add("right")
			if chars[1] & 2: # B1
				keys.add("b1")
			if chars[1] & 8:
				keys.add("b2")
			if chars[1] & 16:
				keys.add("b3")
			if chars[0] & 16:
				keys.add("b4")
			if chars[0] & 8:
				keys.add("b5")
			if chars[0] & 2:
				keys.add("b6")
			data= "+".join(keys)
			try:
				inputCore.manager.executeGesture(InputGestureKeys(data))
			except inputCore.NoInputGestureAction:
				log.debug("No Action for keys {keys}".format(keys=data))
				pass
		else:
			i = 0
			k = max / 2
			while i < k:
				j = 0
				while j < 8:
					if chars[5+i] & (1<<j):
						key = i*8+j+1
						break
					j+=1
				i+=1
			if key: # Routing key is pressed
				try:
					inputCore.manager.executeGesture(InputGestureRouting(key-1))
				except inputCore.NoInputGestureAction:
					log.debug("No Action for routing command")
					pass

	gestureMap = inputCore.GlobalGestureMap({
		"globalCommands.GlobalCommands": {
			"braille_scrollBack": ("br(seika):left",),
			"braille_scrollForward": ("br(seika):right",),
			"braille_previousLine": ("br(seika):b3",),
			"braille_nextLine": ("br(seika):b4",),
			"braille_toggleTether": ("br(seika):b5",),
			"sayAll": ("br(seika):b6",),
			"kb:tab": ("br(seika):b1",),
			"kb:shift+tab": ("br(seika):b2",),
			"kb:alt+tab": ("br(seika):b1+b2",),
			"showGui": ("br(seika):left+right",),
			"braille_routeTo": ("br(seika):routing",),
		},
	})

class InputGestureKeys(braille.BrailleDisplayGesture):

	source = BrailleDisplayDriver.name
	def __init__(self, keys):
		super(InputGestureKeys, self).__init__()
		self.id = keys

class InputGestureRouting(braille.BrailleDisplayGesture):

	source = BrailleDisplayDriver.name

	def __init__(self, index):
		super(InputGestureRouting, self).__init__()

		self.id = "routing"
		self.routingIndex = index


import pandas as pd
import file_sheet_name as fsname

def divide_by_target(excelName, sheetName=None):
    df = pd.read_excel(excelName, skiprows=[], sheet_name=sheetName, keep_default_na=None)
    target_sequence = pd.read_excel(excelName, fsname.sheetName2).iloc[0:28, 1]
    for sequence in target_sequence:
        tmp_df = df[ df['Target sequence'] == sequence ]
        tmp_df.to_excel('./classify/' + sequence + '.xlsx', index=False)

if __name__ == "__main__":
    divide_by_target(fsname.inputFile, fsname.sheetName1)


from aoc import run_solver

def part1(input_str: str) -> str:
    paper = 0
    for line in input_str.strip().split("\n"):
        l, w, h = map(int, line.split("x"))
        surface = 2 * l * w + 2 * w * h + 2 * h * l
        slack = min(l * w, w * h, h * l)
        paper += surface + slack
    return str(paper)

def part2(input_str: str) -> str:
    ribbon = 0
    for line in input_str.strip().split("\n"):
        dimensions = map(int, line.split("x"))
        a, b, c = sorted(dimensions)
        wrap = 2 * (a + b)
        bow = a * b * c
        ribbon += wrap + bow
    return str(ribbon)

if __name__ == "__main__":
    result = run_solver(part1, part2)
    print(result)


class hianyzas:
    def __init__(self,sor):
        sor = sor.strip().split(";")
        self.nev = str(sor[0])
        self.osztaly = sor[1]
        self.elso = int(sor[2])
        self.utolso = int(sor[3])
        self.mulasztas = int(sor[4])
with open("szeptember.txt",encoding="UTF 8") as f:
    lista = [hianyzas(sor) for sor in f]
#2.Feladat
tanulok =[sor.nev for sor in lista]
print(tanulok)
mulasztas = [sor.mulasztas for sor in lista]
print(f"""2. feladat
      Összes mulasztott órák száma:{sum(mulasztas)} óra.
  """)
#3.Feladat
nap = int(input("""3.Feladat
      Aggyon meg egy számot 1 és 30 között: """))
tanulo = input("""      Aggyon egy tanúlo nevet: """)
#4.Feladat
print("4.Feladat")
if tanulo in tanulok:
    print("""       A tanuló hiányzott szeptemberben""")
else:
    print("""       A tanuló nem hiányzott szeptemberben""")
#5.Feladat


import pygame
from pygame.sprite import Sprite

class Ship(Sprite):
    """Klasa przeznaczona do zarządzania statkiem kosmcznym"""

    def __init__(self, ai_game):
        """Inicjalizacja statku kosmicznego i jego polozenie początkowe"""
        super().__init__()

        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.screen_rect = ai_game.screen.get_rect()

        #wczytywanie obrazu stattku kosmicznego i pobranie jego prostokąta
        self.image = pygame.image.load('images/ship2.bmp')
        self.rect = self.image.get_rect()

        #Kazdy nowy statek pojawia sie na dole ekranu
        self.rect.midbottom = self.screen_rect.midbottom

        #Położenie poziome statku jest przetrzymywane w liczbie zmiennoprzecinkowej

        self.x = float(self.rect.x)

        #Opcja wskazujaca na poruszanie sie statku
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """Uaktualnenie położenia statku na podstawie opcji wskazuajcej an jego ruch"""
        if self.moving_right and self.rect.right < self.screen_rect.right:
                self.x += self.settings.ship_speed
        if self.moving_left and self.rect.left > 0:
                self.x -= self.settings.ship_speed

        #Uaktualnienie obiektu rect na podstawie wartsci self.x
        self.rect.x = self.x

    def blitme(self):
        """Wyswietlanie statku w jego aktualnym polozeniu"""
        self.screen.blit(self.image, self.rect)

    def center_ship(self):
        """Umieszczanie statku na środku przy dolnej krawędzi ekranu"""
        self.rect.midbottom = self.screen_rect.midbottom
        self.x = float(self.rect.x)


from detector import Detector
from tracker import Tracker
from manipulations_detector import ManipulationsDetector
from utils.constants import *
from video_processor import VideoProcessor
from utils.video_paths_collector import VideoPathsCollector
from utils.excel_writer import ExcelWriter

# Initialize YOLO Object Detector
detector = Detector(weights_path, cfg_path, classes_path)
# Initialize Deep Sort Tracker
tracker = Tracker(encoder_model_path)
# Initialize Videos Collector
video_paths_collector = VideoPathsCollector(path_to_videos)
# Initialize Excel Writer
excel_writer = ExcelWriter("C:\\Users\\iskan\\PycharmProjects\\ObjectDetectionAndTracking\\resources\\results.xlsx")

def get_video_name(path: str):
    parsed = path.split("\\")
    return parsed[len(parsed) - 1]

if __name__ == '__main__':
    videos_paths = video_paths_collector.collect()
    all_manipulations = {}
    for video_path in videos_paths:
        video_processor = VideoProcessor(video_path, 1000)
        tracks_per_frame = video_processor.process_video(50, detector, tracker)

        manipulations_detector = ManipulationsDetector(tracks_per_frame)
        manipulations = manipulations_detector.detect_manipulations(70)
        print('Manipulations on ', video_path, ':\n', manipulations)
        all_manipulations[get_video_name(video_path)] = manipulations
    if len(all_manipulations) != 0:
        ExcelWriter.write(excel_writer, all_manipulations, True)


#!/usr/bin/env python3

import csv
import re
import yaml
from collections import OrderedDict
from pathlib import Path

basic_rules = {}
firstnames = []
lastnames = []

with open('baseball.csv') as f:
  rows = list(csv.reader(f))
  for row in rows:
    for col in row:
      if col:
        items = col.split(' ')
        while len(items) > 2:
          items = items[1:]
        firstnames.append(items[0])
        lastnames.append(items[1])

basic_rules['firstname'] = {
  'groups': [{
    'tags': [],
    'phrases': firstnames,
  }],
}

basic_rules['lastname'] = {
  'groups': [{
    'tags': [],
    'phrases': lastnames,
  }],
}

with open('../src/improvgrammar/band/names.yaml', 'w') as f:
  yaml.dump(basic_rules, f, indent=2)


from __future__ import print_function
import time
import socket
import struct
import random
import uuid
import msgpack

class Client(object):

  def __init__(self):
    self.sock = None

  def connect(self, addr):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect(addr)

    self.sock = sock
    self._recv_state = 0
    self._recv_buf = ''
    self._packet_len = None

  def call(self, cmd, *cmd_args):
    self.send_packet(2, cmd, *cmd_args)

    while True:
      packet = self.recv_packet()
      #print('recv_packet', packet)
      op = packet[0]
      if op == 3:
        code = packet[1]
        rtn = packet[2]
        reason = packet[3]
        if code == 0:
          return rtn

        raise Exception(reason)

  def recv_packet(self):

    for i in xrange(4096):
      buf = self.sock.recv(4096)

      if not buf:
        print('recv', repr([buf]))
        raise Exception('connectionLost')

      self._recv_buf = self._recv_buf + buf

      if self._recv_state == 0:
        if len(self._recv_buf) >= 4:
          hdr, self._recv_buf = self._recv_buf[:4], self._recv_buf[4:]
          self._packet_len = struct.unpack('>I', hdr)[0]
          self._recv_state = 1

      if self._recv_state == 1:
        if len(self._recv_buf) >= self._packet_len:
          packet, self._recv_buf = self._recv_buf[:self._packet_len], self._recv_buf[self._packet_len:]
          packet = msgpack.unpackb(packet)
          self._packet_len = None
          self._recv_state = 0

          return packet

  def send_packet(self, op, cmd, *cmd_args):
    packet = [op, cmd, cmd_args]
    data = msgpack.packb(packet)
    send_data = struct.pack('>I', len(data)) + data
    self.sock.send(send_data)

def main():

  cli = Client()
  cli.connect(('127.0.0.1', 9422))

  total_rows_count = 0

  for k in xrange(2**20):

    test_args = []

    for i in xrange(32):
      rows = []
      #admin_id = random.choice([69, 70, 71])
      now_t = time.time()
      uts = int(now_t * 10000)

      t_k = "%014x" % uts

      admin_id = random.choice([69])
      out_sn = "%s-%s" % (t_k[:12], str(uuid.uuid4()))

      rows_count = random.randint(1, 100)
      _rnd = random.randint(0, 10000)
      if _rnd > 9000:
        rows_count = random.randint(1, 2048)
      elif _rnd > 7000:
        rows_count = random.randint(1, 256)

      test_args.append((admin_id, out_sn, rows_count))

      for j in xrange(rows_count):
        ts = time.time()
        data = {
          'admin_id': admin_id,
          'out_sn': out_sn,
          'seq': j,
          'rows_count': rows_count,
        }
        row = [ts, 1001, data]
        rows.append(row)

      cli.call('APPEND_ORDER_LOG', *rows)

    for x in test_args:
      admin_id, out_sn, rows_count = x
      rows = cli.call('GET_ORDER_LOG', admin_id, out_sn)[0]
      #first = rows[0]
      #rows_count = first['rows_count']

      total_rows_count += rows_count

      print('GET_ORDER_LOG total_rows_count=%s out_sn=%s' % ('{:,}'.format(total_rows_count), out_sn), 'rows_count', rows_count, 'rows', len(rows))
      assert len(rows) == rows_count

if __name__ == "__main__":
  main()


'''
    Script:      ptm.py
    Description: Python pretty tree maker
    Author:      Xander Jones (xander@xljones.com)
    Web:         xljones.com
    Date:        2 Feb 2021
'''

import os
import uuid

'''
---- root branch with elements
    \
     ---- new branch - all of - its - elements
          \                     \
           --- can have lots     --- of elements on lots of branches

{
    "uuid" : "an element",
    "branch" : {
        "uuid" : "branch element 1",
        "uuid" : "branch element 2"
    ]}
]}
'''

_VERSION = "1.0.0"
_STYLES = {
    "Default": {
        "indent"      : 4,      # the number of spaces to leave per increase in depth
        "symbol_first": "┌── ", # used for the very first element or branch @ index 0, depth 0.
        "symbol_mid"  : "├── ", # used by all elements or branches that are not last in their depth.
        "symbol_last" : "└── ", # used by element or branch that is the last in its depth, OR
                                # by an branch which has > 0 sub-elements
    }
}

class Tree:
    _tree = None
    _style = None

    ''' PRIVATE
        initialize the object with an empty tree
        and a default styling
    '''
    def __init__(self):
        self._tree = {}
        self._style = _STYLES["Default"]

    ''' PRIVATE
        add a new element or branch to the tree.
            elements use new_key = a UUID
                         new_value = the desired value of the element
            branches use new_key = the ID of the branch
                         new_value = {} (empty dict)
    '''
    def _add_to_tree(self, new_key, new_value, path):
        ttree = self._tree # set a new tree to traverse and find the object at 'path'
        key_list = path.split(".")
        if key_list[0] != "":
            for key in key_list[:-1]:
                ttree = ttree[key]
            ttree[key_list[-1]][new_key] = new_value
        else:
            ttree[new_key] = new_value

    ''' PRIVATE
        returns the symbol that should lead up
        to an element or a branch to create the tree
    '''
    def _calc_symbol(self, index, depth, branch, is_branch, element):
        if (len(element) > 0 and is_branch):    # is this a branch that contains no sub-elements?
           return self._style["symbol_last"]
        elif index == 0 and depth == 0:         # is this the first symbol of the entire tree?
            return self._style["symbol_first"]
        elif index == len(branch.items())-1:    # is this the last symbol of this branch?
            return self._style["symbol_last"]
        else:                                   # else, this must be a mid-way part of a branch
            return self._style["symbol_mid"]

    ''' PRIVATE
        returns whether a value is a branch,
        or if it is just an element. Raises a TypeError
        exception if the data type is unexpected
    '''
    def _is_branch(self, value):
        if type(value) == str:
            return False
        elif type(value) == dict:
            return True
        else:
            raise TypeError("Unexpected data type [{0}] in tree".format(type(value)))

    ''' PRIVATE
        print an individual element (str) of the branch
        using the associated format for the depth

        TODO: improve tree tracing from parent branch to next
              parent branch
    '''
    def _print_element(self, symbol, data, depth):
        print("{0}{1}{2}".format(
            " " * self._style["indent"] * depth,
            symbol,
            data))

    ''' PRIVATE
        prints the root_branch, recursively calls this function
        for each new branch found within the root_branch
    '''
    def _print_branch(self, root_branch, depth):
        index = 0
        for key, value in root_branch.items():
            element_is_branch = self._is_branch(value)
            symbol = self._calc_symbol(index, depth, root_branch, element_is_branch, value)
            if self._is_branch(value):
                self._print_element(symbol, key, depth)
                self._print_branch(value, depth+1)
            else:
                self._print_element(symbol, value, depth)
            index += 1

    ''' PUBLIC
        function to add a new branch to the tree
            new_branch_id : the name of the new branch to add
            path          : a dotnotation to the root of the new branch
                            defaults to use the tree root
    '''
    def add_branch(self, new_branch_id, path=""):
        self._add_to_tree(new_branch_id, {}, path)

    ''' PUBLIC
        function to add a new element to the tree
            new_element   : the name of the new branch to add
            path          : a dotnotation to the root of the new element
                            defaults to use the tree root
    '''
    def add_element(self, new_element, path=""):
        self._add_to_tree(uuid.uuid4().hex, new_element, path)

    ''' PUBLIC
        function to print the tree
            style (optional) : select a style to print with,
                               defaults to using the default style
    '''
    def print(self, style="Default"):
        self._style = _STYLES[style]
        self._print_branch(self._tree, 0)

if (__name__ == "__main__"):
    # Uhoh, this is a library, do not pass go, do not collect $200.
    print("'{0}' is a library and cannot be called directly, please see the README.md for this script".format(os.path.basename(__file__)))


"""Tools for word trees.

Authors:
    Lennart Elbe {lenni.elbe@gmail.com}

Examples:

"""

LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZÃ„ÃœÃ–Ã¤Ã¼Ã¶ÃŸ"

def next_word(s):
    """Return the first word (or None) of an input string s and the rest of it.

    args:
        s: The input string.

    returns:
        Tuple containing the first word (str or None) and the rest of s (str).

    Examples:
    >>> next_word('asdf asdf xyqr')
    ('asdf', ' asdf xyqr')
    >>> next_word('echatsteinschalosch')
    ('echatsteinschalosch', '')
    >>> next_word('spam&&ham  ham...')
    ('spam', '&&ham  ham...')

    Leading whitespaces and other invalid characters are removed:
    >>> next_word(' &foo @bar')
    ('foo', ' @bar')

    If the input string contains no valid word, None is returned instead:
    >>> next_word('$$$')
    (None, '')
    >>> next_word('')
    (None, '')

    """
    skip = 0
    for c in s:
        if c in LETTERS:
            break
        else:
            skip += 1
    if skip == len(s):
        return None, ''

    take = 0
    for i in range(skip, len(s)):
        if s[i] in LETTERS:
            take += 1
        else:
            break

    return s[skip:skip + take], s[skip + take:]

class Node:
    """A node of a search tree.

    Attributes:
        mark (str): A word.
        frequency (int): The frequency with which the word (mark) occurs.
        left (tree): The left subtree.
        right (tree): The right subtree.
    """

    def __init__(self, mark, frequency, left, right):
        """Set attributes to their initial values.

        Args:
            mark (str): A word.
            frequency (int): The frequency with which the word (mark) occurs.
            left (tree): The left subtree.
            right (tree): The right subtree.
        """
        self.mark = mark
        self.frequency = frequency
        self.left = left
        self.right = right

def node_str(n):
    """Return a string representation of a search node.

    Args:
        n: A search tree node.

    returns:
        A string representing the search node.
    """
    if n is None:
        return repr(None)
    return "Node(" + repr(n.mark) + ", " + repr(n.frequency) + ", " + node_str(
        n.left) + ", " + node_str(n.right) + ")"

Node.__str__ = node_str

# wenn im Baum
#  dann entweder im Mark
#  oder im linken Baum
#  oder im rechten Baum

def word_in_tree(s, t):
    """Checks to see if a string is present in the tree. If present, returns
    True and location thereof. Otherwise, returns False and None.

    args:
        s {str} --  The word that is being searched for within the tree t.
        t {Node} --  The tree in which the word s is being searched for.

    returns:
        Bool --  True if the word is present in the tree, and false if not.
        Node --  The location at which the word is present.
    """

    # entweder an der aktuellen position
    if t is None:
        return (False, None)
    if t.mark == s:
        return (True, t)  # now we can do t.frequence++
    # oder im linken
    if t.left is not None:
        l, nl = word_in_tree(s, t.left)
        if l:
            return (l, nl)
    # oder im rechten Zweig
    if t.right is not None:
        r, nr = word_in_tree(s, t.right)
        if r:
            return (r, nr)
    # oder das wort ist nicht im Baum
    return (False, None)

def add_to_tree(s, t):
    """Adds a word to a tree at a None location.

    args:
        s {str} -- The word being added.
        t {Node} -- The tree the word is being added to.

    returns:
        Node -- The tree it was added to.
    """

    if t is None:
        t = Node(s, 1, None, None)
        return t
    if t.left is None:
        t.left = Node(s, 1, None, None)
        return t
    if t.right is None:
        t.right = Node(s, 1, None, None)
        return t
    t.right = add_to_tree(s, t.right)
    return t

# Ex. 7.2 (a)
def word_tree(s):
    """Creates a tree from the string of words given.

    args:
        s {str} -- The string of words given.

    returns:
        Node -- The tree created.
    """

    nextword, rest = next_word(s)
    tree = None
    while nextword is not None:
        # if nextword is already in the tree, make counter one larger
        isin, n = word_in_tree(nextword, tree)
        if isin:
            # word is already in tree
            n.frequency += 1
        else:
            tree = add_to_tree(nextword, tree)
        nextword, rest = next_word(rest)
    return tree

# Ex. 7.2 (b)
def word_freq(tree, word):
    """Finds the frequency of a given word in a given tree.

    args:
        tree {[type]} -- The given tree in which to search for the frequency
        of a word.
        word {[type]} -- The word whose frequency is to be searched for.

    returns:
        int -- The frequency of the given word.
    """

    isin, n = word_in_tree(word, tree)
    if not isin:
        return 0
    return n.frequency

# Ex. 7.2 (c)
def print_tree(tree):
    """The tree to be printed in a readable mannar.

    args:
        tree {[type]} -- The given tree to be printed.
    """

    if tree is None:
        return
    print("%s: %d" % (tree.mark, tree.frequency))
    print_tree(tree.right)
    print_tree(tree.left)


import numpy as np

#states will be a tuple like (0, 2)
states = {}

actions = ['up', 'down', 'left', 'right']

def create_world():
    grid = np.array([[0,1,0,0,0,0],
                     [0,0,0,1,0,1],
                     [0,1,1,0,0,0],
                     [0,0,0,0,1,0],
                     [0,0,0,1,2,0],
                     [0,1,0,0,0,0]])

    # 0:air, 1:wall, 2:goal, 3:key, 4:door
    dimensions = (len(grid), len(grid[0]))
    return (grid, dimensions)

def reset():
    world = create_world()
    grid, _ = world
    return grid

world = create_world()

def step(state, action, world):
    grid, dimensions = world
    width, height = dimensions

    prev_row = int(state / width)
    prev_col = state % width
    #print(prev_row)
    #print(prev_col)
    row = prev_row
    col = prev_col

    reward = 0

    if action == 0:
        row = row - 1
    if action == 1:
        row = row + 1
    if action == 2:
        col = col - 1
    if action == 3:
        col = col + 1

    if row < 0:
        row = 0
    if col < 0:
        col = 0
    if row >= width:
        row = width - 1
    if col >= height:
        col = height - 1

    done = False

    entity = grid[row,col]
    if entity == 0:
        pass
    if entity == 1:
        row = prev_row
        col = prev_col
    if entity == 2:
        reward += 10
        done = True
        #print('done')
    if entity == 3:
        reward += 5
        grid[row,col]=0
        #print('key found')
    if entity == 4:
        keys = 0
        for i in range(width):
            for j in range(height):
                if grid[i,j] == 3:
                    keys+=1
                    #print('there exists a key')
        if keys == 0:
            grid[row,col] = 0
            #print('door unlocked')
        else:
            row = prev_row
            col = prev_col
    world = (grid, dimensions)
    reward = reward - 1
    next_state = row * width + col
    return next_state, reward, done, world

num_episodes = 1000
history = []

grid, dimensions = world
width, height = dimensions
num_states = width * height

action_values = np.zeros((num_states, len(actions)))

epsilon = 0.1
discount_factor = 0.99
alpha = 0.5

def e_greedy_policy(state, values):
    nA = len(values)
    policy = np.ones(nA, dtype=float) * epsilon / nA
    best_action = np.argmax(values)
    policy[best_action] += (1.0 - epsilon)
    return policy

def greedy_policy(state, values):
    nA = len(values)
    policy = np.zeros(nA, dtype=float)
    best_action = np.argmax(values)
    policy[best_action] += 1
    return policy

average_steps = 0
for i in range(num_episodes):
    # Reset episode
    world = create_world()
    state = int(np.random.uniform() * num_states)
    sequence = []
    done = False

    total_reward = 0
    while not done:
        # choose action according to policy

        action_probs = e_greedy_policy(state, action_values[state])
        action = np.random.choice(np.arange(len(action_probs)), p=action_probs)

        # take a step
        next_state, reward, done, world = step(state, action, world)

        # update the action values
        next_best_action = np.argmax(action_values[next_state])
        td_target = reward + discount_factor * action_values[next_state, next_best_action]
        td_delta = td_target - action_values[state, action]
        action_values[state, action] += alpha * td_delta

        state = next_state
        total_reward += reward
        sequence.append(action)

    history.append((sequence, total_reward))
    average_steps += 1/(i+1) * (len(sequence) - average_steps)

    if i % int(num_episodes / 20) == 0:
        print('episode ' + str(i))
        print('average steps is ' + str(average_steps))
        print('total reward for this episode: ' + str(total_reward))

a = action_values.reshape((width, height, 4))
print(np.amax(a, axis = 2).astype(int))

a = np.argmax(a, axis = 2)
print(a)
print(grid)

show_best_action_sequence = True
if show_best_action_sequence:
    state = 0
    sequence = []
    done = False
    steps = 0

    while not done and steps < 50:
        # choose action according to policy

        action_probs = greedy_policy(state, action_values[state])
        action = np.random.choice(np.arange(len(action_probs)), p=action_probs)

        # take a step
        next_state, reward, done, world = step(state, action, world)

        state = next_state
        sequence.append(action)
        steps+=1

    s = []
    for i in sequence:
        s.append(actions[i])
    print(s)
    print('moves: ' + str(steps))


import time
from threading import Thread, Event
from sh import netstat,ErrorReturnCode
import re
#import pdb
from monitor import OS_type, OS

#
# Partly based on code from the UNIFY FP7 Demo for the Y1 review 2015,
# by Pontus Sköldström, Acreo Swedish ICT AB / Per Kreuger, SICS Swedish ICT AB.
#

class Sampler(Thread):
    def __init__(self, inq, outq, sample_rate, monitor, interface='eth0', name='Sampler', debug=False):
        Thread.__init__(self, name=name)
        self.inq = inq
        self.outq = outq
        self.request_event = Event()
        self.set_sample_rate(sample_rate)
        self.monitor = monitor
        self.interface = interface
        self.debug = debug
        self.keep_running = True
        self.tx_agg = self.rx_agg = 0.0
        self.txb2 = self.rxb2 = 0.0
        self.tx_file = None
        self.rx_file = None
        self.samples = 0
        self.last_data = self.get_interface_data(self.interface)
        # FIXME: These two should be inferred by checking the word
        #        length of the computer we're running on.
        #        Perhaps with platform.architecture() or sys.maxsize
        #        For now assume 32-bit architecture.
        self.tx_byte_counter_wrap_adjustment = (2 ** 32) - 1
        self.rx_byte_counter_wrap_adjustment = (2 ** 32) - 1

    def run(self):
        if (self.debug):
            self.monitor.debugPrint("sampler.py: starting run()")
        self.last_data = self.get_interface_data(self.interface)
        while self.keep_running:
            timestamp = self.sample()

            while not self.inq.empty():
                request = self.inq.get()
                if request == 'rate_data':
                    self.inq.task_done()
                    self.outq.put({'ts': timestamp, 'samples': self.samples, 'txb2': self.txb2, 'rxb2': self.rxb2, 'tx_agg': self.tx_agg, 'rx_agg': self.rx_agg})
#                    self.samples = 0 # Don't do this!
                elif request == 'stop':
                    self.inq.task_done()
                    self.keep_running = False
                else:
                    self.inq.task_done()
                    pass # unknown request, FIXME: perhaps report an error?
            #
#            time.sleep(self.sleep_time)
            self.request_event.wait(self.sleep_time)
            self.request_event.clear()
        if (self.debug):
            # Race conditions can cause things to be pulled from under
            # our feet, so catch all exceptions here.
            try:
                self.monitor.debugPrint("sampler.py: exit from run()")
            except BaseException:
                pass

    # Read the traffic flow data from the network interface and accumulate the rate
    def sample(self):
        self.samples += 1
        curr = self.get_interface_data(self.interface)

        if curr[1] < self.last_data[1]:
            # tx counter has wrapped
            self.monitor.debugPrint("sampler.py: self.last_data[1] before wrap adjustment: " + str(self.last_data[1]))
            self.last_data[1] -= self.tx_byte_counter_wrap_adjustment

        tx_bytes = curr[1] - self.last_data[1]

        if curr[2] < self.last_data[2]:
            # rx counter has wrapped
            self.monitor.debugPrint("sampler.py: self.last_data[2] before wrap adjustment: " + str(self.last_data[2]))
            self.last_data[2] -= self.rx_byte_counter_wrap_adjustment

        rx_bytes = curr[2] - self.last_data[2]

        timestamp = curr[0] #- self.last_data[0]
        obs_time = timestamp - self.last_data[0]

        if self.debug:
            self.monitor.debugPrint("sampler.py: curr: " + str(curr) + ", self.last_data: " + str(self.last_data))
            self.monitor.debugPrint("sampler.py: tx_bytes: " + str(tx_bytes) + ", rx_bytes: " + str(rx_bytes))
            self.monitor.debugPrint("sampler.py: obs_time: " + str(obs_time))

#        self.last_data = curr
        self.last_data = list(curr) # copy curr

        tx_byte_rate  = tx_bytes / obs_time
        rx_byte_rate  = rx_bytes / obs_time
        self.tx_agg = self.tx_agg + tx_byte_rate
        self.rx_agg = self.rx_agg + rx_byte_rate
        self.txb2 = self.txb2 + (tx_byte_rate*tx_byte_rate)
        self.rxb2 = self.rxb2 + (rx_byte_rate*rx_byte_rate)

        if self.debug:
            self.monitor.debugPrint("sampler.py: tx_byte_rate: " + str(tx_byte_rate) + ", rx_byte_rate: " + str(rx_byte_rate) + ", self.tx_agg: " + str(self.tx_agg) + ". self.rx_agg: " + str(self.rx_agg) + ", self.txb2: " + str(self.txb2) + ", self.rxb2: " + str(self.rxb2))

        return timestamp

    # Read the number of bytes received and sent to/from the network interface
    def get_interface_data(self,interface):
        if OS == OS_type.darwin: # OS X does not have /sys/class/net/...
            # This is only for testing on OS X. Running netstat takes
            # way to much time to be a practical method for reading
            # the byte counters of an interface.
            netstat_output = netstat("-i", "-b", "-I", interface)
            for line in netstat_output:
                if line.startswith(interface):
                    words = line.split()
                    rx_bytes = int(words[6])
                    tx_bytes = int(words[9])
                    return time.time(),rx_bytes,tx_bytes
            return  time.time(),0,0
        else:
            # FIXME: Perhaps open the tx_file and the rx_file in the
            #        __init__ method instead. Is there really a good
            #        reason for doing it this way?
            tx_fn = "/sys/class/net/%s/statistics/tx_bytes" % interface
            rx_fn = "/sys/class/net/%s/statistics/rx_bytes" % interface
            if self.tx_file is None:
                self.tx_file = open(tx_fn)
                tx_bytes = int(self.tx_file.read())
            else:
                self.tx_file.seek(0)
                tx_bytes = int(self.tx_file.read())

            if self.rx_file is None:
                self.rx_file = open(rx_fn)
                rx_bytes = int(self.rx_file.read())
            else:
                self.rx_file.seek(0)
                rx_bytes = int(self.rx_file.read())

#            return time.time(), tx_bytes, rx_bytes
            return [time.time(), tx_bytes, rx_bytes]

    #
    def set_sample_rate(self,sample_rate):
        self.sample_rate = sample_rate
        self.sleep_time = 1.0 / sample_rate

    def get_sample_rate(self):
        return self.sample_rate

    def set_interface(self,interface):
        self.interface = interface

    def get_interface(self):
        return self.interface

    def running(self):
        return self.keep_running

    def stopped(self):
        return not self.keep_running


def convert_basis_function(in_str):
    # possible values: 'CONSENT SEARCH', 'REASONABLE SUSPICION', nan, 'PROBABLE CAUSE'
    if in_str == 'CONSENT SEARCH':
        out_str = 'Consented to be Search'
    elif in_str == 'REASONABLE SUSPICION':
        out_str = 'Reasonable Suspicion'
    elif in_str == 'PROBABLE CAUSE':
        out_str = 'Probable Cause'
    else:
        out_str = 'delete'

    return out_str

def convert_race_function(in_str):
    ''' possible values: 'B(Black)', 'W(White)', 'NO DATA ENTERED', 'UNKNOWN', 'H(Hispanic)',
       'I(American Indian or Alaskan Native)',
       'A(Asian or Pacific Islander)', 'M(Middle Eastern or East Indian)' '''

    if in_str == 'B(Black)':
        out_str = 'black'
    elif in_str == 'W(White)':
        out_str = 'white'
    elif in_str == 'H(Hispanic)':
        out_str = 'hispanic'
    elif in_str == 'I(American Indian or Alaskan Native)':
        out_str = 'american indian'
    elif in_str == 'A(Asian or Pacific Islander)':
        out_str = 'asian'
    elif in_str == 'M(Middle Eastern or East Indian)':
        out_str = 'middle eastern'
    else:
        out_str = 'delete'

    return out_str

def convert_fiofs_type_function(in_str):
    ''' possible values: 'IOFS', 'IO', 'IOF', 'OF', 'I', 'O', 'IF', 'IFS', 'F', 'OFS', 'IS',
       'IOS', 'OS', 'S', 'FS', 'PI', 'PIO', 'PIOS', 'PO', 'PIOFS', 'PIF',
       'PIOF', 'P', 'PIS', 'PF', 'POF' '''

    if in_str == 'O':
        out_str = 'observed'
    elif (in_str == 'IOFS' or in_str == 'IO' or in_str == 'IOF' or in_str == 'OF' or in_str == 'I' or in_str == 'IF' or \
         in_str == 'IFS' or in_str == 'F' or in_str == 'OFS' or in_str == 'IS' or in_str == 'IOS' or in_str == 'OS' or \
         in_str == 'S' or in_str == 'FS'):
        out_str = 'stopped'
    else:
        out_str = 'delete'

    return out_str


import subprocess

class Connector:
    def __init__(self, workspace):
        self._workspace = workspace

    def query(self, queryString, **kwargs):
        results = []
        command = "bloxbatch -db %s -query '%s' " % (self._workspace, queryString)

        # Optional argument
        if "toprint" in kwargs:
            command += "print %s" % (kwargs["toprint"],)

        p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

        for line in p.stdout.readlines():
            results.append(line.strip())

        p.wait()
        return results


import wx
import time

from scipy import linalg as la
from matplotlib.path import Path
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as pl
import matplotlib.patches as patches
import numpy as np

import sys
from os import path, getenv
PPRZ_HOME = getenv("PAPARAZZI_HOME", path.normpath(path.join(path.dirname(path.abspath(__file__)), '../../../../')))
PPRZ_SRC = getenv("PAPARAZZI_SRC", path.normpath(path.join(path.dirname(path.abspath(__file__)), '../../../../')))
sys.path.append(PPRZ_HOME + "/var/lib/python")
sys.path.append(PPRZ_SRC + "/sw/lib/python")
from pprzlink.ivy import IvyMessagesInterface
from pprzlink.message import PprzMessage
from settings_xml_parse import PaparazziACSettings

WIDTH = 800
HEIGHT = 800

class GVFFrame(wx.Frame):
    def __init__(self, ac_id):

        wx.Frame.__init__(self, id=-1, parent=None, \
                name=u'GVF', size=wx.Size(WIDTH, HEIGHT), \
                style=wx.DEFAULT_FRAME_STYLE, title=u'Guidance Vector Field')

        # Vehicle variables
        self.ac_id = ac_id
        self.course = 0
        self.yaw = 0
        self.XY = np.array([0, 0])
        self.altitude = 0
        self.ground_altitude = -1

        # Desired trajectory
        self.s = 0
        self.ke = 0
        self.gvf_error = 0
        self.map_gvf = map2d(np.array([0, 0]), 150000)
        self.traj = None

        # Frame
        self.canvas = FigureCanvas(self, -1, self.map_gvf.fig)
        self.Bind(wx.EVT_CLOSE, self.OnClose)

        self.redraw_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnRedrawTimer, self.redraw_timer)
        self.redraw_timer.Start(100)

        # Ivy
        self.interface = IvyMessagesInterface("GVF")
        self.interface.subscribe(self.message_recv)
        settings = PaparazziACSettings(ac_id)

    def message_recv(self, ac_id, msg):
        if int(ac_id) == self.ac_id:
            if msg.name == 'GPS':
                self.course = int(msg.get_field(3))*np.pi/1800
                self.altitude = float(msg.get_field(4))/1000
            if msg.name == 'NAVIGATION':
                self.XY[0] = float(msg.get_field(2))
                self.XY[1] = float(msg.get_field(3))
            if msg.name == 'NAVIGATION_REF':
                self.ground_altitude = float(msg.get_field(3))
            if msg.name == 'ATTITUDE':
                self.yaw = float(msg.get_field(1))
            if msg.name == 'GVF':
                self.gvf_error = float(msg.get_field(0))
                # Straight line
                if int(msg.get_field(1)) == 0:
                    self.s = int(msg.get_field(2))
                    self.ke = float(msg.get_field(3))
                    param = [float(x) for x in msg.get_field(4)]
                    a = param[0]
                    b = param[1]
                    c = param[2]

                    self.traj = traj_line(np.array([-100,100]), a, b, c)
                    self.traj.vector_field(self.traj.XYoff, self.map_gvf.area, \
                            self.s, self.ke)

                # Ellipse
                elif int(msg.get_field(1)) == 1:
                    self.s = int(msg.get_field(2))
                    self.ke = float(msg.get_field(3))
                    param = [float(x) for x in msg.get_field(4)]
                    ex = param[0]
                    ey = param[1]
                    ea = param[2]
                    eb = param[3]
                    ealpha = param[4]
                    self.traj = traj_ellipse(np.array([ex, ey]), ealpha, ea, eb)
                    self.traj.vector_field(self.traj.XYoff, \
                            self.map_gvf.area, self.s, self.ke)

                # Sin
                elif int(msg.get_field(1)) == 2:
                    self.s = int(msg.get_field(2))
                    self.ke = float(msg.get_field(3))
                    param = [float(x) for x in msg.get_field(4)]
                    a = param[0]
                    b = param[1]
                    alpha = param[2]
                    w = param[3]
                    off = param[4]
                    A = param[5]
                    self.traj = traj_sin(np.array([-100, 100]), a, b, alpha, \
                            w, off, A)
                    self.traj.vector_field(self.traj.XYoff, \
                            self.map_gvf.area, self.s, self.ke)

            if msg.name == 'GVF_PARAMETRIC':
                # Trefoil 2D
                if int(msg.get_field(0)) == 0:
                    self.s = int(msg.get_field(1))
                    self.wb = float(msg.get_field(2))
                    param = [float(x) for x in msg.get_field(3)]
                    xo = param[0]
                    yo = param[1]
                    w1 = param[2]
                    w2 = param[3]
                    ratio = param[4]
                    r = param[5]
                    alpha = param[6]
                    phi = [float(x) for x in msg.get_field(4)]
                    phi_x = phi[0]
                    phi_y = phi[1]
                    self.traj = traj_param_trefoil_2D(np.array([xo, yo]), w1, w2, ratio, r, alpha, self.wb)

                # Ellipse 3D
                elif int(msg.get_field(0)) == 1:
                    self.s = int(msg.get_field(1))
                    self.wb = float(msg.get_field(2))
                    param = [float(x) for x in msg.get_field(3)]
                    xo = param[0]
                    yo = param[1]
                    r = param[2]
                    zl = param[3]
                    zh = param[4]
                    alpha = param[5]
                    phi = [float(x) for x in msg.get_field(4)]
                    phi_x = phi[0]
                    phi_y = phi[1]
                    phi_z = phi[2]
                    self.traj = traj_param_ellipse_3D(np.array([xo,yo]), r, zl, zh, alpha, self.wb)

                # Lissajous 3D
                elif int(msg.get_field(0)) == 2:
                    self.s = int(msg.get_field(1))
                    self.wb = float(msg.get_field(2))
                    param = [float(x) for x in msg.get_field(3)]
                    xo = param[0]
                    yo = param[1]
                    zo = param[2]
                    cx = param[3]
                    cy = param[4]
                    cz = param[5]
                    wx = param[6]
                    wy = param[7]
                    wz = param[8]
                    dx = param[9]
                    dy = param[10]
                    dz = param[11]
                    alpha = param[12]
                    phi = [float(x) for x in msg.get_field(4)]
                    phi_x = phi[0]
                    phi_y = phi[1]
                    phi_z = phi[2]
                    self.traj = traj_param_lissajous_3D(np.array([xo,yo]), zo, cx, cy, cz, \
                            wx, wy, wz, dx, dy, dz, alpha, self.wb)

    def draw_gvf(self, XY, yaw, course, altitude):
        if self.traj is not None:
            self.map_gvf.draw(XY, yaw, course, altitude, self.traj)

    def OnClose(self, event):
        self.interface.shutdown()
        self.Destroy()

    def OnRedrawTimer(self, event):
        self.draw_gvf(self.XY, self.yaw, self.course, self.altitude-self.ground_altitude)
        self.canvas.draw()

class map2d:
    def __init__(self, XYoff, area):
        self.XYoff = XYoff
        self.area = area
        self.fig = pl.figure()

    def vehicle_patch(self, XY, yaw):
        Rot = np.array([[np.cos(yaw), np.sin(yaw)],[-np.sin(yaw), np.cos(yaw)]])

        apex = 45*np.pi/180 # 30 degrees apex angle
        b = np.sqrt(2*(self.area/2000) / np.sin(apex))
        a = b*np.sin(apex/2)
        h = b*np.cos(apex/2)

        z1 = np.array([a/2, -h*0.3])
        z2 = np.array([-a/2, -h*0.3])
        z3 = np.array([0, h*0.6])

        z1 = Rot.dot(z1)
        z2 = Rot.dot(z2)
        z3 = Rot.dot(z3)

        verts = [(XY[0]+z1[0], XY[1]+z1[1]), \
                 (XY[0]+z2[0], XY[1]+z2[1]), \
                 (XY[0]+z3[0], XY[1]+z3[1]), \
                 (0, 0)]

        codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]
        path = Path(verts, codes)

        return patches.PathPatch(path, facecolor='red', lw=2)

    def draw(self, XY, yaw, course, altitude, traj):
        self.fig.clf()
        if traj.dim == 2:
            ax = self.fig.add_subplot(111)
            ax.plot(traj.traj_points[0, :], traj.traj_points[1, :])
            ax.quiver(traj.mapgrad_X, traj.mapgrad_Y, \
                    traj.mapgrad_U, traj.mapgrad_V, color='Teal', \
                    pivot='mid', width=0.002)
            ax.add_patch(self.vehicle_patch(XY, yaw)) # In radians
            apex = 45*np.pi/180 # 30 degrees apex angle
            b = np.sqrt(2*(self.area/2000) / np.sin(apex))
            h = b*np.cos(apex/2)
            ax.arrow(XY[0], XY[1], \
                    h*np.sin(course), h*np.cos(course),\
                    head_width=5, head_length=10, fc='k', ec='k')
            ax.annotate('HOME', xy = (0, 0))
            if isinstance(traj, traj_ellipse):
                ax.annotate('ELLIPSE', xy = (traj.XYoff[0], traj.XYoff[1]))
                ax.plot(0, 0, 'kx', ms=10, mew=2)
                ax.plot(traj.XYoff[0], traj.XYoff[1], 'kx', ms=10, mew=2)
            elif isinstance(traj, traj_sin):
                ax.annotate('SIN', xy = (traj.XYoff[0], traj.XYoff[1]))
                ax.plot(0, 0, 'kx', ms=10, mew=2)
                ax.plot(traj.XYoff[0], traj.XYoff[1], 'kx', ms=10, mew=2)
            elif isinstance(traj, traj_line):
                ax.annotate('LINE', xy = (traj.XYoff[0], traj.XYoff[1]))
                ax.plot(0, 0, 'kx', ms=10, mew=2)
                ax.plot(traj.XYoff[0], traj.XYoff[1], 'kx', ms=10, mew=2)
            elif isinstance(traj, traj_param_trefoil_2D):
                ax.annotate('TREFOIL', xy = (traj.XYoff[0], traj.XYoff[1]))
                ax.plot(0, 0, 'kx', ms=10, mew=2)
                ax.plot(traj.XYoff[0], traj.XYoff[1], 'kx', ms=10, mew=2)
                ax.plot(traj.wpoint[0], traj.wpoint[1], 'rx', ms=10, mew=2)

            ax.set_xlabel('South [m]')
            ax.set_ylabel('West [m]')
            ax.set_title('2D Map')
            ax.set_xlim(self.XYoff[0]-0.5*np.sqrt(self.area), \
               self.XYoff[0]+0.5*np.sqrt(self.area))
            ax.set_ylim(self.XYoff[1]-0.5*np.sqrt(self.area), \
               self.XYoff[1]+0.5*np.sqrt(self.area))
            ax.axis('equal')
            ax.grid()

        if traj.dim == 3:
            a3d = self.fig.add_subplot(2,2,1, projection='3d')
            axy = self.fig.add_subplot(2,2,2)
            axz = self.fig.add_subplot(2,2,3)
            ayz = self.fig.add_subplot(2,2,4)

            a3d.set_title('3D Map')
            axy.set_title('XY Map')
            axz.set_title('XZ Map')
            ayz.set_title('YZ Map')

            # 3D
            a3d.plot(traj.traj_points[0, :], traj.traj_points[1, :], traj.traj_points[2, :])
            if altitude != -1:
                a3d.plot([XY[0]], [XY[1]], [altitude], marker='o', markerfacecolor='r', markeredgecolor='r')
                a3d.plot([traj.wpoint[0]], [traj.wpoint[1]], [traj.wpoint[2]], marker='x', markerfacecolor='r', markeredgecolor='r')

            #a3d.axis('equal')
            if traj.deltaz < 0:
                a3d.set_zlim(traj.zo+1.5*traj.deltaz, traj.zo-1.5*traj.deltaz)
            else:
                a3d.set_zlim(traj.zo-1.5*traj.deltaz, traj.zo+1.5*traj.deltaz)

            # XY
            axy.plot(traj.traj_points[0, :], traj.traj_points[1, :])
            axy.add_patch(self.vehicle_patch(XY, yaw)) # In radians
            apex = 45*np.pi/180 # 30 degrees apex angle
            b = np.sqrt(2*(self.area/2000) / np.sin(apex))
            h = b*np.cos(apex/2)
            axy.arrow(XY[0], XY[1], \
                    h*np.sin(course), h*np.cos(course),\
                    head_width=5, head_length=10, fc='k', ec='k')
            axy.annotate('HOME', xy = (0, 0))
            axy.plot(traj.wpoint[0], traj.wpoint[1], 'rx', ms=10, mew=2)
            if isinstance(traj, traj_param_ellipse_3D):
                axy.annotate('ELLIPSE_3D', xy = (traj.XYoff[0], traj.XYoff[1]))
                axy.plot(0, 0, 'kx', ms=10, mew=2)
                axy.plot(traj.XYoff[0], traj.XYoff[1], 'kx', ms=10, mew=2)
            elif isinstance(traj, traj_param_lissajous_3D):
                axy.annotate('LISSA_3D', xy = (traj.XYoff[0], traj.XYoff[1]))
                axy.plot(0, 0, 'kx', ms=10, mew=2)
                axy.plot(traj.XYoff[0], traj.XYoff[1], 'kx', ms=10, mew=2)

            axy.axis('equal')

            # XZ
            axz.plot(traj.traj_points[0, :], traj.traj_points[2, :])
            if altitude != -1:
                axz.plot([XY[0]], [altitude], 'ro')
                axz.plot(traj.wpoint[0], traj.wpoint[2], 'rx', ms=10, mew=2)
            if traj.deltaz < 0:
                axz.set_ylim(traj.zo+1.5*traj.deltaz, traj.zo-1.5*traj.deltaz)
            else:
                axz.set_ylim(traj.zo-1.5*traj.deltaz, traj.zo+1.5*traj.deltaz)
            # YZ
            ayz.plot(traj.traj_points[1, :], traj.traj_points[2, :])
            if altitude != -1:
                ayz.plot([XY[1]], [altitude], 'ro')
                ayz.plot(traj.wpoint[1], traj.wpoint[2], 'rx', ms=10, mew=2)
            if traj.deltaz < 0:
                axz.set_ylim(traj.zo+1.5*traj.deltaz, traj.zo-1.5*traj.deltaz)
            else:
                ayz.set_ylim(traj.zo-1.5*traj.deltaz, traj.zo+1.5*traj.deltaz)

class traj_line:
    def float_range(self, start, end, step):
        while start <= end:
            yield start
            start += step

    def __init__(self, Xminmax, a, b, alpha):
        self.dim = 2
        self.XYoff = np.array([a, b])
        self.Xminmax = Xminmax
        self.a, self.b, self.alpha = a, b, alpha
        self.traj_points = np.zeros((2, 200))
        self.mapgrad_X = []
        self.mapgrad_Y = []
        self.mapgrad_U = []
        self.mapgrad_V = []

        i = 0
        for t in self.float_range(0, 1, 0.005):
            x = (self.Xminmax[1]-self.Xminmax[0])*t + self.Xminmax[0]
            i = i + 1

        xtr = np.linspace(-200, 200, 400)

        xl =  xtr*np.sin(self.alpha) + a
        yl =  xtr*np.cos(self.alpha) + b

        self.traj_points = np.vstack((xl, yl))

    def param_point(self, t):
        i = 0

    def vector_field(self, XYoff, area, s, ke):
        self.mapgrad_X, self.mapgrad_Y = np.mgrid[XYoff[0]-0.5*np.sqrt(area):\
                XYoff[0]+0.5*np.sqrt(area):30j, \
                XYoff[1]-0.5*np.sqrt(area):\
                XYoff[1]+0.5*np.sqrt(area):30j]

        nx = -np.cos(self.alpha)
        ny =  np.sin(self.alpha)
        tx = s*ny
        ty = -s*nx

        ke = 1e-2*ke

        e = (self.mapgrad_X-self.a)*nx + (self.mapgrad_Y-self.b)*ny

        self.mapgrad_U = tx -ke*e*nx
        self.mapgrad_V = ty -ke*e*ny

        norm = np.sqrt(self.mapgrad_U**2 + self.mapgrad_V**2)

        self.mapgrad_U = self.mapgrad_U/norm
        self.mapgrad_V = self.mapgrad_V/norm

class traj_ellipse:
    def float_range(self, start, end, step):
        while start <= end:
            yield start
            start += step

    def __init__(self, XYoff, rot, a, b):
        self.dim = 2
        self.XYoff = XYoff
        self.a, self.b = a, b
        self.rot = rot
        self.traj_points = np.zeros((2, 200))
        self.mapgrad_X = []
        self.mapgrad_Y = []
        self.mapgrad_U = []
        self.mapgrad_V = []

        i = 0
        for t in self.float_range(0, 1, 0.005):
            self.traj_points[:, i] = self.param_point(t)
            i = i + 1

    def param_point(self, t):
        angle = 2*np.pi*t
        return self.XYoff \
                + np.array([self.a*np.cos(angle)*np.cos(-self.rot) - \
                self.b*np.sin(angle)*np.sin(-self.rot), \
                self.a*np.cos(angle)*np.sin(-self.rot) + \
                self.b*np.sin(angle)*np.cos(-self.rot)])

    def vector_field(self, XYoff, area, s, ke):
        self.mapgrad_X, self.mapgrad_Y = np.mgrid[XYoff[0]-0.5*np.sqrt(area):\
                XYoff[0]+0.5*np.sqrt(area):30j, \
                XYoff[1]-0.5*np.sqrt(area):\
                XYoff[1]+0.5*np.sqrt(area):30j]

        Xel = (self.mapgrad_X-self.XYoff[0])*np.cos(self.rot) \
                - (self.mapgrad_Y-self.XYoff[1])*np.sin(self.rot)

        Yel = (self.mapgrad_X-self.XYoff[0])*np.sin(self.rot) \
                + (self.mapgrad_Y-self.XYoff[1])*np.cos(self.rot)

        nx = 2*Xel*np.cos(self.rot)/self.a**2 \
                + 2*Yel*np.sin(self.rot)/self.b**2
        ny = -2*Xel*np.sin(self.rot)/self.a**2 \
                + 2*Yel*np.cos(self.rot)/self.b**2

        tx = s*ny
        ty = -s*nx

        e = (Xel/self.a)**2 + (Yel/self.b)**2 - 1

        self.mapgrad_U = tx -ke*e*nx
        self.mapgrad_V = ty -ke*e*ny

        norm = np.sqrt(self.mapgrad_U**2 + self.mapgrad_V**2)

        self.mapgrad_U = self.mapgrad_U/norm
        self.mapgrad_V = self.mapgrad_V/norm

class traj_sin:
    def float_range(self, start, end, step):
        while start <= end:
            yield start
            start += step

    def __init__(self, Xminmax, a, b, alpha, w, off, A):
        self.dim = 2
        self.XYoff = np.array([a, b])
        self.Xminmax = Xminmax
        self.a, self.b, self.alpha, self.w, self.off, self.A = \
                a, b, alpha, w, off, A
        self.traj_points = np.zeros((2, 200))
        self.mapgrad_X = []
        self.mapgrad_Y = []
        self.mapgrad_U = []
        self.mapgrad_V = []

        i = 0
        for t in self.float_range(0, 1, 0.005):
            x = (self.Xminmax[1]-self.Xminmax[0])*t + self.Xminmax[0]
            i = i + 1

        xtr = np.linspace(-200, 200, 400)
        ytr = self.A*np.sin(self.w*xtr + self.off)

        xsin = -xtr*np.sin(self.alpha) + ytr*np.cos(self.alpha) + a
        ysin =  xtr*np.cos(self.alpha) + ytr*np.sin(self.alpha) + b

        self.traj_points = np.vstack((xsin, ysin))

    def param_point(self, t):
        i = 0

    def vector_field(self, XYoff, area, s, ke):
        self.mapgrad_X, self.mapgrad_Y = np.mgrid[XYoff[0]-0.5*np.sqrt(area):\
                XYoff[0]+0.5*np.sqrt(area):30j, \
                XYoff[1]-0.5*np.sqrt(area):\
                XYoff[1]+0.5*np.sqrt(area):30j]

        xs =  (self.mapgrad_X-self.XYoff[0])*np.sin(self.alpha) \
                - (self.mapgrad_Y-self.XYoff[1])*np.cos(self.alpha)

        ys =  -(self.mapgrad_X-self.XYoff[0])*np.cos(self.alpha) \
                - (self.mapgrad_Y-self.XYoff[1])*np.sin(self.alpha)

        ang = self.w*xs + self.off

        nx =  -np.cos(self.alpha) - \
                self.A*self.w*np.cos(ang)*np.sin(self.alpha)
        ny =  -np.sin(self.alpha) + \
                self.A*self.w*np.cos(ang)*np.cos(self.alpha)
        tx = s*ny
        ty = -s*nx

        ke = 1e-2*ke

        e = ys - self.A*np.sin(ang)

        self.mapgrad_U = tx -ke*e*nx
        self.mapgrad_V = ty -ke*e*ny

        norm = np.sqrt(self.mapgrad_U**2 + self.mapgrad_V**2)

        self.mapgrad_U = self.mapgrad_U/norm
        self.mapgrad_V = self.mapgrad_V/norm

class traj_param_trefoil_2D:
    def float_range(self, start, end, step):
        while start <= end:
            yield start
            start += step

    def __init__(self, XYoff, w1, w2, ratio, r, alpha, wb):
        self.dim = 2
        self.XYoff, self.w1, self.w2, self.ratio, self.r, self.alpha, self.wb = XYoff, w1, w2, ratio, r, alpha, wb
        self.mapgrad_X = []
        self.mapgrad_Y = []
        self.mapgrad_U = []
        self.mapgrad_V = []

        self.alpha = alpha*np.pi/180

        self.wpoint = self.param_point(self.wb)

        num_points = 1000
        self.traj_points = np.zeros((2, num_points))

        i = 0
        range_points = 1000.0
        for t in self.float_range(0, range_points, range_points/num_points):
            self.traj_points[:, i] = self.param_point(t)
            i = i + 1
            if i >= num_points:
                break

    def param_point(self, t):
        xnr = np.cos(t*self.w1)*(self.r*np.cos(t*self.w2) + self.ratio)
        ynr = np.sin(t*self.w1)*(self.r*np.cos(t*self.w2) + self.ratio)

        x = np.cos(self.alpha)*xnr - np.sin(self.alpha)*ynr
        y = np.sin(self.alpha)*xnr + np.cos(self.alpha)*ynr

        return self.XYoff + np.array([x,y])

class traj_param_ellipse_3D:
    def float_range(self, start, end, step):
        while start <= end:
            yield start
            start += step

    def __init__(self, XYoff, r, zl, zh, alpha, wb):
        self.dim = 3
        self.XYoff, self.r, self.zl, self.zh, self.alpha, self.wb = XYoff, r, zl, zh, alpha, wb
        self.mapgrad_X = []
        self.mapgrad_Y = []
        self.mapgrad_U = []
        self.mapgrad_V = []

        self.deltaz = self.zh - self.zl # For the 3D plot
        self.zo = self.zl + self.deltaz # For the 3D plot
        self.alpha = self.alpha*np.pi/180

        self.wpoint = self.param_point(self.wb)

        num_points = 100
        self.traj_points = np.zeros((3, num_points))

        i = 0
        range_points = 2*np.pi + 0.1
        for t in self.float_range(0, range_points, range_points/num_points):
            self.traj_points[:, i] = self.param_point(t)
            i = i + 1
            if i >= num_points:
                break

    def param_point(self, t):
        x = self.r * np.cos(t) + self.XYoff[0]
        y = self.r * np.sin(t) + self.XYoff[1]
        z = 0.5 * (self.zh + self.zl + (self.zl - self.zh) * np.sin(self.alpha - t))

        return np.array([x,y,z])

class traj_param_lissajous_3D:
    def float_range(self, start, end, step):
        while start <= end:
            yield start
            start += step

    def __init__(self, XYoff, zo, cx, cy, cz, wx, wy, wz, dx, dy, dz, alpha, wb):
        self.dim = 3
        self.XYoff, self.zo, self.cx, self.cy, self.cz, self.wx, self.wy, self.wz, self.dx, self.dy, self.dz, \
                self.alpha, self.wb = XYoff, zo, cx, cy, cz, wx, wy, wz, dx, dy, dz, alpha, wb
        self.mapgrad_X = []
        self.mapgrad_Y = []
        self.mapgrad_U = []
        self.mapgrad_V = []

        self.deltaz = self.cz # For the 3D plot
        self.alpha = self.alpha*np.pi/180
        self.dx = self.dx*np.pi/180
        self.dy = self.dy*np.pi/180
        self.dz = self.dz*np.pi/180

        self.wpoint = self.param_point(self.wb)

        smallest_w = min([self.wx, self.wy, self.wz])

        num_points = 100
        self.traj_points = np.zeros((3, num_points))

        i = 0
        range_points = 3*np.pi / smallest_w
        for t in self.float_range(0, range_points, range_points/num_points):
            self.traj_points[:, i] = self.param_point(t)
            i = i + 1
            if i >= num_points:
                break

    def param_point(self, t):
        xnr = self.cx*np.cos(self.wx*t + self.dx)
        ynr = self.cy*np.cos(self.wy*t + self.dy)
        z = self.cz*np.cos(self.wz*t + self.dz) + self.zo

        x = np.cos(self.alpha)*xnr - np.sin(self.alpha)*ynr + self.XYoff[0]
        y = np.sin(self.alpha)*xnr + np.cos(self.alpha)*ynr + self.XYoff[1]

        return np.array([x,y,z])


from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
from time import sleep
import os

READ_INPUT_FROM_FILE = True             # If False or file doesn't exists, then takes input from user
INPUT_FILE_NAME = "friend_list.txt"     # To store CodeForces user handles in separate lines

def take_handle_input():
    """
    Takes input from a file input.txt and returns a list of handles
    If file doesn't exists then takes input from user
    """

    global READ_INPUT_FROM_FILE

    if not os.path.exists(INPUT_FILE_NAME) or not READ_INPUT_FROM_FILE:
        # File doesn't exists' so taking input from user
        handles = []
        while 1:
            handle = input("Enter CodeForces handle (or press Enter if done): ")
            if handle == "":
                break
            handles.append(handle)
        return handles

    with open(INPUT_FILE_NAME, "r") as f:
        handles = f.readlines()
    return [h.strip() for h in handles]

def wait_for_login(browser):
    """
    Waits for login page to load
    """
    for i in range(1, 300):
        if browser.current_url != "https://codeforces.com/":
            sleep(1)
            if i%10 == 0:
                print("\nPlease Login into codeforces...")
        else:
            return

    print("\n\n\nUser didn't Logged in")
    print("\nProcess Halted!")
    exit(1)

# Main

if __name__ == "__main__":
    handles = take_handle_input()
    login_url = 'https://codeforces.com/enter'

    # CodeForces login
    driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
    driver.get(login_url)
    wait_for_login(driver)

    # Fetching handles that are already friend of this user
    print("\nFetching those handles which are already in your friends...\n")
    driver.get("https://codeforces.com/friends")
    sleep(.5)
    if driver.current_url.startswith("https://codeforces.com/enter"):
        print("\n\n\nUser didn't Logged in")
        print("\nProcess Halted!")
        exit(1)

    soup = BeautifulSoup(driver.page_source, "html.parser")
    friends_list = []
    try:
        table = soup.find("div", {"class": "datatable"}).find("tbody")
        rows = table.find_all("tr")
        for row in rows:
            friend_handle = row.find_all("td")[1].text
            friends_list.append(friend_handle)
    except:
        pass

    # Removing all handles which are already friend of the user
    not_friends = []
    for handle in handles:
        if handle not in friends_list and handle not in not_friends and handle != "":
            not_friends.append(handle)

    # # For debugging
    # print(handles)        # Handles in input file
    # print(friends_list)   # List of friends of user
    # print(not_friends)    # List of handles which are not friends of user

    # Adding friends
    new_friends = []
    for handle in not_friends:
        try:
            driver.get("https://codeforces.com/profile/{}".format(handle))
            page_source = driver.page_source
            soup = BeautifulSoup(page_source, 'lxml')
            h1 = soup.find("h1")

            if "Click to add to friends" in str(h1.img):
                print("\nAdding {} to friends".format(handle))
                star = driver.find_element(By.TAG_NAME, "h1").find_element(By.TAG_NAME, "img")
                star.click()
                sleep(.2)
                new_friends.append(handle)
        except Exception as e:
            print(f"Handle doesn't exist: {handle}")
            # print(e)

    print("\n\n\n\n")
    print(f"\nSuccess: {len(new_friends)} new friends added !")
    print(*new_friends, sep="\n")
    print("\nDone...")

    # Redirecting to My Friends page
    driver.get("https://codeforces.com/friends")
    sleep(6000)


from os import listdir
from os.path import isfile, join
import ast

dir = './tryouts/'

terrorNames = [
    "מהומות בנגב על רקע נטיעות קקל",
    "מבצע שומר החומות",
    "טרור עממי",
    "גל טרור הבודדים",
    "אירועי רמצאן 22"
]
terrorNamesSet = set(terrorNames)

files = [f for f in listdir(dir) if isfile(join(dir, f))]

peakCutOffs = {}
maxNumberOfPeaksBeforeTails = {}
daysOfTails = {}
minTailAverages = {}
maxNonTailAverages = {}
minNumberOfWordss = {}

def AddOne(dict, key):
    count = 0
    if key in dict:
        count = dict[key]
    count += 1
    dict[key] = count

for file in files:
    f = open(join(dir, file), "r")
    content = f.read()
    if content != '[]':
        matchedWaves = ast.literal_eval(content)
        terrorWavesFound = list(filter(lambda x: x in terrorNamesSet, matchedWaves))
        terrorWavesFoundCount = len(terrorWavesFound)
        nonTerrorWavesCount = len(matchedWaves) - terrorWavesFoundCount
        if terrorWavesFoundCount >= 2 and nonTerrorWavesCount == 1:
            split = file.split(';')
            peakCutOff = split[0]
            maxNumberOfPeaksBeforeTail = split[1]
            daysOfTail = split[2]
            minTailAverage = split[3]
            maxNonTailAverage = split[4]
            minNumberOfWords = split[5].split('.')[0]
            AddOne(peakCutOffs, peakCutOff)
            AddOne(maxNumberOfPeaksBeforeTails,maxNumberOfPeaksBeforeTail)
            AddOne(daysOfTails,daysOfTail)
            AddOne(minTailAverages,minTailAverage)
            AddOne(maxNonTailAverages,maxNonTailAverage)
            AddOne(minNumberOfWordss,minNumberOfWords)

print('peakCutOffs', dict(sorted(peakCutOffs.items(), key=lambda item: item[1])))
print('maxNumberOfPeaksBeforeTails', dict(sorted(maxNumberOfPeaksBeforeTails.items(), key=lambda item: item[1])))
print('daysOfTails', dict(sorted(daysOfTails.items(), key=lambda item: item[1])))
print('minTailAverages', dict(sorted(minTailAverages.items(), key=lambda item: item[1])))
print('maxNonTailAverages', dict(sorted(maxNonTailAverages.items(), key=lambda item: item[1])))
print('minNumberOfWordss', dict(sorted(minNumberOfWordss.items(), key=lambda item: item[1])))


# Based on the architecture of: https://arxiv.org/pdf/2008.07515.pdf

import os
# Tell tensorflow not to use the GPU
#os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
# Tone down warning messages
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1'

print("Loading TensorFlow...")
import tensorflow as tf

from tensorflow.keras.layers import Reshape, Dense, Flatten, Conv2D, Conv2DTranspose, Dropout, MaxPooling2D, UpSampling2D
from tensorflow.keras import Model

import random
import numpy as np
import scipy.io as sio
import matplotlib.pyplot as plt
plt.rc('image', cmap='inferno')

import matplotlib.ticker as mplticker

from scipy import ndimage, misc, signal, stats

### Settings ###
EPOCHS = 1000

batchSize = 128

showDiss = False

printDithers = False
trainDynamics = True
trainLatentModel = False

### /Settings ###

# Import training data from MATLAB file
# Generated by makeStraems.m
fname = "../trainingData8000.mat"
print("Reading " + fname + " ...")
trainingData = sio.loadmat(fname)
examples = tf.cast(trainingData['vortOuts'],tf.float32)

spaceSize = examples.shape[-1]
spaceCenter = spaceSize // 2

data_frameTime = trainingData['timeBetweenFrames'][0,0]
data_npu = trainingData['npu'][0,0]
data_dissipations = trainingData['dissipations']
chargeCount = np.squeeze(trainingData['chargeCount'])

if showDiss:
  plt.plot(data_dissipations)
  plt.show(block=True)

print(
  f'Training data metadata:\n'
  f'  frameTime: {data_frameTime}\n'
  f'  npu: {data_npu}\n'
  f'  numDataPoints: {examples.shape[0]}\n'
  )

forcingWiggle = np.fromfunction(lambda x,y: y + 2 * np.sin(4 * 2 * np.math.pi/128 * x),[128,128])
def vizAutoencoder(original,reconstructed,latent,lab="",epc=""):
  vizLatent(reconstructed,latent,lab,epc)
  vizReal(original,reconstructed,lab,epc)

def vizLatent(reconstructed,latent,lab="",epc=""):
  # Latent plot
  f, (ax1,ax2) = plt.subplots(1, 2,figsize=(20,10))
  ax1.set_title("Vorticity")
  ax1.contourf(reconstructed,cmap="cividis",levels=40)

  ax2.set_title("Latent representation, epoch #" + epc)
  embedDimension = latent.shape[0]
  edgeSize = np.floor(np.sqrt(embedDimension)).astype('int32')
  while (np.mod(embedDimension,edgeSize) > 0):
    edgeSize = edgeSize - 1
  ax2.xaxis.set_major_locator(mplticker.MaxNLocator(integer=True))
  ax2.yaxis.set_major_locator(mplticker.MaxNLocator(integer=True))
  f.colorbar(ax2.imshow(np.reshape(latent,[edgeSize,embedDimension // edgeSize]),cmap="binary"),ax=ax2)

  f.savefig("images/latent" + lab + ".png", bbox_inches='tight')
  plt.close(f)

def vizReal(original,reconstructed,lab="",epc="",direc="images"):
  # Real space plot
  f, (ax1) = plt.subplots(1, 1,figsize=(10,10),dpi=150)

  lossAmt = reconstructionLoss(original,reconstructed)
  ax1.set_title("Reconstructed vs Original (" + lab + "), loss = " + str(lossAmt.numpy()) + ", epoch #" + epc)

  ax1.contourf(original,cmap="gray",levels=40)

  ax1.contour(forcingWiggle,colors='green',alpha=0.05,levels=16)
  ax1.contour(reconstructed,cmap="plasma",levels=30)

  f.savefig(direc + "/reconstruction" + lab + ".png", bbox_inches='tight')
  plt.close(f)

  original.numpy().astype('float32').tofile("dumps/original" + lab + '.dat')
  reconstructed.numpy().astype('float32').tofile("dumps/recovered" + lab + '.dat')

print("Data shape: ",examples.shape)

stateDataset = tf.data.Dataset.from_tensor_slices(examples).shuffle(10000).batch(batchSize)
trainStates = stateDataset.shard(2,0)
testStates = stateDataset.shard(2,1)

def makeDynamicPairs(exs):
  return tf.data.Dataset.from_tensor_slices(tf.transpose(tf.convert_to_tensor([exs[:-1],exs[1:]]),perm=[1,0,2]))

class PredictDynamics(Model):
  def __init__(self):
    super(PredictDynamics,self).__init__()
    self.embedDimension = 32
    self.d1 = Dense(32,activation='relu')
    self.d2 = Dense(32,activation='relu')
    self.d3 = Dense(32)

  def call(self,x):
    x = self.d1(x)
    x = self.d2(x)
    x = self.d3(x)
    return x

class LatentModel(Model):
  def __init__(self):
    super(LatentModel, self).__init__()
    self.inp = tf.keras.layers.InputLayer(input_shape=(batchSize,128,128,1))
    self.mp = MaxPooling2D((2,2))
    self.c1 = Conv2D(32,8,activation='relu')
    self.c2 = Conv2D(32,8,activation='relu')
    self.c3 = Conv2D(32,4,activation='relu')
    self.c4 = Conv2D(64,4,activation='relu')
    self.c5 = Conv2D(128,2,activation='relu')

    self.flat = Flatten()

    self.embedDimension = 32
    self.dIn = Dense(self.embedDimension,activation='relu')
    self.drop = Dropout(0.2)
    self.dOut = Dense(128,activation='relu',input_shape=[self.embedDimension])
    self.rshp = Reshape(target_shape=[4,4,8])

    self.up = UpSampling2D((2,2))
    self.dc5 = Conv2DTranspose(128,(2,2),activation='relu')
    self.dc4 = Conv2DTranspose(64,(4,4),activation='relu')
    self.dc3 = Conv2DTranspose(32,(4,4),activation='relu')
    self.dc2 = Conv2DTranspose(16,(8,8),activation='relu')
    self.dc1 = Conv2DTranspose(1,(8,8))

  def encode(self, x):
    x = tf.expand_dims(x,axis=-1)
    x = self.c1(x)
    x = self.mp(x)

    x = self.c2(x)
    x = self.mp(x)

    x = self.c3(x)
    x = self.mp(x)

    x = self.c4(x)
    x = self.mp(x)

    x = self.c5(x)
    x = self.mp(x)

    x = self.flat(x)
    x = self.dIn(x)

    return x

  def decode(self, x):
    x = self.dOut(x)
    x = self.rshp(x)

    x = self.dc5(x)
    x = self.up(x)

    x = self.dc4(x)
    x = self.up(x)

    x = self.dc3(x)
    x = self.up(x)

    x = self.dc2(x)
    x = self.up(x)

    x = self.dc1(x)
    x = tf.image.crop_to_bounding_box(x,5,5,128, 128)
    return tf.squeeze(x)

  def call(self, x):
    x = self.encode(x)
    x = self.drop(x) # Prevents overfitting
    return self.decode(x)

  def getEigs(self):
    oneHots = tf.eye(self.embedDimension)
    return decode(oneHots)

def dynamicalLoss(delta,prediction):
  errors = delta - prediction
  sqErrs = tf.math.log(tf.math.cosh(errors))
  return tf.math.reduce_mean(sqErrs,axis = -1)

def reconstructionLoss(original,reconstructed):
  errors = original - reconstructed
  sqErrs = tf.math.log(tf.math.cosh(errors))
  return tf.math.reduce_mean(sqErrs,axis = (-1,-2))

def symmetryDither(psi):
  rollAmt = np.random.randint(128)
  psi = tf.roll(psi,rollAmt,axis=-1) # Continuous x-translation

  stepsDiscrete = np.random.randint(8)
  for i in range(stepsDiscrete):
    psi = -tf.reverse(tf.roll(psi,128 // 8,axis = -2),axis=[-1])

  doParity = np.random.randint(2)
  if doParity > 0:
    psi = tf.reverse(psi,axis = [-1,-2])
  return psi

def vizDynamics(ae):
  def f(dynModel,pairs,epoch):
    beforeStates = pairs[:,0,:]
    predictedDiff = dynModel(beforeStates)
    beforeRe = ae.decode(beforeStates)
    afterRe = ae.decode(pairs[:,1,:])
    predictAfterRe = ae.decode(pairs[:,0,:] + predictedDiff)
    n = 8
    for k in range(n):
      if k < len(pairs):
        vizSingleDynamic(beforeRe[k],afterRe[k],predictAfterRe[k],beforeStates[k],pairs[k,1] - pairs[k,0],predictedDiff[k],str(k),str(epoch))
  return f

def plotLatent(f,lz,ax):
  embedDimension = lz.shape[0]
  edgeSize = np.floor(np.sqrt(embedDimension)).astype('int32')
  while (np.mod(embedDimension,edgeSize) > 0):
    edgeSize = edgeSize - 1
  ax.xaxis.set_major_locator(mplticker.MaxNLocator(integer=True))
  ax.yaxis.set_major_locator(mplticker.MaxNLocator(integer=True))
  f.colorbar(ax.imshow(np.reshape(lz,[edgeSize,embedDimension // edgeSize]),cmap="binary"),ax=ax)

def vizSingleDynamic(beforeRe,afterRe,predictedRe,before,trueDiff,predictedDiff,lab="",epc=""):

  f, ((axr1,axr2,axr3),(axl1,axl2,axl3)) = plt.subplots(2, 3,figsize=(20,20))
  axr1.set_title("Before (" + lab + ")")
  axr1.contourf(beforeRe,cmap="cividis",levels=40)
  axl1.set_title("Before (" + lab + "), latent representation")
  plotLatent(f,before,axl1)

  axr2.set_title("True After (" + lab + ")")
  axr2.contourf(afterRe,cmap="cividis",levels=40)
  axl2.set_title("True diff (" + lab + "), latent representation")
  plotLatent(f,trueDiff,axl2)

  axr3.set_title("Predicted After (" + lab + "), epoch#" + epc)
  axr3.contourf(predictedRe,cmap="cividis",levels=40)
  axl3.set_title("Predictied diff (" + lab + "), latent representation")
  plotLatent(f,predictedDiff,axl3)

  f.savefig("dynamicsImages/dynamic" + lab + ".png", bbox_inches='tight')
  plt.close(f)

def vizLatentModel(model,test_orig,epoch):
  symOrig = symmetryDither(test_orig)
  recovered = model(symOrig,training=False)
  latent = model.encode(symOrig)
  oneHots = tf.eye(model.embedDimension)
  eigs = model.decode(oneHots)
  n = 8
  for l in range(eigs.shape[0]):
    vizLatent(eigs[l],oneHots[l],"Eigen " + str(l),str(epoch))
  for k in range(n):
    # If this is a truncated epoch, don't crash
    if k < len(test_orig):
      # Save the weights every time we visualize anything, so we can always get that network back
      vizAutoencoder(symOrig[k],recovered[k],latent[k],str(k),str(epoch))

if printDithers:
  testOmega = examples[np.random.randint(examples.shape[0])]
  for i in range(20):
    dithered = symmetryDither(testOmega)
    vizReal(dithered,dithered,"dither" + str(i),"-",direc="dither")

def trainThis(model,trainDir,lossFn,getFeat,getLabel,doViz,trainSet,testSet):
  optimizer = tf.keras.optimizers.Adam()

  train_loss = tf.keras.metrics.Mean(name='train_loss')

  test_loss = tf.keras.metrics.Mean(name='test_loss')

  @tf.function
  def train_step(original):
    # GradientTape keeps track of gradients so we can backprop
    symOrig = getFeat(original)
    lbl = getLabel(original)
    with tf.GradientTape() as tape:
      reconstructed = model(symOrig, training=True)
      loss = lossFn(lbl, reconstructed)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    train_loss(loss)

  @tf.function
  def test_step(original):
    # training=False disables Dropout layer
    reconstructed = model(getFeat(original), training=False)
    t_loss = lossFn(getLabel(original), reconstructed)

    test_loss(t_loss)

  checkpoint_path = "training_data_" + trainDir + "/cp-{epoch:04d}.ckpt"
  checkpoint_dir = os.path.dirname(checkpoint_path)

  # Save the epoch zero weights to ensure the folder is populated
  if not os.path.isdir(checkpoint_dir):
    model.save_weights(checkpoint_path.format(epoch=0))

  latest = tf.train.latest_checkpoint(checkpoint_dir)
  model.load_weights(latest)

  for epoch in range(EPOCHS):
    # Reset the metrics at the start of the next epoch
    train_loss.reset_states()
    test_loss.reset_states()

    for original in trainSet:
      # Progess bar
      print(".",end="",flush=True)
      train_step(original)

    print()

    # How many examples to output as graphs every vizEpochs
    n = 8
    vizEpochs = 50
    vized = False
    for test_orig in testSet:
      print("'",end="",flush=True)
      test_step(test_orig)
      # Also vizualize on last epoch
      if not vized and ((epoch % vizEpochs == 0) or (epoch == EPOCHS - 1)):
        print("\b\"",end="",flush=True)
        doViz(model,test_orig,epoch)
        model.save_weights(checkpoint_path.format(epoch=epoch))
        vized = True
    print()
    print(
      f'Epoch {epoch}, '
      f'Reconstruction Loss: {train_loss.result()}, '
      f'Test Reconstruction Loss: {test_loss.result()}'
    )

  # Still save weights even if n=0 graphs
  model.save_weights(checkpoint_path.format(epoch=EPOCHS))

if trainDynamics:
  ae = LatentModel()
  ae.load_weights(tf.train.latest_checkpoint("training_data_AE"))
  exBatches = tf.unstack(tf.split(examples,100))
  print("Encoding...")
  encExamples = tf.reshape([ae.encode(x) for x in exBatches],[examples.shape[0],ae.embedDimension])

  dynamicsModel = PredictDynamics()
  dynPairs = makeDynamicPairs(encExamples).shuffle(10000).batch(batchSize)
  trainPairs = dynPairs.shard(2,0)
  testPairs = dynPairs.shard(2,1)
  def getBefore(x):
    return x[:,0]
  def getDiff(x):
    return x[:,1] - x[:,0]
  trainThis(dynamicsModel,"dynamics",dynamicalLoss,getBefore,getDiff,vizDynamics(ae),trainPairs,testPairs)
  quit()

if trainLatentModel:
  autoencoder = LatentModel()
  trainThis(autoencoder,"AE",reconstructionLoss,symmetryDither,lambda o: o,vizLatentModel,trainStates,testStates)
  quit()


import time
import cProfile
import pstats
from func import *
from map import *
import sys
from Puzzle import Puzzle
import argparse
from visualization import handle_visualizer
from threading import Thread

def create_puzzle(argv):
    puzzle = Puzzle(argv.sf, argv.num_h_ver)

    b = parse_map(argv.file_name)
    puzzle.size_matr = int(math.sqrt((len(b) + 1) / 2))
    can_i_do_it(b, puzzle.size_matr)  # проверим возможность решения
    ch = make_children(b.split("/"), puzzle.size_matr)  # для исходного состояния рождаем детей(макс 4)
    puzzle.complexity_in_size += len(ch)
    puzzle.must_be_str = str(must_be(puzzle.size_matr)).split('/')
    # и добавляем всех в список открытых вершин

    A = Node(puzzle.size_matr, None, b.split("/"), 0, puzzle.sf, argv.num_h_ver, puzzle)
    if puzzle.must_be_str == A.node:
        print("Init state is equal to goal state")
        sys.exit()

    for c in ch:
        ch_c = Node(puzzle.size_matr, A, c, 1, puzzle.sf, argv.num_h_ver, puzzle)
        puzzle.q.put((ch_c.f, ch_c))
    puzzle.sp_z[A] = A.par
    puzzle.closed_set = set(["/".join(A.node)])
    puzzle.b = b
    return puzzle

class SolverThread(Thread):
    def __init__(self, name, puzzle):
        Thread.__init__(self)
        self.name = name
        self.puzzle = puzzle

    def run(self):
        solve(self.puzzle)

def add_thread(name, sf, hf, argv, threads):
    argv.sf = sf
    argv.num_h_ver = hf
    threads.append(SolverThread(name, create_puzzle(argv)))

def create_threads(argv):
    Printer.print_benchmark_header()
    threads = []
    add_thread("A* Euclidean", 1, 1, argv, threads)
    add_thread("A* Not-in-place", 1, 2, argv, threads)
    add_thread("A* Manhattan", 1, 3, argv, threads)
    add_thread("Greedy Euclidean", 2, 1, argv, threads)
    add_thread("Greedy Not-in-place", 2, 2, argv, threads)
    add_thread("Greedy Manhattan", 2, 3, argv, threads)
    add_thread("Breadth-first search", 3, 3, argv, threads)
    return threads

def main():
    argv = parse_argv(sys.argv)
    if argv.benchmark:
        treads = create_threads(argv)
        [t.start() for t in treads]
    else:
        puzzle = create_puzzle(argv)
        solve(puzzle)

    if not Mode.BENCHMARK_MODE:
        path_print2(puzzle, puzzle.min, puzzle.sp_z, puzzle.size_matr)
        handle_visualizer(puzzle.success, puzzle.b, puzzle.size_matr, puzzle.sp_z, puzzle.min)

def run_benchmark(puzzle):
    print("benchmark mock")

def solve(puzzle):
    while not puzzle.q.empty():
        min = puzzle.q.get()[1]
        puzzle.complexity_in_time += 1
        if puzzle.must_be_str != min.node:
            child = make_children(min.node, min.size)
            for c in child:
                if "/".join(c) not in puzzle.closed_set:
                    ch_c = Node(puzzle.size_matr, min, c, min.g + 1, puzzle.sf, puzzle.num_h_ver, puzzle)
                    puzzle.q.put((ch_c.f, ch_c))
                    puzzle.complexity_in_size += 1
            puzzle.sp_z[min] = min.par
            puzzle.closed_set.add("/".join(min.node))

        else:
            puzzle.sp_z[min] = min.par
            puzzle.success = 1
            puzzle.dt = time.time() - puzzle.t_1
            puzzle.min = min
            break
    if Mode.BENCHMARK_MODE:
        Printer.print_benchmark_result(puzzle)

def parse_argv(argv):
    if len(argv) == 1:
        Printer.print_usage()
    parser = argparse.ArgumentParser()
    parser.add_argument("file_name")
    parser.add_argument("--hf", type=int, dest='num_h_ver', default=0)
    parser.add_argument("--v", action="store_true", help="Enable visualization")
    parser.add_argument("--sf", type=int, default=1)
    parser.add_argument("--b", dest='benchmark', action="store_true", help="Comparise all search functions and heuristics")
    parser.add_argument("--p", action="store_true", help="Get performance statistics")
    args = parser.parse_args()
    if args.sf not in [1, 2, 3]:
        args.sf = 1
    if args.v:
        Mode.VIS_MODE = True
    if args.benchmark:
        Mode.VIS_MODE = False
        Mode.BENCHMARK_MODE = True
    return args

if __name__ == '__main__':
    profiling = False
    for arg in sys.argv[1:]:
        if arg == '--p':
            profiling = True

    try:
        if profiling:
            cProfile.run('main()', 'mainstats')
            p = pstats.Stats('mainstats')
            p.strip_dirs().sort_stats(pstats.SortKey.CUMULATIVE).print_stats(20)
        else:
            main()
    except Exception:
        Printer.print_error_exit("Can`t solve this map. Maybe it is unsovable")


from statistics import statistics as st

# linear regression
def linear_regression_channel(input_array, interval, deviations=1):
    # time: O(n*i), space: O(n*i)
    output_array = [(x, x, x) for x in input_array]

    for t in range(interval-1, len(input_array)):
        x = [i for i in range(t-interval+1,t+1)]
        y = input_array[t-interval+1:t+1]
        x_bar = st.average(x)
        y_bar = st.average(y)
        cov = st.covariance(x, y)
        var_x = st.variance(x)
        stdev_y = (st.variance(y)**0.5)*deviations
        m = cov/var_x
        b = y_bar - (m*x_bar)
        reg_val = m*t+b
        # print(stdev_y, cov, var_x, m, b, x_bar, y_bar, m*t+b)
        output_array[t] = (reg_val-stdev_y, reg_val, reg_val+stdev_y)

    return output_array


from flask import Flask, request, jsonify

app = Flask(__name__, static_folder='frontend', static_url_path='')

# Placeholder text processing function (Replace this with your actual logic)
def process_text(input_text):
    # Simulating text processing, replace this with your actual text processing logic
    summary = "This is a placeholder summary."
    sections = {"Section 1": "Content for section 1", "Section 2": "Content for section 2"}
    return summary, sections

# This endpoint receives the text, processes it, and returns the summary
@app.route('/process_text', methods=['POST'])
def process_text_endpoint():
    text = request.json.get('text')

    # Perform text processing
    summary, sections = process_text(text)

    # Returning a JSON response with the summary and sections
    return jsonify({"summary": summary, "sections": sections})

if __name__ == '__main__':
    print("Flask application running!")
    app.run(debug=True)


N = int(input())

def factorial(number):
    if number == 0:
        factorialNum = 1
    else:
        factorialNum = 1
        for i in range(2, number+1):
            factorialNum = factorialNum*i
    return factorialNum

factorialN = str(factorial(N))
deletedZero = str(factorial(N)).rstrip('0')
print(len(factorialN)-len(deletedZero))


"""
-------------------------------------------------------
[program description]
-------------------------------------------------------
Author:  Roshni Mahindru
ID:      210756010
Email:   mahi6010@mylaurier.ca
__updated__ = "2021-09-25"
-------------------------------------------------------
"""

# receive input from user
principal = float(input("Principal: $"))
interest = float(input("Interest:"))
years = int(input("Number of years:"))
compPeryear = int(input("Number of time interest compounded per year:"))

# calculate balance
balance = principal * ((1 + (interest / compPeryear)) ** (years * compPeryear))

# display balance
print("Balance: $", balance)


#######PYTHON CODE FOR IMD PREPARED BY LEKSHMI S#########
########## https://doi.org/10.5281/zenodo.5674826 ############

import xarray as xr
data="S:/IMD_rainfall_0.25/_Clim_Pred_LRF_New_RF25_IMD0p252020.nc"

############Open the dataset##################
da=xr.open_dataset(data)
print(da)

##############Subset the whole dataset for the required time, lat and lon###############
date='2020-06-15'
lat=18.0
lon=75.0

#METHOD 1
########Using sel function in xarray######################
#########Give the actual coordinate required##############
da_sub=da.sel(TIME=date,LATITUDE=lat,LONGITUDE=lon)       #TIME,LATITUDE,LONGITUDE are the dimension names in file
print(da_sub)

#METHOD 2
##################Using isel function in xarray######################
#########Give the index of the actual coordinate required##############
da_sub1=da.isel(TIME=166,LATITUDE=46,LONGITUDE=34)       #TIME,LATITUDE,LONGITUDE are the dimension names in file
print(da_sub1)


import pygame;

from supplementary import *;

#Constants:

ART_ASSETS = "Art_Assets";
MAIN_MENU = "MainMenu";
JPG_EX = ".jpg";

def loadBackground():

    background = [];

    for index in range(0, 18):
        background.append(loadImg(urlConstructor(ART_ASSETS, MAIN_MENU), MAIN_MENU + str(1000 + index)[1:] + JPG_EX));

    return background;

class BackgroundDisplayLogic:

    #Default Color
    BLACK = (0, 0, 0);

    BACKGROUND_BORDER_THICKNESS = 5;

    #Background boundary check variables
    canContinueMovingLeft = True;
    canContinueMovingRight = True;
    canContinueMovingUp = True;
    canContinueMovingDown = True;

    #Variables initialization
    background = [];
    backgroundWidth = 0;
    backgroundHeight = 0;

    #Controls if backgroundSpriteCount increases or decreases
    backgroundLoopBackwards = False;

    #Counter for current frame of animation
    backgroundSpriteCount = 0;

    #Prevents background from updating too quickly
    backgroundDelay = 3;

    #Controls rendering position in the game (x, y)
    backgroundPos = [];

    #Controls free-roam camera speed:
    autoRoamSpeed = 2;

    currentMovement = speedList();
    currentMovement.adjustSpeed(0, autoRoamSpeed);

    def __init__(self, backgroundList):
        self.background = backgroundList;

        if len(self.background) == 0:
            tempBackground = pygame.Surface((2048, 2048));
            tempBackground.fill(BLACK);
            self.background = [tempBackground];

        self.backgroundWidth = self.background[0].get_width();
        self.backgroundHeight = self.background[0].get_height();
        self.backgroundPos = [-self.backgroundWidth/4, -self.backgroundHeight/4];

    def _checkBounds(self):
        #Check if camera is about to exceed bottom boundary
        if self.backgroundPos[1] <= -self.backgroundHeight/2 + self.BACKGROUND_BORDER_THICKNESS:
            self.canContinueMovingDown = False;
        else:
            self.canContinueMovingDown = True;
        #Check if camera is about to exceed right boundary
        if self.backgroundPos[0] <= -self.backgroundWidth/2 + self.BACKGROUND_BORDER_THICKNESS:
            self.canContinueMovingRight = False;
        else:
            self.canContinueMovingRight = True;
        #Check if camera is about to exceed top boundary
        if self.backgroundPos[1] >= 0 - self.BACKGROUND_BORDER_THICKNESS:
            self.canContinueMovingUp = False;
        else:
            self.canContinueMovingUp = True;
        #Check if camera is about to exceed left boundary
        if self.backgroundPos[0] >= 0 - self.BACKGROUND_BORDER_THICKNESS:
            self.canContinueMovingLeft = False;
        else:
            self.canContinueMovingLeft = True;

    def _determineFreeMovement(self):
        self._checkBounds();

        reachedBottomBound = not self.canContinueMovingDown;
        reachedLeftBound = not self.canContinueMovingLeft;
        reachedTopBound = not self.canContinueMovingUp;
        reachedRightBound = not self.canContinueMovingRight;

        reachedBottomLeft = reachedBottomBound and reachedLeftBound;
        reachedBottomRight = reachedBottomBound and reachedRightBound;
        reachedTopLeft = reachedTopBound and reachedLeftBound;
        reachedTopRight = reachedTopBound and reachedRightBound;

        #Check for Bottom Left Corner
        if reachedBottomLeft:
            self.currentMovement.adjustSpeed(0, -self.autoRoamSpeed); #Go Up

        #Check for Bottom Right Corner
        elif reachedBottomRight:
            self.currentMovement.adjustSpeed(self.autoRoamSpeed, 0); #Go Left

        #Check for Top Left Corner
        elif reachedTopLeft:
            self.currentMovement.adjustSpeed(-self.autoRoamSpeed, 0); #Go Right

        #Check for Top Right Corner
        elif reachedTopRight:
            self.currentMovement.adjustSpeed(0, self.autoRoamSpeed); #Go Down

        if reachedBottomBound and not reachedBottomLeft:
            self.currentMovement.adjustSpeed(self.autoRoamSpeed, 0); #Start going Left

        elif reachedLeftBound and not reachedTopLeft:
            self.currentMovement.adjustSpeed(0, -self.autoRoamSpeed); #Start going Up

        elif reachedTopBound and not reachedTopRight:
            self.currentMovement.adjustSpeed(-self.autoRoamSpeed, 0); #Start going Right

        elif reachedRightBound and not reachedBottomRight:
            self.currentMovement.adjustSpeed(0, self.autoRoamSpeed); #Start going Down

    def _calculatePositionChange(self, moveConfig = "Free", currentMovement = None):
        #Assumes that self.currentMovement represents the camera/window and not the background itself
        if moveConfig == "Free":
            self._determineFreeMovement();

        if currentMovement == None:
            currentMovement = self.currentMovement;

        if not currentMovement.noNetSpeed():
            self.backgroundPos[0] += currentMovement.getNetHorizontalSpeed();
            self.backgroundPos[1] += currentMovement.getNetVerticalSpeed();

    #Called at every iteration of the loop
    def update(self):
        #Controls background positioning
        self._calculatePositionChange();

        #Controls background sprite refresh rate
        if self.backgroundDelay >= 5:
            if self.backgroundLoopBackwards == False:
                self.backgroundSpriteCount += 1;
                if self.backgroundSpriteCount >= len(self.background):
                    self.backgroundLoopBackwards = True;
                    self.backgroundSpriteCount -= 1;
            else:
                self.backgroundSpriteCount -= 1;
                if self.backgroundSpriteCount <= 0:
                    self.backgroundLoopBackwards = False;
                    self.backgroundSpriteCount +=1;

            self.backgroundDelay = 0;
        else:
            self.backgroundDelay += 1;

    def getBackgroundSprite(self):
        return self.background[self.backgroundSpriteCount];

    def resetRenderCoordinates(self):
        self.background_pos = (-self.backgroundWidth/2, -self.backgroundHeight/2);

    def getRenderCoordinates(self):
        return (self.backgroundPos[0], self.backgroundPos[1]);

    def setRenderCoordinates(self, coordinates):
        self.backgroundPos[0] = coordinates[0];
        self.backgroundPos[1] = coordinates[1];


# Baekjoon_13275 가장 긴 팰린드롬 부분 문자열

# Solution01 by wYuYw - using two pointer, pypy3

import sys
input = sys.stdin.readline

# initialize
s = input().strip()
res = 0

# validate function
def validate(left: int, right: int) -> int:
    max_length = 0
    while left >= 0 and right < len(s) and s[left] == s[right]:
        if (right - left + 1) > max_length:
            max_length = right - left + 1
        left -= 1
        right += 1

    return max_length

# base case
if len(s) < 2 or s == s[::-1]:
    print(len(s))

else:
    for i in range(len(s)):
        res = max(res, validate(i, i), validate(i, i + 1))
    print(res)

# Solution02 by wYuYw - using Manacher, cpython

import sys
input = sys.stdin.readline

def manacher(s):
    radius = [0 for i in range(len(s) + 1)]  # palindrome radius
    norm = 0  # index of norm character
    max_radius = 0  # maximum radius of palindrome so far

    for i in range(1,len(s) - 1):
        if i < max_radius:
            radius[i] = min(max_radius - i, radius[2 * norm - i])
        else:
            radius[i] = 1
        while s[i - radius[i]] == s[i + radius[i]]:
            radius[i] += 1
        if max_radius < i + radius[i]:
            norm = i
            max_radius = i + radius[i]
    norm, max_radius = 0,0
    for i in range(len(s)):
        if max_radius < radius[i]:
            norm = i
            max_radius = radius[i]
    return len(s[norm - radius[norm] + 1:norm + radius[norm]].replace('#',''))

s = input().strip()
print(manacher('$#' + '#'.join(s) + '#@'))


# -*- coding: utf-8 -*-
# Author: Rodrigo Cordeiro

# You are going to be given a word. Your job is to return the middle character of the word. If the word's length is odd, return the middle character. If the word's length is even, return the middle 2 characters.

## Examples:
# Kata.getMiddle("test") should return "es"
# Kata.getMiddle("testing") should return "t"
# Kata.getMiddle("middle") should return "dd"
# Kata.getMiddle("A") should return "A"

def get_middle(s):
	a = len(s) #checar tamanho
	b = int(a/2)
	if a > 2:
		if a % 2 ==0:
			return s[b-1:-b+1]
		else:
			return s[b:-b]
	else:
		return s

print(get_middle("test"),"es")
print(get_middle("testing"),"t")
print(get_middle("middle"),"dd")
print(get_middle("A"),"A")
print(get_middle("of"),"of")


f=open("employee","r")

emp_dict={}
for lines in f:
    print(lines)
    data=lines.rstrip("\n").split(",")

    if id not in emp_dict:
        emp_dict[data[0]]={"id":data[0],"name":data[1],"desig":data[2],"exp":data[3],"salary":data[4]}
print(emp_dict)