from time import sleep, perf_counter
from typing import Any, Dict, Optional, Callable
import logging
import threading

from .filament_sensors import FilamentSensor
from .limit_switch import LimitSwitch
from .servo import Servo

_logger = logging.getLogger('Actuator Logger')
_logger.addHandler(logging.NullHandler())

default_actuators = [
    {
        "id": "black_wire",
        "pusher": {"role": "Pusher Servo", "board": 0x40, "channel": 0x0, "min_angle":0, "max_angle":180},
        "moving_clamp": {"role": "Moving Clamp Servo", "board": 0x40, "channel": 0x1, "min_angle":0, "max_angle":180},
        "fixed_clamp": {"role": "Fixed Clamp Servo", "board": 0x40, "channel": 0x2, "min_angle":0, "max_angle":180},
        "pusher_limit_switch": {"board": 0x20, "channel": 0x0},
        "filament_sensor": {"board": 0x21, "channel": 0x0},
    },
]

# Constants for servo positions and delays
OPEN = 0
CLOSED = 1
BACK = 1
FRONT = 0
CLAMP_DELAY_SECONDS = 1
PUSHER_DELAY_SECONDS = 1.5
PUSHER_SWEEP_DEGREES_PER_SECOND = 30 / 0.3

class ActuatorRuntimeError(RuntimeError):
    """Exception raised for runtime errors in the Servo class."""
    def __init__(self, message: str, original_exception: Exception = None):
        self.original_exception = original_exception
        message = f"{message} Original exception:  {self.original_exception}"
        super().__init__(message)

class Actuator:
    def __init__(self, data: Dict[str, Any]):
        self.id = data.get("id")    # Need to rename - this is a nickname, not the id

        self.fixed_clamp = Servo(data.get("fixed_clamp"))
        self.moving_clamp = Servo(data.get("moving_clamp"))
        self.pusher = Servo(data.get("pusher"))
        self.pusher_limit_switch = LimitSwitch(data.get("pusher_limit_switch"))
        self.filament_sensor = FilamentSensor(data.get("filament_sensor"))
        self.hash_code =  data.get("hash_code", "-- hash code_ missing -- ")

        # TODO: add next three to persisted settings data.
        self.distance_to_filament_sensor_mm = data.get("distance_to_filament_sensor_mm", 280)
        self.step_length_in_mm = data.get("step_length_in_mm", 18.0)
        self.time_step_seconds = data.get("time_step_seconds", 0.02)

        self.thread_task = None
        self._task_thread = None
        self._stop_event = threading.Event()
        self.step_index = None
        self.nsteps = None

        slow_step_time = 4
        moderate_step_time = 1
        brisk_step_time = 0.5
        quick_step_time = 0.1

        _logger.info(f"self.step_length_in_mm: {self.step_length_in_mm }")
        self.qualitative_speed_to_mm_per_second = {
            'slow': self.step_length_in_mm/slow_step_time,
            'moderate': self.step_length_in_mm/moderate_step_time,
            'brisk': self.step_length_in_mm/brisk_step_time,
            'quick': self.step_length_in_mm/quick_step_time,
        }

        _logger.info(f"self.qualitative_speed_to_mm_per_second: {self.qualitative_speed_to_mm_per_second }")

    def __str__(self):
        return "Actuator " \
            f"\n   ID: {self.id}," \
            f"\n   Filament Sensor: {self.filament_sensor}, " \
            f"\n   Fixed Clamp: {self.fixed_clamp}," \
            f"\n   Moving Clamp: {self.moving_clamp}, " \
            f"\n   Pusher: {self.pusher}, " \
            f"\n   Pusher Limit Switch: {self.pusher_limit_switch}"

    def __repr__(self):
        return (
            f"Actuator(data={{"
            f"'id': {repr(self.id)}, "
            f"'filament_sensor': {repr(self.filament_sensor)}, "
            f"'fixed_clamp': {repr(self.fixed_clamp)}, "
            f"'moving_clamp': {repr(self.moving_clamp)}, "
            f"'pusher': {repr(self.pusher)}, "
            f"'pusher_limit_switch': {repr(self.pusher_limit_switch)}"
            f"}})"
            )

    def to_data(self):
        return {
            'id': self.id,
            'fixed_clamp': self.fixed_clamp.to_data(),
            'moving_clamp': self.moving_clamp.to_data(),
            'pusher': self.pusher.to_data(),
            'pusher_limit_switch': self.pusher_limit_switch.to_data(),
            'filament_sensor': self.filament_sensor.to_data(),
            'hash_code': self.hash_code
        }

    def task_is_running(self) -> bool:
        return self._task_thread is not None

    def load_filament(self, status_callback: Callable[[Dict], None], speed: Optional[Dict] = None) -> None:
        """
        Method for loading filament into the actuator.
        """
        _logger.info(f"Loading filament for actuator with hash {self.hash_code}")
        self.thread_task = "Load Filament"

        if self._task_thread is not None:
            _logger.error(f"Can't load filament.  Task already running.")
            raise ActuatorRuntimeError(f"Task already running.   Cancel or rety later.")

        # TODO: Parse speed in the foreground so that we can fail fast.
        max_steps = max(1, int(self.distance_to_filament_sensor_mm/self.step_length_in_mm))
        stop_at = {
            "step": max_steps,
            "filament_sensed": True
        }
        # This is a long running task, so we'll run it in a thread.
        def task_runner():
            self._stop_event.clear()
            # Advance until number of steps reached or filament is sensed
            self.advance_filament(stop_at=stop_at, speed=speed, status_callback=status_callback)

            if not self._stop_event.is_set():
                # Retract one step, so that the filament is ready to be loaded,
                # but not signalling that it is loaded into printer.
                # TODO:  Implement stop_at limit switch going from triggered to not.
                self.retract_filament(speed=speed, status_callback=status_callback)

            _logger.info(f"load_filament finished.")
            if status_callback is not None:
                _logger.info(f"Making status_callback with completed status")
                status_callback({
                    "thread_task": self.thread_task,
                    "nickname": self.id,
                    "completed": "true",
                    "step": self.step_index,
                    "nsteps": self.nsteps,
                    "filament_sensed": self.filament_sensor.is_filament_sensed(),
                    "pusher_position": self.pusher.position,
                    "pusher_limit_switch_is_triggered":  self.pusher_limit_switch.is_triggered()
            })
            self._task_thread = None
            self.thread_task = None

        self._task_thread = threading.Thread(target=task_runner)
        self._task_thread.daemon = True
        self._task_thread.start()

    def unload_filament(self, status_callback: Callable[[Dict], None], speed: Optional[Dict] = None) -> None:
        """
        Method for unloading filament from the actuator.
        """
        _logger.info(f"Unloading filament for actuator with hash {self.hash_code}")

        self.task_unload_filament(speed)

    def task_unload_filament(self, status_callback: Callable[[Dict], None], speed: Optional[Dict] = None) -> None:
        """
        Task method that handles the actual unloading of the filament.
        """
        # Your unloading logic here
        pass

    def advance_filament(self, status_callback: Callable[[Dict], None], stop_at: Optional[Dict] = None, speed: Optional[Dict] = None) -> None:
        _logger.info(f"Advancing filament for actuator with hash {self.hash_code}, stopping at {stop_at} with speed {speed}")
        self.task_advance_filament(stop_at=stop_at, speed=speed, status_callback=status_callback)

    def share_status(self, status_callback, speed, servo_move_count=None):
        if status_callback is not None:
            rate_in_mm_per_sec = self.rate_from_speed(speed)
            status = {
                "thread_task": self.thread_task,
                "nickname": self.id,
                "step": self.step_index,
                "nsteps": self.nsteps,
                "filament_sensed": self.filament_sensor.is_filament_sensed(),
                "pusher_position": self.pusher.position,
                "pusher_limit_switch_is_triggered":  self.pusher_limit_switch.is_triggered(),
                "rate_in_mm_per_sec": rate_in_mm_per_sec,
                "servo_move_count": servo_move_count,
            }
            _logger.info(f"Task status_callback status: {status}")
            status_callback(status)
            _logger.info(f"In share_status, callback returned.")

    def task_advance_filament(
            self,
            status_callback: Callable[[Dict], None],
            stop_at: Optional[Dict] = None,
            speed: Optional[Dict] = None) -> None:

        # Default to one step if "step" is not provided in stop_at
        nsteps = 1
        if stop_at and "step" in stop_at:
            try:
                nsteps = int(stop_at["step"])
            except ValueError:
                _logger.error("Invalid step value provided in stop_at.")
                return

        self.nsteps = nsteps
        self.step_index = 0
        # At start of task, want to inform progress dialog of number of steps and condition of sensors
        self.share_status(status_callback, speed)
        _logger.info(f"In task_advance_filament, initial status shared.")

        do_stop_at_filament_sensor = stop_at is not None and stop_at.get("filament_sensed", False)
        for self.step_index in range(self.nsteps):
            self.task_advance_filament_one_step(stop_at=stop_at, speed=speed, status_callback=status_callback)
            if do_stop_at_filament_sensor:
                if self.filament_sensor.is_filament_sensed():
                    break
            if self._stop_event.is_set():
                _logger.info(f"In task_advance_filament, task canceled by stop event.")
                break;

    def task_advance_filament_one_step(
            self,
            status_callback: Callable[[Dict], None],
            stop_at: Optional[Dict] = None,
            speed: Optional[Dict] = None,
            start_position=BACK,
            end_position=FRONT):

        rate_in_mm_per_sec = self.rate_from_speed(speed)
        do_stop_at_filament_sensor = stop_at is not None and stop_at.get("filament_sensed", False)

        # Lock the filament so that the pusher can pull back
        self.fixed_clamp.position = CLOSED
        sleep(CLAMP_DELAY_SECONDS)
        self.moving_clamp.position = OPEN
        sleep(CLAMP_DELAY_SECONDS)

        # Retract the pusher
        self.pusher.at_rest = False
        _logger.info("Start of retraction sweep")
        self.pusher.sweep_to_position(start_position, PUSHER_SWEEP_DEGREES_PER_SECOND)
        _logger.info("End of retraction sweep")
        # self.pusher.position = start_position
        sleep(PUSHER_DELAY_SECONDS)
        if self._stop_event.is_set():
            _logger.info(f"In task_advance_filament_one_step, task canceled by stop event.")
            self.fixed_clamp.position = OPEN
            self.moving_clamp.position = OPEN
            self.pusher.at_rest = True
            return;

        # Lock the filament so that the pusher advance filament
        self.fixed_clamp.position = OPEN
        sleep(CLAMP_DELAY_SECONDS)
        self.moving_clamp.position = CLOSED
        sleep(CLAMP_DELAY_SECONDS)

        # Advance the filament at the desired rate
        _logger.info(f"Advance the filament one step from {start_position} to {end_position} "
                     f"at the desired rate: {rate_in_mm_per_sec} mm/sec, from speed: {speed}")
        servo_move_count = 0
        for position in self.next_position(rate_in_mm_per_sec, start_position, end_position):
            _logger.debug(f"position: {position}")
            self.pusher.position = position
            servo_move_count += 1
            sleep(self.time_step_seconds)
            if self.pusher_limit_switch.is_triggered():
                _logger.warning("Limit switch triggered! Stopping filament advance.")
                break
            if do_stop_at_filament_sensor:
                if self.filament_sensor.is_filament_sensed():
                    _logger.info(f"Step is terminated by sensing filament.")
                    break

        # Open up clamp in preparation for next step
        self.moving_clamp.position = OPEN
        sleep(CLAMP_DELAY_SECONDS)

        # Need to share status before resting servos:
        self.share_status(status_callback, speed, servo_move_count=servo_move_count)

        # Rest all of the servos, so that they don't chatter and strain.
        self.pusher.at_rest = True
        self.moving_clamp.at_rest = True
        self.fixed_clamp.at_rest = True

    def retract_filament(self, status_callback: Callable[[Dict], None], stop_at: Optional[Dict] = None, speed: Optional[Dict] = None) -> None:
        _logger.info(f"Retracting filament for actuator with hash {self.hash_code}, stopping at {stop_at} with speed {speed}")
        self.task_retract_filament(stop_at, speed)

    def task_retract_filament(self, stop_at: Optional[Dict] = None, speed: Optional[Dict] = None) -> None:
        # Default to one step if "step" is not provided in stop_at
        steps = 1

        if stop_at and "step" in stop_at:
            try:
                steps = int(stop_at["step"])
            except ValueError:
                _logger.error("Invalid step value provided in stop_at.")
                return
            if steps < 0:
                _logger.error(f"Invalid step value {stop_at['step']}provided in stop_at.")

        for _ in range(steps):
            self.task_retract_filament_one_step(stop_at=stop_at, speed=speed)
            if self._stop_event.is_set():
                _logger.info(f"In task_retract_filament, task canceled by stop event.")
                break;

    def task_retract_filament_one_step(self, stop_at: Optional[Dict] = None, speed: Optional[Dict] = None, start_position=FRONT, end_position=BACK):
        # TODO: generalize this to move filament_one_step, and handle limit switch correctly for both advance an retraction.
        rate_in_mm_per_sec = self.rate_from_speed(speed)
        # Ignore stop_at for now.

        # Lock the filament so that the pusher can move to starting position
        self.fixed_clamp.position = CLOSED
        # Try to move both servos at same time:  sleep(CLAMP_DELAY_SECONDS)
        self.moving_clamp.position = OPEN
        sleep(CLAMP_DELAY_SECONDS)

        # Retract the pusher
        self.pusher.position = start_position
        sleep(PUSHER_DELAY_SECONDS)

        # Lock the filament so that the pusher advance filament
        self.fixed_clamp.position = OPEN
        # Try to move both servos at same time:  sleep(CLAMP_DELAY_SECONDS)
        self.moving_clamp.position = CLOSED
        sleep(CLAMP_DELAY_SECONDS)

        # Move the filament at the desired rate
        _logger.info(f"Retract the filament on step from {start_position} to {end_position} at the desired rate: {rate_in_mm_per_sec} mm/sec, from speed: {speed}")
        for position in self.next_position(rate_in_mm_per_sec, start_position, end_position):
            _logger.debug(position)
            self.pusher.position = position
            sleep(self.time_step_seconds)
            # TODO: When checking for jams need to see if the pusher is still triggered
            # if the position is out of range of the limit switch and enough
            # time has passed and the switch is not being ignore.
            # if self.pusher_limit_switch.is_triggered() and other conditions:
            #     _logger.warning("Limit switch still triggered! Likely jam or malfunction. Stopping filament retraction.")
            #     break

        # Open up clamp in preparation for next step
        self.moving_clamp.position = OPEN
        sleep(CLAMP_DELAY_SECONDS)

        # Rest all of the servos, so that they don't chatter and strain.
        self.pusher.at_rest = True
        self.moving_clamp.at_rest = True
        self.fixed_clamp.at_rest = True

    def cancel_filament_move(self):
        _logger.info(f"In cancel_filament_move")
        self._stop_event.set()

    def calc_position_from_location(self, location_mm):
        position = location_mm/self.step_length_in_mm # Front is 0, back is 0
        return max(min(position, BACK), FRONT)

    def calc_location_from_position(self, position):
        # Location is measured from front to back.
        # The position must be between  the front and the back
        position = max(min(position, BACK), FRONT)
        location = position * self.step_length_in_mm
        return location

    def next_position(self, rate_in_mm_per_sec, start_position, end_position):
        start_time = perf_counter()
        start_mm = self.calc_location_from_position(start_position)
        end_mm = self.calc_location_from_position(end_position)
        end_time = start_time + abs(end_mm - start_mm) / rate_in_mm_per_sec
        direction = 1 if end_mm > start_mm else -1

        def mm_at_time(t):
            elapsed_time = t - start_time
            distance_moved = elapsed_time * rate_in_mm_per_sec
            return start_mm + direction * distance_moved

        current_time = start_time
        while current_time < end_time:
            yield self.calc_position_from_location(mm_at_time(current_time))
            current_time = perf_counter()

        yield self.calc_position_from_location(end_mm)

    def rate_from_speed(self, speed: Optional[Dict] = None) -> float:

        if speed is None:
            speed = {}

        qualitative_speed = speed.get("qualitive", "quick")
        try:
            mm_per_second = self.qualitative_speed_to_mm_per_second[qualitative_speed]
        except KeyError:
            raise ValueError(f"Unknown qualitative speed value: {qualitative_speed} speed: {speed}")

        # Attempt to override with quantitative speed if it exists
        try:
            quantitative_speed = speed.get("quantitative")
            if quantitative_speed is not None:
                mm_per_second = float(quantitative_speed)
        except ValueError:
            raise ValueError(f"Invalid quantitative speed value: {quantitative_speed} speed: {speed}")

        return mm_per_second

class Actuators:
    def __init__(self, logger, actuators_data):
        global _logger
        _logger = logger
        self.items = [Actuator(data) for data in actuators_data]
        self.filament_in_printer = None

    def __iter__(self):
        return iter(self.items)

    def __str__(self):
        return "\n".join(str(actuator) for actuator in self.items)

    def hash_codes_str(self):
        return "\n      ".join(f"'{actuator.hash_code}'" for actuator in self.items)

    def task_is_running(self):
        for actuator in self.items:
            if actuator.task_is_running():
                return True
        return False

    def handle_command(self, command, hash_code, stop_at=None, speed=None, status_callback=None):
        _logger.info(f"In Actuators.handle_command with command: {command}  hash_code: {hash_code} stop_at: {stop_at}, speed: {speed} status_callback: {status_callback}")

        # Searching for the actuator
        target_actuator = None
        for actuator in self.items:
            if actuator.hash_code == hash_code:
                target_actuator = actuator
                break

        if target_actuator is None:
            error_msg = (
                f"No actuator found with hash_code '{hash_code}'.\n "
                f"  Type of hash_code: {type(hash_code)}"
                f"  Possible hash_codes: {self.hash_codes_str()}"
            )
            _logger.warning(error_msg)
            return error_msg

        if command == "load_filament":
            target_actuator.load_filament(speed=speed, status_callback=status_callback)
        elif command == "unload_filament":
            target_actuator.unload_filament(speed=speed, status_callback=status_callback)
        elif command == "advance_filament":
            _logger.info(f"Calling advance_filament with stop_at: {stop_at}, speed: {speed}")
            target_actuator.advance_filament(stop_at=stop_at, speed=speed, status_callback=status_callback)
        elif command == "retract_filament":
            target_actuator.retract_filament(stop_at=stop_at, speed=speed, status_callback=status_callback)
        elif command == "cancel_filament_move":
            target_actuator.cancel_filament_move()
        else:
            # Unknown command
            return f"Unknown command {command}"

        # If everything goes well
        return None

    def to_data(self):
        return [actuator.to_data() for actuator in self.items]

    def dump(self):
        for actuator in self.items:
            _logger.info(f"Actuator Identifier: {actuator.hash_code}")

    def data_to_store(self) -> Dict[str, Any]:
        return {
            'filament_in_printer': self.filament_in_printer
        }

    def restore_data(self, data: Dict[str, Any]) -> None:
        self.filament_in_printer = data.get('filament_in_printer')


#!/usr/bin/python

import paho.mqtt.client as mqtt
import json
import logging

logging.basicConfig(filename='voltlog.log', level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')

def on_connect(client, userdata, flags, rc):
	client.subscribe("tele/sonoffpow/ENERGY")

def on_message(client, userdata, msg):
	carga = json.loads(msg.payload)
	volts = carga['Voltage']
	print(str(volts)+" volts")
	logging.info(volts)

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("10.0.0.254", 1883, 60)

try:
	client.loop_forever()

except KeyboardInterrupt:
	print("Exiting")


import random
# state = (playerCardValueExcludingAces, dealerCardValue, numAces)
# dealerCardValue belongs to {1, 2, 3, 4, ..., 10}

"""
Author: Shing Hei Ho (Adrian)
"""
###### helper method of the world dynamics #######

def dealCard(deck, dealerCards, playerCards, isToPlayer):
    card = random.choice(deck)
    deck.remove(card)
    if isToPlayer:
        playerCards[card] = playerCards.get(card, 0) + 1
    else:
        dealerCards.append(card)
    return card

def getPlayerCardValueExcludeAce(playerCards):
    cardValuesExcludeAces = 0
    numAces = 0
    for card, count in playerCards.items():
        if card != 1:
            cardValuesExcludeAces += card * count
        else:
            numAces+=count

    return cardValuesExcludeAces, numAces

def getDealerCardValueExcludeAce(dealerCards):
    cardValuesExcludeAces = 0
    numAces = 0
    for card in dealerCards:
        if card != 1:
            cardValuesExcludeAces += card
        else:
            numAces+=1

    return cardValuesExcludeAces, numAces

def computePlayerTotalValue(playerCards):
    playerCardValue, numAces = getPlayerCardValueExcludeAce(playerCards)

    if playerCardValue+numAces > 21:
        #bust
        return playerCardValue+numAces

    # values by caes
    if numAces==0:
        return playerCardValue
    elif numAces==1:
        options = [playerCardValue+1, playerCardValue+11]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue
    elif numAces==2:
        options = [playerCardValue+2, playerCardValue+11+1]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue
    elif numAces==3:
        options = [playerCardValue+3, playerCardValue+11+2]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue
    elif numAces==4:
        options = [playerCardValue+4, playerCardValue+11+3]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue

def computeDealerTotalValue(dealerCards):
    dealerCardValue, numAces = getDealerCardValueExcludeAce(dealerCards)

    if dealerCardValue+numAces > 21:
        #bust
        return dealerCardValue+numAces

    # values by caes
    if numAces==0:
        return dealerCardValue
    elif numAces==1:
        options = [dealerCardValue+1, dealerCardValue+11]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue
    elif numAces==2:
        options = [dealerCardValue+2, dealerCardValue+11+1]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue
    elif numAces==3:
        options = [dealerCardValue+3, dealerCardValue+11+2]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue
    elif numAces==4:
        options = [dealerCardValue+4, dealerCardValue+11+3]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue

def getLegalActions(state):
        if isTerminal(state):
            return []
        else:
            return ["hit", "stand"]

def isTerminal(state):
    playerCardValue, _, numAces = state
    if playerCardValue+numAces > 21:
        #bust
        return True

    # values by caes
    if numAces==0:
        return playerCardValue==21
    elif numAces==1:
        options = [playerCardValue+1, playerCardValue+11]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue==21
    elif numAces==2:
        options = [playerCardValue+2, playerCardValue+11+1]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue==21
    elif numAces==3:
        options = [playerCardValue+3, playerCardValue+11+2]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue==21
    elif numAces==4:
        options = [playerCardValue+4, playerCardValue+11+3]
        bestValue = 0
        for value in options:
            if value <= 21 and value > bestValue:
                bestValue = value
        return bestValue==21

def dealerPlay(dealerCards, deck, playerCards):
    dealerTotal = computeDealerTotalValue(dealerCards)

    while dealerTotal < 17:
        dealCard(deck, dealerCards, playerCards, isToPlayer = False)
        dealerTotal = computeDealerTotalValue(dealerCards)

    dealerTotal = computeDealerTotalValue(dealerCards)
    playerTotal = computePlayerTotalValue(playerCards)
    reward = 0.0
    if dealerTotal > 21:
        reward = 1.0
    elif dealerTotal < playerTotal:
        reward = 1.0
    elif dealerTotal == playerTotal:
        reward == 0.0
    else:
        reward = -1.0

    return reward


import sys
input = sys.stdin.readline

INF = 10**9
WHITE = -100
GRAY = -1000
BLACK = -10000

def main():
	m = int(input().strip())
	s = [[] for _ in range(m)]
	for i in range(m):
		s[i] = list(map(int, input().strip().split()))
	d = [INF] * m
	color = [WHITE] * m
	p = [-1] * m
	d[0] = 0
	u = 0
	color[0] = BLACK
	# 周囲を探索→移動の流れを1ループにした
	while True:
		for v in range(m):
			if color[v] != BLACK and s[u][v] != -1:
				if s[u][v] < d[v]:
					d[v] = s[u][v]
					p[v] = u

		mincost = INF
		for i in range(m):
			if color[i] != BLACK and d[i] < mincost:
				mincost = d[i]
				u = i

		if mincost == INF:
			break

		color[u] = BLACK

					# color[v] = GRAY
	ans = 0
	for i in range(1, m):
		ans += s[i][p[i]]
	print(ans)

if __name__ == '__main__':
	main()


"""Support for Tesla switches."""
import logging

from homeassistant.components.switch import SwitchEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from teslajsonpy.car import TeslaCar

from . import TeslaDataUpdateCoordinator
from .base import TeslaCarEntity
from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)

async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entities):
    """Set up the Tesla switches by config_entry."""
    entry_data = hass.data[DOMAIN][config_entry.entry_id]
    coordinators = entry_data["coordinators"]
    cars = entry_data["cars"]
    entities = []

    for vin, car in cars.items():
        coordinator = coordinators[vin]
        entities.append(TeslaCarHeatedSteeringWheel(car, coordinator))
        entities.append(TeslaCarSentryMode(car, coordinator))
        entities.append(TeslaCarPolling(car, coordinator))
        entities.append(TeslaCarCharger(car, coordinator))
        entities.append(TeslaCarValetMode(car, coordinator))

    async_add_entities(entities, update_before_add=True)

class TeslaCarHeatedSteeringWheel(TeslaCarEntity, SwitchEntity):
    """Representation of a Tesla car heated steering wheel switch."""

    type = "heated steering"
    _attr_icon = "mdi:steering"

    def __init__(
        self,
        car: TeslaCar,
        coordinator: TeslaDataUpdateCoordinator,
    ) -> None:
        """Initialize heated steering wheel entity."""
        # Entity is disabled for cars with variable heated steering wheel.
        self._enabled_by_default = car.get_heated_steering_wheel_level() is not None
        super().__init__(car, coordinator)

    @property
    def available(self) -> bool:
        """Return True if steering wheel heater is available."""
        return super().available and self._car.steering_wheel_heater

    @property
    def is_on(self):
        """Return True if steering wheel heater is on."""
        return self._car.is_steering_wheel_heater_on

    async def async_turn_on(self, **kwargs):
        """Send the on command."""
        await self._car.set_heated_steering_wheel(True)
        self.async_write_ha_state()

    async def async_turn_off(self, **kwargs):
        """Send the off command."""
        await self._car.set_heated_steering_wheel(False)
        self.async_write_ha_state()

class TeslaCarPolling(TeslaCarEntity, SwitchEntity):
    """Representation of a polling switch."""

    type = "polling"
    _attr_icon = "mdi:car-connected"
    _attr_entity_category = EntityCategory.DIAGNOSTIC

    @property
    def is_on(self) -> bool | None:
        """Return True if updates available."""
        controller = self.coordinator.controller
        get_updates = controller.get_updates(vin=self._car.vin)
        if get_updates is None:
            return None
        return bool(get_updates)

    async def async_turn_on(self, **kwargs):
        """Send the on command."""
        _LOGGER.debug("Enable polling: %s %s", self.name, self._car.vin)
        self.coordinator.controller.set_updates(vin=self._car.vin, value=True)
        self.async_write_ha_state()

    async def async_turn_off(self, **kwargs):
        """Send the off command."""
        _LOGGER.debug("Disable polling: %s %s", self.name, self._car.vin)
        self.coordinator.controller.set_updates(vin=self._car.vin, value=False)
        self.async_write_ha_state()

class TeslaCarCharger(TeslaCarEntity, SwitchEntity):
    """Representation of a Tesla car charger switch."""

    type = "charger"
    _attr_icon = "mdi:ev-station"

    @property
    def is_on(self):
        """Return charging state."""
        return self._car.charging_state == "Charging"

    async def async_turn_on(self, **kwargs):
        """Send the on command."""
        await self._car.start_charge()
        self.async_write_ha_state()

    async def async_turn_off(self, **kwargs):
        """Send the off command."""
        await self._car.stop_charge()
        self.async_write_ha_state()

class TeslaCarSentryMode(TeslaCarEntity, SwitchEntity):
    """Representation of a Tesla car sentry mode switch."""

    type = "sentry mode"
    _attr_icon = "mdi:shield-car"

    def __init__(
        self,
        car: TeslaCar,
        coordinator: TeslaDataUpdateCoordinator,
    ) -> None:
        """Initialize sentry mode entity."""
        # Entity is only enabled upon first install if sentry mode is available
        self._enabled_by_default = car.sentry_mode_available
        super().__init__(car, coordinator)

    @property
    def available(self) -> bool:
        """Return True if sentry mode switch is available."""
        return super().available and self._car.sentry_mode_available

    @property
    def is_on(self):
        """Return True if sentry mode is on."""
        sentry_mode_available = self._car.sentry_mode_available
        sentry_mode_status = self._car.sentry_mode
        return bool(sentry_mode_available and sentry_mode_status)

    async def async_turn_on(self, **kwargs):
        """Send the on command."""
        await self._car.set_sentry_mode(True)
        self.async_write_ha_state()

    async def async_turn_off(self, **kwargs):
        """Send the off command."""
        await self._car.set_sentry_mode(False)
        self.async_write_ha_state()

class TeslaCarValetMode(TeslaCarEntity, SwitchEntity):
    """Representation of a Tesla car valet mode switch."""

    type = "valet mode"
    _attr_icon = "mdi:room-service"

    @property
    def is_on(self):
        """Return valet mode state."""
        return self._car.is_valet_mode

    async def async_turn_on(self, **kwargs):
        """Send the on command."""
        # pylint: disable=protected-access
        if self._car._vehicle_data.get("vehicle_state", {}).get("valet_pin_needed"):
            _LOGGER.debug("Pin required for valet mode, set pin in vehicle or app.")
        else:
            await self._car.valet_mode(True)
            self.async_write_ha_state()

    async def async_turn_off(self, **kwargs):
        """Send the off command."""
        # pylint: disable=protected-access
        if self._car._vehicle_data.get("vehicle_state", {}).get("valet_pin_needed"):
            _LOGGER.debug("Pin required for valet mode, set pin in vehicle or app.")
        else:
            await self._car.valet_mode(False)
            self.async_write_ha_state()


#! python3
# add bullet in front of list copied from web or somewhere else

import pyperclip

text = pyperclip.paste()

lines = text.split('\n')
""" to split the copied string by new line character """

for i in range(len(lines)):
    lines[i] = '* ' + lines[i]

text = '\n'.join(lines)

pyperclip.copy(text)

# this file has bat file


import json

from project.tests.base import BaseTestCase

class TestEncryptService(BaseTestCase):
    def test_encrypt_returns_a_value(self):
        """Ensure the api can call the encryptor properly"""
        with self.client:
            plaintext = "Hello, I'm a string to encrypt."
            response = self.client.get("/encrypt/{plaintext}")
            data = json.loads(response.data.decode())
            assert response.status_code == 200
            assert data['data']['ciphertext'] != plaintext

    # def test_ping(self):
    #     with self.client:
    #         response = self.client.get('/encrypt/ping')
    #         assert response.status_code == 200


## 2. Array Comparisons ##

countries_canada = world_alcohol[:,2] == 'Canada'
years_1984 = world_alcohol[:,0] == '1984'

## 3. Selecting Elements ##

country_is_algeria = world_alcohol[:, 2] == 'Algeria'

country_algeria = world_alcohol[country_is_algeria, :]

## 4. Comparisons with Multiple Conditions ##

is_algeria_and_1986 = ((world_alcohol[:,0] == '1986') &  (world_alcohol[:,2] == 'Algeria'))
rows_with_algeria_and_1986 = world_alcohol[is_algeria_and_1986]

## 5. Replacing Values ##

all_1986 = world_alcohol[:,0] == '1986'
world_alcohol[all_1986, 0] = '2014'

all_wine = world_alcohol[:,3] == 'Wine'
world_alcohol[all_wine, 3] = 'Grog'

## 6. Replacing Empty Strings ##

is_value_empty = world_alcohol[:,4] == ''
world_alcohol[is_value_empty, 4] = '0'

## 7. Converting Data Types ##

alcohol_consumption = world_alcohol[:, 4]
alcohol_consumption.astype(float)

## 8. Computing with NumPy ##

total_alcohol = alcohol_consumption.sum()
average_alcohol = alcohol_consumption.mean()

## 9. Total Annual Alcohol Consumption ##

canada_1986 = world_alcohol[(world_alcohol[:,0] == '1986') & (world_alcohol[:,2] == 'Canada'),:]
canada_1986[canada_1986[:,4] == '',4] = '0'
canada_alcohol = canada_1986[:,4].astype(float)

total_canadian_drinking = canada_alcohol.sum()

## 10. Calculating Consumption for Each Country ##

totals = {}

year = world_alcohol[world_alcohol[:,0] == '1989',:]

for c in countries:
    country_consumption = year[year[:,2] == c,:]

    country_consumption[country_consumption[:,4] == '', 4] = '0'
    country_consumption = country_consumption[:,4].astype(float)

    totals[c] = country_consumption.sum()

totals

## 11. Finding the Country that Drinks the Most ##

highest_value = 0
highest_key = None
for country, total in totals.items():

    if total > highest_value:
        highest_key = country
        highest_value = total


from datetime import datetime

import dash_bootstrap_components as dbc
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

from dash import callback, dcc, dash_table, html
from dash.dependencies import Input, Output, State

from external import datasets

class CierreTable():
    def __init__(
        self,
        signal_update,
        id=None,
        cierre_id=None,
        offset_store_id=None,
        sort_action=None,
    ):
        self.signal_update = signal_update
        self.id = id
        self.cierre_id = cierre_id
        self.offset_store_id = offset_store_id
        self.sort_action = sort_action

    def display(self):
        table_args = {
            'style_table': {'overflow': 'auto'},
        }
        if (self.id):
            table_args['id'] = self.id
        if (self.sort_action):
            table_args['sort_action'] = self.sort_action

        self.layout = dash_table.DataTable(**table_args)
        self.register_callbacks()

        return self.layout

    def register_callbacks(self):
        if (self.cierre_id):
            @callback(
                Output(self.layout, 'columns'),
                Output(self.layout, 'data'),
                Input(self.signal_update, 'data'),
                Input(self.cierre_id, 'value'),
                prevent_initial_call=False,
            )
            def update_table(_, cierre_date):
                df = datasets.stats_cierre(dataviz=True)

                cierre_date = datetime.strptime(cierre_date, '%Y-%m-%d').date()
                df = df.query('FECHA_CIERRE == @cierre_date')

                if (df.shape[0] == 0):
                    return ([], [])

                columns = [{'name': i, 'id': i} for i in df.columns]
                data = df.to_dict('records')

                return (columns, data)
        elif (self.offset_store_id):
            @callback(
                Output(self.layout, 'columns'),
                Output(self.layout, 'data'),
                Input(self.signal_update, 'data'),
                Input(self.offset_store_id, 'data'),
                prevent_initial_call=False,
            )
            def update_table(_, offset_data):
                df = datasets.stats_cierre(dataviz=True)
                df = datasets.filter_dataframe(
                    df, 'FECHA_CIERRE', offset_data)
                columns = [{'name': i, 'id': i, } for i in df.columns]
                data = df.to_dict('records')

                return (columns, data)


#Amanda Maglaras
#amanda.maglaras1@marist.edu
#This project allows us to find prime numbers

def prime(n):
    a = []
    b = []
    for i in range(2,n+1):
        if i not in a:
            b.append(i)
            for j in range(i*i,n+1,i):
                a.append(j)
    return b
primenumber = int(input("Enter a number: "))
print(prime(primenumber))

prime


from django import forms
from .models import Produto

class Form_Produto(forms.ModelForm):
    class Meta:
        model = Produto
        fields = "__all__"
        labels = {
                'nome_produto': 'Nome do Produto',
                'codigo_produto': 'Codigo do Produto',
                'quatidade': 'Quantidade',
                'quantidade_minima': 'Quantidade Mínima',
                'categoria': 'Categoria',
                'preco_custo': 'Preço do Produto',
                'preco_venda' : 'Preço de Venda'
        }


import torch
from torch.utils.data import Dataset
import json
import numpy as np
import os
from PIL import Image, ImageDraw
from torchvision import transforms as T
from pathlib import Path

from .ray_utils import *

ORIGINAL_W = 2048
ORIGINAL_H = 1536

def add_perturbation(img, perturbation, seed):
    if 'color' in perturbation:
        np.random.seed(seed)
        img_np = np.array(img)/255.0
        s = np.random.uniform(0.8, 1.2, size=3)
        b = np.random.uniform(-0.2, 0.2, size=3)
        img_np[..., :3] = np.clip(s*img_np[..., :3]+b, 0, 1)
        img = Image.fromarray((255*img_np).astype(np.uint8))
    if 'occ' in perturbation:
        draw = ImageDraw.Draw(img)
        np.random.seed(seed)
        left = np.random.randint(200, 400)
        top = np.random.randint(200, 400)
        for i in range(10):
            np.random.seed(10*seed+i)
            random_color = tuple(np.random.choice(range(256), 3))
            draw.rectangle(((left+20*i, top), (left+20*(i+1), top+200)),
                            fill=random_color)
    return img

class BehaveDataset(Dataset):
    def __init__(self, root_dir, split='train', img_wh=(2048, 1536),
                 perturbation=[]):
        self.root_dir = root_dir
        self.split = split
        self.img_wh = img_wh
        self.define_transforms()

        # self.perturbation = perturbation
        # if self.split == 'train':
        #     print(f'add {self.perturbation} perturbation!')
        self.read_meta()
        self.white_back = True

    def read_meta(self):
        # Process paths
        self.seq_dir = Path(self.root_dir)
        self.root_dir = self.root_dir.split('/')
        scene_name, seq_name = self.root_dir[-2:]
        self.root_dir = Path('/'.join(self.root_dir[:-2]))
        intrinsics_dir = self.root_dir / 'calibs' / 'intrinsics'
        extrinsics_dir = self.root_dir / 'calibs' / scene_name / 'config'
        self.cam_intrinsics_meta = []
        self.cam_extrinsics_meta = []
        for i in range(4):
            with open(intrinsics_dir / f"{i}" / 'calibration.json', 'r') as f:
                self.cam_intrinsics_meta.append(json.load(f))
            with open(extrinsics_dir / f"{i}" / 'config.json', 'r') as f:
                self.cam_extrinsics_meta.append(json.load(f))

        w, h = self.img_wh
        w_ratio = w / ORIGINAL_W
        h_ratio = h / ORIGINAL_H
        self.focal = []
        self.K = []
        for i in range(4):
            fx = self.cam_intrinsics_meta[i]['color']['fx'] * w_ratio
            fy = self.cam_intrinsics_meta[i]['color']['fy'] * h_ratio
            cx = self.cam_intrinsics_meta[i]['color']['cx'] * w_ratio
            cy = self.cam_intrinsics_meta[i]['color']['cy'] * h_ratio
            self.focal.append((fx, fy))
            K = np.eye(3)
            K[0, 0] = fx
            K[1, 1] = fy
            K[0, 2] = cx
            K[1, 2] = cy
            self.K.append(K)

        # bounds, common for all scenes
        self.near = 0.1
        self.far = 20
        self.bounds = np.array([self.near, self.far])

        # ray directions for all pixels, same for all images (same H, W, focal)
        self.directions = []
        for i in range(4):
            self.directions.append(get_ray_directions(h, w, self.K[i])) # (h, w, 3)

        # create buffer of all rays and rgb data
        self.all_rays = []
        self.all_rgbs = []
        # Get list of all frame directories.
        def sort_frame(path):
            return int(path.name[1:5])
        frame_dir_list = []
        for frame_dir in self.seq_dir.iterdir():
            if frame_dir.name == 'info.json':
                continue
            frame_dir_list.append(frame_dir)
        # frame_dir_list.sort(key=sort_frame)

        # Do train/validation split
        num_frames_train = int(len(frame_dir_list) * 0.8)
        if self.split == 'train':
            t = 0
            frame_dir_list = frame_dir_list[:num_frames_train]
        elif self.split == 'val':
            t = num_frames_train * 4    # TODO: this should be modified if not all frame dir has 4 images.
            frame_dir_list = frame_dir_list[num_frames_train:]

        for frame_dir in frame_dir_list:
            for file in frame_dir.iterdir():
                if 'color.jpg' not in file.name:
                    continue
                image_path = str(file)
                cam_idx = int(file.name.split('.')[0][1])
                c2w = np.zeros((3, 4))
                rotation = np.array(self.cam_extrinsics_meta[cam_idx]['rotation']).reshape((3, 3))
                translation = np.array(self.cam_extrinsics_meta[cam_idx]['translation'])
                c2w[:3, :3] = rotation
                c2w[:3, 3] = translation
                c2w = torch.tensor(c2w, dtype=torch.float32)

                with Image.open(image_path) as img:
                    img = self.transform(img)  # (4, h, w)
                    img = img.view(3, -1).permute(1, 0)  # (h*w, 4) RGBA
                    # img = img[:, :3] * img[:, -1:] + (1 - img[:, -1:])  # blend A to RGB
                    self.all_rgbs += [img]

                    rays_o, rays_d = get_rays(self.directions[cam_idx], c2w)  # both (h*w, 3)
                    rays_t = t * torch.ones(len(rays_o), 1)

                    self.all_rays += [torch.cat([rays_o, rays_d,
                                                 self.near * torch.ones_like(rays_o[:, :1]),
                                                 self.far * torch.ones_like(rays_o[:, :1]),
                                                 rays_t],
                                                1)]  # (h*w, 8)
                t += 1

        if self.split == 'train':
            self.all_rays = torch.cat(self.all_rays, 0) # (len(self.meta['frames])*h*w, 3)
            self.all_rgbs = torch.cat(self.all_rgbs, 0) # (len(self.meta['frames])*h*w, 3)

    def define_transforms(self):
        self.transform = T.Compose([
            T.ToTensor(),
            T.Resize(size=self.img_wh)
        ])

    def __len__(self):
        if self.split == 'train':
            return len(self.all_rays)
        elif self.split == 'val':
            return len(self.all_rays)

    def __getitem__(self, idx):
        if self.split == 'train':
            sample = {'rays': self.all_rays[idx, :8],
                      'ts': self.all_rays[idx, 8].long(),
                      'rgbs': self.all_rgbs[idx]}
        elif self.split == 'val':
            sample = {
                'rays': self.all_rays[idx][:, :8],
                'ts': self.all_rays[idx][:, 8].long(),
                'rgbs': self.all_rgbs[idx]
            }

        return sample


# cell_inverter.py <filename.xlsx> - inverts the row and column positions of all cells in the spreadsheet

import openpyxl
from openpyxl.utils import get_column_letter, column_index_from_string
import sys

if len(sys.argv) == 2:
	work_book = openpyxl.load_workbook(sys.argv[1])
else:
	print('\ncell_inverter.py <filename.xlsx> - inverts the row and column positions of all cells in the spreadsheet')

sheet = work_book.active
new_sheet = {}

# store every value from every cell in the new_sheet dict with the key being the inverted position
for i in range(1, sheet.max_row+1):
	for cell in sheet[i]:
		new_col = str(get_column_letter(cell.row))
		new_row = str(column_index_from_string(cell.column))
		new_sheet[new_col+new_row] = cell.value

# write the cell values to their inverted positions
for position in new_sheet.keys():
	sheet[position].value = new_sheet[position]

# always save to a new file name
work_book.save('inverted.xlsx')


# one-to-one = every row in the left tables is related to one to one and only one row in the right table
# one-to-many = every row in left table in related to one or more rows in the right table
ward_licenses = wards.merge(licenses, on="ward", suffixes=('_ward', '_lic'))
ward_licenses.head()

print(wards_shape)
# (50, 4)

print(ward_licenses.shape)
(10000, 9)

# Merge the licenses and biz_owners table on account
licenses_owners = licenses.merge(biz_owners, on="account")

# Group the results by title then count the number of accounts
counted_df = licenses_owners.groupby("title").agg({'account':'count'})

# Sort the counted_df in desending order
sorted_df = counted_df.sort_values("account", ascending=False)

# Use .head() method to print the first few rows of sorted_df
print(sorted_df.head())


# -*- coding: utf-8 -*-
from __future__ import print_function
import os
import sys
import ctypes
from ctypes.wintypes import (
    BOOL,
    LPARAM,
    INT,
    HWND,
    DWORD,
    HANDLE,
    RECT,
    WPARAM
)

user32 = ctypes.windll.User32
kernel32 = ctypes.windll.Kernel32

NULL = None
MAX_PATH = 260
PROCESS_QUERY_INFORMATION = 0x0400
SW_FORCEMINIMIZE = 11
SW_HIDE = 0
SW_MAXIMIZE = 3
SW_MINIMIZE = 6
SW_RESTORE = 9
SW_SHOW = 5
SW_SHOWDEFAULT = 10
SW_SHOWMAXIMIZED = 3
SW_SHOWMINIMIZED = 2
SW_SHOWMINNOACTIVE = 7
SW_SHOWNA = 8
SW_SHOWNOACTIVATE = 4
SW_SHOWNORMAL = 1
SWP_NOMOVE = 0x0002
SWP_NOSIZE = 0x0001
SWP_SHOWWINDOW = 0x0040

HWND_TOP = 0

WM_CLOSE = 0x0010

# BOOL BringWindowToTop(
#   HWND hWnd
# );
BringWindowToTop = user32.BringWindowToTop
BringWindowToTop.restype = BOOL

# HWND GetFocus();
GetFocus = user32.GetFocus
GetFocus.restype = HWND

# HWND SetFocus(
#   HWND hWnd
# );
SetFocus = user32.SetFocus
SetFocus.restype = HWND

# BOOL PostMessageW(
#   HWND   hWnd,
#   UINT   Msg,
#   WPARAM wParam,
#   LPARAM lParam
# );

_PostMessage = user32.PostMessageW
_PostMessage.restype = BOOL

# BOOL SetWindowPos(
#   HWND hWnd,
#   HWND hWndInsertAfter,
#   int  X,
#   int  Y,
#   int  cx,
#   int  cy,
#   UINT uFlags
# );
_SetWindowPos = user32.SetWindowPos
_SetWindowPos.restype = BOOL

# BOOL IsIconic(
#   HWND hWnd
# );
IsIconic = user32.IsIconic
IsIconic.restype = BOOL

# BOOL IsZoomed(
#   HWND hWnd
# );
IsZoomed = user32.IsZoomed
IsZoomed.restype = BOOL

# BOOL IsWindowVisible(
#   HWND hWnd
# );
IsWindowVisible = user32.IsWindowVisible
IsWindowVisible.restype = BOOL

# BOOL CALLBACK EnumWindowsProc(
#   _In_ HWND   hwnd,
#   _In_ LPARAM lParam
# );
_EnumWindows = user32.EnumWindows
_EnumWindows.restype = BOOL

# BOOL DestroyWindow(
#   HWND hWnd
# );
DestroyWindow = user32.DestroyWindow
DestroyWindow.restype = BOOL

# BOOL GetWindowRect(
#   HWND   hWnd,
#   LPRECT lpRect
# );

_GetWindowRect = user32.GetWindowRect
_GetWindowRect.restype = BOOL

# BOOL ShowWindow(
#   HWND hWnd,
#   int  nCmdShow
# );
ShowWindow = user32.ShowWindow
ShowWindow.restype = BOOL

# BOOL IsWindow(
#   HWND hWnd
# );
IsWindow = user32.IsWindow
IsWindow.restype = BOOL

# int GetWindowTextLengthW(
#   HWND hWnd
# );
_GetWindowTextLength = user32.GetWindowTextLengthW
_GetWindowTextLength.restype = INT

# int GetWindowTextW(
#   HWND   hWnd,
#   LPWSTR lpString,
#   int    nMaxCount
# );
_GetWindowText = user32.GetWindowTextW
_GetWindowText.restype = INT

# DWORD GetWindowThreadProcessId(
#   HWND    hWnd,
#   LPDWORD lpdwProcessId
# );
_GetWindowThreadProcessId = user32.GetWindowThreadProcessId
_GetWindowThreadProcessId.restype = DWORD

# HANDLE OpenProcess(
#   DWORD dwDesiredAccess,
#   BOOL  bInheritHandle,
#   DWORD dwProcessId
# );
_OpenProcess = kernel32.OpenProcess
_OpenProcess.restype = HANDLE

# BOOL QueryFullProcessImageNameW(
#   HANDLE hProcess,
#   DWORD  dwFlags,
#   LPWSTR lpExeName,
#   PDWORD lpdwSize
# );

_QueryFullProcessImageName = kernel32.QueryFullProcessImageNameW
_QueryFullProcessImageName.restype = BOOL

WNDENUMPROC = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)

def EnumWindows():
    windows = []

    def callback(hwnd, lparam):
        windows.append(hwnd)
        return 1

    lpEnumFunc = WNDENUMPROC(callback)
    lParam = NULL

    _EnumWindows(lpEnumFunc, lParam)

    return windows

def GetWindowText(hwnd):
    if not isinstance(hwnd, HWND):
        hwnd = HWND(hwnd)

    nMaxCount = _GetWindowTextLength(hwnd) + 1
    lpString = ctypes.create_unicode_buffer(nMaxCount)

    _GetWindowText(hwnd, lpString, nMaxCount)

    return lpString.value

def GetProcessName(hwnd):
    if not isinstance(hwnd, HWND):
        hwnd = HWND(hwnd)

    lpdwProcessId = DWORD()
    _GetWindowThreadProcessId(hwnd, ctypes.byref(lpdwProcessId))

    hProcess = _OpenProcess(
        DWORD(PROCESS_QUERY_INFORMATION),
        BOOL(False),
        lpdwProcessId
    )

    lpdwSize = DWORD(MAX_PATH)

    lpExeName = ctypes.create_string_buffer(MAX_PATH)
    _QueryFullProcessImageName(
        hProcess,
        DWORD(0),
        lpExeName,
        ctypes.byref(lpdwSize)
    )

    if sys.version_info[0] == 2:
        res = ''
    else:
        res = b''

    for i in range(260):
        if sys.version_info[0] == 2:
            if lpExeName[i] == '\x00':
                continue
        else:
            if lpExeName[i] == b'\x00':
                continue

        res += lpExeName[i]

    if res:
        res = os.path.split(res)[-1]
    return res

def PostMessage(hwnd, msg, wparam, lparam):
    if not isinstance(wparam, WPARAM):
        wparam = WPARAM(wparam)

    if not isinstance(lparam, LPARAM):
        lparam = LPARAM(lparam)

    return _PostMessage(hwnd, msg, wparam, lparam)

def SetWindowPos(hwnd, pos=None, size=None):
    if pos is None:
        uFlags = SWP_NOMOVE
        width, height = size
        x = INT(0)
        y = INT(0)
        cx = INT(width)
        cy = INT(height)
    else:
        uFlags = SWP_NOSIZE
        x, y = pos
        x = INT(x)
        y = INT(y)
        cx = INT(0)
        cy = INT(0)

    hWndInsertAfter = HWND_TOP

    if not IsWindowVisible(hwnd):
        uFlags |= SWP_SHOWWINDOW

    return _SetWindowPos(hwnd, hWndInsertAfter, x, y, cx, cy, uFlags)

def GetWindowRect(hwnd):

    rect = RECT()

    _GetWindowRect(hwnd, ctypes.byref(rect))
    return rect

if __name__ == '__main__':
    for hwnd in EnumWindows():
        name = GetProcessName(hwnd)

        print(name, repr(name))


"""
CSE 163
A file that contains multiple functions
that make several visualizations to analyze
the Seattle crime dataset.
"""
# pip install geopandas
# pip install folium
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import folium
import seaborn as sns
from scipy.stats import pearsonr
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
sns.set()

def crimeMap(crimeData, geoData):
    """
    This function takes the grouped data
    and plots the scatter plot to indicate
    relationship between household income
    and crime rate in a file 'income_crime_plot.png'.
    """
    df = pd.read_csv(crimeData).dropna()
    mcpp = gpd.read_file(geoData)
    dis = df.groupby('MCPP', as_index=False).size()
    merged_df = dis.merge(mcpp, left_on='MCPP',
                          right_on='NAME', how='outer').dropna()
    merged_df.rename({'size': 'Incidents'}, axis=1, inplace=True)
    merged_df = gpd.GeoDataFrame(merged_df)
    seaMap = folium.Map([47.6062, -122.3321], zoom_start=9)
    # Create map
    folium.TileLayer('CartoDB positron', name="Light Map",
                     control=False).add_to(seaMap)
    choropleth = folium.Choropleth(
        geo_data=merged_df,
        fill_opacity=0.5,
        line_weight=1.5,
        data=merged_df,
        columns=['MCPP', 'Incidents'],
        key_on='feature.properties.MCPP',
        highlight=True,
        fill_color='YlOrRd',
        nan_fill_opacity=0,
        name='Incidents',
    ).add_to(seaMap)
    choropleth.geojson.add_child(
        folium.features.GeoJsonTooltip(['MCPP', 'Incidents'], labels=True)
    )
    seaMap.save('vis/seaChoropleth.html')

def income_crime_plot(group_data):
    """
    This function takes the grouped data
    and plots the scatter plot to indicate
    relationship between household income
    and crime rate in a file 'income_crime_plot.png'.
    """
    group_data = pd.read_csv(group_data)
    sns.lmplot(x="Avg. Income/H/hold", y="Crime Rate", data=group_data)
    plt.title('Household Income vs Crime Rate')
    plt.xlabel('Household Income')
    plt.ylabel('Crime Rate')
    plt.xticks(rotation=-45, fontsize=8)
    plt.savefig('vis/income_crime_plot.png')
    corr, _ = pearsonr(group_data['Avg. Income/H/hold'],
                       group_data['Crime Rate'])
    print('Pearsons correlation: %.3f' % corr)

def income_bar_plot(income_file):
    """
    This function takes the grouped data
    and plots the bar chart to indicate
    the area with relatively low income
    in a file 'income_plot.png'.
    """
    income = pd.read_csv(income_file,
                         usecols=["Zip Code",
                                  "Avg. Income/H/hold",
                                  "Population"]).dropna()
    string = 'Avg. Income/H/hold'
    income[string] = income[string].str.replace(',', '')
    income[string] = income[string].str.replace('$', '').astype(float)
    top_5_area = income.sort_values(by=string)
    top_5_area = top_5_area.loc[(top_5_area[string] > 0)]
    fig, ax = plt.subplots(figsize=(8, 8))
    sns.barplot(x="Zip Code", y=string,
                data=top_5_area.head(), ax=ax)
    plt.title('Top 5 Low Household Income in Seattle', fontsize=15)
    plt.xlabel('Area')
    plt.ylabel('Income', fontsize=15)
    plt.xticks(rotation=-45, fontsize=10)
    plt.savefig('vis/income_plot.png')

def prediction(crimeData):
    """
    This function takes the cleaned crime data
    train a machine learning model with offense
    parent group as label and MCPP, year, month,
    day, and hour as features.
    Print out the accurancy for both training and
    testing sets.
    And produce a graph with accuracy and for both groups
    as y, and max depth as x.
    """
    data = pd.read_csv(crimeData)

    data = data[["Offense Parent Group", 'MCPP',
                 'Year', 'Month', 'Day', 'Hour']]
    data = data[data['Year'] >= 2014]

    labels = data['Offense Parent Group']

    features = data.loc[:, data.columns != 'Offense Parent Group']
    features = pd.get_dummies(features)
    features_train, features_test, labels_train, labels_test = \
        train_test_split(features, labels, test_size=0.2)

    print(len(features_train), len(features_test))

    model2 = DecisionTreeClassifier(max_depth=2)

    model2.fit(features_train, labels_train)

    train_predictions = model2.predict(features_train)
    print('Train Accuracy:', accuracy_score(labels_train, train_predictions))

    # Compute test accuracy
    test_predictions = model2.predict(features_test)
    print('Test  Accuracy:', accuracy_score(labels_test, test_predictions))

    accuracies = []
    for i in range(1, 20):
        model = DecisionTreeClassifier(max_depth=i, random_state=1)
        model.fit(features_train, labels_train)

        pred_train = model.predict(features_train)
        train_acc = accuracy_score(labels_train, pred_train)

        pred_test = model.predict(features_test)
        test_acc = accuracy_score(labels_test, pred_test)

        accuracies.append({'max depth': i, 'train accuracy': train_acc,
                           'test accuracy': test_acc})
    accuracies = pd.DataFrame(accuracies)

    def plot_accuracies(accuracies, column, name):
        """
        Parameters:
            * accuracies: A DataFrame show the train/test accuracy
            * for various max_depths
            * column: Which column to plot (e.g., 'train accuracy')
            * name: The display name for this column (e.g., 'Train')
        """
        sns.relplot(kind='line', x='max depth', y=column, data=accuracies)
        plt.title(f'{name} Accuracy as Max Depth Changes')
        plt.xlabel('Max Depth')
        plt.ylabel(f'{name} Accuracy')
        plt.ylim(0, 1)

        plt.show()  # Display the graph

    # Plot the graphs
    plot_accuracies(accuracies, 'train accuracy', 'Train')
    plot_accuracies(accuracies, 'test accuracy', 'Test')
    importance = dict(zip(features_train.columns, model2.feature_importances_))
    print(importance)

def crime_cases_trend(filename, export_name):
    """
    Take in the cleaned plotting data and a file name.
    Plot the number fo cases for each crime by year.
    Export the plot with the name passed in
    """
    df = pd.read_csv(filename)
    col = 'Offense Parent Group'
    top_10 = df.groupby(col)[col].count().nlargest(10)
    top_10 = pd.DataFrame(top_10)
    print(top_10)
    top_10_type = top_10.index.values.tolist()
    df = df.loc[df['Offense Parent Group'].isin(top_10_type)]
    df = df.groupby(['Offense Parent Group', 'Year']).size()
    sns.relplot(data=df, kind='line', x='Year',
                y=df.values, hue='Offense Parent Group')
    plt.xticks([2016, 2017, 2018, 2019, 2020, 2021, 2022])
    plt.ylabel('Counts')
    plt.title('Trend of Top 10 Crimes By Type')
    plt.savefig(export_name)

def pie_chart_most_common(filename, export_name):
    """
    Take in the cleaned plotting data and a file name.
    Plot a pie chart that shows the proportion of each crime
    Export the plot with the name passed in
    """
    df = pd.read_csv(filename)
    df = df.groupby('Offense Parent Group')['Offense Parent Group'].count()
    plt.pie(x=df.values, radius=1.6)
    plt.legend(labels=df.index, fontsize=5, loc='upper right')
    plt.title('Crime_Count')
    plt.savefig(export_name)

def graph_top_ten_university_by_timezone(filename):
    df = pd.read_csv(filename)
    col = 'Offense Parent Group'
    top_10 = df.groupby(col)[col].count().nlargest(10)
    top_10 = pd.DataFrame(top_10)
    print(top_10)
    top_10_type = top_10.index.values.tolist()
    df = df.loc[df['Offense Parent Group'].isin(top_10_type)]
    df = df.groupby(['Offense Parent Group', 'Timezone']).size()
    sns.relplot(data=df, x='Timezone', y=df.values,
                hue='Offense Parent Group', kind='line')
    plt.xticks(['1:Earlymonring', '2:Morning', '3:Afternoon', '4:Night'])
    plt.ylabel('Counts')
    plt.savefig('Toptencrimesinuniversitybytimezone.png')

def main():
    income_crime_plot('data/income_crime_rate.csv')
    income_bar_plot('data/income/median_income.csv')
    crimeMap('data/cleaned_crime_data.csv', 'data/mapping/cleaned_dis.shp')
    prediction('data/cleaned_crime_data.csv')
    crime_cases_trend('data/plot_data.csv', 'vis/seattle.png')
    crime_cases_trend('data/university.csv', 'vis/university.png')
    pie_chart_most_common('data/plot_data.csv', 'vis/seattle_pie.png')
    pie_chart_most_common('data/university.csv', 'vis/university_pie.png')
    graph_top_ten_university_by_timezone('data/university.csv')

if __name__ == "__main__":
    main()


"""Define class to import Quotes from a Docx-file."""

from typing import List
import docx

from .IngestorInterface import IngestorInterface
from QuoteEngine import QuoteModel

class DocxIngestor(IngestorInterface):
    """Define ingest of Quotes from Docx files."""

    def __repr__(self) -> str:
        """Define representation of object as string."""
        return "Docx Ingestor"

    allowed_extensions = ["docx"]

    @classmethod
    def parse(cls, path: str) -> List[QuoteModel]:
        """Parse Quotes from a Docx-file to a list of QuoteModel objects."""
        if not cls.can_ingest(path):
            raise Exception("cannot ingest exception")

        quotes = []
        doc = docx.Document(path)

        for para in doc.paragraphs:
            if para.text != "":
                parse = para.text.split(" - ")
                body = parse[0].strip('"')
                new_quote = QuoteModel(body, parse[1])
                quotes.append(new_quote)

        return quotes


import numpy as np
import cv2
from scipy.signal import find_peaks
from scipy.ndimage import gaussian_filter1d

from .contour import find_new_features_of_contours, return_contours_of_interested_region
from .resize import resize_image
from .rotate import rotate_image

def get_marginals(text_with_lines, text_regions, num_col, slope_deskew, kernel=None):
    mask_marginals=np.zeros((text_with_lines.shape[0],text_with_lines.shape[1]))
    mask_marginals=mask_marginals.astype(np.uint8)

    text_with_lines=text_with_lines.astype(np.uint8)
    ##text_with_lines=cv2.erode(text_with_lines,self.kernel,iterations=3)

    text_with_lines_eroded=cv2.erode(text_with_lines,kernel,iterations=5)

    if text_with_lines.shape[0]<=1500:
        pass
    elif text_with_lines.shape[0]>1500 and text_with_lines.shape[0]<=1800:
        text_with_lines=resize_image(text_with_lines,int(text_with_lines.shape[0]*1.5),text_with_lines.shape[1])
        text_with_lines=cv2.erode(text_with_lines,kernel,iterations=5)
        text_with_lines=resize_image(text_with_lines,text_with_lines_eroded.shape[0],text_with_lines_eroded.shape[1])
    else:
        text_with_lines=resize_image(text_with_lines,int(text_with_lines.shape[0]*1.8),text_with_lines.shape[1])
        text_with_lines=cv2.erode(text_with_lines,kernel,iterations=7)
        text_with_lines=resize_image(text_with_lines,text_with_lines_eroded.shape[0],text_with_lines_eroded.shape[1])

    text_with_lines_y=text_with_lines.sum(axis=0)
    text_with_lines_y_eroded=text_with_lines_eroded.sum(axis=0)

    thickness_along_y_percent=text_with_lines_y_eroded.max()/(float(text_with_lines.shape[0]))*100

    #print(thickness_along_y_percent,'thickness_along_y_percent')

    if thickness_along_y_percent<30:
        min_textline_thickness=8
    elif thickness_along_y_percent>=30 and thickness_along_y_percent<50:
        min_textline_thickness=20
    else:
        min_textline_thickness=40

    if thickness_along_y_percent>=14:

        text_with_lines_y_rev=-1*text_with_lines_y[:]
        #print(text_with_lines_y)
        #print(text_with_lines_y_rev)

        #plt.plot(text_with_lines_y)
        #plt.show()

        text_with_lines_y_rev=text_with_lines_y_rev-np.min(text_with_lines_y_rev)

        #plt.plot(text_with_lines_y_rev)
        #plt.show()
        sigma_gaus=1
        region_sum_0= gaussian_filter1d(text_with_lines_y, sigma_gaus)

        region_sum_0_rev=gaussian_filter1d(text_with_lines_y_rev, sigma_gaus)

        #plt.plot(region_sum_0_rev)
        #plt.show()
        region_sum_0_updown=region_sum_0[len(region_sum_0)::-1]

        first_nonzero=(next((i for i, x in enumerate(region_sum_0) if x), None))
        last_nonzero=(next((i for i, x in enumerate(region_sum_0_updown) if x), None))

        last_nonzero=len(region_sum_0)-last_nonzero

        ##img_sum_0_smooth_rev=-region_sum_0

        mid_point=(last_nonzero+first_nonzero)/2.

        one_third_right=(last_nonzero-mid_point)/3.0
        one_third_left=(mid_point-first_nonzero)/3.0

        #img_sum_0_smooth_rev=img_sum_0_smooth_rev-np.min(img_sum_0_smooth_rev)

        peaks, _ = find_peaks(text_with_lines_y_rev, height=0)

        peaks=np.array(peaks)

        #print(region_sum_0[peaks])
        ##plt.plot(region_sum_0)
        ##plt.plot(peaks,region_sum_0[peaks],'*')
        ##plt.show()
        #print(first_nonzero,last_nonzero,peaks)
        peaks=peaks[(peaks>first_nonzero) & ((peaks<last_nonzero))]

        #print(first_nonzero,last_nonzero,peaks)

        #print(region_sum_0[peaks]<10)
        ####peaks=peaks[region_sum_0[peaks]<25 ]

        #print(region_sum_0[peaks])
        peaks=peaks[region_sum_0[peaks]<min_textline_thickness ]
        #print(peaks)
        #print(first_nonzero,last_nonzero,one_third_right,one_third_left)

        if num_col==1:
            peaks_right=peaks[peaks>mid_point]
            peaks_left=peaks[peaks<mid_point]
        if num_col==2:
            peaks_right=peaks[peaks>(mid_point+one_third_right)]
            peaks_left=peaks[peaks<(mid_point-one_third_left)]

        try:
            point_right=np.min(peaks_right)
        except:
            point_right=last_nonzero

        try:
            point_left=np.max(peaks_left)
        except:
            point_left=first_nonzero

        #print(point_left,point_right)
        #print(text_regions.shape)
        if point_right>=mask_marginals.shape[1]:
            point_right=mask_marginals.shape[1]-1

        try:
            mask_marginals[:,point_left:point_right]=1
        except:
            mask_marginals[:,:]=1

        #print(mask_marginals.shape,point_left,point_right,'nadosh')
        mask_marginals_rotated=rotate_image(mask_marginals,-slope_deskew)

        #print(mask_marginals_rotated.shape,'nadosh')
        mask_marginals_rotated_sum=mask_marginals_rotated.sum(axis=0)

        mask_marginals_rotated_sum[mask_marginals_rotated_sum!=0]=1
        index_x=np.array(range(len(mask_marginals_rotated_sum)))+1

        index_x_interest=index_x[mask_marginals_rotated_sum==1]

        min_point_of_left_marginal=np.min(index_x_interest)-16
        max_point_of_right_marginal=np.max(index_x_interest)+16

        if min_point_of_left_marginal<0:
            min_point_of_left_marginal=0
        if max_point_of_right_marginal>=text_regions.shape[1]:
            max_point_of_right_marginal=text_regions.shape[1]-1

        #print(np.min(index_x_interest) ,np.max(index_x_interest),'minmaxnew')
        #print(mask_marginals_rotated.shape,text_regions.shape,'mask_marginals_rotated')
        #plt.imshow(mask_marginals)
        #plt.show()

        #plt.imshow(mask_marginals_rotated)
        #plt.show()

        text_regions[(mask_marginals_rotated[:,:]!=1) & (text_regions[:,:]==1)]=4

        #plt.imshow(text_regions)
        #plt.show()

        pixel_img=4
        min_area_text=0.00001
        polygons_of_marginals=return_contours_of_interested_region(text_regions,pixel_img,min_area_text)

        cx_text_only,cy_text_only ,x_min_text_only,x_max_text_only, y_min_text_only ,y_max_text_only,y_cor_x_min_main=find_new_features_of_contours(polygons_of_marginals)

        text_regions[(text_regions[:,:]==4)]=1

        marginlas_should_be_main_text=[]

        x_min_marginals_left=[]
        x_min_marginals_right=[]

        for i in range(len(cx_text_only)):

            x_width_mar=abs(x_min_text_only[i]-x_max_text_only[i])
            y_height_mar=abs(y_min_text_only[i]-y_max_text_only[i])
            #print(x_width_mar,y_height_mar,y_height_mar/x_width_mar,'y_height_mar')
            if x_width_mar>16 and y_height_mar/x_width_mar<18:
                marginlas_should_be_main_text.append(polygons_of_marginals[i])
                if x_min_text_only[i]<(mid_point-one_third_left):
                    x_min_marginals_left_new=x_min_text_only[i]
                    if len(x_min_marginals_left)==0:
                        x_min_marginals_left.append(x_min_marginals_left_new)
                    else:
                        x_min_marginals_left[0]=min(x_min_marginals_left[0],x_min_marginals_left_new)
                else:
                    x_min_marginals_right_new=x_min_text_only[i]
                    if len(x_min_marginals_right)==0:
                        x_min_marginals_right.append(x_min_marginals_right_new)
                    else:
                        x_min_marginals_right[0]=min(x_min_marginals_right[0],x_min_marginals_right_new)

        if len(x_min_marginals_left)==0:
            x_min_marginals_left=[0]
        if len(x_min_marginals_right)==0:
            x_min_marginals_right=[text_regions.shape[1]-1]

        #print(x_min_marginals_left[0],x_min_marginals_right[0],'margo')

        #print(marginlas_should_be_main_text,'marginlas_should_be_main_text')
        text_regions=cv2.fillPoly(text_regions, pts =marginlas_should_be_main_text, color=(4,4))

        #print(np.unique(text_regions))

        #text_regions[:,:int(x_min_marginals_left[0])][text_regions[:,:int(x_min_marginals_left[0])]==1]=0
        #text_regions[:,int(x_min_marginals_right[0]):][text_regions[:,int(x_min_marginals_right[0]):]==1]=0

        text_regions[:,:int(min_point_of_left_marginal)][text_regions[:,:int(min_point_of_left_marginal)]==1]=0
        text_regions[:,int(max_point_of_right_marginal):][text_regions[:,int(max_point_of_right_marginal):]==1]=0

        ###text_regions[:,0:point_left][text_regions[:,0:point_left]==1]=4

        ###text_regions[:,point_right:][ text_regions[:,point_right:]==1]=4
        #plt.plot(region_sum_0)
        #plt.plot(peaks,region_sum_0[peaks],'*')
        #plt.show()

        #plt.imshow(text_regions)
        #plt.show()

        #sys.exit()
    else:
        pass
    return text_regions


# encoding = utf8
# import pandas as pd
import csv

# 加载实体词典
def load_entity(dic_path):
    entity_list = []
    max_len = 0
    entity_dict = {}

    """ 实体词典: {'大众点评' : 'FPE', '位置信息' : 'SPT', '使用基于位置提供的服务' : 'OPS', 'IP 地址' : 'SPT'} """
    # df = pd.read_csv(dic_path, header=None, names=["entity", "tag"], encoding='ANSI')
    # entity_dict = {entity.strip(): tag.strip() for entity, tag in df.values.tolist()}

    # """ 计算词典中实体的最大长度 """
    # df["len"] = df["entity"].apply(lambda x: len(x))
    # max_len = max(df["len"])

    reader = csv.reader(open(dic_path))
    for line in reader:
        entity, tag = line
        entity_dict[entity] = tag
        if len(entity) > max_len:
            max_len = len(entity)
    return entity_dict, max_len

class BMM:
    def __init__(self, dic_path):
        self.entity_dict, self.max_len = load_entity(dic_path)

    # 前向最大匹配实体标注
    def positive_maximal_matching(self, sent):
        words_pos_seg = []
        sent_len = len(sent)

        while sent_len > 0:

            """ 如果句子长度小于实体最大长度，则切分的最大长度为句子长度 """
            max_len = min(sent_len, self.max_len)

            """ 从左向右截取max_len个字符，去词典中匹配 """
            sub_sent = sent[:max_len]

            while max_len > 0:
                """ 如果切分的词在实体词典中，那就是切出来的实体 """
                if sub_sent in self.entity_dict:
                    tag = self.entity_dict[sub_sent]
                    words_pos_seg.append((sub_sent, tag))
                    break

                elif max_len == 1:
                    """ 如果没有匹配上，那就把单个字切出来，标签为O """
                    tag = "O"
                    words_pos_seg.append((sub_sent, tag))
                    break

                else:
                    """ 如果没有匹配上，又还没剩最后一个字，就去掉右边的字,继续循环 """
                    max_len -= 1
                    sub_sent = sub_sent[:max_len]

            """ 把分出来的词（实体或单个字）去掉，继续切分剩下的句子 """
            sent = sent[max_len:]
            sent_len -= max_len

        return words_pos_seg

    # 后向最大匹配实体标注
    def reverse_maximal_matching(self, sent):
        words_pos_seg = []
        sent_len = len(sent)

        while sent_len > 0:
            """ 如果句子长度小于实体最大长度，则切分的最大长度为句子长度 """
            max_len = min(sent_len, self.max_len)

            """ 从右向左截取max_len个字符，去词典中匹配 """
            sub_sent = sent[-max_len:]

            while max_len > 0:
                """ 如果切分的词在实体词典中，那就是切出来的实体 """
                if sub_sent in self.entity_dict:
                    tag = self.entity_dict[sub_sent]
                    words_pos_seg.append((sub_sent, tag))
                    break

                elif max_len == 1:
                    """ 如果没有匹配上，那就把单个字切出来，标签为O """
                    tag = "O"
                    words_pos_seg.append((sub_sent, tag))
                    break

                else:
                    """ 如果没有匹配上，又还没剩最后一个字，就去掉右边的字,继续循环 """
                    max_len -= 1
                    sub_sent = sub_sent[-max_len:]

            """ 把分出来的词（实体或单个字）去掉，继续切分剩下的句子 """
            sent = sent[:-max_len]
            sent_len -= max_len

        """ 把切分的结果反转 """
        return words_pos_seg[::-1]

    # 双向最大匹配实体标注
    def bidirectional_maximal_matching(self, sent):

        """ 1: 前向和后向的切分结果 """
        words_psg_fw = self.positive_maximal_matching(sent)
        words_psg_bw = self.reverse_maximal_matching(sent)

        """ 2: 前向和后向的词数 """
        words_fw_size = len(words_psg_fw)
        words_bw_size = len(words_psg_bw)

        """ 3: 前向和后向的词数，则取词数较少的那个 """
        if words_fw_size < words_bw_size: return words_psg_fw

        if words_fw_size > words_bw_size: return words_psg_bw

        """ 4: 结果相同，可返回任意一个 """
        if words_psg_fw == words_psg_bw: return words_psg_fw

        """ 5: 结果不同，返回单字较少的那个 """
        fw_single = sum([1 for i in range(words_fw_size) if len(words_psg_fw[i][0]) == 1])
        bw_single = sum([1 for i in range(words_fw_size) if len(words_psg_bw[i][0]) == 1])

        if fw_single < bw_single:
            return words_psg_fw
        else:
            return words_psg_bw

if __name__ == "__main__":
    dict_path = "privacy_ner_dic.csv"
    text = "设备状态，用于确定设备识别码，以保证账号登录的安全性。拒绝授权后，我行手机银行将不读取设备状态，同时可能需要通过其他方式进行账号登录的安全验证。"
    # fp = open('raw_corpus/金融理财/com.cib.cibmb.txt', 'r', encoding='utf8')
    # text = fp.read()
    # print(text)
    seg = BMM(dict_path)
    words_tags = seg.bidirectional_maximal_matching(text)
    # print(tags)
    for word_tag in words_tags:
        if word_tag[1] != 'O':
            print(word_tag)


from collections import namedtuple

import numpy as np
import tensorflow as tf
import tensorflow.contrib.slim as slim

from bilinear_sampler import *
from pydnet import *

monodepth_parameters = namedtuple('parameters',
                        'encoder, '
                        'height, width, '
                        'batch_size, '
                        'num_threads, '
                        'num_epochs, '
                        'do_stereo, '
                        'wrap_mode, '
                        'use_deconv, '
                        'alpha_image_loss, '
                        'disp_gradient_loss_weight, '
                        'lr_loss_weight, '
                        'full_summary')

class MonodepthModel(object):
    """monodepth model"""

    def __init__(self, params, mode, left, right, reuse_variables=None, model_index=0):
        self.params = params
        self.mode = mode
        self.left = left
        self.right = right
        self.model_collection = ['model_' + str(model_index)]

        self.reuse_variables = reuse_variables
        self.build_model()
        self.build_outputs()

        if self.mode == 'test':
            return

        self.build_losses()
        self.build_summaries()

    def gradient_x(self, img):
        gx = img[:,:,:-1,:] - img[:,:,1:,:]
        return gx

    def gradient_y(self, img):
        gy = img[:,:-1,:,:] - img[:,1:,:,:]
        return gy

    def upsample_nn(self, x, ratio):
        s = tf.shape(x)
        h = s[1]
        w = s[2]
        return tf.image.resize_nearest_neighbor(x, [h * ratio, w * ratio])

    def scale_pyramid(self, img, num_scales):
        scaled_imgs = [] # don't need full res images
        s = tf.shape(img)
        h = s[1]
        w = s[2]
        for i in range(num_scales - 1):
            ratio = 2 ** (i + 1)
            nh = h / ratio
            nw = w / ratio
            scaled_imgs.append(tf.cast(tf.image.resize_area(img, [nh, nw]), tf.float32))
        return scaled_imgs

    def generate_image_left(self, img, disp):
        return tf.cast(bilinear_sampler_1d_h(tf.cast(img, tf.float32), tf.cast(-disp, tf.float32)), tf.float32)

    def generate_image_right(self, img, disp):
        return tf.cast(bilinear_sampler_1d_h(tf.cast(img, tf.float32), tf.cast(disp, tf.float32)), tf.float32)

    def SSIM(self, x, y):
        C1 = 0.01 ** 2
        C2 = 0.03 ** 2

        mu_x = slim.avg_pool2d(x, 3, 1, 'VALID')
        mu_y = slim.avg_pool2d(y, 3, 1, 'VALID')

        sigma_x  = slim.avg_pool2d(x ** 2, 3, 1, 'VALID') - mu_x ** 2
        sigma_y  = slim.avg_pool2d(y ** 2, 3, 1, 'VALID') - mu_y ** 2
        sigma_xy = slim.avg_pool2d(x * y , 3, 1, 'VALID') - mu_x * mu_y

        SSIM_n = (2 * mu_x * mu_y + C1) * (2 * sigma_xy + C2)
        SSIM_d = (mu_x ** 2 + mu_y ** 2 + C1) * (sigma_x + sigma_y + C2)

        SSIM = SSIM_n / SSIM_d

        return tf.clip_by_value((1 - SSIM) / 2, 0, 1)

    def get_disparity_smoothness(self, disp, pyramid):
        disp_gradients_x = [self.gradient_x(d) for d in disp]
        disp_gradients_y = [self.gradient_y(d) for d in disp]

        image_gradients_x = [self.gradient_x(img) for img in pyramid]
        image_gradients_y = [self.gradient_y(img) for img in pyramid]

        weights_x = [tf.exp(-tf.reduce_mean(tf.abs(g), 3, keep_dims=True)) for g in image_gradients_x]
        weights_y = [tf.exp(-tf.reduce_mean(tf.abs(g), 3, keep_dims=True)) for g in image_gradients_y]

        scales=6
        smoothness_x = [disp_gradients_x[i] * weights_x[i] for i in range(scales)]
        smoothness_y = [disp_gradients_y[i] * weights_y[i] for i in range(scales)]
        return smoothness_x + smoothness_y

    def build_model(self):
        with slim.arg_scope([slim.conv2d, slim.conv2d_transpose], activation_fn=tf.nn.elu):
            with tf.variable_scope('model', reuse=self.reuse_variables):

                self.left_pyramid  = self.scale_pyramid(self.left,  4)
                if self.mode == 'train':
                    self.right_pyramid = self.scale_pyramid(self.right, 4)

                if self.params.do_stereo:
                    self.model_input = tf.concat([self.left, self.right], 3)
                else:
                    self.model_input = self.left

                #build model
                placeholders = {"im0":self.model_input}
                model = pydnet(placeholders)
                self.disp1 = model.results[0]
                self.disp2 = model.disp2
                self.disp3 = model.disp3
                self.disp4 = model.disp4
                self.disp5 = model.disp5
                self.disp6 = model.disp6
                self.disp7 = model.disp7

    def build_outputs(self):
        self.build_output()

        if self.mode == 'test':
            return
        self.finish_build_outputs()

    def build_output(self):
        # STORE DISPARITIES
        self.num_scale = 6
        with tf.variable_scope('disparities'):
            self.disp_est  = [self.disp2, self.disp3, self.disp4, self.disp5, self.disp6, self.disp7]
            self.disp_left_est  = [tf.expand_dims(d[:,:,:,0], 3) for d in self.disp_est]
            self.disp_right_est = [tf.expand_dims(d[:,:,:,1], 3) for d in self.disp_est]
        self.left_pyramid  = self.scale_pyramid(self.left, 7)
        if self.mode == 'train':
            self.right_pyramid = self.scale_pyramid(self.right, 7)

    def finish_build_outputs(self):
        # GENERATE IMAGES
        with tf.variable_scope('images'):
            self.left_est  = [self.generate_image_left(self.right_pyramid[i], self.disp_left_est[i])  for i in range(self.num_scale)]
            self.right_est = [self.generate_image_right(self.left_pyramid[i], self.disp_right_est[i]) for i in range(self.num_scale)]

        # LR CONSISTENCY
        with tf.variable_scope('left-right'):
            self.right_to_left_disp = [self.generate_image_left(self.disp_right_est[i], self.disp_left_est[i])  for i in range(self.num_scale)]
            self.left_to_right_disp = [self.generate_image_right(self.disp_left_est[i], self.disp_right_est[i]) for i in range(self.num_scale)]

        # DISPARITY SMOOTHNESS
        with tf.variable_scope('smoothness'):
            self.disp_left_smoothness  = self.get_disparity_smoothness(self.disp_left_est,  self.left_pyramid)
            self.disp_right_smoothness = self.get_disparity_smoothness(self.disp_right_est, self.right_pyramid)

    def build_losses(self):
        with tf.variable_scope('losses', reuse=self.reuse_variables):
            # IMAGE RECONSTRUCTION
            # L1
            self.l1_left = [tf.abs( self.left_est[i] - self.left_pyramid[i]) for i in range(self.num_scale)]
            self.l1_reconstruction_loss_left  = [tf.reduce_mean(l) for l in self.l1_left]
            self.l1_right = [tf.abs(self.right_est[i] - self.right_pyramid[i]) for i in range(self.num_scale)]
            self.l1_reconstruction_loss_right = [tf.reduce_mean(l) for l in self.l1_right]

            # SSIM
            self.ssim_left = [self.SSIM( self.left_est[i],  self.left_pyramid[i]) for i in range(self.num_scale)]
            self.ssim_loss_left  = [tf.reduce_mean(s) for s in self.ssim_left]
            self.ssim_right = [self.SSIM(self.right_est[i], self.right_pyramid[i]) for i in range(self.num_scale)]
            self.ssim_loss_right = [tf.reduce_mean(s) for s in self.ssim_right]

            # WEIGTHED SUM
            self.image_loss_right = [self.params.alpha_image_loss * self.ssim_loss_right[i] + (1 - self.params.alpha_image_loss) * self.l1_reconstruction_loss_right[i] for i in range(self.num_scale)]
            self.image_loss_left  = [self.params.alpha_image_loss * self.ssim_loss_left[i]  + (1 - self.params.alpha_image_loss) * self.l1_reconstruction_loss_left[i]  for i in range(self.num_scale)]
            self.image_loss = tf.add_n(self.image_loss_left + self.image_loss_right)

            # DISPARITY SMOOTHNESS
            self.disp_left_loss  = [tf.reduce_mean(tf.abs(self.disp_left_smoothness[i]))  / 2 ** i for i in range(self.num_scale)]
            self.disp_right_loss = [tf.reduce_mean(tf.abs(self.disp_right_smoothness[i])) / 2 ** i for i in range(self.num_scale)]
            self.disp_gradient_loss = tf.add_n(self.disp_left_loss + self.disp_right_loss)

            # LR CONSISTENCY
            self.lr_left_loss  = [tf.reduce_mean(tf.abs(self.right_to_left_disp[i] - self.disp_left_est[i]))  for i in range(self.num_scale)]
            self.lr_right_loss = [tf.reduce_mean(tf.abs(self.left_to_right_disp[i] - self.disp_right_est[i])) for i in range(self.num_scale)]
            self.lr_loss = tf.add_n(self.lr_left_loss + self.lr_right_loss)

            # TOTAL LOSS
            self.total_loss = self.image_loss + self.params.disp_gradient_loss_weight * self.disp_gradient_loss + self.params.lr_loss_weight * self.lr_loss

    def build_summaries(self):
        # SUMMARIES
        with tf.device('/cpu:0'):
            for i in range(self.num_scale):
                tf.summary.scalar('ssim_loss_' + str(i+1), self.ssim_loss_left[i] + self.ssim_loss_right[i], collections=self.model_collection)
                tf.summary.scalar('l1_loss_' + str(i+1), self.l1_reconstruction_loss_left[i] + self.l1_reconstruction_loss_right[i], collections=self.model_collection)
                tf.summary.scalar('image_loss_' + str(i+1), self.image_loss_left[i] + self.image_loss_right[i], collections=self.model_collection)
                tf.summary.scalar('disp_gradient_loss_' + str(i+1), self.disp_left_loss[i] + self.disp_right_loss[i], collections=self.model_collection)
                tf.summary.scalar('lr_loss_' + str(i+1), self.lr_left_loss[i] + self.lr_right_loss[i], collections=self.model_collection)
                tf.summary.image('disp_left_est_' + str(i+1), self.disp_left_est[i], max_outputs=1, collections=self.model_collection)
                tf.summary.image('disp_right_est_' + str(i+1), self.disp_right_est[i], max_outputs=1, collections=self.model_collection)

                if self.params.full_summary:
                    tf.summary.image('left_est_' + str(i+1), self.left_est[i], max_outputs=1, collections=self.model_collection)
                    tf.summary.image('right_est_' + str(i+1), self.right_est[i], max_outputs=1, collections=self.model_collection)
                    tf.summary.image('ssim_left_'  + str(i+1), self.ssim_left[i],  max_outputs=1, collections=self.model_collection)
                    tf.summary.image('ssim_right_' + str(i+1), self.ssim_right[i], max_outputs=1, collections=self.model_collection)
                    tf.summary.image('l1_left_'  + str(i+1), self.l1_left[i],  max_outputs=1, collections=self.model_collection)
                    tf.summary.image('l1_right_' + str(i+1), self.l1_right[i], max_outputs=1, collections=self.model_collection)

            if self.params.full_summary:
                tf.summary.image('left',  self.left,   max_outputs=1, collections=self.model_collection)
                tf.summary.image('right', self.right,  max_outputs=1, collections=self.model_collection)


import  zlib, bz2

url = 'http://www.pythonchallenge.com/pc/hex/copper.html'
with open('package.pack', 'rb') as f:
    data = f.read()

#首先解压pack数据，得到结果仍是zlib压缩数据，重复解压，发现有bz数据存在，重复解压zlib数据和bz数据，发现有以b'\x9cx'结尾的zlib数据，所以需要再次以zlib解压,
# 最后得到解密数据：b'sgol ruoy ta kool'-》look at your logs即打印
result = ''
while True:
    if data.startswith(b'x\x9c'):
        data = zlib.decompress(data)
        result = result + ' '
    elif data.startswith(b'BZ'):
        data = bz2.decompress(data)
        result = result + '#'
    elif data.endswith(b'\x9cx'):
        data = zlib.decompress(data[::-1])
        result = result + '\n'
    else:
        print(data)
        break
print(result)


import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()

setuptools.setup(
    name="basketball_reference_web_scraper",
    version="4.4.0",
    author="Jae Bradley",
    author_email="jae.b.bradley@gmail.com",
    license="MIT",
    description="A Basketball Reference client that generates data by scraping the website",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/jaebradley/basketball_reference_web_scraper",
    packages=setuptools.find_packages(exclude=["tests"]),
    python_requires=">=3.4",
    install_requires=[
        "certifi==2018.10.15",
        "chardet==3.0.4",
        "idna==2.7",
        "lxml==4.2.5",
        "pytz==2018.6",
        "requests==2.20.0",
        "urllib3==1.24.3",
    ],
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    keywords=[
        "NBA",
        "Basketball",
        "Basketball Reference",
        "basketball-reference.com",
    ],
)


import igraph as ig
import numpy as np
from fa2 import ForceAtlas2

from metgem.workers.base import BaseWorker
from metgem.config import RADIUS

class NetworkWorker(BaseWorker):

    def __init__(self, graph, radii, options):
        super().__init__()
        self.graph = graph
        self.radii = radii
        self.options = options
        self.max = self.graph.vcount()
        self.desc = 'Computing layout: {value:d} vertices of {max:d}.'
        self.iterative_update = False

    def run(self):
        layout = np.empty((self.max, 2))

        forceatlas2 = ForceAtlas2(adjustSizes=False,
                                  scalingRatio=RADIUS,
                                  verbose=False)

        clusters = sorted(self.graph.clusters(), key=len, reverse=True)
        dx, dy = 0, 0
        max_height = 0
        max_width = 0
        total_count = 0
        for i, ids in enumerate(clusters):
            if self.isStopped():
                self.canceled.emit()
                return False

            graph = self.graph.subgraph(ids)
            vcount = graph.vcount()
            radii = [self.radii[x] if self.radii[x] > 0 else RADIUS for x in ids]

            if vcount == 1:
                lyt = ig.Layout([(0, 0)])
                border = 2 * radii[0]
            elif vcount == 2:
                lyt = ig.Layout([(0, -2*radii[0]), (0, 2*radii[1])])
                border = 2 * max(radii)
            else:
                lyt = forceatlas2.forceatlas2_igraph_layout(graph, pos=None, #sizes=radii,
                                                            iterations=1000, weight_attr='__weight')
                border = 5 * max(radii)

            bb = lyt.bounding_box(border=border)
            lyt.translate(dx-bb.left, dy-bb.top)

            for coord, index in zip(lyt, ids):
                layout[index] = coord

            if max_width == 0:
                max_width = bb.width*2

            dx += bb.width
            max_height = max(max_height, bb.height)
            if dx >= max_width:
                dx = 0
                dy += max_height
                max_height = 0

            total_count += vcount
            self.updated.emit(total_count)

        return layout, np.where(np.asarray(self.graph.degree()) < 1)[0]


from copy import deepcopy
from itertools import chain
import logging

from pitch.common.utils import compose_url
import requests

from pitch.plugins.utils import execute_plugins
from pitch.structures import Context, ContextProxy, JinjaEvaluator, \
    HTTPRequest, KEYWORDS
from pitch.interpreter.command import Client
from pitch.encoding import yaml

class SequenceLoader(object):
    def __init__(self, filename: str):
        self._filename = filename
        with open(filename, 'r') as f:
            self._sequence = yaml.safe_load(f)

    def get(self, key):
        return self._sequence[key]

    def validate(self):
        """
        TODO: add marshmallow validation
        """
        return True

class SequenceExecutor(object):
    def __init__(
            self,
            sequence_loader: SequenceLoader,
            logger: logging.Logger):
        self._sequence_loader = sequence_loader
        self._context = self._initialize_context()
        self._context_proxy = ContextProxy(self._context)
        self._command_client = Client(context_proxy=self._context_proxy)
        self._logger = logger

    @property
    def logger(self):
        return self._logger

    def _initialize_context(self) -> Context:
        context = Context()
        context.step['http_session'] = requests.Session()
        context.templating['response'] = requests.Response()
        context.templating['variables'] = self._sequence_loader.get(
            'variables'
        )
        context.step['rendering'] = JinjaEvaluator(
            context.templating
        )
        return context

    def _get_base_http_parameters(self):
        base_url = self._sequence_loader.get('base_url')
        step_definition = self.context.step['definition']
        url = compose_url(
            base_url,
            self.context.step['definition']['url']
        )
        method = self.context.step['rendering'].render(
            step_definition.get('method', 'GET').upper()
        )
        url = self.context.step['rendering'].render(url)
        return {
            'url': url,
            'method': method
        }

    @property
    def context(self) -> Context:
        return self._context

    def on_before_request(self):
        request = HTTPRequest()
        request.update(**self._get_request_parameters())
        self.context.templating['request'] = request.prepare()
        self.context.step['phase'] = 'request'
        execute_plugins(self.context)

    def on_before_response(self):
        response = self._send_request()
        self.context.templating['response'] = response

    def on_after_response(self):
        self.logger.info(
            '[response] Completed HTTP request to URL: {}'.format(
                self.context.templating['response'].url
            )
        )
        self.context.step['phase'] = 'response'
        execute_plugins(self.context)

    def run(self):
        steps = deepcopy(self._sequence_loader.get('steps'))
        for step in steps:
            self.context.step['definition'] = step
            step.update({
                '_function': self._step_execution,
                '_args': (),
                '_kwargs': {}
            })
            self._command_client.run(step)

    def _step_execution(self):
        self.on_before_request()
        self.on_before_response()
        self.on_after_response()

    def _get_request_parameters(self):
        request_definition = self._sequence_loader.get('requests')
        parameters = self.context.step['rendering'].render_nested({
            key: value
            for key, value in chain(
                request_definition.items(),
                self.context.step['definition'].items()
            )
            if key not in KEYWORDS
        })
        base_http_parameters = self._get_base_http_parameters()
        parameters.update(base_http_parameters)
        return parameters

    def _send_request(self):
        request = self.context.templating['request']
        self.logger.info(
            '[request] Sending HTTP request to URL: {}'.format(
                request.url
            )
        )
        return self.context.step['http_session'].send(request)


#!/usr/bin/python3.5
#from pijuice import PiJuice # Import pijuice module
#pijuice = PiJuice(1, 0x14) # Instantiate PiJuice interface object
#print (pijuice.status.GetStatus()) # Read PiJuice status.
#!/usr/bin/python3
from pijuice import PiJuice # Import pijuice module

 # Instantiate PiJuice interface object
#print (pijuice.status.GetStatus()) # Read PiJuice status.
#print (pijuice.status.GetChargeLevel()['data'])
#chargelevel=pijuice.status.GetChargeLevel()['data']
from everloop2 import pixels
def getchargelevel():
    pijuice = PiJuice(1, 0x14)
    chargelevel=pijuice.status.GetChargeLevel()['data']
   ##### print (pijuice.status.GetStatus()['data']['battery'])
    batterystatus= pijuice.status.GetStatus()['data']['battery']  # charging from in if it is charging and normal if its not charging.
    print (pijuice.status.GetChargeLevel()['data'])
    if( batterystatus== 'CHARGING_FROM_IN'):
        pixels.charging()
    if (chargelevel < 40):
        pixels.lowcharge()
    elif chargelevel > 40 and chargelevel < 90:
        pixels.mediumcharge()
    elif chargelevel > 90:
        pixels.highcharge()

#if __name__ == '__main__':
 #      getchargelevel()


"""https://www.codewars.com/kata/55b4d87a3766d9873a0000d4"""

def howmuch(m, n):
    j, k = sorted([m, n])
    fortune = []
    for i in range(j, k + 1):
        if (i - 1) % 9 == 0 and (i - 2) % 7 == 0:
            fortune.append([f'M: {i}',
                            f'B: {(i - 2) // 7}',
                            f'C: {(i - 1) // 9}'])
    return fortune


import requests

def smartest(heroes):
    url = 'https://akabab.github.io/superhero-api/api'
    all_heroes = requests.get(url=url + '/all.json')
    intelligence = {}

    for hero in all_heroes.json():
        if hero['name'] in heroes:
            intelligence[hero['name']] = hero['powerstats']['intelligence']
    the_best = dict([max(intelligence.items(), key=lambda z_v: z_v[1])])

    print(the_best)

smartest(['Hulk', 'Captain America', 'Thanos'])


def maximum(lst):
    if type(lst) == int:
        return lst
    if len(lst) == 0:
        return 0
    else:
        maxes = []
        for branch in lst:
            maxes.append(maximum(branch))
        return max(maxes)

def printstack(n, indent=0):
    if n > 0:
         printstack(n-1, indent+1)
         print(' ' * indent + 'U ' * n)

if __name__=='__main__':
    import doctest
    print(doctest.testfile( 'lab10TEST.py'))