# Created by Sphero Inc.
# Modified by Aaron Goff
# Additinoal code from ~/sphero/getting_started/asyncio/driving

import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import asyncio

from helper_keyboard_input import KeyboardHelper
from sphero_sdk import SerialAsyncDal
from sphero_sdk import SpheroRvrAsync
from sphero_sdk import SerialAsyncDal
from sphero_sdk import DriveFlagsBitmask

# initialize global variables
key_helper = KeyboardHelper()
current_key_code = -1
driving_keys = [119, 97, 115, 100, 32]
speed = 0
speedSet = 0
heading = 0
headingAngle = 0
flags = 0

# Reference asyncio loop & SpheroRvrAsync
loop = asyncio.get_event_loop()
rvr = SpheroRvrAsync(
    dal=SerialAsyncDal(
        loop
    )
)

# Allow RVR to drive autonomously with code from ~/sphero/getting_started/asyncio/driving/drive_with_heading
async def autonomousDrive():
    await rvr.wake()

    # Give RVR time to wake up
    await asyncio.sleep(2)

    await rvr.reset_yaw()

    await rvr.drive_with_heading(
        speed=128,  # Valid speed values are 0-255
        heading=0,  # Valid heading values are 0-359
        flags=DriveFlagsBitmask.none.value
    )

    # Delay to allow RVR to drive
    await asyncio.sleep(1)

    await rvr.drive_with_heading(
        speed=128,  # Valid speed values are 0-255
        heading=0,  # Valid heading values are 0-359
        flags=DriveFlagsBitmask.drive_reverse.value
    )

    # Delay to allow RVR to drive
    await asyncio.sleep(1)

    await rvr.drive_with_heading(
        speed=128,  # Valid speed values are 0-255
        heading=90,  # Valid heading values are 0-359
        flags=DriveFlagsBitmask.none.value
    )

    # Delay to allow RVR to drive
    await asyncio.sleep(1)

    await rvr.drive_with_heading(
        speed=128,  # Valid speed values are 0-255
        heading=270,  # Valid heading values are 0-359
        flags=DriveFlagsBitmask.none.value
    )

    # Delay to allow RVR to drive
    await asyncio.sleep(1)

    await rvr.drive_with_heading(
        speed=0,  # Valid heading values are 0-359
        heading=0,  # Valid heading values are 0-359
        flags=DriveFlagsBitmask.none.value
    )

    # Delay to allow RVR to drive
    await asyncio.sleep(1)

# Update keycode and print
def keycode_callback(keycode):
    global current_key_code
    current_key_code = keycode
    print("Key code updated: ", str(current_key_code))

# Allow RVR to set forward & reverse speed
def speedChange():
    global speedSet
    if current_key_code == 121: # Y - Speed Up
        speedSet += 64
    elif current_key_code == 104: # H - Speed Down
        speedSet -= 64

    if speedSet > 255:
        speedSet = 192
    elif speedSet < 0:
        speedSet = 0
    print('Current Speed: ' + str(speedSet))

# Allow RVR to set left & right pitch angle
def headingAng():
    global headingAngle
    if current_key_code == 114: # R - Angle Up
        headingAngle += 15
    elif current_key_code == 102: # F - Angle Down
        headingAngle -= 15

    # check the heading value, and wrap as necessary.
    if headingAngle > 90:
        headingAngle = 90
    elif headingAngle < 0:
        headingAngle = 0
    print('Current angle: ' + str(headingAngle))

# Start main and create loop
async def main():
    global current_key_code
    global speed
    global heading
    global flags

    await rvr.wake()

    await rvr.reset_yaw()

    # Create infinite loop to constantly watch for keyboard inputs
    while True:

        if current_key_code == 121 or current_key_code == 104: # Y - Speed Up OR H - Speed Down
            speedChange()
        elif current_key_code == 114 or current_key_code == 102: # R - Angle Up OR F - Angle Down
            headingAng()
        elif current_key_code == 119:  # W - Forward
            flags = 0
            speed = speedSet
        elif current_key_code == 115:  # S - Reverse
            flags = 1
            speed = speedSet
        elif current_key_code == 97:  # A - Left
            heading -= (headingAngle)
        elif current_key_code == 100:  # D - Right
            heading += headingAngle
        elif current_key_code == 120:  # X - Autonomous
            await autonomousDrive()

        elif current_key_code == 32:  # SPACE - Stop
            # reset speed and flags, but don't modify heading.
            speed = 0
            flags = 0

        # check the heading value, and wrap as necessary.
        if heading > 359:
            heading = heading - 359
        elif heading < 0:
            heading = 359 + heading

        # reset the key code every loop
        current_key_code = -1

        # issue the driving command
        await rvr.drive_with_heading(speed, heading, flags)

        # sleep the infinite loop for a 10th of a second to avoid flooding the serial port.
        await asyncio.sleep(0.1)

# Run loop
def run_loop():
    global loop
    global key_helper
    key_helper.set_callback(keycode_callback)
    loop.run_until_complete(
        asyncio.gather(
            main()
        )
    )

# Program starts here
if __name__ == "__main__":
    loop.run_in_executor(None, key_helper.get_key_continuous)
    try:
        run_loop()
    except KeyboardInterrupt:
        print("Keyboard Interrupt...")
        key_helper.end_get_key_continuous()
    finally:
        print("Press any key to exit.")
        exit(1)


def run(args = None):
    import sys
    import doctest

    if args is not None:
        sys.argv = args
    return doctest.testmod(sys.modules.get(__name__))

if __name__ == '__main__':
    print("running...")
    import sys
    status = run()[0]
    if (status == 0): print("Done.")
    sys.exit(status)


from django.forms import ValidationError
from django.test import TestCase
from .models import Order
# Create your tests here.
class OrderTestCase(TestCase):

    def setUp(self):
        Order.objects.create(
            number=1,
            amount=10,
            weight=2.5,
            width=30,
            height=20,
            length=40,
            zip_from='01001000',
            zip_to='04005000'
        )

    def test_order_str_method(self):
        order = Order.objects.get(number=1)
        self.assertEqual(str(order), "1")

    def test_order_zip_from_validator(self):
        invalid_order = Order(
            number=2,
            amount=5,
            weight=1.2,
            width=10,
            height=10,
            length=10,
            zip_from='invalid_zip'
        )
        with self.assertRaises(ValidationError):
            invalid_order.full_clean()

    def test_order_zip_to_validator(self):
        invalid_order = Order(
            number=3,
            amount=5,
            weight=1.2,
            width=10,
            height=10,
            length=10,
            zip_from='01001000',
            zip_to='invalid_zip'
        )
        with self.assertRaises(ValidationError):
            invalid_order.full_clean()

    def test_order_fields(self):
        order = Order.objects.get(number=1)
        self.assertEqual(order.amount, 10)
        self.assertEqual(order.weight, 2.5)
        self.assertEqual(order.width, 30)
        self.assertEqual(order.height, 20)
        self.assertEqual(order.length, 40)
        self.assertEqual(order.zip_from, '01001000')
        self.assertEqual(order.zip_to, '04005000')


from datetime import datetime, timedelta
from binascii import hexlify
from os import urandom
import caldav
from caldav.elements import dav

class Event:
    """A variant of event formatted to my liking for use with iCloud"""

    def __init__(self, event_object: caldav.Event = None):
        # Generate new event
        uid_parts = [4, 2, 2, 2, 6]
        for index, size in enumerate(uid_parts):
            uid_parts[index] = str(hexlify(urandom(size)))[2:-1]
        self._uid = '-'.join(uid_parts)

        # Free to edit these variables at will
        self.summary = ''
        self.description = ''
        self.location = ''
        self.timezone = ''

        # These attributes are monitored, but free
        self._start = self._end = self._dtstamp = self._created = datetime.now().strftime('%Y%m%dT%H%M%S')

        # These really shouldnt be used
        self._original_object = event_object
        self.__set_lastmodified__()
        self._sequence = 0

        # Overwrite with passed event
        if event_object is not None:
            self.__process_event_string_(event_object.data)
            return

    def __str__(self):
        return self.summary + \
               ' on ' + \
               self.start.strftime('%m%/%d%/%Y') + \
               ' from ' + \
               self.start.strftime('%H%:%M') + \
               ' to ' + \
               self.end.strftime('%H%:%M')

    def remove(self):
        self._original_object.delete()

    @property
    def sequence(self):
        return self._sequence

    @property
    def uid(self):
        return self._uid

    @property
    def start(self):
        year = int(self._start[:4])
        month = int(self._start[4:6])
        day = int(self._start[6:8])
        hour = int(self._start[9:11])
        minute = int(self._start[11:13])
        return datetime(year, month, day, hour, minute)

    @start.setter
    def start(self, to: datetime):
        self.__set_lastmodified__()
        self._start = to.strftime('%Y%m%dT%H%M%S')

    @property
    def end(self):
        year = int(self._end[:4])
        month = int(self._end[4:6])
        day = int(self._end[6:8])
        hour = int(self._end[9:11])
        minute = int(self._end[11:13])
        return datetime(year, month, day, hour, minute)

    @end.setter
    def end(self, to: datetime):
        self.__set_lastmodified__()
        self._end = to.strftime('%Y%m%dT%H%M%S')

    def __set_lastmodified__(self):
        self.lastmodified = datetime.now().strftime('%Y%m%dT%H%M%S')

    def ical_string(self) -> str:
        """Gathers all of the events data into a push string"""
        tz = ''
        if self.timezone != '':
            tz = ';TZID=' + self.timezone
        result = ['BEGIN:VCALENDAR',
                  'BEGIN:VEVENT',
                  'CREATED:' + self._created,
                  'DESCRIPTION:' + self.description,
                  'DTEND' + tz + ':' + self._end,
                  'DTSTAMP' + tz + ':' + self._dtstamp,
                  'DTSTART' + tz + ':' + self._start,
                  'LAST-MODIFIED:' + self.lastmodified,
                  'LOCATION:' + self.location,
                  'SEQUENCE:' + str(self._sequence),
                  'SUMMARY:' + self.summary,
                  'UID:' + self._uid,
                  'END:VEVENT',
                  'END:VCALENDAR']
        return '\n'.join(result)

    def __process_event_string_(self, event_string: str):
        details = []
        ignore_previous = False

        # Convert the raw data into more workable data (mostly just removing Apple's weird stuff)
        for line in event_string.split('\n'):
            if ':' in line:
                ignore_previous = False
                details.append(line)
            elif not ignore_previous \
                    and 'x-apple' not in line.lower() \
                    and 'x-master' not in line.lower():
                details[len(details) - 1] = details[len(details) - 1] + ' ' + line
            else:
                ignore_previous = True

        # Go through all of the details
        for detail in details:
            # Todo: Figure out what causes this
            if detail.count(':') > 2:
                print('Warning: I assumed something wrong and it might break')
                print(detail)

            heading, value = detail.split(':', 1)
            # Try to update timezone first
            if self.timezone == '' and 'tzid' in heading.lower():
                self.timezone = heading.split(';TZID=')[1]
            heading = heading.lower()

            # Map all attributes to proper space
            if 'created' in heading:
                self._created = value
                continue
            if 'dtend' in heading:
                self._end = value
                continue
            if 'dtstart' in heading:
                self._start = value
                continue
            if 'last-modified' in heading:
                self.lastmodified = value
                continue
            if 'dtstamp' in heading:
                self._dtstamp = value
                continue
            if 'summary' in heading:
                self.summary = value
                continue
            if 'description' in heading:
                self.description = value
                continue
            if 'location' in heading:
                self.location = value
                continue
            if 'uid' in heading:
                self._uid = value
                continue
            if 'sequence' in heading:
                self._sequence = value
                continue

    def push(self, calendar: caldav.objects.Calendar):
        # TODO: Check calendar if event already exists to increment sequence
        if self._original_object is None:
            self._original_object = caldav.Event(calendar.client, None, self.ical_string())
        calendar.add_event(self.ical_string())

class Calendar:
    """A CalDav variant formatted to my liking for use with iCloud"""

    important_labels = ['summary', 'description', 'dtend', 'dtstart']
    time_labels = ['dtend', 'dtstart', 'dtstamp', 'last-modified', 'created']
    active_calendar = None

    def __init__(self, username, password, calendar_name=None):
        url = 'https://' + username + ':' + password + '@caldav.icloud.com:443'
        self.client = caldav.DAVClient(url)
        self.principal = self.client.principal()
        self.events = []
        self._calendar = None
        if calendar_name is not None:
            self.calendar = calendar_name

    @property
    def calendars(self):
        calendar_names = []
        for calendar in self.principal.calendars():
            calendar_names.append(calendar.get_properties([dav.DisplayName(), ])['{DAV:}displayname'])
        return calendar_names

    @property
    def calendar(self):
        return self._calendar.get_properties([dav.DisplayName(), ])['{DAV:}displayname']

    @calendar.setter
    def calendar(self, calendar_name):
        for calendar in self.principal.calendars():
            if calendar.get_properties([dav.DisplayName(), ])['{DAV:}displayname'].lower() == calendar_name.lower():
                self._calendar = calendar
                return
        raise ValueError('Calendar does not exist on this user')

    def get_events(self, start_date: datetime, end_date: datetime):
        """Return events over specified amount of time"""

        events = []
        # Iterate through all events over the given
        for event_string in self._calendar.date_search(start_date, end_date):
            events.append(Event(event_string))
        return events

    def add_event(self, event: Event):
        events = self.get_events(event.start - timedelta(1), event.end + timedelta(1))
        print('looking at', len(events))
        for comparable in events:
            print('  Comparing', comparable)
            if str(event) == str(comparable):
                if event.summary == comparable.summary and \
                   event.description == comparable.description and \
                   event.location == comparable.location:
                    # Events are the same in terms of important details
                    print('Skipping', event)
                    return
                else:
                    print('Deleting', comparable)
                    comparable.remove()
                    break
        print('Adding', event)
        self._calendar.add_event(event.ical_string())

    def clear_thirty(self):
        now = datetime.today()
        start = datetime(now.year, now.month, now.day, 0, 0)
        for event in self.get_events(start, start + timedelta(30)):
            event.remove()


# --------------------------------------------------------
# Fast/er R-CNN
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------

import numpy as np

def unique_boxes(boxes, scale=1.0):
    """Return indices of unique boxes."""
    v = np.array([1, 1e3, 1e6, 1e9])
    hashes = np.round(boxes * scale).dot(v).astype(np.int)
    _, index = np.unique(hashes, return_index=True)
    return np.sort(index)

def xywh_to_xyxy(boxes):
    """Convert [x y w h] box format to [x1 y1 x2 y2] format."""
    return np.hstack((boxes[:, 0:2], boxes[:, 0:2] + boxes[:, 2:4] - 1))

def xyxy_to_xywh(boxes):
    """Convert [x1 y1 x2 y2] box format to [x y w h] format."""
    return np.hstack((boxes[:, 0:2], boxes[:, 2:4] - boxes[:, 0:2] + 1))

def validate_boxes(boxes, width=0, height=0):
    """Check that a set of boxes are valid."""
    x1 = boxes[:, 0]
    y1 = boxes[:, 1]
    x2 = boxes[:, 2]
    y2 = boxes[:, 3]
    assert (x1 >= 0).all()
    assert (y1 >= 0).all()
    assert (x2 >= x1).all()
    assert (y2 >= y1).all()
    assert (x2 < width).all()
    assert (y2 < height).all()

def filter_small_boxes(boxes, min_size):
    w = boxes[:, 2] - boxes[:, 0]
    h = boxes[:, 3] - boxes[:, 1]
    keep = np.where((w >= min_size) & (h > min_size))[0]
    return keep

def filter_validate_boxes(boxes, width, height):
    x1 = boxes[:, 0]
    y1 = boxes[:, 1]
    x2 = boxes[:, 2]
    y2 = boxes[:, 3]

    a = x1 >= 0
    b = y1 >= 0
    c = x2 >= x1
    d = y2 >= y1
    e = x2 < width
    f = y2 < height

    return np.logical_and(a, np.logical_and(b, np.logical_and(c, np.logical_and(d, np.logical_and(e, f)))))

def overlaps(boxes1, boxes2):
    ovrs = np.zeros((boxes1.shape[0], boxes2.shape[0]), dtype=np.float32)
    areas1 = (boxes1[:, 2] - boxes1[:, 0]) * (boxes1[:, 3] - boxes1[:, 1])
    areas2 = (boxes2[:, 2] - boxes2[:, 0]) * (boxes2[:, 3] - boxes2[:, 1])
    for i in range(boxes1.shape[0]):
        xx1 = np.maximum(boxes1[i, 0], boxes2[:, 0])
        yy1 = np.maximum(boxes1[i, 1], boxes2[:, 1])
        xx2 = np.minimum(boxes1[i, 2], boxes2[:, 2])
        yy2 = np.minimum(boxes1[i, 3], boxes2[:, 3])

        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        ovr = inter / (areas1[i] + areas2 - inter)
        ovrs[i, :] = ovr[:]
    return ovrs

def overlap(box, boxes):
    area = (box[2] - box[0]) * (box[3] - box[1])
    areas = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1])

    xx1 = np.maximum(box[0], boxes[:, 0])
    yy1 = np.maximum(box[1], boxes[:, 1])
    xx2 = np.minimum(box[2], boxes[:, 2])
    yy2 = np.minimum(box[3], boxes[:, 3])

    w = np.maximum(0.0, xx2 - xx1 + 1)
    h = np.maximum(0.0, yy2 - yy1 + 1)
    inter = w * h
    ovr = inter / (areas + areas - inter)

    return ovr


from calendar import HTMLCalendar
import calendar
from cgitb import small, text
from posixpath import split
from django.shortcuts import render,redirect
from django.http import HttpResponse
from .forms import Video_form
from .models import Video
from datetime import datetime

def upload_video(request):
    all_video=Video.objects.all()
    if request.method == "POST":
        form=Video_form(data=request.POST,files=request.FILES)
        if form.is_valid():
            video= form.cleaned_data['video']

            # price of video output in terminal

            filesize=video.size
            if filesize<4194304000:
                print("5$")
            else:
                print("12.5$")

            form.save()
            return HttpResponse("<h1> Uploaded successfully </h1>")
    else:
        form=Video_form()
    return render(request,'upload_video.html',{"form":form})

def videos(request):
    all_video=Video.objects.all()
    return render(request,'videos.html',{"all":all_video})

def videos_sort_by_date(request):
        video_list_by_time=''
        if request.method=="POST":
            fromdate=request.POST.get('fromdate')
            todate=request.POST.get('todate')
            biggestsize=request.POST.get('biggest size')
            video_list_by_time=Video.objects.filter(created_time__gte=fromdate,created_time__lte=todate)
        return render (request,'videos_search.html',{"all":video_list_by_time})


import csv
import encodings
import locale
import sys
from datetime import (date, datetime, time)
from enum import IntEnum, Enum
from typing import (Any, Callable, List, Iterator, Optional, Mapping, Tuple,
                    Iterable)

# values of cell_typing
from py4lo_commons import float_to_date, date_to_float, uno_path_to_url
from py4lo_helper import (provider as pr, make_pvs, parent_doc, get_cell_type,
                          get_used_range_address, Target,
                          FrameSearchFlag)
from py4lo_typing import (UnoCell, UnoSheet, UnoSpreadsheetDocument,
                          StrPath, UnoService)

try:
    # noinspection PyUnresolvedReferences
    from com.sun.star.lang import Locale

    class NumberFormat:
        # noinspection PyUnresolvedReferences
        from com.sun.star.util.NumberFormat import (DATE, TIME, DATETIME,
                                                    LOGICAL)
except (ModuleNotFoundError, ImportError):
    from mock_constants import (Locale, NumberFormat)

class CellTyping(Enum):
    String = 0
    Minimal = 1
    Accurate = 2

##########
# Reader #
##########

def create_read_cell(cell_typing: CellTyping = CellTyping.Minimal,
                     oFormats: Optional[UnoService] = None
                     ) -> Callable[[UnoCell], Any]:
    """
    Create a function to read a cell
    @param cell_typing: one of `CellTyping.String` (return the String value),
                      `CellTyping.Minimal` (String or Value),
                      `CellTyping.Accurate` (the most accurate type)
    @param oFormats: the container for NumberFormats.
    @return: a function to read the cell value
    """

    def read_cell_string(oCell: UnoCell) -> str:
        """
        Read a cell value
        @param oCell: the cell
        @return: the cell value as string
        """
        return oCell.String

    def read_cell_minimal(oCell: UnoCell) -> Any:
        """
        Read a cell value
        @param oCell: the cell
        @return: the cell value as float or str
        """
        cell_type = get_cell_type(oCell)

        if cell_type == 'EMPTY':
            return None
        elif cell_type == 'TEXT':
            return oCell.String
        elif cell_type == 'VALUE':
            return oCell.Value
        else:
            raise ValueError()

    def read_cell_accurate(oCell: UnoCell) -> Any:
        """
        Read a cell value
        @param oCell: the cell
        @return: the cell value as float, bool, date or str
        """
        cell_type = get_cell_type(oCell)

        if cell_type == 'EMPTY':
            return None
        elif cell_type == 'TEXT':
            return oCell.String
        elif cell_type == 'VALUE':
            key = oCell.NumberFormat
            cell_data_type = oFormats.getByKey(key).Type
            value = oCell.Value
            if cell_data_type in {NumberFormat.DATE, NumberFormat.DATETIME,
                                  NumberFormat.TIME}:
                return float_to_date(value)
            elif cell_data_type == NumberFormat.LOGICAL:
                return bool(value)
            else:
                return value
        else:
            raise ValueError()

    if cell_typing == CellTyping.String:
        return read_cell_string
    elif cell_typing == CellTyping.Minimal:
        return read_cell_minimal
    elif cell_typing == CellTyping.Accurate:
        if oFormats is None:
            raise ValueError("Need formats to type all values")
        return read_cell_accurate
    else:
        raise ValueError("cell_typing must be one of TYPE_* values")

class reader(Iterator[List[Any]]):
    """
    A reader that returns rows as lists of values.
    """

    def __init__(self, oSheet: UnoSheet,
                 cell_typing: CellTyping = CellTyping.Minimal,
                 oFormats: Optional[UnoService] = None,
                 read_cell: Optional[Callable[[UnoCell], Any]] = None):
        if read_cell is not None:
            self._read_cell = read_cell
        else:
            if cell_typing == CellTyping.Accurate and oFormats is None:
                oFormats = oSheet.DrawPage.Forms.Parent.NumberFormats
            self._read_cell = create_read_cell(cell_typing, oFormats)
        self._oSheet = oSheet
        self.line_num = 0
        self._oRangeAddress = get_used_range_address(oSheet)

    def __iter__(self) -> "reader":
        return self

    def __next__(self) -> List[Any]:
        i = self._oRangeAddress.StartRow + self.line_num
        if i > self._oRangeAddress.EndRow:
            raise StopIteration

        self.line_num += 1
        row = [self._read_cell(self._oSheet.getCellByPosition(j, i))
               for j in range(self._oRangeAddress.StartColumn,
                              self._oRangeAddress.EndColumn + 1)]

        # left strip the row
        i = len(row) - 1
        while row[i] is None and i > 0:
            i -= 1
        return row[:i + 1]

class dict_reader:
    """
    A reader that returns rows as dicts.
    """

    def __init__(self, oSheet: UnoSheet,
                 fieldnames: Optional[Tuple[str, ...]] = None,
                 restkey: Optional[str] = None,
                 restval: Optional[Any] = None,
                 cell_typing=CellTyping.Minimal, oFormats=None,
                 read_cell=None):
        self._reader = reader(oSheet, cell_typing, oFormats, read_cell)
        if fieldnames is None:
            self.fieldnames = next(self._reader)
        else:
            self.fieldnames = fieldnames
        self._width = len(self.fieldnames)
        self.restkey = restkey
        self.restval = restval

    def __iter__(self):
        return self

    def __next__(self):
        row = next(self._reader)
        row_width = len(row)
        if row_width == self._width:
            return dict(zip(self.fieldnames, row))
        elif row_width < self._width:
            row += [self.restval] * (self._width - row_width)
            return dict(zip(self.fieldnames, row))
        elif self.restkey is None:
            return dict(zip(self.fieldnames, row))
        else:
            d = dict(zip(self.fieldnames, row))
            d[self.restkey] = row[self._width:]
            return d

    @property
    def line_num(self):
        return self._reader.line_num

##########
# Writer #
##########
def find_number_format_style(oFormats: UnoService, format_id: NumberFormat,
                             oLocale: Locale = Locale()) -> int:
    """
    @param oFormats: the formats
    @param format_id: a NumberFormat
    @param oLocale: the locale
    @return: the id of the format
    """
    return oFormats.getStandardFormat(format_id, oLocale)

def create_write_cell(cell_typing: CellTyping = CellTyping.Minimal,
                      oFormats: Optional[UnoService] = None
                      ) -> Callable[[UnoCell, Any], None]:
    """
    Create a cell writer
    @param cell_typing: see `create_read_cell`
    @param oFormats: the NumberFormats
    @return: a function
    """

    def write_cell_string(oCell: UnoCell, value: Any):
        """
        Write a cell value
        @param oCell: the cell
        @param value: the value
        """
        oCell.String = str(value)

    def write_cell_minimal(oCell: UnoCell, value: Any):
        """
        Write a cell value
        @param oCell: the cell
        @param value: the value
        """
        if value is None:
            oCell.String = ""
        elif isinstance(value, str):
            oCell.String = value
        elif isinstance(value, (date, datetime, time)):
            oCell.Value = date_to_float(value)
        elif isinstance(value, bool):
            oCell.Value = int(value)
        else:
            oCell.Value = value

    def create_write_cell_all(oFormats: UnoService
                              ) -> Callable[[UnoCell, Any], None]:
        # todo: Add locale parameter
        date_id = find_number_format_style(oFormats, NumberFormat.DATE)
        datetime_id = find_number_format_style(oFormats, NumberFormat.DATETIME)
        boolean_id = find_number_format_style(oFormats, NumberFormat.LOGICAL)

        def write_cell_all(oCell: UnoCell, value: Any):
            """
            Write a cell value
            @param oCell: the cell
            @param value: the value
            @return: the cell value as float or text
            """
            if value is None:
                oCell.String = ""
            elif isinstance(value, str):
                oCell.String = value
            elif isinstance(value, (datetime, time)):
                oCell.Value = date_to_float(value)
                oCell.NumberFormat = datetime_id
            elif isinstance(value, date):
                oCell.Value = date_to_float(value)
                oCell.NumberFormat = date_id
            elif isinstance(value, bool):
                oCell.Value = int(value)
                oCell.NumberFormat = boolean_id
            else:
                oCell.Value = value

        return write_cell_all

    if cell_typing == CellTyping.String:
        return write_cell_string
    elif cell_typing == CellTyping.Minimal:
        return write_cell_minimal
    elif cell_typing == CellTyping.Accurate:
        if oFormats is None:
            raise ValueError("Need formats to type all values")
        return create_write_cell_all(oFormats)
    else:
        raise ValueError("cell_typing must be one of TYPE_* values")

class writer:
    """
    A writer that takes lists
    """

    def __init__(self, oSheet: UnoSheet,
                 cell_typing: CellTyping = CellTyping.Minimal,
                 oFormats: Optional[UnoService] = None,
                 write_cell: Optional[Callable[[UnoCell, Any], None]] = None,
                 initial_pos: Tuple[int, int] = (0, 0)):
        self._oSheet = oSheet
        self._row, self._base_col = initial_pos
        if write_cell is not None:
            self._write_cell = write_cell
        else:
            if cell_typing == CellTyping.Accurate and oFormats is None:
                oFormats = oSheet.DrawPage.Forms.Parent.NumberFormats
            self._write_cell = create_write_cell(cell_typing, oFormats)

    def writerow(self, row):
        for i, value in enumerate(row, self._base_col):
            oCell = self._oSheet.getCellByPosition(i, self._row)
            self._write_cell(oCell, value)
        self._row += 1

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)

class dict_writer:
    """
    A writer that takes dicts
    """

    def __init__(self, oSheet: UnoSheet, fieldnames: List[str],
                 restval: str = '', extrasaction: str = 'raise',
                 cell_typing: CellTyping = CellTyping.Minimal,
                 oFormats: Optional[UnoService] = None,
                 write_cell: Optional[Callable[[UnoCell, Any], None]] = None):
        self.writer = writer(oSheet, cell_typing, oFormats, write_cell)
        self.fieldnames = fieldnames
        self._set_fieldnames = set(fieldnames)
        self.restval = restval
        self.extrasaction = extrasaction

    def writeheader(self):
        self.writer.writerow(self.fieldnames)

    def writerow(self, row: Mapping[str, Any]):
        if self.extrasaction == 'raise' and set(row) - self._set_fieldnames:
            raise ValueError()
        flat_row = [row.get(name, self.restval) for name in self.fieldnames]
        self.writer.writerow(flat_row)

    def writerows(self, rows: Iterable[Mapping[str, Any]]):
        for row in rows:
            self.writerow(row)

#####################
# Import/Export CSV #
#####################
###
# Filters
###
class Filter(str, Enum):
    XML = "StarOffice XML (Calc)"  # Standard XML filter
    # XML filter for templates
    XML_TEMPLATE = "calc_StarOffice_XML_Calc_Template"
    STARCALC_5 = "StarCalc 5.0"  # The binary format of StarOffice Calc 5.x
    # StarOffice Calc 5.x templates
    STARCALC_5_TEMPLATE = "StarCalc 5.0 Vorlage/Template"
    STARCALC_4 = "StarCalc 4.0"  # The binary format of StarCalc 4.x
    # StarCalc 4.x templates
    STARCALC_4_TEMPLATE = "StarCalc 4.0 Vorlage/Template"
    STARCALC_3 = "StarCalc 3.0"  # The binary format of StarCalc 3.x
    # StarCalc 3.x templates
    STARCALC_3_TEMPLATE = "StarCalc 3.0 Vorlage/Template"
    HTML = "HTML (StarCalc)"  # HTML filter
    # HTML filter for external data queries
    HTML_WEBQUERY = "calc_HTML_WebQuery"
    EXCEL_97 = "MS Excel 97"  # Microsoft Excel 97/2000/XP
    # Microsoft Excel 97/2000/XP templates
    EXCEL_97_TEMPLATE = "MS Excel 97 Vorlage/Template"
    EXCEL_95 = "MS Excel 95"  # Microsoft Excel 5.0/95
    # Microsoft Excel 5.0/95 templates
    EXCEL_95_TEMPLATE = "MS Excel 95 Vorlage/Template"
    EXCEL_2_3_4 = "MS Excel 4.0"  # Microsoft Excel 2.1/3.0/4.0
    # Microsoft Excel 2.1/3.0/4.0 templates
    EXCEL_2_3_4_TEMPLATE = "MS Excel 4.0 Vorlage/Template"
    LOTUS = "Lotus"  # Lotus 1-2-3
    CSV = "Text - txt - csv (StarCalc)"  # Comma separated values
    RTF = "Rich Text Format (StarCalc)"  #
    DBASE = "dBase"  # dBase
    SYLK = "SYLK"  # Symbolic Link
    DIF = "DIF"  # Data Interchange Format

# see https://api.libreoffice.org/docs/cpp/ref/a00391_source.html
# (rtl/textenc.h)
CHARSET_ID_BY_NAME = {
    'unknown': 0,
    'cp1252': 1,
    'mac_roman': 2,
    'cp437': 3,
    'cp850': 4,
    'cp860': 5,
    'cp861': 6,
    'cp863': 7,
    'cp865': 8,
    sys.getdefaultencoding(): 9,
    'symbol': 10,
    'ascii': 11,
    'iso8859_1': 12,
    'iso8859_2': 13,
    'iso8859_3': 14,
    'iso8859_4': 15,
    'iso8859_5': 16,
    'iso8859_6': 17,
    'iso8859_7': 18,
    'iso8859_8': 19,
    'iso8859_9': 20,
    'iso8859_14': 21,
    'iso8859_15': 22,
    'cp737': 23,
    'cp775': 24,
    'cp852': 25,
    'cp855': 26,
    'cp857': 27,
    'cp862': 28,
    'cp864': 29,
    'cp866': 30,
    'cp869': 31,
    'cp874': 32,
    'cp1250': 33,
    'cp1251': 34,
    'cp1253': 35,
    'cp1254': 36,
    'cp1255': 37,
    'cp1256': 38,
    'cp1257': 39,
    'cp1258': 40,
    'mac_arabic': 41,
    'mac_centeuro': 42,
    'mac_croatian': 43,
    'mac_cyrillic': 44,
    'mac_devanagari': 45,
    'mac_farsi': 46,
    'mac_greek': 47,
    'mac_gujarati': 48,
    'mac_gurmukhi': 49,
    'mac_hebrew': 50,
    'mac_iceland': 51,
    'mac_romanian': 52,
    'mac_thai': 53,
    'mac_turkish': 54,
    'mac_ukrainian': 55,
    'mac_chinsimp': 56,
    'mac_chintrad': 57,
    'mac_japanese': 58,
    'mac_korean': 59,
    'cp932': 60,
    'cp936': 61,
    'cp949': 62,
    'cp950': 63,
    'shift_jis': 64,
    'gb2312': 65,
    'gbt12345': 66,
    'gbk': 67,
    'big5': 68,
    'euc_jp': 69,
    'euc_cn': 70,
    'euc_tw': 71,
    'iso2022_jp': 72,
    'iso2022_cn': 73,
    'koi8_r': 74,
    'utf_7': 75,
    'utf_8': 76,
    'iso8859_10': 77,
    'iso8859_13': 78,
    'euc_kr': 79,
    'iso2022_kr': 80,
    'jis_x_0201': 81,
    'jis_x_0208': 82,
    'jis_x_0212': 83,
    'cp1361': 84,
    'gb18030': 85,
    'big5hkscs': 86,
    'tis_620': 87,
    'koi8_u': 88,
    'iscii_devanagari': 89,
    'java_utf8': 90,
    'adobe_standard': 91,
    'adobe_symbol': 92,
    'ptcp154': 93,
    'adobe_dingbats': 94,
    'user_start': 32768,
    'user_end': 61439,
    'utf_32': 65534,
    'utf_16': 65535,
}

FORMAT_STANDARD = 1
FORMAT_TEXT = 2
FORMAT_MM_DD_YY = 3
FORMAT_DD_MM_YY = 4
FORMAT_YY_MM_DD = 5
FORMAT_IGNORE = 9
FORMAT_US_ENGLISH = 10

# see https://docs.microsoft.com/en-us/openspecs/office_standards
# /ms-oe376/6c085406-a698-4e12-9d4d-c3b0ee3dbc4a
LANGUAGE_ID_BY_CODE = {
    "ar_SA": 1025,
    "bg_BG": 1026,
    "ca_ES": 1027,
    "zh_TW": 1028,
    "cs_CZ": 1029,
    "da_DK": 1030,
    "de_DE": 1031,
    "el_GR": 1032,
    "en_US": 1033,
    "es_ES": 1034,
    "fi_FI": 1035,
    "fr_FR": 1036,
    "he_IL": 1037,
    "hu_HU": 1038,
    "is_IS": 1039,
    "it_IT": 1040,
    "ja_JP": 1041,
    "ko_KR": 1042,
    "nl_NL": 1043,
    "nb_NO": 1044,
    "pl_PL": 1045,
    "pt_BR": 1046,
    "rm_CH": 1047,
    "ro_RO": 1048,
    "ru_RU": 1049,
    "hr_HR": 1050,
    "sk_SK": 1051,
    "sq_AL": 1052,
    "sv_SE": 1053,
    "th_TH": 1054,
    "tr_TR": 1055,
    "ur_PK": 1056,
    "id_ID": 1057,
    "uk_UA": 1058,
    "be_BY": 1059,
    "sl_SI": 1060,
    "et_EE": 1061,
    "lv_LV": 1062,
    "lt_LT": 1063,
    "tg_Cyrl_TJ": 1064,
    "fa_IR": 1065,
    "vi_VN": 1066,
    "hy_AM": 1067,
    "az_Latn_AZ": 1068,
    "eu_ES": 1069,
    "wen_DE": 1070,
    "mk_MK": 1071,
    "st_ZA": 1072,
    "ts_ZA": 1073,
    "tn_ZA": 1074,
    "ven_ZA": 1075,
    "xh_ZA": 1076,
    "zu_ZA": 1077,
    "af_ZA": 1078,
    "ka_GE": 1079,
    "fo_FO": 1080,
    "hi_IN": 1081,
    "mt_MT": 1082,
    "se_NO": 1083,
    "gd_GB": 1084,
    "yi": 1085,
    "ms_MY": 1086,
    "kk_KZ": 1087,
    "ky_KG": 1088,
    "sw_KE": 1089,
    "tk_TM": 1090,
    "uz_Latn_UZ": 1091,
    "tt_RU": 1092,
    "bn_IN": 1093,
    "pa_IN": 1094,
    "gu_IN": 1095,
    "or_IN": 1096,
    "ta_IN": 1097,
    "te_IN": 1098,
    "kn_IN": 1099,
    "ml_IN": 1100,
    "as_IN": 1101,
    "mr_IN": 1102,
    "sa_IN": 1103,
    "mn_MN": 1104,
    "bo_CN": 1105,
    "cy_GB": 1106,
    "km_KH": 1107,
    "lo_LA": 1108,
    "my_MM": 1109,
    "gl_ES": 1110,
    "kok_IN": 1111,
    "mni": 1112,
    "sd_IN": 1113,
    "syr_SY": 1114,
    "si_LK": 1115,
    "chr_US": 1116,
    "iu_Cans_CA": 1117,
    "am_ET": 1118,
    "tmz": 1119,
    "ks_Arab_IN": 1120,
    "ne_NP": 1121,
    "fy_NL": 1122,
    "ps_AF": 1123,
    "fil_PH": 1124,
    "dv_MV": 1125,
    "bin_NG": 1126,
    "fuv_NG": 1127,
    "ha_Latn_NG": 1128,
    "ibb_NG": 1129,
    "yo_NG": 1130,
    "quz_BO": 1131,
    "nso_ZA": 1132,
    "ig_NG": 1136,
    "kr_NG": 1137,
    "gaz_ET": 1138,
    "ti_ER": 1139,
    "gn_PY": 1140,
    "haw_US": 1141,
    "la": 1142,
    "so_SO": 1143,
    "ii_CN": 1144,
    "pap_AN": 1145,
    "ug_Arab_CN": 1152,
    "mi_NZ": 1153,
    "ar_IQ": 2049,
    "zh_CN": 2052,
    "de_CH": 2055,
    "en_GB": 2057,
    "es_MX": 2058,
    "fr_BE": 2060,
    "it_CH": 2064,
    "nl_BE": 2067,
    "nn_NO": 2068,
    "pt_PT": 2070,
    "ro_MD": 2072,
    "ru_MD": 2073,
    "sr_Latn_CS": 2074,
    "sv_FI": 2077,
    "ur_IN": 2080,
    "az_Cyrl_AZ": 2092,
    "ga_IE": 2108,
    "ms_BN": 2110,
    "uz_Cyrl_UZ": 2115,
    "bn_BD": 2117,
    "pa_PK": 2118,
    "mn_Mong_CN": 2128,
    "bo_BT": 2129,
    "sd_PK": 2137,
    "tzm_Latn_DZ": 2143,
    "ks_Deva_IN": 2144,
    "ne_IN": 2145,
    "quz_EC": 2155,
    "ti_ET": 2163,
    "ar_EG": 3073,
    "zh_HK": 3076,
    "de_AT": 3079,
    "en_AU": 3081,
    "fr_CA": 3084,
    "sr_Cyrl_CS": 3098,
    "quz_PE": 3179,
    "ar_LY": 4097,
    "zh_SG": 4100,
    "de_LU": 4103,
    "en_CA": 4105,
    "es_GT": 4106,
    "fr_CH": 4108,
    "hr_BA": 4122,
    "ar_DZ": 5121,
    "zh_MO": 5124,
    "de_LI": 5127,
    "en_NZ": 5129,
    "es_CR": 5130,
    "fr_LU": 5132,
    "bs_Latn_BA": 5146,
    "ar_MO": 6145,
    "en_IE": 6153,
    "es_PA": 6154,
    "fr_MC": 6156,
    "ar_TN": 7169,
    "en_ZA": 7177,
    "es_DO": 7178,
    "fr_029": 7180,
    "ar_OM": 8193,
    "en_JM": 8201,
    "es_VE": 8202,
    "fr_RE": 8204,
    "ar_YE": 9217,
    "en_029": 9225,
    "es_CO": 9226,
    "fr_CG": 9228,
    "ar_SY": 10241,
    "en_BZ": 10249,
    "es_PE": 10250,
    "fr_SN": 10252,
    "ar_JO": 11265,
    "en_TT": 11273,
    "es_AR": 11274,
    "fr_CM": 11276,
    "ar_LB": 12289,
    "en_ZW": 12297,
    "es_EC": 12298,
    "fr_CI": 12300,
    "ar_KW": 13313,
    "en_PH": 13321,
    "es_CL": 13322,
    "fr_ML": 13324,
    "ar_AE": 14337,
    "en_ID": 14345,
    "es_UY": 14346,
    "fr_MA": 14348,
    "ar_BH": 15361,
    "en_HK": 15369,
    "es_PY": 15370,
    "fr_HT": 15372,
    "ar_QA": 16385,
    "en_IN": 16393,
    "es_BO": 16394,
    "en_MY": 17417,
    "es_SV": 17418,
    "en_SG": 18441,
    "es_HN": 18442,
    "es_NI": 19466,
    "es_PR": 20490,
    "es_US": 21514,
    "es_419": 58378,
    "fr_015": 58380
}

class Format(IntEnum):
    STANDARD = 1  # Standard
    TEXT = 2  # Text
    MM_DD_YY = 3  # MM/DD/YY
    DD_MM_YY = 4  # DD/MM/YY
    YY_MM_DD = 5  # YY/MM/DD
    IGNORE = 9  # IGNORE FIELD (do not import)
    US = 10  # US-English

def import_from_csv(oDoc: UnoSpreadsheetDocument, sheet_name: str, dest_position: int,
                    path: StrPath, *args, **kwargs):
    """
    @param sheet_name: the sheet name
    @param dest_position: position
    @param path: path to the file
    @param dialect: the Python csv dialect
    @param encoding: the source file encoding
    @param first_line: the first line
    @param format_by_idx: a mappin col -> type (type is FORMAT_MM_DD_YY)
    @param language_code: en_US
    @param detect_special_numbers: if true, detect numbers
    @return: the sheet
    """
    filter_options = create_import_filter_options(*args, **kwargs)
    pvs = make_pvs({"FilterName": Filter.CSV, "FilterOptions": filter_options,
                    "Hidden": True})

    oDoc.lockControllers()
    url = uno_path_to_url(path)
    oSource = pr.desktop.loadComponentFromURL(url, Target.BLANK,
                                              FrameSearchFlag.AUTO, pvs)
    oSource.Sheets.getByIndex(0).Name = sheet_name
    name = oSource.Sheets.ElementNames[0]
    oDoc.Sheets.importSheet(oSource, name, dest_position)
    oSource.close(True)
    oDoc.unlockControllers()

def create_import_filter_options(*args, **kwargs) -> str:
    if len(args) == 1:
        dialect = args[0]
        delimiter = kwargs.pop("delimiter", dialect.delimiter)
        quotechar = kwargs.pop("quotechar", dialect.quotechar)
        quoted_field_as_text = kwargs.pop("quoted_field_as_text",
                                          dialect.quoting == csv.QUOTE_ALL)
        return _create_import_filter_options(
            delimiter=delimiter, quotechar=quotechar,
            quoted_field_as_text=quoted_field_as_text,
            **kwargs
        )
    elif len(args) == 0:
        return _create_import_filter_options(**kwargs)
    else:
        raise ValueError("At most one positional parameters allowed")

def _create_import_filter_options(
        delimiter: str = ",", quotechar: str = '"',
        quoted_field_as_text: bool = False,
        encoding: str = "utf-8", language_code=locale.getlocale()[0],
        first_line: int = 1,
        format_by_idx: Optional[Mapping[int, Format]] = None,
        detect_special_numbers: bool = False) -> str:
    """
    # See https://wiki.openoffice.org/wiki/Documentation
    /DevGuide/Spreadsheets/Filter_Options
    @param delimiter: the delimiter
    @param quotechar: the quotechar
    @param quoted_field_as_text: see checkbox
    @param encoding: the source file encoding
    @param language_code: en_US
    @param first_line: the first line
    @param format_by_idx: a mappin col -> type (type is FORMAT_MM_DD_YY)
    @param detect_special_numbers: if true, detect numbers
    @return: a filter options string
    """
    quoting = "true" if quoted_field_as_text else "false"
    detect = "true" if detect_special_numbers else "false"
    tokens = _base_filter_tokens(
        delimiter, quotechar, encoding, language_code, first_line,
        format_by_idx
    ) + [quoting, detect]
    return ",".join(tokens)

def export_to_csv(oSheet: UnoSheet, path: StrPath, *args, **kwargs):
    """
    save a sheet to a csv file

    @param oSheet:
    @param path:
    @param dialect: the Python csv dialect
    @param encoding: the source file encoding
    @param first_line: the first line
    @param language_code: en_US
    @param overwrite:
    @return: tokens
    """
    overwrite = kwargs.pop("overwrite", True)
    filter_options = create_export_filter_options(*args, **kwargs)
    pvs = make_pvs({"FilterName": Filter.CSV, "FilterOptions": filter_options,
                    "Overwrite": overwrite})
    oDoc = parent_doc(oSheet)
    oActive = oDoc.CurrentController.ActiveSheet
    oDoc.lockControllers()
    oDoc.CurrentController.ActiveSheet = oSheet
    url = uno_path_to_url(path)
    oDoc.storeToURL(url, pvs)
    oDoc.CurrentController.ActiveSheet = oActive
    oDoc.unlockControllers()

def _get_charset_id(encoding: str) -> int:
    norm_encoding = encodings.normalize_encoding(encoding)
    norm_encoding = encodings.aliases.aliases.get(
        norm_encoding.lower(), norm_encoding)
    return CHARSET_ID_BY_NAME.get(norm_encoding, 0)

def _build_field_formats(format_by_idx: Optional[Mapping[int, int]]) -> str:
    if format_by_idx is None:
        field_formats = ""
    else:
        field_formats = "/".join(["{}/{}".format(idx, fmt)
                                  for idx, fmt in format_by_idx.items()])
    return field_formats

def _base_filter_tokens(
        delimiter: str, quotechar: str, encoding: str, language_code: str,
        first_line: int, format_by_idx: Optional[Mapping[int, int]]
) -> List[str]:
    """
    See: https://wiki.openoffice.org/wiki/Documentation
    /DevGuide/Spreadsheets/Filter_Options
    Common to import/export

    @param delimiter: the delimiter
    @param quotechar: the quotechar
    @param encoding: the encoding
    @param first_line: the first line
    @param format_by_idx: a mapping field index (starting at 1) -> field format
    @return: a list of options
    """
    encoding_index = _get_charset_id(encoding)
    language_id = LANGUAGE_ID_BY_CODE.get(language_code, 0)
    field_formats = _build_field_formats(format_by_idx)
    return [str(ord(delimiter)), str(ord(quotechar)), str(encoding_index),
            str(first_line), field_formats, str(language_id)]

def create_export_filter_options(*args, **kwargs) -> str:
    """
    See https://wiki.openoffice.org/wiki/Documentation
    /DevGuide/Spreadsheets/Filter_Options

    @param dialect: the Python csv dialect
    @param encoding: the source file encoding
    @param first_line: the first line
    @param language_code: en_US
    @return: tokens
    """
    if len(args) == 1:
        dialect = args[0]
        delimiter = kwargs.pop("delimiter", dialect.delimiter)
        quotechar = kwargs.pop("quotechar", dialect.quotechar)
        quote_all_text_cells = kwargs.pop("store_numeric_cells_as_text",
                                          dialect.quoting == csv.QUOTE_ALL)
        return _create_export_filter_options(
            delimiter=delimiter, quotechar=quotechar,
            store_numeric_cells_as_text=quote_all_text_cells,
            **kwargs
        )
    elif len(args) == 0:
        return _create_export_filter_options(**kwargs)
    else:
        raise ValueError("At most one positional parameters allowed")

def _create_export_filter_options(
        delimiter: str = ",", quotechar: str = '"',
        store_numeric_cells_as_text: bool = False,
        encoding: str = "utf-8", language_code=locale.getlocale()[0],
        first_line: int = 1,
        format_by_idx: Optional[Mapping[int, Format]] = None,
        save_cell_contents_as_shown: bool = True) -> str:
    store_as_text = "true" if store_numeric_cells_as_text else "false"
    save_as_shown = "true" if save_cell_contents_as_shown else "false"
    tokens = _base_filter_tokens(
        delimiter, quotechar, encoding, language_code, first_line,
        format_by_idx
    ) + [store_as_text, store_as_text, save_as_shown]
    return ",".join(tokens)


from AdventClasses import IntComputer

f = open("advent_05_input.txt", "r")
puzzle_data = f.read()

# Initiate an Int computer
intcomputer = IntComputer()

# Set input manually to a specific number (given in assigment)
intcomputer.set_input(5)

# Parse the puzzle input in the RAM of the int computer
intcomputer.parse_instruction(puzzle_data)

intcomputer.execute_programm()


from unittest import mock

from absl.testing import absltest
from intrinsic.world.proto import object_world_service_pb2
from intrinsic.world.python import object_world_client
from intrinsic.world.python import object_world_ids

class ObjectWorldClientTest(absltest.TestCase):

  def setUp(self):
    super().setUp()
    self._stub = mock.MagicMock()

  def _create_object_proto(
      self, *, name: str = '', object_id: str = '', world_id: str = ''
  ) -> object_world_service_pb2.Object:
    return object_world_service_pb2.Object(
        world_id=world_id,
        name=name,
        name_is_global_alias=True,
        id=object_id,
        object_component=object_world_service_pb2.ObjectComponent(),
    )

  def test_get_object(self):
    self._stub.GetObject.return_value = self._create_object_proto(
        name='my_object', object_id='15', world_id='world'
    )
    world_client = object_world_client.ObjectWorldClient('world', self._stub)

    self.assertEqual(
        world_client.get_object(
            object_world_ids.WorldObjectName('my_object')
        ).name,
        'my_object',
    )
    self.assertEqual(
        world_client.get_object(
            object_world_ids.WorldObjectName('my_object')
        ).id,
        '15',
    )

  def test_object_attribute(self):
    my_object = self._create_object_proto(
        name='my_object', object_id='15', world_id='world'
    )
    self._stub.GetObject.return_value = my_object
    self._stub.ListObjects.return_value = (
        object_world_service_pb2.ListObjectsResponse(objects=[my_object])
    )
    world_client = object_world_client.ObjectWorldClient('world', self._stub)

    self.assertEqual(world_client.my_object.name, 'my_object')
    self.assertEqual(world_client.my_object.id, '15')

if __name__ == '__main__':
  absltest.main()


# Functions to normalize the data
# Function to shuffle the data
# Function to augment the data
# Function for learning rate finder

import numpy as np

from sklearn.preprocessing import OneHotEncoder

def normalize_data(values):
    # normalize based on zero mean/unit variance
    return (values / 255)

def shuffle_data(values, labels):

    values = np.array(values)
    labels = np.array(labels)

    s = np.arange(values.shape[0])
    np.random.shuffle(s)

    values = values[s]
    labels = labels[s]

    return values, labels

def one_hot_encode(labels):
    labels = np.array(labels)
    labels = labels.reshape(len(labels), 1)
    label_enocder = OneHotEncoder()
    label_enocder.fit(labels)
    labels_np = label_enocder.transform(labels).toarray()
    return labels_np


from django.db import models
from django.contrib.auth import get_user_model
from synthomniaapi.models.mood import Mood
User = get_user_model()

class Artist(models.Model):
    """
    models for Artist
    """
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE
        )
    bio = models.CharField(
        max_length=500,
        # on_delete=models.CASCADE
    )
    mood = models.ManyToManyField(
        Mood,
        related_name="mood"
    )


black = (0,0,0)
green = (10,249, 50)
red = (255,0,0)

blue_green = (0,255,247)
blue = (34,0,255)
violet = (222,0,255)

size = 40
background_color = (110,110,5)

class Apple:
    def __init__(self, parent_screen):
        self.parent_screen = parent_screen
        self.apple_x = random.randint(1,32) * size
        self.apple_y = random.randint(1,16) * size
        self.apple = pygame.image.load("D:/snakegame_materials/apples.jpg").convert()

    def move(self):
        self.apple_x = random.randint(1, 32) * size
        self.apple_y = random.randint(1, 16) * size
        pygame.display.flip()

    def draw(self):
        self.parent_screen.blit(self.apple, (self.apple_x, self.apple_y))
        pygame.display.flip()

class Snake:
    def __init__(self, parent_screen, length, length1):
        self.parent_screen = parent_screen
        self.direction = 'down'
        self.snake = pygame.image.load("D:/snakegame_materials/blocks.jpg").convert()

        self.length = length
        self.block_x = [600] * length
        self.block_y = [size] * length

        self.snake1 = pygame.image.load("D:/snakegame_materials/blocks1.png").convert()
        self.direction1 = 'up'

        self.length1 = length1
        self.block_x1 = [600] * length1 #
        self.block_y1 = [600] * length1

        self.x = len(self.block_x)
        self.x1 = len(self.block_x1)

    def increase_length(self):
        self.length += 1
        self.block_x.append(-1)
        self.block_y.append(-1)
    def increase_length1(self):
        self.length1 += 1
        self.block_x1.append(-1)
        self.block_y1.append(-1)

    def draw(self):
        for i in range(self.length1):
            self.parent_screen.blit(self.snake, (self.block_x1[i], self.block_y1[i]))
        for j in range(self.length):
            self.parent_screen.blit(self.snake1, (self.block_x[j], self.block_y[j]))
        pygame.display.flip()

    def move_down(self):
        self.direction = "down"

    def move_up(self):
        self.direction = "up"

    def move_left(self):
        self.direction = "left"

    def move_right(self):
        self.direction = "right"

    def move_down1(self):
        self.direction1 = "down"

    def move_up1(self):
        self.direction1 = "up"

    def move_left1(self):
        self.direction1 = "left"

    def move_right1(self):
        self.direction1 = "right"

    def walk(self):
        for i in range(self.length - 1, 0, -1):
            self.block_x[i] = self.block_x[i - 1]
            self.block_y[i] = self.block_y[i - 1]
        if self.direction == "down":
            self.block_y[0] += size
        if self.direction == "up":
            self.block_y[0] -= size
        if self.direction == "right":
            self.block_x[0] += size
        if self.direction == "left":
            self.block_x[0] -= size
        self.draw()

        for j in range(self.length1 - 1, 0, -1):
            self.block_x1[j] = self.block_x1[j - 1]
            self.block_y1[j] = self.block_y1[j - 1]
        if self.direction1 == "down":
            self.block_y1[0] += size
        if self.direction1 == "up":
            self.block_y1[0] -= size
        if self.direction1 == "right":
            self.block_x1[0] += size
        if self.direction1 == "left":
            self.block_x1[0] -= size
        self.draw()

class Game:
    def __init__(self):

        pygame.init()
        pygame.mixer.init()
        self.play_background_music()
        self.surface = pygame.display.set_mode((1320,680))
        self.surface.fill((110,110,5))
        self.snake = Snake(self.surface, length=2, length1=1)
        self.snake.draw()
        self.apple = Apple(self.surface)
        self.apple.draw()

    def is_collision(self, x1, y1, x2, y2):
        if x1 >= x2 and x1 < x2 + size:
            if y1 >= y2 and y1 < y2 + size:
                return True
            return False

    def hit_boudary(self):
        if not (0 <= self.snake.block_x[0] <= 1319 and 0 <= self.snake.block_y[0] <= 650):
            sound = pygame.mixer.Sound("D:/snakegame_materials/crash.mp3")
            pygame.mixer.Sound.play(sound)
            raise "Hit the boundry error"
        if not (0 <= self.snake.block_x1[0] <= 1319 and 0 <= self.snake.block_y1[0] <= 650):
            sound = pygame.mixer.Sound("D:/snakegame_materials/crash.mp3")
            pygame.mixer.Sound.play(sound)
            raise "Hit the boundry error"

    def colliding_with_apple(self):
        if self.is_collision(self.snake.block_x[0], self.snake.block_y[0], self.apple.apple_x, self.apple.apple_y):
            sound = pygame.mixer.Sound("D:/snakegame_materials/ding.mp3")
            pygame.mixer.Sound.play(sound)
            self.snake.increase_length()
            self.apple.move()
        if self.is_collision(self.snake.block_x1[0], self.snake.block_y1[0], self.apple.apple_x, self.apple.apple_y):
            sound = pygame.mixer.Sound("D:/snakegame_materials/ding.mp3")
            pygame.mixer.Sound.play(sound)
            self.snake.increase_length1()
            self.apple.move()

    def colliding_with_itself(self):
        for i in range(1, self.snake.length):
            if self.is_collision(self.snake.block_x[0], self.snake.block_y[0], self.snake.block_x[i], self.snake.block_y[i]):
                sound1 = pygame.mixer.Sound("D:/snakegame_materials/crash.mp3")
                pygame.mixer.Sound.play(sound1)
                raise "Game over"
        for j in range(1, self.snake.length1):
            if self.is_collision(self.snake.block_x1[0], self.snake.block_y1[0], self.snake.block_x1[j], self.snake.block_y1[j]):
                sound1 = pygame.mixer.Sound("D:/snakegame_materials/crash.mp3")
                pygame.mixer.Sound.play(sound1)
                raise "Game over"

    def play_background_music(self):
        pygame.mixer.music.load("D:/snakegame_materials/pou1.mp3")
        pygame.mixer.music.play()

    def render_background(self):
        self.bg = pygame.image.load("D:/snakegame_materials/background.jpg")
        self.surface.blit(self.bg, (0,0))
        self.level()
        pygame.display.flip()

    def level(self):
        if self.snake.length >= 6 and self.snake.length <= 10:
            self.surface.fill(blue)
        if self.snake.length1 >= 5 and self.snake.length1 <= 10:
            self.surface.fill(blue_green)

        if self.snake.length > 10 and self.snake.length <= 20:
            self.surface.fill(red)
        if self.snake.length1 > 10 and self.snake.length1 <= 20:
            self.surface.fill(violet)

        if self.snake.length > 20 and self.snake.length <= 30:
            self.surface.fill(green)
        if self.snake.length1 > 20 and self.snake.length1 <= 30:
            self.surface.fill(black)

        if self.snake.length > 30 and self.snake.length <= 40:
            self.surface.fill((102,102,255))#light blue
        if self.snake.length1 > 30 and self.snake.length1 <= 40:
            self.surface.fill((153,255,153)) #light green

        if self.snake.length > 40 and self.snake.length <= 50:
            self.surface.fill((255, 128, 0))#orange
        if self.snake.length1 > 40 and self.snake.length1 <= 50:
            self.surface.fill((160,160,160)) #gray

    def collide_with_other_snake(self):
        if self.is_collision(self.snake.block_x[0], self.snake.block_y[0], self.snake.block_x1[0], self.snake.block_y1[0]):
            sound = pygame.mixer.Sound("D:/snakegame_materials/crash.mp3")
            pygame.mixer.Sound.play(sound)
            raise "collide with other snake"

    def play(self):
        self.render_background()
        self.level()
        self.snake.walk()
        self.apple.draw()
        self.display_score()
        self.colliding_with_apple()
        pygame.display.flip()

        # self.collide_all_snake()
        self.colliding_with_itself()
        self.hit_boudary()
        pygame.display.flip()
        self.collide_with_other_snake()

    def display_score(self):
        font = pygame.font.SysFont("Arial", 20)
        self.score = font.render(f"Yellow Snake {self.snake.length1}", True, (255,255,255))
        self.surface.blit(self.score, (170, 10))
        self.score1 = font.render(f"Blue Snake {self.snake.length - 1}", True, (255,255,255))
        self.surface.blit(self.score1, (1000, 10))

    def show_game_over(self):
        self.surface.fill(background_color)
        font = pygame.font.SysFont("Arial", 30)
        line1 = font.render(f"Score: Yellow Snake {self.snake.length - 1}", True, (255,255,0))
        self.surface.blit(line1, (510,200))
        line2 = font.render("To play again hit enter, to exit pres Escape", True, (255,255,255))
        self.surface.blit(line2, (400,400))

        font1 = pygame.font.SysFont("Arial", 50)
        line21 = font1.render("Game over", True, (255,0,0))
        self.surface.blit(line21, (520,300))
        line3 = font.render(f"Score: Blue Snake {self.snake.length1}", True, (0,0,255))
        self.surface.blit(line3, (510,250))
        pygame.display.flip()
        pygame.mixer.music.pause()

    def text_pause(self):
        font = pygame.font.SysFont("Arial", 50)
        line = font.render("Game paused, Press Enter to resume, press ESC to exit", True, (0,0,0))
        self.surface.blit(line, (120,300))
        pygame.display.flip()

    def reset(self):
        self.snake = Snake(self.surface, length=2, length1=1)
        self.apple = Apple(self.surface)

    def Time(self):
        self.t = time.sleep(0.1)

    def run(self):
        self.running = False
        self.pause = False
        howtoloop = True

        font2 = pygame.font.SysFont('Agency fb', 30)
        font7 = pygame.font.SysFont('Arial', 35)

        howto_1 = "How to Play:"
        howto_2 = "Player 1 = W,A,S,D controls the Yellow Snake."
        howto_3 = "player 2 = Arrow keys control the Blue Snake."
        howto_4 = "key space to pause the game"
        howto_5 = "key enter to resume"
        howto_6 = "key esc to quit"
        howto_7 = "Press Key_Space to Play"

        while howtoloop:
            pygame.mixer.music.stop()
            light_green = 102,255,255
            light_green1 = 178, 255, 102
            light_pink = 255,153,253
            light_red = 255,153,51

            self.surface.fill((0,102,0))
            h1 = font2.render(howto_1, True, (light_green))
            h2 = font2.render(howto_2, True, (light_pink))
            h3 = font2.render(howto_3, True, (light_red))
            h4 = font2.render(howto_4, True, (light_green1))
            h5 = font2.render(howto_5, True, (0, 0, 0))
            h6 = font2.render(howto_6, True, (0, 0, 0))
            h7 = font7.render(howto_7, True, (255,255,51))

            self.surface.blit(h1, (350, 20))
            self.surface.blit(h2, (480, 100))
            self.surface.blit(h3, (480, 140))
            self.surface.blit(h4, (480, 180))
            self.surface.blit(h5, (480, 220))
            self.surface.blit(h6, (480, 260))
            self.surface.blit(h7, (480, 600))

            c1 = (0,0,0)
            clickme = self.surface.blit(font7.render("Press me to continue", True, c1), (480, 550))

            pygame.display.update()
            for event in pygame.event.get():
                if event.type == QUIT:
                    sys.exit()

                if event.type == pygame.MOUSEBUTTONDOWN:
                    pos1 = event.pos
                    if clickme.collidepoint(pos1):
                        howtoloop = False
                        self.running = True
                        pygame.mixer.music.play()

                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        sys.exit()
                    if event.key == K_SPACE:
                        pygame.mixer.music.play()
                        howtoloop = False
                        self.running = True

        while self.running:
            for event in pygame.event.get():
                if event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        self.running = False

                    if event.key == K_RETURN:
                        self.pause = False
                        pygame.mixer.music.play()
                    if not self.pause:
                        if event.key == K_s:
                            self.snake.move_down()
                        if event.key == K_w:
                            self.snake.move_up()
                        if event.key == K_a:
                            self.snake.move_left()
                        if event.key == K_d:
                            self.snake.move_right()

                        if event.key == K_DOWN:
                            self.snake.move_down1()
                        if event.key == K_UP:
                            self.snake.move_up1()
                        if event.key == K_LEFT:
                            self.snake.move_left1()
                        if event.key == K_RIGHT:
                            self.snake.move_right1()

                    if event.key == K_SPACE:
                        self.text_pause()
                        self.pause = True
                        pygame.mixer.music.pause()

                elif event.type == QUIT:
                    self.running = False
            try:
                if not self.pause:
                    self.play()
            except Exception as e:
                self.show_game_over()
                self.pause = True
                self.reset()

            self.Time()

if __name__ == "__main__":
    game = Game()
    game.run()


import math
num=int(input("enter value:"))
sum=0
temp=num
while(temp>0):
    d=temp%10
    fact=math.factorial(d)
    temp=temp//10
    sum=sum+fact
if sum==num:
    print(" strong number ")
else :
    print("not a strong numer ")


import serial
from tkinter import *

ser = serial.Serial(port='COM3', baudrate=115200)
main = Tk()

main.geometry("400x400")

text = StringVar()
label = Label(main, textvariable=text, font=('Arial', 30))
label.pack(pady=100)

while True:
    testData = ser.readline().decode('utf-8')
    data = testData.rstrip().split(',')
    if data[0] == "0x1213FFC":
        text.set(str(int(data[8], 16) * 0.25))
        label.update()
    main.mainloop()