"""Support for Xiaomi curtain."""
from typing import Any

from homeassistant.components.cover import (
    ATTR_POSITION,
    ATTR_CURRENT_POSITION,
    ATTR_TILT_POSITION,
    CoverEntity,
    CoverEntityFeature,
)
from homeassistant.const import (
    ATTR_BATTERY_LEVEL,
    STATE_CLOSING,
    STATE_OPENING,
    STATE_UNKNOWN
)

from . import GatewayGenericDevice
from .core.gateway import Gateway
from .core.const import (
    ATTR_FW_VER,
    ATTR_LQI,
    ATTR_CHIP_TEMPERATURE,
    BATTERY,
    CHIP_TEMPERATURE,
    DOMAIN,
    FW_VER,
    LQI,
    RUN_STATES,
)

ATTR_POLARITY = 'polarity'
ATTR_MOTOR_STROKE = 'motor stroke'
ATTR_CHARGING_STATUS = 'charging status'
ATTR_WORKING_TIME = 'working time'
POLARITY = 'polarity'
POSITION = 'position'
TILT_POSITION = 'tilt_position'
CHARGING_STATUS = 'charging_status'
WORKING_TIME = 'working_time'
MOTOR_STROKE = 'motor_stroke'
RUN_STATE = 'run_state'

CHARGING_STATUS_ = {0: "Not Charging", 1: "Charging", 2: "Stop Charging", 3: "Charging Failure"}
MOTOR_STROKES = {0: "No stroke", 1: "The stroke has been set"}

DEVICES_WITH_BATTERY = ['lumi.curtain.acn002', 'lumi.curtain.acn003', 'lumi.curtain.agl001']

async def async_setup_entry(hass, config_entry, async_add_entities):
    """Perform the setup for Xiaomi devices."""
    def setup(gateway: Gateway, device: dict, attr: str):
        if device['model'] == 'lumi.curtain.acn002':
            async_add_entities([AqaraRollerShadeE1(gateway, device, attr)])
        elif device['model'] == 'lumi.curtain.acn011':
            async_add_entities([AqaraVerticalBlindsController(gateway, device, attr)])
        else:
            if device.get('mi_spec'):
                async_add_entities([XiaomiCoverMIOT(gateway, device, attr)])
            else:
                async_add_entities([XiaomiGenericCover(gateway, device, attr)])

    aqara_gateway: Gateway = hass.data[DOMAIN][config_entry.entry_id]
    aqara_gateway.add_setup('cover', setup)

async def async_unload_entry(hass, entry):
    # pylint: disable=unused-argument
    """ unload entry """
    return True

class XiaomiGenericCover(GatewayGenericDevice, CoverEntity):
    """Representation of a XiaomiGenericCover."""

    def __init__(self, gateway, device, atrr):
        """Initialize the XiaomiGenericCover."""
        self._pos = 0
        self._state = None
        self._chip_temperature = None
        self._fw_ver = None
        self._lqi = None
        self._polarity = None
        self._motor_stroke = None
        self._charging_status = None
        self._working_time = None
        if device['model'] in DEVICES_WITH_BATTERY:
            self._battery = None
        super().__init__(gateway, device, atrr)

    @property
    def current_cover_position(self):
        """Return the current position of the cover."""
        return self._attrs.get(ATTR_CURRENT_POSITION)

    @property
    def is_opening(self):
        """Return if the cover is opening."""
        return self._state == STATE_OPENING

    @property
    def is_closing(self):
        """Return if the cover is closing."""
        return self._state == STATE_CLOSING

    @property
    def is_closed(self):
        """Return if the cover is closed."""
        return self.current_cover_position == 0

    def update(self, data: dict = None):
        """ update state """
        for key, value in data.items():
            if key == BATTERY:
                if hasattr(self, "_battery"):
                    self._battery = value
            if key == CHIP_TEMPERATURE:
                self._chip_temperature = value
            if key == FW_VER or key == 'back_version':
                self._fw_ver = value
            if key == LQI:
                self._lqi = value
            if key == POLARITY:
                self._polarity = value
            if key == MOTOR_STROKE:
                self._motor_stroke = MOTOR_STROKES.get(value)
            if key == CHARGING_STATUS:
                self._charging_status = CHARGING_STATUS_.get(value)
            if key == WORKING_TIME:
                self._working_time = value
            if key == POSITION:
                self._pos = value
            if key == RUN_STATE:
                self._state = RUN_STATES.get(value, STATE_UNKNOWN)

        self.schedule_update_ha_state()

    def close_cover(self, **kwargs):
        """Close the cover."""
        self.gateway.send(self.device, {'position': 0})

    def open_cover(self, **kwargs):
        """Open the cover."""
        self.gateway.send(self.device, {'position': 100})

    def stop_cover(self, **kwargs):
        """Stop the cover."""
        self.gateway.send(self.device, {'motor': 2})

    def set_cover_position(self, **kwargs):
        """Move the cover to a specific position."""
        position = kwargs.get(ATTR_POSITION)
        self.gateway.send(self.device, {'position': position})

    @property
    def extra_state_attributes(self):
        """Return the state attributes."""
        self._attrs[ATTR_CURRENT_POSITION] = self._pos
        self._attrs[ATTR_CHIP_TEMPERATURE] = self._chip_temperature
        self._attrs[ATTR_FW_VER] = self._fw_ver
        self._attrs[ATTR_LQI] = self._lqi
        self._attrs[ATTR_POLARITY] = self._polarity
        self._attrs[ATTR_MOTOR_STROKE] = self._motor_stroke
        self._attrs[ATTR_CHARGING_STATUS] = self._charging_status
        self._attrs[ATTR_WORKING_TIME] = self._working_time
        if hasattr(self, "_battery"):
            self._attrs[ATTR_BATTERY_LEVEL] = self._battery
        return self._attrs

class XiaomiCoverMIOT(XiaomiGenericCover):
    def open_cover(self, **kwargs):
        self.gateway.send(self.device, {'motor': 2})

    def close_cover(self, **kwargs):
        self.gateway.send(self.device, {'motor': 1})

    def stop_cover(self, **kwargs):
        self.gateway.send(self.device, {'motor': 0})

    def open_cover_tilt(self, **kwargs: Any) -> None:
        """Open the cover tilt."""
        self.gateway.send(self.device, {'motor': 5})

    def close_cover_tilt(self, **kwargs: Any) -> None:
        """Close the cover tilt."""
        self.gateway.send(self.device, {'motor': 6})

class AqaraRollerShadeE1(XiaomiGenericCover):
    """ Aqara Roller Shade E1 (lumi.curtain.acn002) """

    _attr_supported_features = (
        CoverEntityFeature.OPEN
        | CoverEntityFeature.CLOSE
        | CoverEntityFeature.SET_POSITION
        | CoverEntityFeature.STOP
        | CoverEntityFeature.OPEN_TILT
        | CoverEntityFeature.CLOSE_TILT
    )

    def __init__(self, gateway, device, atrr):
        super().__init__(gateway, device, atrr)
        self._mi_mode = True if device.get('mi_spec') else False

    def stop_cover(self, **kwargs):
        if self._mi_mode:
            self.gateway.send(self.device, {'motor': 0})
        else:
            self.gateway.send(self.device, {'motor': 2})

    def open_cover_tilt(self, **kwargs: Any) -> None:
        """Open the cover tilt."""
        if self._mi_mode:
            self.gateway.send(self.device, {'motor': 4})
        else:
            self.gateway.send(self.device, {'motor': 6})

    def close_cover_tilt(self, **kwargs: Any) -> None:
        """Close the cover tilt."""
        if self._mi_mode:
            self.gateway.send(self.device, {'motor': 3})
        else:
            self.gateway.send(self.device, {'motor': 5})

class AqaraVerticalBlindsController(XiaomiGenericCover):

    _attr_current_cover_tilt_position: int = 0

    def update(self, data: dict = None):
        """ update state """
        super().update(data)
        if TILT_POSITION in data:
            value = data[TILT_POSITION]  # value is -90~90
            self._attr_current_cover_tilt_position = int((value + 90) / 180 * 100)  # 0~100
            self.schedule_update_ha_state()

    def open_cover_tilt(self, **kwargs: Any) -> None:
        """Open the cover tilt."""
        self.gateway.send(self.device, {'tilt_position': 0})

    def close_cover_tilt(self, **kwargs: Any) -> None:
        """Close the cover tilt."""
        self.gateway.send(self.device, {'tilt_position': -90})

    def set_cover_tilt_position(self, **kwargs):
        """Move the cover tilt to a specific position."""
        tilt_position = kwargs.get(ATTR_TILT_POSITION)  # 0~100
        self.gateway.send(self.device, {'tilt_position': tilt_position / 100 * 180 - 90})  # -90~90

    def stop_cover_tilt(self, **kwargs: Any) -> None:
        self.gateway.send(self.device, {'tilt_motor': 2})


import json
from typing import Any

from django.utils.translation import get_language
from rest_framework import serializers
from rest_framework.utils.serializer_helpers import ReturnDict

from my_apps.shop.models import Banner, BasketItem, Category, Faq, Order, Product, Review

class CategorySerializer(serializers.ModelSerializer):
    sub = serializers.SerializerMethodField()
    icon = serializers.ImageField(source="img_small")
    url = serializers.CharField(source="slug")

    class Meta:
        model = Category
        fields = [
            "id",
            "url",
            "name",
            "icon",
            "img",
            "sub",
        ]

    def get_sub(self, obj) -> ReturnDict[Any, Any]:
        serializer = CategorySerializer(obj.get_sub_categories(), context=self.context, many=True)
        return serializer.data

class ProductCatalogSerializer(serializers.ModelSerializer):
    category = serializers.CharField(source="get_category_name")

    class Meta:
        model = Product
        fields = [
            "id",
            "name",
            "quantity",
            "img",
            "category",
            "price",
            "discount",
            "global_rating",
        ]

class ProductCardSerializer(serializers.ModelSerializer):
    category = serializers.CharField(source="get_category_name")
    code = serializers.CharField(source="slug")
    img = serializers.SerializerMethodField()
    # faq = serializers.CharField(source="get_faq_list")

    class Meta:
        model = Product
        fields = [
            "id",
            "name",
            "category",
            "price",
            "discount",
            "img",
            "quantity",
            "code",
            "global_rating",
            "description",
            # "faq",
            "rate_by_criteria",
            "rate_by_stars",
        ]

    def get_reviews(self, obj):
        serializer = ReviewSerializer(obj.get_rewievs(), context=self.context, many=True)
        return serializer.data

    #
    # def get_faq(self, obj) -> str:
    #     list_faq: list = obj.get_list_faq()
    #     return json.dumps(list_faq)

    def get_img(self, obj):
        request = self.context.get("request")
        domain = request.build_absolute_uri("/")

        list_foto = obj.images()
        list_link = []
        for image in list_foto:
            list_link.append(domain + image)
        return list_link

class OrderSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Order
        fields = ["id", "customer", "manager", "status", "order_date", "total_amount"]

    status = serializers.CharField(source="get_status_display")

class CreateReviewSerializer(serializers.ModelSerializer):
    class Meta:
        model = Review
        fields = ["text", "date"]

    def save(self, owner, product):
        text = self.validated_data["text"]
        rewiev = Review(text=text, author=owner, product=product)
        rewiev.save()
        return rewiev

class ReviewSerializer(serializers.ModelSerializer):
    author = serializers.CharField(source="get_user_name")

    class Meta:
        model = Review
        fields = ["id", "author", "text", "rate_by_stars", "rate_by_criteria"]

class BannerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = ["id", "img", "mobileImg", "link"]

class BasketSerializer(serializers.Serializer):
    product_id = serializers.UUIDField()
    amount = serializers.IntegerField()

class BasketItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = BasketItem
        fields = ["product", "quantity"]

class OrderIdSerializer(serializers.Serializer):
    order_id = serializers.UUIDField()


from kivy.uix.widget import Widget
from kivy.clock import Clock
from runnable import run_on_ui_thread
from  kivy.event import EventDispatcher
from jnius import autoclass
from webviewclient import WebviewClient

#Load Native Modules
WebView = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
activity = autoclass('org.kivy.android.PythonActivity').mActivity
LayoutParams = autoclass('android.view.ViewGroup$LayoutParams')
View = autoclass('android.view.View')

class WebviewEngine(Widget,EventDispatcher):

	is_visible = True

	_webview_obj = None

	#events
	_webview_events = ['on_page_started','on_page_finished',
					   'on_received_error','on_page_commit_visible',
					   'on_should_override_url_loading'
					  ]

	 #initialize :D -- Sweet
	def __init__(self, **kwargs):

		self.webviewWidth = kwargs.get('width') if kwargs.has_key('width') else LayoutParams.MATCH_PARENT

		self.webviewPosX = kwargs.get('posX') if kwargs.has_key('posX') else 0

		self.webviewPosY = kwargs.get('posY') if kwargs.has_key('posY') else 0

		self.webviewHeight = kwargs.get('height') if kwargs.has_key('height') else LayoutParams.MATCH_PARENT

		#register Events
		self._register_events()

		super(WebviewEngine, self).__init__(**kwargs)

		Clock.schedule_once(self.create_webview, 0)

	#method for dispatching events
	def dispatch_event(self,event_name,**kwargs):

		#dispatch
		self.dispatch(event_name,**kwargs)
		print('--- Eevent %s dispatched \n' %event_name, kwargs)

	#default event handler
	def _event_default_handler(self,**kwargs):
		pass

	#Event registrar
	def _register_events(self):

		events = self._webview_events

		#loop and register them
		for event_name in events:

			#create the default handler
			setattr(self,event_name,self._event_default_handler)

			#register the event
			self.register_event_type(event_name)

	#Magic Method to pipe java's webview methods to this class
	def __getattr__(self,method_name):

		print("----%s--- has been called ====" % method_name)
		#else if the method is a webview Obj
		if hasattr(self._webview_obj,method_name):

			#create a dummy function
			call_method = lambda *x: getattr(self._webview_obj,method_name)(*x)

			#return method
			return call_method

		else:
			raise Exception("Method %s not define" % method_name)

	@run_on_ui_thread
	def create_webview(self,*args):

		#if the webview is created already, skip it
		if(self._webview_obj):
			return True

		#if we have reached this point, then mean the webview is not created
		webview = WebView(activity)

		settings = webview.getSettings()
		settings.setJavaScriptEnabled(True)
		settings.setUseWideViewPort(True) # enables viewport html meta tags
		settings.setLoadWithOverviewMode(True) # uses viewport
		settings.setSupportZoom(True) # enables zoom
		settings.setBuiltInZoomControls(True) # enables zoom controls

		#set java events
		webviewClient = WebviewClient(self)

		webview.setWebViewClient(webviewClient)

		#webview.setWebChromeClient(WebChromeClient)

		#set Postions
		webview.setX(self.webviewPosX)
		webview.setY(self.webviewPosY)

		#webview.testNum = 12

		activity.addContentView(webview, LayoutParams(self.webviewWidth,self.webviewHeight))

		webview.loadUrl('http://www.526net.com')

		self._webview_obj = webview

	#hide - This will hide the webview widget
	@run_on_ui_thread
	def hide(self):
		if self._webview_obj is None and self.is_visible == False:
			return False

		self._webview_obj.setVisibility(View.GONE)


import sys
from itertools import combinations

N = int(sys.stdin.readline())

area = [i for i in range(1,N+1)]
human_num = dict()
num = list(map(int,sys.stdin.readline().rstrip().split()))
for i in range(1,N+1) :
    human_num[i] = num[i-1]

node = dict()
visited = [0] * (N+1)
for i in range(1,N+1) :
    line = list(map(int,sys.stdin.readline().rstrip().split()))
    temp = []
    for j in range(line[0]) :
        temp.append(line[j+1])
    node[i] = temp
minVal = float('inf')

def dfs(x,arr) :
    global flag
    visited[x] = 1
    # print(x,arr,visited)
    if visited.count(1) == len(arr) :
        # print(x, arr, visited)
        flag = True
        return
    else :
        for n in node[x] :
            if n in arr and visited[n] == 0:
                visited[n] = 1
                dfs(n,arr)

for n in range(1,N+1) :
    com = list(combinations(area,n))
    for c in com :
        one, two = [], []
        for i in c :
            one.append(i)
        for a in area :
            if a not in one :
                two.append(a)
        visited = [0] * (N+1)
        flag = False
        dfs(one[0], one)
        if flag == True :
            visited = [0] * (N + 1)
            flag = False
            if len(two) > 0 :
                dfs(two[0], two)

        if flag == True :
            cnt1, cnt2 = 0, 0
            for o in one:
                cnt1 += human_num[o]
            for t in two:
                cnt2 += human_num[t]
            minVal = min(minVal, (abs(cnt1 - cnt2)))
if minVal == float('inf') :
    print(-1)
else :
    print(minVal)


from __future__ import (
    absolute_import,
    division,
    print_function
)

import json
import logging
import time

import boto.swf.layer2 as swf
import boto.sqs.connection as sqs
import boto.sqs.queue as sqs_queue

from .state_machine import StateMachine

_LOGGER = logging.getLogger(__name__)

class SWFDecider(swf.Decider):

    name = 'generic'
    version = '1.0'

    def __init__(self, domain, task_list, output_queue, plan=None):
        self.domain = domain
        self.task_list = task_list
        super(SWFDecider, self).__init__()

        self.statemachine = StateMachine(plan)
        self.sqs = sqs.SQSConnection()

        self.output_queue = sqs_queue.Queue(self.sqs, output_queue)

    def run(self):
        decision_task = self.poll()
        _LOGGER.info('Received decision task: %r', decision_task)
        if 'events' in decision_task:
            # Collect the entire history if there are enough events to become
            # paginated
            events = decision_task['events']
            while 'nextPageToken' in decision_task:
                decision_task = self.poll(
                    next_page_token=decision_task['nextPageToken']
                )
                if 'events' in decision_task:
                    events.extend(decision_task['events'])

            # Compute decision based on events
            decisions = self._run(events, decision_task['workflowExecution'])
            self.complete(decisions=decisions)

        _LOGGER.debug('Tic')
        return True

    def _run(self, events, workflowExecution):
        # Run the statemachine on the events
        results = self.statemachine.eval(events)

        # Now we can do 4 things:
        #  - Complete the workflow
        #  - Fail the workflow
        #  - Schedule more activities
        #  - Nothing
        decisions = swf.Layer1Decisions()

        if self.statemachine.is_succeeded:
            self.sqs.send_message(self.output_queue, json.dumps({
                'time': time.time(),
                'type': 'WORKFLOW_COMPLETED',
                'data': {
                    'workflow': workflowExecution
                }
            }))
            decisions.complete_workflow_execution(result=None)
            return decisions

        elif self.statemachine.is_failed:
            # FIXME: Improve error reporting
            self.sqs.send_message(self.output_queue, json.dumps({
                'time': time.time(),
                'type': 'WORKFLOW_FAILED',
                'data': {
                    'workflow': workflowExecution
                }
            }))
            decisions.fail_workflow_execution(reason='State machine aborted')
            return decisions

        # We are still going, start any ready activity
        for next_step in results:

            activity = next_step.activity
            # FIXME: We are assuming JSON activity input here
            activity_input = (
                json.dumps(next_step.activity_input)
                if next_step.activity_input is not None
                else None
            )

            self.sqs.send_message(self.output_queue, json.dumps({
                'time': time.time(),
                'type': 'ACTIVITY_SCHEDULED',
                'data': {
                    'workflow': workflowExecution,
                    'activity': {
                        'activityId': next_step.name,
                        'activityType': activity.name,
                        'activityVersion': activity.version
                    }
                }
            }))
            decisions.schedule_activity_task(
                activity_id=next_step.name,
                activity_type_name=activity.name,
                activity_type_version=activity.version,
                task_list=activity.task_list,
                control=None,  # FIXME: Do we want to pass context data?
                heartbeat_timeout=activity.heartbeat_timeout,
                schedule_to_close_timeout=activity.schedule_to_close_timeout,
                schedule_to_start_timeout=activity.schedule_to_start_timeout,
                start_to_close_timeout=activity.start_to_close_timeout,
                input=activity_input,
            )

        return decisions


from elasticsearch_dsl import (
    connections,
    Document,
    Text, Keyword,
    Integer, Long
)

class Job(Document):
    custno = Keyword()
    jobno = Integer()
    description = Keyword() #
    job = Keyword() #
    # job = Text(index='not_analyzed')  # issue: https://github.com/elastic/elasticsearch/issues/21134
    others = Keyword() #
    addr_no = Long()
    edu = Long()
    exp_jobcat1 = Long()
    exp_jobcat2 = Long()
    exp_jobcat3 = Long()
    industry = Long()
    jobcat1 = Long()
    jobcat2 = Long()
    jobcat3 = Long()
    language1 = Long()
    language2 = Long()
    language3 = Long()
    major_cat = Integer()
    major_cat2 = Integer()
    major_cat3 = Integer()
    need_emp = Long()
    need_emp1 = Long()
    period = Long()
    role = Long()
    role_status = Long()
    s2 = Long()
    s3 = Long()
    s9 = Long()
    salary_high = Long()
    salary_low = Long()
    startby = Long()
    worktime = Integer()
    invoice = Long()
    management = Keyword()  #
    name = Keyword()  #
    product = Keyword()  #
    profile = Keyword()  #
    welfare = Keyword()  #

    class Index:
        name = 'hack104'

    @classmethod
    def from_row(cls, row):
        all_fields = row.__fields__
        token_fields = ['description', 'job', 'others', 'management', 'name', 'product', 'profile', 'welfare']
        pk_field = 'jobno'

        doc = cls()

        for field in all_fields:
            if field in token_fields:
                setattr(doc, field, getattr(getattr(row, field), 'token'))
            else:
                setattr(doc, field, getattr(row, field))

        doc.meta.id = pk_field

        return doc

    tfidf_fields = ['description', 'job', 'others', 'management', 'name', 'product', 'profile', 'welfare']

    @classmethod
    def from_dict(cls, obj):
        token_fields = ['description', 'job', 'others', 'management', 'name', 'product', 'profile', 'welfare']
        pk_field = 'jobno'

        doc = cls()
        try:
            for field, body in obj.items():
                if field in token_fields:
                    setattr(doc, field, body.get('token'))
                else:
                    setattr(doc, field, body)
        except Exception as err:
            print('@@@@', 'field', field)
            print('@@@@', 'body', body)
            print('@@@@', obj)

            raise err

        doc.meta.id = obj.get(pk_field)

        return doc

if __name__ == '__main__':
    connections.create_connection(hosts=['localhost:9201'], timeout=20)
    print('Initiating index: `hack104` for type: `Job`')
    Job.init()

    import fileinput, json
    print('Press Enter to leave')
    for line in fileinput.input():
        if len(line.strip()) == 0:
            break
        print(json.dumps(Job.from_dict(json.loads(line)).to_dict(include_meta=True)))


from typing import final
import gi
gi.require_version('Handy', '1')
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Handy, GLib, Gdk

from datetime import date, datetime
from time import sleep

from .custom_widgets import *
from . import utils

from uuid import uuid4
import threading

import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(asctime)s, %(funcName)s:%(lineno)d: %(message)s")

class KeystrokesWindow(Handy.ApplicationWindow):
    __gtype_name__ = 'KeystrokesWindow'

    Handy.init()

    key_listener = None
    mouse_listener = None

    display_cleaner_thread = None
    stop_display_cleaner_thread = False

    last_key = None
    last_key_id = None
    last_active_app = None

    active_app = None

    key_ids = {}

    repeat_key_counter = 0

    key_press_timestamp = datetime.now()
    key_press_timestamp_old = datetime.now()
    key_press_timestamp_diff = 0
    key_press_timeout = 50
    key_press_count = 0

    timeout_id = 0
    repeated_key = None

    app_startup = True

    key_displays_grid_idx = 0

    mouse_distance = 0

    before_xy = None
    current_xy = None
    mouse_moving = False

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.app = self.props.application

        self.header = self.generate_headerbar()
        self.standby_revealer = self.generate_standby_revealer()
        self.movement_revealer = self.generate_movement_revealer()

        self.key_displays_grid = Gtk.Grid()

        self.grid = Gtk.Grid()
        self.grid.props.expand = True
        self.grid.attach(self.key_displays_grid, 0, 0, 1, 1)
        self.grid.attach(self.standby_revealer, 0, 0, 1, 1)
        self.grid.attach(self.movement_revealer, 0, 0, 1, 1)

        overlay = Gtk.Overlay()
        overlay.add(self.grid)
        overlay.add_overlay(self.header)

        window_handle = Handy.WindowHandle()
        window_handle.add(overlay)

        self.add(window_handle)
        self.props.name = "main"
        self.setup_ui()
        self.show_all()
        self.set_resizable(False)
        self.set_keep_above(True)
        self.set_size_request(200, 180)
        self.reposition()
        if self.app.window_manager is not None:
            self.app.window_manager._run(callback=self.on_active_window_changed)

        # screen = self.get_screen()
        # display = screen.get_display()
        # display.connect("monitor-added", self.on_n_monitor_changed, "monitor-added")
        # display.connect("monitor-removed", self.on_n_monitor_changed, "monitor-removed")
        # n_monitors = display.get_n_monitors()
        ...

    def setup_ui(self, transparency_value=None):
        if transparency_value is None:
            transparency_value = float(self.app.gio_settings.get_int("display-transparency")/100)
        css = "window#main.background {background-color: rgba(0,0,0," + str(transparency_value) + ");}"
        css_provider = Gtk.CssProvider()
        css_provider.load_from_data(bytes(css.encode()))
        self.get_style_context().add_provider(css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

        if self.app.gio_settings.get_value("sticky-mode"):
            self.stick()

        self.connect("button-press-event", self.show_window_controls)
        # self.connect("screen-changed", self.on_screen_changed)
        self.connect("configure-event", self.on_configure_event)

    def generate_headerbar(self):
        settings_button = Gtk.Button(image=Gtk.Image().new_from_icon_name("settings-symbolic", Gtk.IconSize.SMALL_TOOLBAR))
        settings_button.props.always_show_image = True
        settings_button.props.can_focus = False
        settings_button.props.margin = 2
        # settings_button.set_size_request(16, 16)
        settings_button.get_style_context().remove_class("image-button")
        settings_button.get_style_context().add_class("titlebutton")
        settings_button.connect("clicked", self.on_settings_clicked)
        self.settings_revealer = Gtk.Revealer()
        self.settings_revealer.props.transition_duration = 250
        self.settings_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
        self.settings_revealer.add(settings_button)

        header = Handy.HeaderBar()
        header.props.name = "main"
        header.props.hexpand = True
        header.props.valign = Gtk.Align.START
        header.props.halign = Gtk.Align.FILL
        header.props.spacing = 0
        header.props.has_subtitle = False
        header.props.show_close_button = False
        header.props.decoration_layout = "close:"
        header.get_style_context().add_class(Gtk.STYLE_CLASS_FLAT)
        header.pack_end(self.settings_revealer)

        return header

    def generate_standby_revealer(self):
        standby_label = Gtk.Label("•••")
        standby_label.props.name = "standby"
        standby_label.props.expand = True
        standby_label.props.halign = standby_label.props.valign = Gtk.Align.CENTER
        standby_revealer = Gtk.Revealer()
        standby_revealer.add(standby_label)
        standby_revealer.set_reveal_child(True)
        return standby_revealer

    def generate_movement_revealer(self):
        label = "x: 0\ny: 0"
        self.movement_label = Gtk.Label()
        self.movement_label.props.name = "movement"
        self.movement_label.props.expand = True
        self.movement_label.props.margin_top = 24
        self.movement_label.props.justify = Gtk.Justification.LEFT
        self.movement_label.props.halign = Gtk.Align.CENTER
        self.movement_label.props.valign = Gtk.Align.CENTER
        self.movement_label.set_label(label)
        movements_image = Gtk.Image().new_from_icon_name(icon_name="movements6", size=Gtk.IconSize.DIALOG)
        movements_image.props.expand = True
        movements_image.props.margin_bottom = 24
        movements_image.props.valign = Gtk.Align.START
        movements_grid = Gtk.Grid()
        movements_grid.props.expand = True
        movements_grid.attach(movements_image, 0, 0, 1, 1)
        movements_grid.attach(self.movement_label, 0, 0, 1, 1)
        movement_revealer = Gtk.Revealer()
        movement_revealer.props.name = "movement-revealer"
        movement_revealer.props.expand = True
        movement_revealer.props.halign = Gtk.Align.CENTER
        movement_revealer.props.valign = Gtk.Align.CENTER
        movement_revealer.props.margin_top = 10
        movement_revealer.props.margin_bottom = 10
        movement_revealer.props.margin_left = 15
        movement_revealer.props.margin_right = 15
        movement_revealer.add(movements_grid)
        return movement_revealer

    def generate_settings_dialog(self, *args):

        self.settings_grid = Settings(gtk_application=self.app)

        self.settings_dialog = CustomDialog(
            dialog_parent_widget=self,
            dialog_title="Keystrokes Settings",
            dialog_content_widget=self.settings_grid,
            action_button_label=None,
            action_button_name=None,
            action_callback=None,
            action_type=None,
            size=[400, 300],
            data=None
        )

        self.settings_dialog.header.props.show_close_button = True

    def reposition(self, *args):

        # defaults
        a, b, c, d = 0, 1, 1, 2
        align = Gtk.Align.END

        # clear key_info_grid
        # for i in range(4):
        #     self.key_info_grid.remove_column(0)

        if self.app.gio_settings.get_value("auto-position"):

            gravity = Gdk.Gravity(self.app.gio_settings.get_int("screen-position"))

            window_width, window_height = self.get_size()
            root_x, root_y = self.get_position()

            screen = self.get_screen()
            screen_width = screen.width()
            screen_height = screen.height()
            # logging.info("screen:{0}".format((screen_width, screen_height)))

            display = screen.get_display()
            n_monitors = display.get_n_monitors()
            # logging.info("n_monitors:{0}".format(n_monitors))

            monitor = screen.get_monitor_at_window(self.get_window())
            # logging.info("get_monitor_at_window:{0}".format(monitor))

            monitor_geometry = screen.get_monitor_geometry(monitor)
            # logging.info("get_monitor_at_window:{0}".format((monitor_geometry.x, monitor_geometry.y, monitor_geometry.width, monitor_geometry.height)))

            work_area = screen.get_monitor_workarea(monitor)
            # logging.info("work_area:{0}".format((work_area.x, work_area.y, work_area.width, work_area.height)))

            offset_x = monitor_geometry.height - work_area.height
            offset_y = (screen_height-work_area.height)-work_area.y
            # logging.info("offset:{0}".format((offset_x, offset_y)))

            monitor = screen.get_primary_monitor()
            # logging.info("get_primary_monitor:{0}".format(monitor))

            monitor_geometry = screen.get_monitor_geometry(monitor)
            # logging.info("get_monitor_at_window:{0}".format((monitor_geometry.x, monitor_geometry.y, monitor_geometry.width, monitor_geometry.height)))

            work_area = screen.get_monitor_workarea(monitor)
            # logging.info("work_area:{0}".format((work_area.x, work_area.y, work_area.width, work_area.height)))

            offset_y = monitor_geometry.height - work_area.height
            offset_x = (screen_height-work_area.height)-work_area.y
            # logging.info("offset:{0}".format((offset_x, offset_y)))

            safe_area_width = screen_width - (screen_height - work_area.height - work_area.y) * 2
            # logging.info("safe_area:{}, window_width:{}".format(safe_area_width,window_width))

            # defaults
            # x, y = screen_width-window_width-(screen_height-work_area.height)+work_area.y, screen_height-window_height

            self.set_position(Gtk.WindowPosition.NONE)

            if gravity.value_name == "GDK_GRAVITY_NORTH_WEST":
                x, y = (screen_height-work_area.height)-work_area.y, (screen_height-work_area.height)
                a, b, c, d = 2, 1, 1, 0
                align = Gtk.Align.START
            elif gravity.value_name =="GDK_GRAVITY_NORTH":
                x, y = (screen_width/2)-(window_width/2), (screen_height-work_area.height)
                align = Gtk.Align.CENTER
            elif gravity.value_name == "GDK_GRAVITY_NORTH_EAST":
                x, y = screen_width-window_width-(screen_height-work_area.height)+work_area.y, (screen_height-work_area.height)
                align = Gtk.Align.END
            elif gravity.value_name == "GDK_GRAVITY_EAST":
                x, y = screen_width-window_width-(screen_height-work_area.height)+work_area.y, (screen_height/2)-(window_height/2)
                align = Gtk.Align.END
            elif gravity.value_name == "GDK_GRAVITY_SOUTH_EAST":
                x, y = screen_width-window_width-(screen_height-work_area.height)+work_area.y, screen_height-window_height
                align = Gtk.Align.END
            elif gravity.value_name == "GDK_GRAVITY_SOUTH":
                x, y = (screen_width/2)-(window_width/2), screen_height-window_height
                align = Gtk.Align.CENTER
            elif gravity.value_name == "GDK_GRAVITY_SOUTH_WEST":
                x, y = (screen_height-work_area.height)-work_area.y, screen_height-window_height
                a, b, c, d = 2, 1, 1, 0
                align = Gtk.Align.START
            elif gravity.value_name == "GDK_GRAVITY_WEST":
                x, y = (screen_height-work_area.height)-work_area.y, (screen_height/2)-(window_height/2)
                a, b, c, d = 2, 1, 1, 0
                align = Gtk.Align.START
            elif gravity.value_name == "GDK_GRAVITY_CENTER":
                x, y = (screen_width/2)-(window_width/2), (screen_height/2)-(window_height/2)
                align = Gtk.Align.CENTER
            else:
                pass

            x, y = int(x), int(y)
            # logging.info("move:{0}".format((x,y)))
            self.move(x, y)
            # gdk_window.move(x, y)

        else:
            if self.app.gio_settings.get_string("current-position") in ["upper-left", "lower-left"] :
                a, b, c, d = 2, 1, 1, 0
                align = Gtk.Align.START
                gravity = Gdk.Gravity.NORTH_WEST
            elif self.app.gio_settings.get_string("current-position") in ["upper-right", "lower-right"] :
                a, b, c, d = 0, 1, 1, 2
                align = Gtk.Align.END
                gravity = Gdk.Gravity.NORTH_EAST

        self.set_gravity(gravity)
        # self.key_info_grid.props.halign = align
        # self.key_info_grid.attach(self.movement_revealer, a, 0, 1, 1)
        # self.key_info_grid.attach(self.key_press_revealer, b, 0, 1, 1)
        # self.key_info_grid.attach(self.key_release_revealer, c, 0, 1, 1)
        # self.key_info_grid.attach(self.active_app_image, d, 0, 1, 1)
        ...

    def show_window_controls(self, *args):
        self.header.props.show_close_button = True
        self.settings_revealer.set_reveal_child(True)
        GLib.timeout_add(5000, self.header.set_show_close_button, False)
        GLib.timeout_add(5000, self.settings_revealer.set_reveal_child, False)

    def on_n_monitor_changed(self, display, monitor, event_type):
        logging.info((event_type, monitor))

    def on_configure_event(self, widget, event):
        position = ""

        root_x, root_y = self.get_position()

        screen = self.get_screen()

        display = screen.get_display()
        n_monitors = display.get_n_monitors()

        monitor = screen.get_monitor_at_window(self.get_window())
        monitor = screen.get_primary_monitor()

        monitor_geometry = screen.get_monitor_geometry(monitor)

        work_area = screen.get_monitor_workarea(monitor)

        if root_x >= 0 and root_x <= monitor_geometry.width/2 and root_y >= 0 and root_y <= monitor_geometry.height/2:
            position = "upper-left"
        elif root_x >= monitor_geometry.width/2 and root_y >= 0 and root_y <= monitor_geometry.height/2:
            position = "upper-right"
        elif root_x >= 0 and root_x <= monitor_geometry.width/2 and root_y >= monitor_geometry.height/2:
            position = "lower-left"
        elif root_x >= monitor_geometry.width/2 and root_y >= monitor_geometry.height/2:
            position = "lower-right"

        if position not in self.app.gio_settings.get_string("current-position"):
            self.app.gio_settings.set_string("current-position", position)
            self.reposition()
            ...

    def on_active_window_changed(self, window_id):

        @utils.run_async
        def queue_key_display_remove(key_display, *args):
            while len(key_display.key_grid.get_children()) != 0:
                sleep(0.25)
            else:
                GLib.idle_add(key_display.self_remove, None)

        app_data = self.app.utils.get_app_by_window_id(window_id)

        if app_data is not None and len(app_data) != 0:
            self.active_app = app_data[0]

            # app startup
            if not self.app_startup and self.active_app != "Keystrokes":

                key_displays = [child for child in self.key_displays_grid.get_children() if (isinstance(child, Gtk.Grid) and hasattr(child, 'active'))]

                # logging.info("len(key_displays):{0}".format(len(key_displays)))

                if len(key_displays) == 0:
                    key_display_grid = KeyDisplayContainer(self.active_app, True)
                    key_display_grid.active_app_image.set_from_icon_name(icon_name=app_data[1], size=Gtk.IconSize.DND)
                    key_display_grid.active_app_image.set_pixel_size(48)
                    self.key_displays_grid.attach(key_display_grid, 0, self.key_displays_grid_idx, 1, 1)
                    self.key_displays_grid.show_all()
                    self.key_displays_grid_idx += 1

                else:
                    active_key_display = [child for child in self.key_displays_grid.get_children() if (isinstance(child, Gtk.Grid) and hasattr(child, 'active') and child.active is True)]
                    if len(active_key_display) != 0:
                        active_key_display = active_key_display[0]

                        if self.active_app != active_key_display.props.name:

                            active_key_display.active = False
                            queue_key_display_remove(active_key_display)

                            key_display_grid = KeyDisplayContainer(self.active_app, True)
                            key_display_grid.active_app_image.set_from_icon_name(icon_name=app_data[1], size=Gtk.IconSize.DND)
                            key_display_grid.active_app_image.set_pixel_size(48)
                            self.key_displays_grid.attach(key_display_grid, 0, self.key_displays_grid_idx, 1, 1)
                            self.key_displays_grid.show_all()
                            self.key_displays_grid_idx += 1

        self.app_startup = False

    def on_settings_clicked(self, button):
        self.generate_settings_dialog()

    def on_screen_changed(self, widget, previous_screen):
        logging.info(previous_screen)
        self.reposition()
        ...

    def on_event(self):
        GLib.idle_add(self.reposition, None)
        if self.app.app_id.split(".")[-1].lower() in self.active_app.lower():
            return False
        else:
            return True

    def on_key_event(self, key, event):
        if self.on_event():
            self.key_press_timestamp = datetime.now()
            key_type = "keyboard"

            try:
                _key = key.char
                shape_type = "square"
                is_modifier = False
            except AttributeError:
                _key = key.name
                shape_type = "rectangle"
                is_modifier = True
            else:
            # print(Gdk.keyval_name(key.vk))
                if key.vk:
                    if key.vk == 65032: #temporary workaround for issue https://github.com/moses-palmer/pynput/issues/215
                        _key = "shift"
                        shape_type = "rectangle"
                        is_modifier = True
            finally:
                key = _key

            # if key == self.last_key:
            #     self.repeat_key_counter += 1

            data = {(key, key_type, shape_type, event, self.active_app)}
            self.queue_to_display(data)

            # self.last_key = key
            ...

    def on_key_press(self, key):
        if self.app.gio_settings.get_value("monitor-key-press"):
            self.on_key_event(key, "pressed")

    def on_key_release(self, key):
        if self.app.gio_settings.get_value("monitor-key-release"):
            self.on_key_event(key, "released")

    def on_mouse_move(self, x=0, y=0):

        @utils.run_async
        def queue_movement_revealer_remove():
            while self.mouse_moving:
                if self.before_xy == self.current_xy:
                    sleep(1)
                    self.mouse_moving = False
                    self.movement_revealer.set_reveal_child(False)
                    sleep(0.25)
                    key_display = [child for child in self.key_displays_grid.get_children() if (isinstance(child, Gtk.Grid) and hasattr(child, 'active') and child.active is True)]
                    if len(key_display) == 0 or len(key_display[0].key_grid.get_children()) == 0:
                        self.standby_revealer.set_reveal_child(True)

                    self.grid.remove(self.movement_revealer)

                    break
                self.before_xy = self.current_xy

        def update_movement(data):
            self.before_xy = self.current_xy
            self.current_xy = data
            self.new_x, self.new_y = data
            self.movement_label.props.label = "x: {0}\ny: {1}".format(self.new_x, self.new_y)

        if self.app.gio_settings.get_value("monitor-movements"):

            key_display = [child for child in self.key_displays_grid.get_children() if (isinstance(child, Gtk.Grid) and hasattr(child, 'active') and child.active is True and child.key_grid_revealer.is_visible())]

            if len(key_display) == 0:
                self.movement_revealer.set_reveal_child(True)
                self.standby_revealer.set_reveal_child(False)
            else:
                self.movement_revealer.set_reveal_child(False)

            GLib.idle_add(update_movement, (x, y))

    def on_mouse_click(self, x, y, button, pressed):
        if self.app.gio_settings.get_value("monitor-clicks"):
            if self.on_event():
                self.key_press_timestamp = datetime.now()
                key_type = "mouse"
                try:
                    key = button.name
                    shape_type= "square"
                except AttributeError:
                    pass
                if pressed:
                    data = {(key, key_type, shape_type, "clicked", self.active_app)}
                    self.queue_to_display(data)

    def on_mouse_scroll(self, x, y, dx, dy):
        if self.app.gio_settings.get_value("monitor-scrolls"):
            if self.on_event():
                key_type = "mouse"
                try:
                    if dy < 0:
                        key = "scrolldown"
                    elif dy > 0:
                        key = "scrollup"
                    elif dx < 0:
                        key = "scrollleft"
                    elif dx > 0:
                        key = "scrollright"
                    shape_type= "square"

                    data = {(key, key_type, shape_type, "scroll", self.active_app)}
                    self.queue_to_display(data)
                except AttributeError:
                    pass

    def add_key(self, data):

        key_display, key, key_type, shape_type, id, event, active_app = data

        if shape_type == "square":
            if key_type == "mouse":
                widget = MouseContainer(key, key_type, event)
            else:
                widget = KeySquareContainer(key, key_type, event)
        else:
            widget = KeyRectangleContainer(key, key_type, event)

        key_display.key_grid.add(ContainerRevealer(key, widget, id, event, active_app))
        key_display.key_grid.show_all()

        for child in key_display.key_grid.get_children():
            if isinstance(child, Gtk.Revealer):
                child.set_reveal_child(True)

        self.key_ids[id] = widget.get_parent().get_parent()

        self.last_key = key
        self.last_key_id = id
        self.last_active_app = active_app

    def queue_to_display(self, data):
        '''
        data = {(key, key_type, shape_type, event, self.active_app)}
        receive parameters as set to make the values immutable

        then convert it back into list and individual variables
        key, key_type, shape_type, event, active_app = list(data)[0]
        '''

        key, key_type, shape_type, event, active_app = list(data)[0]

        @utils.run_async
        def add(key_display, id, *args):

            self.standby_revealer.set_reveal_child(False)
            self.movement_revealer.set_reveal_child(False)
            sleep(0.25)
            key_display.active_app_revealer.set_reveal_child(True)
            key_display.key_grid_revealer.set_visible(True)
            sleep(0.25)
            key_display.key_grid_revealer.set_reveal_child(True)

            if self.app.gio_settings.get_value("monitor-repeatkeys") and key == self.last_key and active_app == self.last_active_app:
                self.key_ids[self.last_key_id].repeat_key = True
                self.key_ids[self.last_key_id].counter_revealer.set_reveal_child(True)
                self.key_ids[self.last_key_id].repeat_key_counter += 1
                self.key_ids[self.last_key_id].counter.set_text(str(self.key_ids[self.last_key_id].repeat_key_counter))

            elif self.app.gio_settings.get_value("monitor-repeatkeys") and key != self.last_key or not self.app.gio_settings.get_value("monitor-repeatkeys"):
                GLib.idle_add(self.add_key, (key_display, key, key_type, shape_type, id, event, active_app))

            if self.display_cleaner_thread is None:
                self.run_display_cleaner()

        @utils.run_async
        def released(*args):
            sleep(0.5)
            for key_id in self.key_ids.keys():
                if event + key + active_app + self.key_ids[key_id].event + self.key_ids[key_id].name + self.key_ids[key_id].active_app == "released" + key + active_app + "pressed" + key + active_app:
                    self.key_ids[key_id].overlay.get_child().get_style_context().add_class("animate-released")
                    break

        # press
        # release
        # press + release
        # press + repeat
        # release + repeat
        # press + release + repeat

        id = uuid4().hex

        if (event == "pressed" and self.app.gio_settings.get_value("monitor-key-press")) or (event == "clicked" and self.app.gio_settings.get_value("monitor-clicks")) or (event == "scroll" and self.app.gio_settings.get_value("monitor-scrolls")):
            add(self.get_key_display(active_app), id)

        elif event == "released" and self.app.gio_settings.get_value("monitor-key-release"):
            released()

    def get_key_display(self, active_app):
        try:
            key_display = [child for child in self.key_displays_grid.get_children() if (isinstance(child, Gtk.Grid) and hasattr(child, 'active_app') and child.active_app == active_app)]
            if len(key_display) != 0:
                return key_display[0]
        except:
            key_display = [child for child in self.key_displays_grid.get_children() if (isinstance(child, Gtk.Grid) and hasattr(child, 'active') and child.active is True)]
            if len(key_display) != 0:
                return key_display[0]

    def run_display_cleaner(self):

        timeout = datetime.now()
        # timeout = 0

        def init_manager():
            while True:
                logging.info("loop")
                sleep(self.app.gio_settings.get_int("display-timeout")/1000)

                if len(self.key_ids) != 0:

                    first_value = list(self.key_ids.keys())[0]
                    first_key_container = self.key_ids[first_value]

                    try:
                        second_value = list(self.key_ids.keys())[1]
                        second_key_container = self.key_ids[second_value]
                        if first_key_container.repeat_key and not second_key_container.repeat_key:
                            first_key_container.repeat_key = False
                            logging.info("stopped repeating")
                    except:
                        second_value = None

                    # logging.info("first:{}, second:{}, repeat:{}".format(first_value,second_value))

                    if not first_key_container.repeat_key:
                        logging.info("not repeating")
                        sleep(0.125)
                        first_key_container.set_reveal_child(False)
                        sleep(0.125)
                        GLib.idle_add(first_key_container.self_remove, None)
                        try:
                            del self.key_ids[first_value]
                        except:
                            pass
                        finally:
                            self.last_key = None
                            self.last_key_id = None

                        # sleep(0.25)

                        if len(self.key_ids) == 0:
                            logging.info("key_ids zero")
                            sleep(0.25)
                            key_display = [child for child in self.key_displays_grid.get_children() if (isinstance(child, Gtk.Grid) and hasattr(child, 'active') and child.active is True)]
                            if len(key_display) != 0:
                                key_display = key_display[0]

                                if len(key_display.key_grid.get_children()) == 0:
                                    key_display.key_grid_revealer.set_reveal_child(False)
                                    sleep(0.25)
                                    key_display.active_app_revealer.set_reveal_child(False)
                                    sleep(0.25)
                                    key_display.key_grid_revealer.set_visible(False)
                                    sleep(0.25)
                                    self.standby_revealer.set_reveal_child(True)
                                    GLib.idle_add(self.reposition, None)

                            self.stop_display_cleaner()
                            break

                    elif (datetime.now() - timeout).seconds > (self.app.gio_settings.get_int("repeat-timeout")/1000):
                        logging.info("timeout")
                        first_key_container.repeat_key = False

        self.display_cleaner_thread = threading.Thread(target=init_manager)
        self.display_cleaner_thread.daemon = True
        self.display_cleaner_thread.start()

    def stop_display_cleaner(self):
        self.stop_display_cleaner_thread = True
        self.display_cleaner_thread = None
        self.stop_display_cleaner_thread = False
        logging.info("stopped")

    def get_safe_area(self):
        window_width, window_height = self.get_size()
        root_x, root_y = self.get_position()

        screen = self.get_screen()
        screen_width = screen.width()
        screen_height = screen.height()
        # logging.info("screen:{0}".format((screen_width, screen_height)))

        display = screen.get_display()
        n_monitors = display.get_n_monitors()
        # logging.info("n_monitors:{0}".format(n_monitors))

        monitor = screen.get_monitor_at_window(self.get_window())
        # logging.info("get_monitor_at_window:{0}".format(monitor))

        monitor_geometry = screen.get_monitor_geometry(monitor)
        # logging.info("get_monitor_at_window:{0}".format((monitor_geometry.x, monitor_geometry.y, monitor_geometry.width, monitor_geometry.height)))

        work_area = screen.get_monitor_workarea(monitor)
        # logging.info("work_area:{0}".format((work_area.x, work_area.y, work_area.width, work_area.height)))

        offset_x = monitor_geometry.height - work_area.height
        offset_y = (screen_height-work_area.height)-work_area.y
        # logging.info("offset:{0}".format((offset_x, offset_y)))

        monitor = screen.get_primary_monitor()
        # logging.info("get_primary_monitor:{0}".format(monitor))

        monitor_geometry = screen.get_monitor_geometry(monitor)
        # logging.info("get_monitor_at_window:{0}".format((monitor_geometry.x, monitor_geometry.y, monitor_geometry.width, monitor_geometry.height)))

        work_area = screen.get_monitor_workarea(monitor)
        # logging.info("work_area:{0}".format((work_area.x, work_area.y, work_area.width, work_area.height)))

        offset_y = monitor_geometry.height - work_area.height
        offset_x = (screen_height-work_area.height)-work_area.y
        # logging.info("offset:{0}".format((offset_x, offset_y)))

        safe_area_width = screen_width - (screen_height - work_area.height - work_area.y) * 2
        # logging.info("safe_area:{}, window_width:{}".format(safe_area_width,window_width))

        return safe_area_width, window_width


import testenv; testenv.configure_for_tests()
import doctest, sys, unittest

def suite():
    unittest_modules = ['ext.activemapper',
                        'ext.assignmapper',
                        'ext.declarative',
                        'ext.orderinglist',
                        'ext.associationproxy']

    if sys.version_info >= (2, 4):
        doctest_modules = ['sqlalchemy.ext.sqlsoup']
    else:
        doctest_modules = []

    alltests = unittest.TestSuite()
    for name in unittest_modules:
        mod = __import__(name)
        for token in name.split('.')[1:]:
            mod = getattr(mod, token)
        alltests.addTest(unittest.findTestCases(mod, suiteClass=None))
    for name in doctest_modules:
        alltests.addTest(doctest.DocTestSuite(name))
    return alltests

if __name__ == '__main__':
    testenv.main(suite())


import random
import pytest
from keywords.utils import random_string

@pytest.mark.usefixtures("class_init")
class TestDictionary(object):

    @pytest.mark.parametrize("key, value", [
        (random_string(5), ""),
        (random_string(5), random_string(1)),
        (random_string(5), random_string(10)),
        (random_string(5), "_{}".format(random_string(5))),
        (random_string(5), "{}_".format(random_string(8))),
        (random_string(5), "_{}_".format(random_string(9))),
        (random_string(5), random_string(9).capitalize()),
        (random_string(5), random_string(9).upper()),
        (random_string(5), "{}12".format(random_string(5))),
        (random_string(5), random_string(10, digit=True))
    ])
    def test_create(self, key, value):
        '''
        @summary: Testing create method of Dictionary API
        '''
        if self.liteserv_platform == "ios" and value == "":
            pytest.skip("Test not applicable for ios")

        content_dict = self.dict_obj.create()
        self.dict_obj.setString(content_dict, key, value)
        assert self.dict_obj.getString(content_dict, key) == value

        hashmap = {}
        hashmap[key] = value
        content_dict_2 = self.dict_obj.create(hashmap)
        assert self.dict_obj.getString(content_dict_2, key) == value

    @pytest.mark.parametrize("key, value", [
        (random_string(5), random.uniform(1, 10)),
        (random_string(5), random.random()),
        (random_string(5), random.randint(1, 1000)),
        (random_string(5), random.randint(100000, 10000000)),
        (random_string(5), random_string(6))
    ])
    def test_contains(self, key, value):
        '''
        @summary: Testing contains method of Dictionary API
        '''
        test_dict = self.dict_obj.create()
        self.dict_obj.setString(test_dict, key, value)
        assert self.dict_obj.contains(test_dict, key)

    @pytest.mark.parametrize("num_of_keys", [
        9,
        99,
        999,
        9999
    ])
    def test_count(self, num_of_keys):
        '''
        @summary: Testing count method of Dictionary API
        '''
        hashmap = {}
        key = "string_key"
        value = "Test String"
        for i in range(num_of_keys):
            hashmap["{}_{}".format(key, i)] = value
        content_dict = self.dict_obj.create(hashmap)
        assert num_of_keys == self.dict_obj.count(content_dict)

    @pytest.mark.parametrize("key, value", [
        (random_string(6), True),
        (random_string(6), False)
    ])
    def test_get_set_boolean(self, key, value):
        '''
        @summary: Testing get and set Boolean methods of Dictionary API
        '''
        content_dict = self.dict_obj.create()
        self.dict_obj.setBoolean(content_dict, key, value)
        assert self.dict_obj.getBoolean(content_dict, key) == value

    def test_get_set_date(self):
        '''
        @summary: Testing get and set Date methods of Dictionary API
        '''
        key = "Date_key"
        value = self.datatype.setDate()
        content_dict = self.dict_obj.create()
        self.dict_obj.setDate(content_dict, key, value)
        assert self.datatype.compareDate(value, self.dict_obj.getDate(content_dict, key))

    def test_get_set_dictionary(self):
        '''
        @summary: Testing get and set Dictionary methods of Dictionary API
        '''
        hashmap = {}
        key = "Date_key"
        value = self.datatype.setDate()
        hashmap[key] = value
        key = "Double_key"
        value = self.datatype.setDouble(2.0)
        hashmap[key] = value
        key = "Float_key"
        value = self.datatype.setFloat(3.0)
        hashmap[key] = value
        key = "Integer_key"
        value = 4
        hashmap[key] = value
        key = "Long_key"
        value = self.datatype.setLong(1234567890)
        hashmap[key] = value
        key = "String_key"
        value = "Test String"
        hashmap[key] = value
        content = self.dict_obj.create(hashmap)
        content_dict = self.dict_obj.create()
        self.dict_obj.setDictionary(content_dict, "hashmap", content)
        content_check = self.dict_obj.getDictionary(content_dict, "hashmap")
        for key in hashmap:
            assert self.dict_obj.contains(content_check, key)

    @pytest.mark.parametrize("key, value", [
        (random_string(6), "{}".format(random.uniform(0, 1))),
        (random_string(6), "{}".format(random.uniform(1, 10))),
        (random_string(6), "{}".format(random.uniform(11, 100))),
        (random_string(6), "{}".format(random.uniform(101, 1000)))
    ])
    def test_get_set_double(self, key, value):
        '''
        @summary: Testing get and set Double methods of Dictionary API
        '''
        double_value = self.datatype.setDouble(float(value))
        content_dict = self.dict_obj.create()
        self.dict_obj.setDouble(content_dict, key, double_value)
        assert self.datatype.compareDouble(double_value, self.dict_obj.getDouble(content_dict, key))

    @pytest.mark.parametrize("key, value", [
        (random_string(6), round(random.uniform(0, 1), 3)),
        (random_string(6), round(random.uniform(1, 10), 3)),
        (random_string(6), round(random.uniform(11, 100), 3)),
        (random_string(6), round(random.uniform(101, 1000), 3))
    ])
    def test_get_set_float(self, key, value):
        '''
        @summary: Testing get and set Float methods of Dictionary API
        '''
        content_dict = self.dict_obj.create()
        self.dict_obj.setFloat(content_dict, key, value)
        assert value == self.dict_obj.getFloat(content_dict, key)

    @pytest.mark.parametrize("key, value", [
        (random_string(6), random.randint(0, 9)),
        (random_string(6), random.randint(10, 99)),
        (random_string(6), random.randint(100, 999)),
        (random_string(6), random.randint(1000, 9999))
    ])
    def test_get_set_int(self, key, value):
        '''
        @summary: Testing get and set Integer methods of Dictionary API
        '''
        content_dict = self.dict_obj.create()
        self.dict_obj.setInt(content_dict, key, value)
        assert value == self.dict_obj.getInt(content_dict, key)

    @pytest.mark.parametrize("key, value", [
        (random_string(6), "{}".format(random.randint(0, 1))),
        (random_string(6), "{}".format(random.randint(1, 10))),
        (random_string(6), "{}".format(random.randint(11, 100))),
        (random_string(6), "{}".format(random.randint(101, 1000)))
    ])
    def test_get_set_long(self, key, value):
        '''
        @summary: Testing get and set Long methods of Dictionary API
        '''
        if self.liteserv_platform == "ios":
            pytest.skip("Test not applicable for ios")

        long_value = self.datatype.setLong(value)
        content_dict = self.dict_obj.create()
        self.dict_obj.setLong(content_dict, key, long_value)
        assert self.datatype.compare(long_value,
                                     self.dict_obj.getLong(content_dict,
                                                           key))

    @pytest.mark.parametrize("key, value", [
        (random_string(5), ""),
        (random_string(5), random_string(1)),
        (random_string(5), random_string(10)),
        (random_string(5), "_{}".format(random_string(5))),
        (random_string(5), "{}_".format(random_string(8))),
        (random_string(5), "_{}_".format(random_string(9))),
        (random_string(5), random_string(9).capitalize()),
        (random_string(5), random_string(9).upper()),
        (random_string(5), "{}12".format(random_string(5))),
        (random_string(5), random_string(10, digit=True)),
        (random_string(128), random_string(128, True, True)),
    ])
    def test_get_set_string(self, key, value):
        '''
        @summary: Testing get and set String methods of Dictionary API
        '''
        content_dict = self.dict_obj.create()
        self.dict_obj.setString(content_dict, key, value)
        assert value == self.dict_obj.getString(content_dict, key)

    @pytest.mark.parametrize("key, value, num_of_keys", [
        (random_string(5), random_string(5), 9),
        (random_string(5), random_string(5), 99),
        (random_string(5), random_string(5), 999),
        (random_string(5), random_string(5), 9999)
    ])
    def test_getKeys(self, key, value, num_of_keys):
        '''
        @summary: Testing getKeys methods of Dictionary API
        '''
        hashmap = {}
        keys_list = []
        for i in range(num_of_keys):
            keys_list.append("{}_{}".format(key, i))
            hashmap["{}_{}".format(key, i)] = value
        content_dict = self.dict_obj.create(hashmap)
        keys_list.sort()
        assert sorted(self.dict_obj.getKeys(content_dict)) == keys_list

    @pytest.mark.parametrize("key, value", [
        (random_string(5), random.uniform(1, 10)),
        (random_string(5), random.random()),
        (random_string(5), random.randint(1, 1000)),
        (random_string(5), random.randint(100000, 10000000)),
        (random_string(5), random_string(6))
    ])
    def test_remove(self, key, value):
        '''
        @summary: Testing remove method of Dictionary API
        '''
        hashmap = {}
        hashmap[key] = value
        content = self.dict_obj.create(hashmap)
        self.dict_obj.remove(content, key)
        assert not self.dict_obj.contains(content, key)

    def test_toMap(self):
        '''
        @summary: Testing remove method of Dictionary API
        '''
        hashmap = {
            "Float_key": "{}".format(random.random()),
            "Integer_key": random.randint(1, 1000),
            "Long_key": random.randint(100000, 10000000),
            "String_key": random_string(6)
        }
        content_dict = self.dict_obj.create(hashmap)
        result_dict = self.dict_obj.toMap(content_dict)
        assert hashmap == result_dict


from configparser import ConfigParser
from os.path import exists as file_exists

config = ConfigParser()

def tbaAppend(tbaSecret):
    print(tbaSecret)
    config.set('main', 'TBA-KEY', tbaSecret)
    with open('settings.ini', 'w+') as f:
        config.write(f)
    return str(config.get('main', 'TBA-KEY'))

# function for the settings creation and checker, called every time the main program is run to make sure a settings file always exists
def configSetup():

    config.read('settings.ini')

    #check for settings.ini. If it exists, we good. Otherwise, create with these default values.
    if file_exists('settings.ini'):
        print("settings.ini already exists!")

    else:
        config.add_section('main')
        #Need to make a way to ask the user for key on first time startup
        config.set('main', 'TBA-KEY', '')
        config.set('main', "rounding",'2')
        config.set('main',"stop-time",'35')

        with open('settings.ini', 'w') as f:
            config.write(f)
        print("Settings.ini has been created.")


class Solution:
    #time - O(n)
    #space - O(1)
    def findDuplicates(self, nums: List[int]) -> List[int]:
        result = []

        for i, val in enumerate(nums):
            val = abs(val)
            if nums[val - 1] < 0:
                result.append(val)
            else:
                nums[val - 1] = -nums[val - 1]

        return result

#sorting was helping me group numbers together, same as hashmap

#[0,1,2,3,4,5,6,7]

#[-4,-3,-2,-7,8,2,-3,-1]

#[2,3]

#go thru each value in my array, treat each value as an index itslef
#mark each index value, if it has been marked, push to array


from typing import Dict, Optional, Any, List

from helix_fhir_client_sdk.dictionary_writer import convert_dict_to_str

class FhirValidationException(Exception):
    def __init__(
        self,
        *,
        request_id: Optional[str],
        url: str,
        json_data: str,
        response_text: Optional[str],
        response_status_code: Optional[int],
        message: str,
        headers: Dict[str, str],
        issue: Optional[List[Dict[str, Any]]],
    ) -> None:
        """
        Validation Failure

        :param request_id: request id
        :param url: url that was being accessed
        :param json_data: data that was being sent
        :param response_text: response from the FHIR server
        :param response_status_code: status code returned by FHIR server
        :param message: error message
        :param issue: FHIR OperationOutcomeIssue
        """
        self.request_id: Optional[str] = request_id
        self.url: str = url
        self.data: str = json_data
        self.headers = headers
        self.issue: Optional[List[Dict[str, Any]]] = issue
        json = {
            "message": f"FHIR validation failed: {message}",
            "request_id": request_id,
            "url": url,
            "status_code": response_status_code,
            "headers": headers,
            "response_text": response_text,
            "json_data": json_data,
            "issue": issue,
        }

        super().__init__(convert_dict_to_str(json))


import numpy as np
from die import Die
from players import Players

debug = True

def random_number():
    return np.random.randint(1,7)

def setup_dice(player):
    dice = []
    for numbers in range(player.get_die_count()):
        die = Die(6)
        dice.append(die.roll())

    return dice

def compare(attacker, defender):
    if attacker > defender:
        return True
    return False

def match_round(attacker, defender):

    attacker_loses = 0
    while (attacker.units > 0 and defender.units > 0 and attacker.loses > attacker_loses):
        attacker_dice = setup_dice(attacker)
        defender_dice = setup_dice(defender)
        attacker_dice.sort(reverse=True)
        defender_dice.sort(reverse=True)

        while (attacker_dice and defender_dice and attacker.loses > attacker_loses):
            if debug: print ('Attacker Dice: {}'.format(attacker_dice))
            if debug: print ('Defender Dice: {}'.format(defender_dice))
            outcome = compare(attacker_dice[0], defender_dice[0])
            if outcome:
                if debug: print ('attacker wins')
                defender.lost_unit()
                attacker.won_unit()

            else:
                if debug: print ('defender wins')
                attacker.lost_unit()
                defender.won_unit()
                attacker_loses += 1

            attacker_dice.pop(0)
            defender_dice.pop(0)

    print ("Attacker: {} remaining; Defender: {} remaining".format(attacker.units, defender.units))
    if debug: print (attacker_loses)

def ask_user():
    attack_units = int(input("Number of attackers: "))
    defender_units = int(input("Number of defenders: "))
    acceptable_loses = int(input("Number attack stops at: "))
    attacker = Players("attacker", attack_units)
    attacker.allowed_loses(acceptable_loses)
    defender = Players("defender", defender_units)
    return attacker, defender

def main():
    attacker, defender = ask_user()
    match_round(attacker, defender)

if __name__ == "__main__":
    main()


# !/usr/bin/python3
# -*- coding: UTF-8 -*-

import redis
import uuid
import time

class MyLock:

    def acquire_lock(self, conn, lockname, acquire_lock_time=10, lock_time_out=10):
        identifier = str(uuid.uuid4())
        print(identifier)

        end_time = time.time() + acquire_lock_time
        lockname = "lock:" + lockname
        print(lockname)
        while time.time() < end_time:
            if conn.setnx(lockname, identifier):
                conn.expire(lockname, lock_time_out)
                return identifier
            elif conn.ttl(lockname) == -1:
                # 如果没有设置过期时间
                conn.expire(lockname, lock_time_out)
            time.sleep(.001)
        return False

    def release_lock(self, conn, lockname, locked):
        pipe = conn.pipeline(True)
        lockname = "lock:" + lockname
        while True:
            try:
                pipe.watch(lockname)
                if pipe.get(lockname) == locked:
                    pipe.multi()
                    pipe.delete(lockname)
                    pipe.execute()
                    return True
                pipe.unwatch()
                break

            except redis.exceptions.WatchError:
                pass

        return False


import csv
import logging
import string

import six

from ..core.qt import QtCore, Qt
from camelot.view.controls import delegates
from camelot.admin.action.list_action import DeleteSelection
from camelot.admin.object_admin import ObjectAdmin
from camelot.admin.table import Table
from camelot.admin.action import Action, RowNumberAction
from camelot.view.art import ColorScheme
from camelot.core.exception import UserException
from camelot.core.utils import ugettext, ugettext_lazy as _
from camelot.view.utils import local_date_format

from . import action_steps

logger = logging.getLogger('camelot.view.import_utils')

class RowData(object):
    """Class representing the data in a single row of the imported file as an
    object with attributes column_0, column_1, ..., each representing the data
    in a single column of that row.

    since the imported file might contain less columns than expected in
    some rows, the RowData object returns None for not existing attributes

    :param row_data: a list containing the data
        [column_0_data, column_1_data, ...] for a single row
    """

    def __init__(self, row_number, row_data):
        self.id = row_number + 1
        i = 0
        for i, data in enumerate(row_data):
            self.__setattr__('column_%i' % i, data)
        self.columns = i + 1

    def __getattr__(self, attr_name):
        return None

    def __len__(self):
        return self.columns

    def __getitem__(self, i):
        return getattr(self, 'column_%i'%i)

def column_name(column):
    """Create a column name starting from an index starting at 0
    eg : column=0 -> name='A'
    """
    if column <= 25:
        return string.ascii_uppercase[column];
    else:
        return column_name((column//26)-1) + column_name(column%26)

class ColumnMapping( object ):
    """
    Object that maps a column in the rows to import to a field of the
    data model.

    :param column: a number that indicates which column is mapped
    :param rows: the list of RowData objects to import, the list should
        not be empty
    :param default_field: the default field that is mapped, or `None`

    """

    def __init__(self, column, rows, default_field=None):
        # show row is the row that will be previewed in the column
        # selection form
        self.column = column
        self.column_name = column_name(column)
        self.rows = rows
        self.field = default_field
        self.value = None
        self.preview_row = None
        self.set_preview_row(0)

    def get_preview_row(self):
        return self.preview_row

    def set_preview_row(self, row):
        if row >= 0 and row < len(self.rows):
            self.preview_row = row
            if self.column < len(self.rows[row]):
                self.value = self.rows[row][self.column]
            else:
                self.value = None

class ShowNext(Action):

    verbose_name = _('Show next')

    def model_run(self, model_context):
        for mapping in model_context.get_collection():
            mapping.set_preview_row(mapping.get_preview_row()+1)
            yield action_steps.UpdateObject(mapping)

class ShowPrevious(Action):

    verbose_name = _('Show previous')

    def model_run(self, model_context):
        for mapping in model_context.get_collection():
            mapping.set_preview_row(mapping.get_preview_row()-1)
            yield action_steps.UpdateObject(mapping)

class MatchNames(Action):
    """Use the data in the current row to determine field names"""

    verbose_name = _('Match names')

    def model_run(self, model_context):
        field_choices = model_context.admin.field_choices
        # create a dict that  will be used to search field names
        matches = dict( (six.text_type(verbose_name).lower(), fn)
                         for fn, verbose_name in field_choices if fn )
        matches.update( dict( (fn.lower().replace('_',''), fn)
                              for fn, _verbose_name in field_choices if fn) )
        for mapping in model_context.get_collection():
            if mapping.value is not None:
                field = matches.get(mapping.value.replace('_','').lower(), None)
                mapping.field = field
            else:
                mapping.field = None
            yield action_steps.UpdateObject(mapping)

class ColumnMappingAdmin(ObjectAdmin):
    """Admin class that allows the user to manipulate the column mappings

    :param admin: the admin object of the model in which to import
    :param entity: the class that is used to define the column mapping
    :param field_choices: the list of fields out of which the user can select
    """

    verbose_name = _('Select field')
    verbose_name_plural = _('Select fields')

    list_action = None
    list_display = ['column_name', 'field', 'value']
    field_attributes = {'column_name': {'name':_('Column'),},}

    def __init__(self, admin, entity = ColumnMapping, field_choices=[]):
        super(ColumnMappingAdmin, self).__init__(admin, entity)
        self.field_choices = [(None,'')] + field_choices

    def get_field_attributes( self, field_name ):
        fa = ObjectAdmin.get_field_attributes(self, field_name)
        if field_name=='field':
            fa.update({'delegate':delegates.ComboBoxDelegate,
                        'editable':True,
                        'choices': self.field_choices })
        return fa

    def get_related_toolbar_actions(self, toolbar_area, direction):
        return [ShowNext(), ShowPrevious(), MatchNames()]

class ColumnSelectionAdmin(ColumnMappingAdmin):
    """Admin to edit a `ColumnMapping` class without data preview
    """

    list_display = ['column_name', 'field']
    list_actions = []
    related_toolbar_actions = []

    def get_related_toolbar_actions(self, toolbar_area, direction):
        return self.related_toolbar_actions

# see http://docs.python.org/library/csv.html
class UTF8Recoder( six.Iterator ):
    """Iterator that reads an encoded stream and reencodes the input to
    UTF-8."""

    def __init__(self, f, encoding):
        self.reader = f

    def __iter__(self):
        return self

    def __next__(self):
        return six.next(self.reader).encode('utf-8')

# see http://docs.python.org/library/csv.html
class UnicodeReader( six.Iterator ):
    """A CSV reader which will iterate over lines in the CSV file "f", which is
    encoded in the given encoding."""

    def __init__(self, f, dialect=csv.excel, encoding='utf-8', **kwds):
        if six.PY3==False:
            f = UTF8Recoder(f, encoding)
        self.encoding = encoding
        self.reader = csv.reader(f, dialect=dialect, **kwds)
        self.line = 0

    def __next__( self ):
        self.line += 1
        try:
            row = six.next(self.reader)
            if six.PY3==False:
                return [six.text_type(s, 'utf-8') for s in row]
            else:
                return row
        except UnicodeError as exception:
            raise UserException( text = ugettext('This file contains unexpected characters'),
                                 resolution = ugettext('Recreate the file with %s encoding') % self.encoding,
                                 detail = ugettext('Exception occured at line %s : ') % self.line + six.text_type( exception ) )

    def __iter__( self ):
        return self

class XlsReader( six.Iterator ):
    """Read an XLS/XLSX file and iterator over its lines.

    The iterator returns each line of the excel as a list of strings.

    The to_string field attribute is supposed to be able to interprete those
    strings and create a valid datatype.

    :param filename: the name of the xls or xlsx file
    """

    def __init__( self, filename ):
        import xlrd
        try:
            workbook = xlrd.open_workbook(filename, formatting_info=True)
        except NotImplementedError:
            # xlsx does not yet support formatting info
            workbook = xlrd.open_workbook(filename)
        self.xf_list = workbook.xf_list
        self.datemode = workbook.datemode
        self.format_map = workbook.format_map
        self.sheets = workbook.sheets()
        self.sheet = self.sheets[0]
        self.current_row = 0
        self.date_format = local_date_format()
        self.locale = QtCore.QLocale()

    def get_format_string( self, xf_index ):
        """:return: the string that specifies the format of a cell"""
        # xlsx has no formatting info, as such the xf_index is None
        if xf_index == None:
            return '0.00'
        try:
            xf = self.xf_list[ xf_index ]
        except IndexError:
            return '0.00'
        if xf._format_flag == 0:
            return self.get_format_string( xf.parent_style_index )
        f = self.format_map[ xf.format_key ]
        return f.format_str

    def __next__( self ):
        import xlrd
        if self.current_row < self.sheet.nrows:
            vector = []
            for column in range( self.sheet.ncols ):
                cell = self.sheet.cell( self.current_row, column )
                ctype = cell.ctype
                value = ''
                if ctype in( xlrd.XL_CELL_EMPTY,
                             xlrd.XL_CELL_ERROR,
                             xlrd.XL_CELL_BLANK ):
                    pass
                elif ctype == xlrd.XL_CELL_TEXT:
                    value = six.text_type( cell.value )
                elif ctype == xlrd.XL_CELL_NUMBER:
                    format_string = self.get_format_string( cell.xf_index )
                    # try to display the number with the same precision as
                    # it was displayed in excel
                    precision = max( 0, format_string.count('0') - 1 )
                    # see the arguments format documentation of QString
                    # format can be eiter 'f' or 'e', where 'e' is scientific
                    # so maybe the format string should be parsed further to
                    # see if it specifies scientific notation.  scientific
                    # notation is not used because it loses precision when
                    # converting to a string
                    value = six.text_type( self.locale.toString( cell.value,
                                                           format = 'f',
                                                           precision = precision ) )
                elif ctype == xlrd.XL_CELL_DATE:
                    # this only handles dates, no datetime or time
                    date_tuple = xlrd.xldate_as_tuple( cell.value,
                                                       self.datemode )
                    dt = QtCore.QDate( *date_tuple[:3] )
                    value = six.text_type( dt.toString( self.date_format ) )
                elif ctype == xlrd.XL_CELL_BOOLEAN:
                    value = 'false'
                    if cell.value == 1:
                        value = 'true'
                else:
                    logger.error( 'unknown ctype %s when importing excel'%ctype )
                vector.append( value )
            self.current_row += 1
            return vector
        else:
            raise StopIteration()

    def __iter__( self ):
        return self

class RowDataAdmin(object):
    """Decorator that transforms the Admin of the class to be imported to an
    Admin of the RowData objects to be used when previewing and validating the
    data to be imported.

    based on the field attributes of the original mode, it will turn the
    background color pink if the data is invalid for being imported.

    :param admin: the `camelot.admin.object_admin.ObjectAdmin` admin object
        of the objects that will be imported
    :param column_mappings: list of `ColumnMapping` object that maps the columns
        in the row data to fields of the objects.
    """

    list_action = RowNumberAction()
    list_actions = [DeleteSelection()]

    def __init__(self, admin, column_mappings):
        self.admin = admin
        self._new_field_attributes = {}
        self._columns = []
        for column_mapping in column_mappings:
            field_name = 'column_%i'%column_mapping.column
            original_field = column_mapping.field
            if original_field != None:
                fa = self.new_field_attributes(original_field)
                self._columns.append( (field_name, fa) )
                self._new_field_attributes[field_name] = fa

    def get_columns(self):
        return self._columns

    def get_verbose_identifier(self, obj):
        return six.text_type()

    def __getattr__(self, attr):
        return getattr(self.admin, attr)

    def get_fields(self):
        return self.get_columns()

    def get_table(self):
        return Table( [fn for fn, _fa in self.get_columns()] )

    def get_all_fields_and_attributes(self):
        """
        reimplementation needed to support replace field contents during import
        """
        return self._new_field_attributes

    def get_validator(self, model):
        """Creates a validator that validates the data to be imported, the
        validator will check if the background of the cell is pink, and if it
        is it will mark that object as invalid.
        """
        from camelot.admin.validator.object_validator import ObjectValidator

        class NewObjectValidator(ObjectValidator):

            def validate_object(self, obj):
                columns = self.admin.get_columns()
                dynamic_attributes = self.admin.get_dynamic_field_attributes(
                    obj,
                    [c[0] for c in columns]
                )
                for attrs in dynamic_attributes:
                    if attrs['background_color'] == ColorScheme.pink_1:
                        logger.debug('we have an invalid field')
                        return ['invalid field']
                return []

        return NewObjectValidator(self, model)

    def flush(self, obj):
        """When flush is called, don't do anything, since we'll only save the
        object when importing them for real"""
        pass

    def is_persistent(self, obj):
        return True

    def delete(self, obj):
        pass

    def get_related_toolbar_actions(self, toolbar_area, direction):
        if toolbar_area==Qt.RightToolBarArea:
            return self.list_actions

    def get_field_attributes(self, field_name):
        return self._new_field_attributes[field_name]

    def get_static_field_attributes(self, field_names):
        for field_name in field_names:
            attributes = self.get_field_attributes(field_name)
            yield {'editable':True,
                   'name': attributes['name'],
                   'delegate': attributes['delegate'],
                   'column_width': attributes['column_width'],
                   'field_name': field_name}

    def get_dynamic_field_attributes(self, obj, field_names):
        for field_name in field_names:
            attributes = self.get_field_attributes(field_name)
            string_value = getattr(obj, field_name)
            valid = True
            value = None
            if 'from_string' in attributes:
                try:
                    value = attributes['from_string'](string_value)
                except Exception:
                    valid = False
                # 0 is valid
                if value != 0 and not value and not attributes['nullable']:
                    valid = False
            if valid:
                yield {'background_color':None}
            else:
                yield {'background_color':ColorScheme.pink_1}

    def new_field_attributes(self, original_field):
        from camelot.view.controls import delegates

        original_field_attributes = self.admin.get_field_attributes(original_field)
        attributes = dict(original_field_attributes)
        attributes['delegate'] = delegates.PlainTextDelegate
        attributes['python_type'] = str
        attributes['original_field'] = original_field

        # remove some attributes that might disturb the import wizard
        for attribute in ['background_color', 'tooltip']:
            attributes[attribute] = None

        return attributes


from nes_py.wrappers import JoypadSpace
import gym_super_mario_bros
from gym_super_mario_bros.actions import SIMPLE_MOVEMENT
from IPython import embed
import gym
from gym.wrappers import *
import matplotlib.pyplot as plt
from ppo import Agent
import numpy as np
import torch

env = gym_super_mario_bros.make('SuperMarioBros-v2')
env = JoypadSpace(env, SIMPLE_MOVEMENT)
env = gym.wrappers.ResizeObservation(env, (84, 84))
env = gym.wrappers.GrayScaleObservation(env)
env = gym.wrappers.FrameStack(env, 4)

done = False
state = env.reset()

agent = Agent().cuda()

agent.load_state_dict(torch.load("ppo-12648448.pt"))

agent.eval()

steps = 0
obs = env.reset()
while not done:
    action, logprob, _, value = agent.get_action_and_value(torch.Tensor(obs).unsqueeze(0).cuda())
    obs, reward, done, info = env.step(action.item())
    num_lives = info["life"]

    if num_lives < 2:
        done = True

    if done:
        break

    steps += 1
    env.render()

env.close()
print(steps)


from __future__ import unicode_literals

from django.core.files.storage import FileSystemStorage
from django.utils.encoding import force_bytes

from mayan.apps.storage.utils import fs_cleanup, mkdtemp

from ..models import Cache

from .literals import (
    TEST_CACHE_LABEL, TEST_CACHE_MAXIMUM_SIZE, TEST_CACHE_NAME,
    TEST_CACHE_PARTITION_FILE_FILENAME, TEST_CACHE_PARTITION_FILE_SIZE,
    TEST_CACHE_PARTITION_NAME, TEST_CACHE_STORAGE_INSTANCE_PATH
)

test_storage = None

class CacheTestMixin(object):
    def setUp(self):
        super(CacheTestMixin, self).setUp()
        global test_storage
        self.temporary_directory = mkdtemp()
        test_storage = FileSystemStorage(location=self.temporary_directory)

    def tearDown(self):
        fs_cleanup(filename=self.temporary_directory)
        super(CacheTestMixin, self).tearDown()

    def _create_test_cache(self):
        self.test_cache = Cache.objects.create(
            label=TEST_CACHE_LABEL,
            storage_instance_path=TEST_CACHE_STORAGE_INSTANCE_PATH,
            maximum_size=TEST_CACHE_MAXIMUM_SIZE,
            name=TEST_CACHE_NAME,
        )

    def _create_test_cache_partition(self):
        self.test_cache_partition = self.test_cache.partitions.create(
            name=TEST_CACHE_PARTITION_NAME
        )

    def _create_test_cache_partition_file(self):
        with self.test_cache_partition.create_file(filename=TEST_CACHE_PARTITION_FILE_FILENAME) as file_object:
            file_object.write(
                force_bytes(' ' * TEST_CACHE_PARTITION_FILE_SIZE)
            )

        self.test_cache_partition_file = self.test_cache_partition.files.get(
            filename=TEST_CACHE_PARTITION_FILE_FILENAME
        )

class CacheViewTestMixin(object):
    def _request_test_cache_list_view(self):
        return self.get(viewname='file_caching:cache_list')

    def _request_test_cache_purge_view(self):
        return self.post(
            viewname='file_caching:cache_purge', kwargs={
                'cache_id': self.test_cache.pk
            }
        )

    def _request_test_cache_multiple_purge_view(self):
        return self.post(
            viewname='file_caching:cache_multiple_purge', data={
                'id_list': self.test_cache.pk
            }
        )


from fastapi import APIRouter, Depends, Request, status, HTTPException, File, UploadFile
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from sqlalchemy.orm import Session
from fastapi.security import HTTPBearer
from db import get_db
import crud
import models as mod

image_router = APIRouter(tags=['Image'])

@image_router.post('/api/create-image/{plant_id}', dependencies=[Depends(HTTPBearer())])
async def create_image(plant_id: int, header_param: Request, db: Session = Depends(get_db), file: UploadFile = File(...)):
    result = await crud.create_image(plant_id, header_param, db, file)
    if result == -1:
        return HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
    if result == -2:
        result = {'msg': 'Вы не можете добавлять больше 6 картинок!!!'}
        result = jsonable_encoder(result)
        return JSONResponse(content=result, status_code=status.HTTP_200_OK)
    if result:
        result = jsonable_encoder(result)
        result['msg'] = 'Создано!'
        return JSONResponse(content=result, status_code=status.HTTP_201_CREATED)
    else:
        return HTTPException(status_code=status.HTTP_204_NO_CONTENT)

@image_router.get('/api/get-image/{plant_id}')
async def get_image(plant_id: int, db: Session = Depends(get_db)):
    result = await crud.read_image(plant_id, db)
    if result == -1:
        return HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
    if result:
        result = jsonable_encoder(result)
        return JSONResponse(content=result, status_code=status.HTTP_200_OK)
    else:
        return HTTPException(status_code=status.HTTP_204_NO_CONTENT)

@image_router.delete('/api/delete-image/{id}', dependencies=[Depends(HTTPBearer())])
async def delete_image(id: int, header_param: Request, db: Session = Depends(get_db)):
    result = await crud.delete_image(id, header_param, db)
    if result == -1:
        return HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
    if result:
        result = jsonable_encoder(result)
        return JSONResponse(content=result, status_code=status.HTTP_200_OK)
    else:
        return HTTPException(status_code=status.HTTP_204_NO_CONTENT)