import socket
import struct
import time
import math
from bitstring import BitArray

# Initial Code Taken From: https://elinux.org/Python_Can

# CAN frame packing/unpacking (see `struct can_frame` in <linux/can.h>)
# 8 bytes of data is sent to the motor
can_frame_fmt_send = "=IB3x8s"
# 6 bytes are received from the motor
can_frame_fmt_recv = "=IB3x6s"
# Total CAN Frame size is 14 Bytes: 8 Bytes overhead + 6 Bytes data
recvBytes = 14

# List of Motors Supported by this Driver
legitimate_motors = [
                    "AK80_6_V1",
                    "AK80_6_V1p1",
                    "AK80_6_V2",
                    "AK80_9_V1p1",
                    "AK80_9_V2",
                    "AK70_10_V1p1",
                    "AK10_9_V1p1"
                    ]

# Constants for conversion
# Working parameters for AK80-6 V1.0 firmware
AK80_6_V1_PARAMS = {
                "P_MIN" : -95.5,
                "P_MAX" : 95.5,
                "V_MIN" : -45.0,
                "V_MAX" : 45.0,
                "KP_MIN" : 0.0,
                "KP_MAX" : 500,
                "KD_MIN" : 0.0,
                "KD_MAX" : 5.0,
                "T_MIN" : -18.0,
                "T_MAX" : 18.0,
                "AXIS_DIRECTION" : -1
                }

# Working parameters for AK80-6 V1.1 firmware
AK80_6_V1p1_PARAMS = {
                "P_MIN" : -12.5,
                "P_MAX" : 12.5,
                "V_MIN" : -22.5,
                "V_MAX" : 22.5,
                "KP_MIN" : 0.0,
                "KP_MAX" : 500,
                "KD_MIN" : 0.0,
                "KD_MAX" : 5.0,
                "T_MIN" : -12.0,
                "T_MAX" : 12.0,
                "AXIS_DIRECTION" : -1
                }

# Working parameters for AK80-6 V2.0 firmware
AK80_6_V2_PARAMS = {
                "P_MIN" : -12.5,
                "P_MAX" : 12.5,
                "V_MIN" : -76.0,
                "V_MAX" : 76.0,
                "KP_MIN" : 0.0,
                "KP_MAX" : 500.0,
                "KD_MIN" : 0.0,
                "KD_MAX" : 5.0,
                "T_MIN" : -12.0,
                "T_MAX" : 12.0,
                "AXIS_DIRECTION" : 1
                }

# Working parameters for AK80-9 V1.1 firmware
AK80_9_V1p1_PARAMS = {
                "P_MIN" : -12.5,
                "P_MAX" : 12.5,
                "V_MIN" : -22.5,
                "V_MAX" : 22.5,
                "KP_MIN" : 0.0,
                "KP_MAX" : 500,
                "KD_MIN" : 0.0,
                "KD_MAX" : 5.0,
                "T_MIN" : -18.0,
                "T_MAX" : 18.0,
                "AXIS_DIRECTION" : 1
                }

# Working parameters for AK80-9 V2.0 firmware
AK80_9_V2_PARAMS = {
                    "P_MIN" : -12.5,
                    "P_MAX" : 12.5,
                    "V_MIN" : -25.64,
                    "V_MAX" : 25.64,
                    "KP_MIN" : 0.0,
                    "KP_MAX" : 500.0,
                    "KD_MIN" : 0.0,
                    "KD_MAX" : 5.0,
                    "T_MIN" : -18.0,
                    "T_MAX" : 18.0,
                    "AXIS_DIRECTION" : 1
                    }

#  Working parameters for AK70-10 V1.1 firmware
AK70_10_V1p1_params = {
                      "P_MIN" :  -12.5,
                      "P_MAX" :  12.5,
                      "V_MIN" :  -50,
                      "V_MAX" :  50,
                      "KP_MIN" :  0,
                      "KP_MAX" :  500,
                      "KD_MIN" :  0,
                      "KD_MAX" :  5,
                      "T_MIN" :  -24.0,
                      "T_MAX" :  24.0,
                      "AXIS_DIRECTION" :  1
                    }

# Working parameters for AK10-9 V1.1 firmware
AK10_9_V1p1_PARAMS = {
                "P_MIN" : -12.5,
                "P_MAX" : 12.5,
                "V_MIN" : -50.0,
                "V_MAX" : 50.0,
                "KP_MIN" : 0.0,
                "KP_MAX" : 500,
                "KD_MIN" : 0.0,
                "KD_MAX" : 5.0,
                "T_MIN" : -65.0,
                "T_MAX" : 65.0,
                "AXIS_DIRECTION" : -1
                }

maxRawPosition = 2**16 - 1                      # 16-Bits for Raw Position Values
maxRawVelocity = 2**12 - 1                      # 12-Bits for Raw Velocity Values
maxRawTorque = 2**12 - 1                        # 12-Bits for Raw Torque Values
maxRawKp = 2**12 - 1                            # 12-Bits for Raw Kp Values
maxRawKd = 2**12 - 1                            # 12-Bits for Raw Kd Values
maxRawCurrent = 2**12 - 1                       # 12-Bits for Raw Current Values
dt_sleep = 0.0001                               # Time before motor sends a reply
set_zero_sleep = 1.5                            # Time to wait after setting zero. Motor takes extra time to set zero.

def float_to_uint(x, x_min, x_max, numBits):
    span = x_max - x_min
    offset = x_min
    # Attempt to speedup by using pre-computation. Not used currently.
    if numBits == 16:
        bitRange = maxRawPosition
    elif numBits == 12:
        bitRange = maxRawVelocity
    else:
        bitRange = 2**numBits - 1
    return int(((x - offset) * (bitRange)) / span)

def uint_to_float(x_int, x_min, x_max, numBits):
    span = x_max - x_min
    offset = x_min
    if numBits == 16:
        bitRange = maxRawPosition
    elif numBits == 12:
        bitRange = maxRawVelocity
    else:
        bitRange = 2**numBits - 1
    return ((x_int * span) / (bitRange)) + offset

def waitOhneSleep(dt):
    startTime = time.time()
    while time.time() - startTime < dt:
        pass

class CanMotorController:
    """
    Class for creating a Mini-Cheetah Motor Controller over CAN. Uses SocketCAN driver for
    communication.
    """
    can_socket_declared = False
    motor_socket = None

    def __init__(self, can_socket="can0", motor_id=0x01, motor_type="AK80_6_V1p1", socket_timeout=0.05):
        """
        Instantiate the class with socket name, motor ID, and socket timeout.
        Sets up the socket communication for rest of the functions.
        """
        self.motorParams = AK80_6_V1p1_PARAMS  # default choice
        print("Using Motor Type: {}".format(motor_type))
        assert motor_type in legitimate_motors, "Motor Type not in list of accepted motors."
        if motor_type == "AK80_6_V1":
            self.motorParams = AK80_6_V1_PARAMS
        elif motor_type == "AK80_6_V1p1":
            self.motorParams = AK80_6_V1p1_PARAMS
        elif motor_type == "AK80_6_V2":
            self.motorParams = AK80_6_V2_PARAMS
        elif motor_type == "AK80_9_V1p1":
            self.motorParams = AK80_9_V1p1_PARAMS
        elif motor_type == "AK80_9_V2":
            self.motorParams = AK80_9_V2_PARAMS
        elif motor_type == "AK10_9_V1p1":
            # Experimental Support
            self.motorParams = AK10_9_V1p1_PARAMS
            # This motor/firmware also sends back temperature data
            # and an error code. Hence data is 2 bytes longer.
            recvBytes = 16
            can_frame_fmt_recv = "=IB3x8s"
        elif motor_type == "AK70_10_V1p1":
            self.motorParams = AK70_10_V1p1_params

        can_socket = (can_socket,)
        self.motor_id = motor_id
        if not CanMotorController.can_socket_declared:
            # create a raw socket and bind it to the given CAN interface
            try:
                CanMotorController.motor_socket = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
                CanMotorController.motor_socket.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_LOOPBACK, 0)
                CanMotorController.motor_socket.bind(can_socket)
                CanMotorController.motor_socket.settimeout(socket_timeout)
                print("Bound to: ", can_socket)
                CanMotorController.can_socket_declared = True
            except Exception as e:
                print("Unable to Connect to Socket Specified: ", can_socket)
                print("Error:", e)
        elif CanMotorController.can_socket_declared:
            print("Socket already available. Using:  ", CanMotorController.motor_socket)

        # Initialize the command BitArrays for performance optimization
        self._p_des_BitArray = BitArray(
            uint=float_to_uint(0, self.motorParams["P_MIN"], self.motorParams["P_MAX"], 16), length=16
        )
        self._v_des_BitArray = BitArray(
            uint=float_to_uint(0, self.motorParams["V_MIN"], self.motorParams["V_MAX"], 12), length=12
        )
        self._kp_BitArray = BitArray(uint=0, length=12)
        self._kd_BitArray = BitArray(uint=0, length=12)
        self._tau_BitArray = BitArray(uint=0, length=12)
        self._cmd_bytes = BitArray(uint=0, length=64)
        self._recv_bytes = BitArray(uint=0, length=48)

    def _send_can_frame(self, data):
        """
        Send raw CAN data frame (in bytes) to the motor.
        """
        can_dlc = len(data)
        can_msg = struct.pack(can_frame_fmt_send, self.motor_id, can_dlc, data)
        try:
            CanMotorController.motor_socket.send(can_msg)
        except Exception as e:
            print("Unable to Send CAN Frame.")
            print("Error: ", e)

    def _recv_can_frame(self):
        """
        Receive a CAN frame and unpack it. Returns can_id, can_dlc (data length), data (in bytes)
        """
        try:
            # The motor sends back only 6 bytes.
            frame, addr = CanMotorController.motor_socket.recvfrom(recvBytes)
            can_id, can_dlc, data = struct.unpack(can_frame_fmt_recv, frame)
            return can_id, can_dlc, data[:can_dlc]
        except Exception as e:
            print("Unable to Receive CAN Frame.")
            print("Error: ", e)

    def enable_motor(self):
        """
        Sends the enable motor command to the motor.
        """
        try:
            # Bugfix: To remove the initial kick at motor start.
            # The current working theory is that the motor is not
            # set to zero position when enabled. Hence the
            # last command is executed. So we set zero position
            # and then enable the motor.
            self.set_zero_position()
            self._send_can_frame(b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC")
            waitOhneSleep(dt_sleep)
            can_id, can_dlc, motorStatusData = self._recv_can_frame()
            rawMotorData = self.decode_motor_status(motorStatusData)
            pos, vel, curr = self.convert_raw_to_physical_rad(rawMotorData[0], rawMotorData[1], rawMotorData[2])
            print("Motor Enabled.")
            return pos, vel, curr
        except Exception as e:
            print("Error Enabling Motor!")
            print("Error: ", e)

    def disable_motor(self):
        """
        Sends the disable motor command to the motor.
        """
        try:
            # Bugfix: To remove the initial kick at motor start.
            # The current working theory is that the motor "remembers" the last command. And this
            # causes an initial kick as the motor controller starts. The fix is then to set the
            # last command to zero so that this does not happen. For the user, the behavior does
            # not change as zero command + disable is same as disable.
            _, _, _ = self.send_rad_command(0, 0, 0, 0, 0)

            # Do the actual disabling after zero command.
            self._send_can_frame(b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD')
            waitOhneSleep(dt_sleep)
            can_id, can_dlc, motorStatusData = self._recv_can_frame()
            rawMotorData = self.decode_motor_status(motorStatusData)
            pos, vel, curr = self.convert_raw_to_physical_rad(rawMotorData[0], rawMotorData[1], rawMotorData[2])
            print("Motor Disabled.")
            return pos, vel, curr
        except Exception as e:
            print("Error Disabling Motor!")
            print("Error: ", e)

    def set_zero_position(self):
        """
        Sends command to set current position as Zero position.
        """
        try:
            self._send_can_frame(b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE")
            waitOhneSleep(set_zero_sleep)
            can_id, can_dlc, motorStatusData = self._recv_can_frame()
            rawMotorData = self.decode_motor_status(motorStatusData)
            pos, vel, curr = self.convert_raw_to_physical_rad(rawMotorData[0], rawMotorData[1], rawMotorData[2])
            print("Zero Position set.")
            return pos, vel, curr
        except Exception as e:
            print("Error Setting Zero Position!")
            print("Error: ", e)

    def decode_motor_status(self, data_frame):
        """
        Function to decode the motor status reply message into its constituent raw values.

        /// CAN Reply Packet Structure ///
        /// 16 bit position, between -4*pi and 4*pi
        /// 12 bit velocity, between -30 and + 30 rad/s
        /// 12 bit current, between -40 and 40;
        /// CAN Packet is 5 8-bit words
        /// Formatted as follows.  For each quantity, bit 0 is LSB
        /// 0: [position[15-8]]
        /// 1: [position[7-0]]
        /// 2: [velocity[11-4]]
        /// 3: [velocity[3-0], current[11-8]]
        /// 4: [current[7-0]]

        returns: the following raw values as (u)int: position, velocity, current
        """

        # Convert the message from motor to a bit string as this is easier to deal with than hex
        # while seperating individual values.
        self._recv_bytes.bytes = data_frame
        dataBitArray = self._recv_bytes.bin

        # Separate motor status values from the bit string.
        # Motor ID not considered necessary at the moment.
        # motor_id = dataBitArray[:8]
        positionBitArray = dataBitArray[8:24]
        velocityBitArray = dataBitArray[24:36]
        currentBitArray = dataBitArray[36:48]

        # motor_id = int(motor_id, 2)
        positionRawValue = int(positionBitArray, 2)
        velocityRawValue = int(velocityBitArray, 2)
        currentRawValue = int(currentBitArray, 2)

        # TODO: Is it necessary/better to return motor_id?
        # return motor_id, positionRawValue, velocityRawValue, currentRawValue
        return positionRawValue, velocityRawValue, currentRawValue

    def convert_raw_to_physical_rad(self, positionRawValue, velocityRawValue, currentRawValue):
        """
        Function to convert the raw values from the motor to physical values:

        /// CAN Reply Packet Structure ///
        /// 16 bit position, between -4*pi and 4*pi
        /// 12 bit velocity, between -30 and + 30 rad/s
        /// 12 bit current, between -40 and 40;
        /// CAN Packet is 5 8-bit words
        /// Formatted as follows.  For each quantity, bit 0 is LSB
        /// 0: [position[15-8]]
        /// 1: [position[7-0]]
        /// 2: [velocity[11-4]]
        /// 3: [velocity[3-0], current[11-8]]
        /// 4: [current[7-0]]

        returns: position (radians), velocity (rad/s), current (amps)
        """

        physicalPositionRad = uint_to_float(positionRawValue, self.motorParams["P_MIN"], self.motorParams["P_MAX"], 16)
        physicalVelocityRad = uint_to_float(velocityRawValue, self.motorParams["V_MIN"], self.motorParams["V_MAX"], 12)
        physicalCurrent = uint_to_float(currentRawValue, self.motorParams["T_MIN"], self.motorParams["T_MAX"], 12)

        # Correct Axis Direction
        physicalPositionRad = physicalPositionRad * self.motorParams["AXIS_DIRECTION"]
        physicalVelocityRad = physicalVelocityRad * self.motorParams["AXIS_DIRECTION"]
        physicalCurrent = physicalCurrent * self.motorParams["AXIS_DIRECTION"]

        return physicalPositionRad, physicalVelocityRad, physicalCurrent

    def convert_physical_rad_to_raw(self, p_des_rad, v_des_rad, kp, kd, tau_ff):

        # Correct the Axis Direction
        p_des_rad = p_des_rad * self.motorParams["AXIS_DIRECTION"]
        v_des_rad = v_des_rad * self.motorParams["AXIS_DIRECTION"]
        tau_ff = tau_ff * self.motorParams["AXIS_DIRECTION"]

        rawPosition = float_to_uint(p_des_rad, self.motorParams["P_MIN"], self.motorParams["P_MAX"], 16)
        rawVelocity = float_to_uint(v_des_rad, self.motorParams["V_MIN"], self.motorParams["V_MAX"], 12)
        rawTorque = float_to_uint(tau_ff, self.motorParams["T_MIN"], self.motorParams["T_MAX"], 12)

        rawKp = (maxRawKp * kp) / self.motorParams["KP_MAX"]

        rawKd = (maxRawKd * kd) / self.motorParams["KD_MAX"]

        return int(rawPosition), int(rawVelocity), int(rawKp), int(rawKd), int(rawTorque)

    def _send_raw_command(self, p_des, v_des, kp, kd, tau_ff):
        """
        Package and send raw (uint) values of correct length to the motor.

        _send_raw_command(desired position, desired velocity, position gain, velocity gain,
                        feed-forward torque)

        Sends data over CAN, reads response, and returns the motor status data (in bytes).
        """
        self._p_des_BitArray.uint = p_des
        self._v_des_BitArray.uint = v_des
        self._kp_BitArray.uint = kp
        self._kd_BitArray.uint = kd
        self._tau_BitArray.uint = tau_ff
        cmd_BitArray = (
            self._p_des_BitArray.bin
            + self._v_des_BitArray.bin
            + self._kp_BitArray.bin
            + self._kd_BitArray.bin
            + self._tau_BitArray.bin
        )

        self._cmd_bytes.bin = cmd_BitArray

        try:
            self._send_can_frame(self._cmd_bytes.tobytes())
            waitOhneSleep(dt_sleep)
            can_id, can_dlc, data = self._recv_can_frame()
            return data
        except Exception as e:
            print("Error Sending Raw Commands!")
            print("Error: ", e)

    def send_deg_command(self, p_des_deg, v_des_deg, kp, kd, tau_ff):
        """
        Function to send data to motor in physical units:
        send_deg_command(position (deg), velocity (deg/s), kp, kd, Feedforward Torque (Nm))
        Sends data over CAN, reads response, and prints the current status in deg, deg/s, amps.
        If any input is outside limits, it is clipped. Only if torque is outside limits, a log
        message is shown.
        """
        p_des_rad = math.radians(p_des_deg)
        v_des_rad = math.radians(v_des_deg)

        pos_rad, vel_rad, curr = self.send_rad_command(p_des_rad, v_des_rad, kp, kd, tau_ff)
        pos = math.degrees(pos_rad)
        vel = math.degrees(vel_rad)
        return pos, vel, curr

    def send_rad_command(self, p_des_rad, v_des_rad, kp, kd, tau_ff):
        """
        Function to send data to motor in physical units:
        send_rad_command(position (rad), velocity (rad/s), kp, kd, Feedforward Torque (Nm))
        Sends data over CAN, reads response, and prints the current status in rad, rad/s, amps.
        If any input is outside limits, it is clipped. Only if torque is outside limits, a log
        message is shown.
        """
        # Check for Torque Limits
        if tau_ff < self.motorParams["T_MIN"]:
            print("Torque Commanded lower than the limit. Clipping Torque...")
            print("Commanded Torque: {}".format(tau_ff))
            print("Torque Limit: {}".format(self.motorParams["T_MIN"]))
            tau_ff = self.motorParams["T_MIN"]
        elif tau_ff > self.motorParams["T_MAX"]:
            print("Torque Commanded higher than the limit. Clipping Torque...")
            print("Commanded Torque: {}".format(tau_ff))
            print("Torque Limit: {}".format(self.motorParams["T_MAX"]))
            tau_ff = self.motorParams["T_MAX"]

        # Clip Position if outside Limits
        p_des_rad = min(max(self.motorParams["P_MIN"], p_des_rad), self.motorParams["P_MAX"])
        # Clip Velocity if outside Limits
        v_des_rad = min(max(self.motorParams["V_MIN"], v_des_rad), self.motorParams["V_MAX"])
        # Clip Kp if outside Limits
        kp = min(max(self.motorParams["KP_MIN"], kp), self.motorParams["KP_MAX"])
        # Clip Kd if outside Limits
        kd = min(max(self.motorParams["KD_MIN"], kd), self.motorParams["KD_MAX"])

        rawPos, rawVel, rawKp, rawKd, rawTauff = self.convert_physical_rad_to_raw(p_des_rad, v_des_rad, kp, kd, tau_ff)

        motorStatusData = self._send_raw_command(rawPos, rawVel, rawKp, rawKd, rawTauff)
        rawMotorData = self.decode_motor_status(motorStatusData)
        pos, vel, curr = self.convert_raw_to_physical_rad(rawMotorData[0], rawMotorData[1], rawMotorData[2])

        return pos, vel, curr

    def change_motor_constants(
        self,
        P_MIN_NEW,
        P_MAX_NEW,
        V_MIN_NEW,
        V_MAX_NEW,
        KP_MIN_NEW,
        KP_MAX_NEW,
        KD_MIN_NEW,
        KD_MAX_NEW,
        T_MIN_NEW,
        T_MAX_NEW,
    ):
        """
        Function to change the global motor constants. Default values are for AK80-6 motor from
        CubeMars. For a different motor, the min/max values can be changed here for correct
        conversion.
        change_motor_params(P_MIN_NEW (radians), P_MAX_NEW (radians), V_MIN_NEW (rad/s),
                            V_MAX_NEW (rad/s), KP_MIN_NEW, KP_MAX_NEW, KD_MIN_NEW, KD_MAX_NEW,
                            T_MIN_NEW (Nm), T_MAX_NEW (Nm))
        """
        self.motorParams["P_MIN"] = P_MIN_NEW
        self.motorParams["P_MAX"] = P_MAX_NEW
        self.motorParams["V_MIN"] = V_MIN_NEW
        self.motorParams["V_MAX"] = V_MAX_NEW
        self.motorParams["KP_MIN"] = KP_MIN_NEW
        self.motorParams["KP_MAX"] = KP_MAX_NEW
        self.motorParams["KD_MIN"] = KD_MIN_NEW
        self.motorParams["KD_MAX"] = KD_MAX_NEW
        self.motorParams["T_MIN"] = T_MIN_NEW
        self.motorParams["T_MAX"] = T_MAX_NEW


# -*- coding: utf-8 -*-
import json

import scrapy
from theatres.items import EventCover

from theatres.parseTransport import parseTransport

class ConcertEventsSpider(scrapy.Spider):
    name = 'concert_events'

    start_urls = ['http://www.offi.fr/']

    #placeName = None

    def parse(self, response):
        data_file = open('concerts.json')
        theatres = json.load(data_file)
        data_file.close()

        for t in theatres:
            placeName = t['name']

            for e in t['events']:
                request = scrapy.Request(response.urljoin(e), callback=self.parse_event)
                request.meta['item'] = placeName
                yield request

    def parse_event(self, response):
        placeName = response.meta['item']

        name = response.css('h1::text').extract_first()

        performers = ""
        for value in response.css('[itemprop=performers] [itemprop=name]::text').extract_first():
            performers += " " + value

        description = performers

        #description = response.css('.detail li:nth-child(4)::text').extract_first()

        #Details
        details = response.css('.detail')
        dateStart = ""
        dateEnd = ""

        img = response.css(".imgFiche img").xpath("@src")
        imageURL = img.extract_first()

        #Yield data
        yield EventCover (
            placeName = placeName,
            name = name,
            description = description,
            dateStart = dateStart,
            dateEnd = dateEnd,
            image_urls = [imageURL]
        )


import requests

response = requests.get("https://s3b.astro.ncu.edu.tw/ai_202309/data/q07.data")

splitted = response.content.split(b"\n")
counted = []

for word in splitted:
    if word not in counted:
        print(f"the word {word} appear in the table {splitted.count(word)} times")
        counted.append(word)


#!/usr/bin/env python

"""Loads tagged sentences. (Do not run main script as it is memory intensive.)"""

import argparse
import nicer
from multiprocessing import Pool
from itertools import repeat
from nltk.probability import FreqDist

from sent_tools import *

"""
Typical usage :
    Imports
"""

def dist_output(dist, output):
    # Writes distribution to output depending in order of frequency
    # Input : distribution, output file
    for x in dist.most_common():
        output.write(str(x[0]) + '  ' + str(x[1]))
        output.write("\n")
    output.write("\n")

def nnp_dist(tagfile, cores):
    # Creates distribution of words that begin sentenes and are taggged NNP
    ids, sents, dist = first_word_filter(tagfile, cores, "NNP")
    return dist

def first_word_filter(fname, cores, tag):
    # Returns list of first words of every sentence if the predicted pos tag is tag
    ids, tag_list = load_tags(fname, cores)
    filtered_ids = []
    filtered_sents = []
    word_dist = FreqDist()
    with Pool(processes=cores) as p:
            for return_tuple in p.starmap(
                check_one_sent_tag,
                zip(ids,
                tag_list,
                repeat(tag),
                ),
                1000,
            ):
                if return_tuple:
                    filtered_ids += return_tuple[0]
                    filtered_sents += return_tuple[1]
                    word_dist.update(return_tuple[2])

    return filtered_ids, filtered_sents, word_dist

def check_one_sent_tag(this_id, this_sent, tag):
    # Checks if first word of the sentence is tagged tag
    if this_sent[0][1] == tag:
        return this_id, this_sent, this_sent[0][1]

def untag_line_to_tokens(line):
    sent_id, sent = split_sentence_id(line)
    tokenized = tokenize(sent)
    tokens = [word.split('_')[0] for word in tokenized]
    return tokens

def load_one_sent_tags(line):
    # Loads one sentence of tags
    sent_id, sent = split_sentence_id(line)
    tokenized = tokenize(sent)
    tags = [tuple(word.split('_')) for word in tokenized]
    return sent_id, tags

def load_tag_lines(lines, cores=5):
    with Pool(processes=cores) as p:
            tags = p.imap(
                load_one_sent_tags,
                lines,
                250,
            )
            all_tags = list(zip(*tags))
            ids = all_tags[0]
            sents = all_tags[1]

    return ids, sents

def load_tags(tagfile, cores=5):
    # Loads tags from file of tagged sentences
    all_tags = []
    with Pool(processes=cores) as p:
            tags = p.imap(
                load_one_sent_tags,
                tagfile.readlines(),
                250,
            )
            all_tags = list(zip(*tags))
            ids = all_tags[0]
            sents = all_tags[1]
    tagfile.close()

    return ids, sents

def is_sent(sent):
    # Checks if the list (sentence) is actually a sentence
    for word in sent:
        if type(word) is not tuple or len(word) != 2:
            return False

    return True

def main(args):
    # DO NOT RUN!
    # Super memory intensive
    dist = nnp_dist(args.file, args.cores)
    dist_output(args, dist)

if __name__ == '__main__':
    nicer.make_nice()
    parser = argparse.ArgumentParser()

    parser.add_argument("--file", "-f",type=argparse.FileType("r"),
                            help="txt file to read proof/tags from")

    parser.add_argument("--output_sentences", "-os", type=argparse.FileType('w'),
                            help="txt file to write tagged sentences to")

    parser.add_argument("--output_wordlist", "-ow", type=argparse.FileType('w'),
                            help="txt file to write wordlist to")

    parser.add_argument( "--cores", "-c",
                            help="Number of cores to use", type=int, default=4)

    parser.add_argument("--tag", "-t", default=None,
                            help="specifies pos tag (given by off the shelf tagger) to filter")

    parser.add_argument("--output", "-o", type=argparse.FileType('w'),
                            help="txt file to write to")

    args = parser.parse_args()

    main(args)
    args.file.close()


class n:
    def __init__(s,v):
        s.v = v
        s.l = None
        s.r = None

class bst:
    def __init__(self,v):
        # if not self.root:
        self.root = n(v)

    def ins(self, v, node):
        if not node:
            return n(v)
        if v < node.v:
            node.l = self.ins(v, node.l)
        else:
            node.r = self.ins(v, node.r)
        return node

    def _print(self,n,s):
        if not n:
            return ""
        s += str(n.v) + "-"

        if n.l:
            s = self._print(n.l,s)
        if n.r:
            s = self._print(n.r,s)

        return s

    def print(self):
        print(self._print(self.root,""))

    def insert(self,v):
        self.ins(v,self.root)

    def _search(self,n,v):
        if not n:
            return False
        if n.v == v:
            return True
        elif  v < n.v:
            return self._search(n.l,v)
        else:
            return self._search(n.r,v)
    def search(self,v):
        print(v, "does exists in tree? ",self._search(self.root,v))

    def _sat(self,node,f):
        if node.l:
            if node.v < node.l.v:
                return False
        if node.r:
            if node.v > node.r.v:
                return False

        if node.l:
            f= self._sat(node.l,f)
        if node.r:
            f= self._sat(node.r,f)

        if f:
            return True
        return False

    def is_bst_satisfied(self):
        print(self._sat(self.root,True))

t = bst(50)
t.insert(40)
t.insert(60)
t.insert(45)
t.insert(65)
t.insert(55)
t.insert(55)
# t.root.r.v=2

t.print()
t.search(100)
t.search(45)
t.is_bst_satisfied()


# -*- coding: utf-8 -*-
# @Time : 2018/10/24 14:58
# @Author : chenpeng
# @Site : pengguoko@163.com
# @File : wuyou.py
from utils.makesession import create_51session
from bs4 import BeautifulSoup
from utils.mongomodel import WuYou, WuYouId

home = "https://ehire.51job.com"
session = create_51session()

def sto(s):
    d = s.split("_")
    s = "$".join(d)
    return s

def parse_item(payload):
    for key in list(payload.keys()):
        if key != "__VIEWSTATE" and key != "__EVENTTARGET":
            del payload[key]
    payload["send_cycle"] = "1"
    payload["send_time"] = "7"
    payload["send_sum"] = "10"
    payload["ctrlSerach$hidIsRecDisplay"] = "1"
    payload["pagerTopNew$ctl06"] = "10"
    payload["cbxColumns$0"] = "AGE"
    payload["cbxColumns$1"] = "WORKYEAR"
    payload["cbxColumns$2"] = "SEX"
    payload["cbxColumns$3"] = "AREA"
    payload["cbxColumns$4"] = "WORKFUNC"
    payload["cbxColumns$5"] = "TOPDEGREE"
    payload["cbxColumns$6"] = "LASTUPDATE"
    payload["cbxColumns$11"] = "TOPMAJOR"
    payload["cbxColumns$12"] = "TOPSCHOOL"
    payload["hidStrAuthority"] = "0"
    payload["hidDownloadNum"] = "20"
    payload["hidKeywordCookie"] = ""
    payload["ctrlSerach$search_expectsalaryf_input"] = "不限"
    payload["ctrlSerach$search_expectsalaryt_input"] = "不限"
    payload["ctrlSerach$search_wyf_input"] = "不限"
    payload["ctrlSerach$search_wyt_input"] = "不限"
    payload["ctrlSerach$search_df_input"] = "不限"
    payload["ctrlSerach$search_dt_input"] = "不限"
    payload["ctrlSerach$search_cursalaryf_input"] = "不限"
    payload["ctrlSerach$search_cursalaryt_input"] = "不限"
    payload["ctrlSerach$search_age_input"] = "年龄"
    payload["ctrlSerach$search_expjobarea_input"] = "期望工作地"
    payload["ctrlSerach$search_forlang_input"] = "语言"
    payload["ctrlSerach$search_fl_input"] = "不限"
    payload["ctrlSerach$search_fllsabilityll_input"] = "不限"
    payload["ctrlSerach$search_englishlevel_input"] = "英语等级"
    payload["ctrlSerach$search_sex_input"] = "性别"
    payload["ctrlSerach$search_major_input"] = "专业"
    payload["ctrlSerach$search_hukou_input"] = "户口"
    payload["ctrlSerach$search_rsmupdate_input"] = "近1年"
    payload["ctrlSerach$search_jobstatus_input"] = "求职状态"
    payload["pagerTopNew$ctl06"] = "50"
    payload["ctrlSerach$hidIsRecDisplay"] = "1"
    # print(payload)
    r = session.post(
        "https://ehire.51job.com/Candidate/SearchResumeNew.aspx", data=payload
    )
    soup = BeautifulSoup(r.text, "lxml")
    div = soup.find("div", {"class": "Common_list-table"})
    trs = div.find_all("tr")
    for item in trs:
        tds = item.find_all("td")
        if len(tds) == 12:
            res = {}
            unid = WuYouId.objects(uid=tds[1].text)
            if unid:
                w = WuYou.objects.filter(uid=tds[1].text).first()
                if "detail" in w.to_mongo():
                    continue
                else:
                    a = tds[1].find("a")
                    url2 = home + a["href"]
                    try:
                        dd = parse_data(url2)
                        for key in dd.keys():
                            w.key = dd[key]
                        w.save()
                    except Exception as e:
                        print(e)
                        print(url2)
                        pass
            else:
                a = tds[1].find("a")
                url2 = home + a["href"]
                try:
                    dd = parse_data(url2)
                    res.update(dd)
                except Exception as e:
                    print(e)
                    print(url2)
                    pass
                res["uid"] = tds[1].text
                res["age"] = tds[2].text
                res["work_years"] = tds[3].text
                res["gender"] = tds[4].text
                res["address"] = tds[5].text
                res["job_category"] = tds[6].text
                res["edu"] = tds[7].text
                res["updated"] = tds[8].text
                res["major"] = tds[9].text
                res["school"] = tds[10].text
                w = WuYou(**res)
                w.save()
                wid = WuYouId(uid=res["uid"])
                wid.save()
                print("find a new person ", res)
    paydata = {}
    # inputs = soup.find_all('input', {"type": "hidden"})
    inputs = soup.find_all("input")
    for item in inputs:
        try:
            if item["value"]:
                paydata[item["name"]] = item["value"]
            else:
                paydata[item["name"]] = ""
        except:
            pass
    div = soup.find("div", {"class": "Search_page-numble"})
    manya = div.find_all("a")
    current_page = 0
    for item in manya:
        try:
            if item["class"] and item["class"][0] == "active":
                current_page = int(item["title"])
        except:
            pass
        try:
            if current_page:
                if item["title"] == str(current_page + 1):
                    paydata["__EVENTTARGET"] = sto(item["id"])
        except:
            pass
    return paydata, current_page

def parse_data(url1):
    res = {}
    r = session.get(url1)
    soup = BeautifulSoup(r.text, "lxml")
    ta = soup.find("table", {"class": "box1"})
    img = ta.find("img")
    if img:
        if img["src"].startswith("//"):
            res["img"] = "https:" + img["src"]
        else:
            res["img"] = home + img["src"].strip()[img["src"].strip().find("/") :]
    else:
        res["img"] = ""
    try:
        div = soup.find("div", {"id": "divResume"})
        ta = div.find("table", {"class": "column"})
        tables = ta.find_all("table")
        resu = ""
        for table in tables:
            resu = resu + table.text
        res["detail"] = resu
    except Exception as e:
        pass
    print(res)
    return res

def next_page():
    r = session.get("https://ehire.51job.com/Candidate/SearchResumeNew.aspx")
    soup = BeautifulSoup(r.text, "lxml")
    # inputs = soup.find_all('input', {"type": "hidden"})
    inputs = soup.find_all("input")
    paydata = {}
    for item in inputs:
        try:
            if item["value"]:
                paydata[item["name"]] = item["value"]
            else:
                paydata[item["name"]] = ""
        except:
            pass
    div = soup.find("div", {"class": "Search_page-numble"})
    manya = div.find_all("a")
    current_page = 0
    for item in manya:
        try:
            if item["class"] and item["class"][0] == "active":
                current_page = int(item["title"])
        except:
            pass
        try:
            if current_page != 0:
                if item["title"] == str(current_page + 1):
                    paydata["__EVENTTARGET"] = sto(item["id"])
        except:
            pass
    return paydata, current_page

def crawl():
    payload, current_page = next_page()
    while current_page < 101:
        payload1, current_page1 = parse_item(payload)
        payload = payload1
        current_page = int(current_page1)
        print("the parse page is ", current_page)

crawl()


from inkscape_layer_utils import __version__

extensions = [
    "sphinx.ext.autodoc",
    "sphinx.ext.napoleon",
    "sphinx.ext.viewcode",
]

html_theme = "sphinx_rtd_theme"

master_doc = "index"
project = "Inkscape Layer Utils"
copyright = "2023, twyleg"
author = "Torsten Wylegala"
version = release = __version__


registration_types = []

class JoinTableDefinition:
    """Object holding a table that should be joinedloaded into its parent
    and a list of nested JoinTableDefinitions that should be joinedloaded
    into this specific object.
    """

    def __init__(self, table_name, inner_joins):
        self.table_name = table_name
        self.inner_joins = inner_joins

class RegistrationTypeConfig:
    """Object holding all the configuration values needed
    for a registration type during ETL.
    """

    def __init__(
        self, type_name, full_name, main_table, pk_col, mongo_collection, sourceKey
    ):
        self.type_name = type_name
        self.full_name = full_name
        self.main_table = main_table
        self.pk_col = pk_col
        self.mongo_collection = mongo_collection
        self.location_table = None
        self.registration_history_table = None
        self.join_tables = []
        self.sourceKey = sourceKey

    def set_location_table(self, location_table):
        self.location_table = location_table

    def set_registration_history_table(self, registration_history_table):
        self.registration_history_table = registration_history_table

    def set_join_tables(self, join_tables):
        for jt in join_tables:
            self.join_tables.append(jt)

def init_registration_types():
    # Init gmw
    gmw = RegistrationTypeConfig(
        type_name="gmw",
        full_name="Grondwatermonitoringput",
        main_table="gmw_monitoring_well",
        pk_col="monitoring_well_id",
        mongo_collection="specificGMW",
        sourceKey="sourceGMW",
    )
    gmw.set_join_tables(
        [
            JoinTableDefinition(
                "gmw_monitoring_tube_collection",
                [
                    JoinTableDefinition(
                        "gmw_geo_ohm_cable_collection",
                        [JoinTableDefinition("gmw_electrode_collection", [])],
                    )
                ],
            )
        ]
    )
    registration_types.append(gmw)

    # Init sfr
    sfr = RegistrationTypeConfig(
        type_name="sfr",
        full_name="BodemkundigWandonderzoek",
        main_table="soil_face_research",
        pk_col="soil_face_research_pk",
        mongo_collection="specificSFR",
        sourceKey="sourceSFR",
    )
    sfr.set_location_table("deliveredLocationCollection")
    sfr.set_registration_history_table("registrationHistoryCollection")
    sfr.set_join_tables(
        [
            JoinTableDefinition("delivered_location_collection", []),
            JoinTableDefinition("registration_history_collection", []),
        ]
    )
    registration_types.append(sfr)

    # Init cpt
    cpt = RegistrationTypeConfig(
        type_name="cpt",
        full_name="GeotechnischSondeeronderzoek",
        main_table="cpt_geotechnical_survey",
        pk_col="geotechnical_survey_id",
        mongo_collection="specificCPT",
        sourceKey="sourceCPT",
    )
    cpt.set_join_tables(
        [
            JoinTableDefinition(
                "cpt_cone_penetrometer_survey_collection",
                [JoinTableDefinition("cpt_cone_penetration_test_collection", [])],
            )
        ]
    )
    registration_types.append(cpt)

    # Init bhr-gt
    bhrgt = RegistrationTypeConfig(
        type_name="bhr-gt",
        full_name="GeotechnischBooronderzoek",
        main_table="borehole_research",
        pk_col="borehole_research_pk",
        mongo_collection="specificBHRGT",
        sourceKey="sourceBHRGT",
    )
    bhrgt.set_location_table("deliveredLocationCollection")
    bhrgt.set_registration_history_table("registrationHistoryCollection")
    bhrgt.set_join_tables(
        [
            JoinTableDefinition("boring_collection", []),
            JoinTableDefinition("registration_history_collection", []),
            JoinTableDefinition("delivered_location_collection", []),
        ]
    )
    registration_types.append(bhrgt)

    # Init bhr-p
    bhrp = RegistrationTypeConfig(
        type_name="bhr-p",
        full_name="BodemkundigBooronderzoek",
        main_table="borehole_research",
        pk_col="borehole_research_pk",
        mongo_collection="specificBHR",
        sourceKey="sourceBHRP",
    )
    bhrp.set_location_table("deliveredLocationCollection")
    bhrp.set_registration_history_table("registrationHistoryCollection")
    bhrp.set_join_tables(
        [
            JoinTableDefinition("delivered_location_collection", []),
            JoinTableDefinition("registration_history_collection", []),
        ]
    )
    registration_types.append(bhrp)

    # Init gmn
    gmn = RegistrationTypeConfig(
        type_name="gmn",
        full_name="Grondwatermonitoringnet",
        main_table="groundwater_monitoring_net",
        pk_col="groundwater_monitoring_net_pk",
        mongo_collection="specificGMN",
        sourceKey="sourceGMN",
    )
    gmn.set_registration_history_table("registrationHistoryCollection")
    gmn.set_join_tables(
        [
            JoinTableDefinition("registration_history_collection", []),
            JoinTableDefinition(
                "measuring_point_with_history_collection",
                [JoinTableDefinition("groundwater_monitoring_tube_collection", [])],
            ),
        ]
    )
    registration_types.append(gmn)


import datetime

from django.utils import timezone
from django.core.exceptions import MultipleObjectsReturned

from cdms_api.exceptions import CDMSNotFoundException

from migrator.tests.queries.models import SimpleObj
from migrator.tests.queries.base import BaseMockedCDMSApiTestCase
from migrator.exceptions import ObjectsNotInSyncException

from cdms_api.tests.utils import mocked_cdms_get

class BaseGetTestCase(BaseMockedCDMSApiTestCase):
    def setUp(self):
        super(BaseGetTestCase, self).setUp()
        self.obj = SimpleObj.objects.skip_cdms().create(
            cdms_pk='cdms-pk', name='name'
        )

class GetByIdTestCase(BaseGetTestCase):
    def test_local_exists(self):
        """
        MyObject.objects.get(pk=..) should hit the cdms api and return the local obj.
        """
        obj = SimpleObj.objects.get(pk=self.obj.pk)
        self.assertEqual(obj.pk, self.obj.pk)

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': self.obj.cdms_pk}
        )
        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

    def test_local_doesnt_exist(self):
        """
        MyObject.objects.get(pk=..) should raise DoesNotExist and not hit the db if the local obj doesn't exist
        """
        self.assertRaises(
            SimpleObj.DoesNotExist,
            SimpleObj.objects.get,
            pk=0
        )

        self.assertNoAPICalled()

class GetByCmdPKTestCase(BaseGetTestCase):
    def test_local_exists(self):
        """
        MyObject.objects.get(cdms_pk=..) when local obj exists,
        should hit the cdms api and return the local obj.
        """
        obj = SimpleObj.objects.get(cdms_pk=self.obj.cdms_pk)
        self.assertEqual(obj.pk, self.obj.pk)

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': self.obj.cdms_pk}
        )
        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

    def test_local_doesnt_exist(self):
        """
        MyObject.objects.get(cdms_pk=..) when local obj does not exist,
        should hit the cdms api, create a local obj and return it.
        """
        modified_on = (timezone.now() + datetime.timedelta(days=1)).replace(microsecond=0)
        self.mocked_cdms_api.get.side_effect = mocked_cdms_get(
            get_data={
                'ModifiedOn': modified_on,
                'Name': 'new name',
                'DateTimeField': None,
                'IntField': None,
                'FKField': None
            }
        )

        SimpleObj.objects.skip_cdms().all().delete()
        self.assertEqual(SimpleObj.objects.skip_cdms().count(), 0)

        obj = SimpleObj.objects.get(cdms_pk='cdms-pk')
        self.assertEqual(SimpleObj.objects.skip_cdms().count(), 1)
        self.assertEqual(obj.cdms_pk, 'cdms-pk')
        self.assertEqual(obj.name, 'new name')
        self.assertEqual(obj.modified, modified_on)

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': 'cdms-pk'}
        )
        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

        # reload obj and check
        obj = SimpleObj.objects.skip_cdms().get(pk=obj.pk)
        self.assertEqual(obj.cdms_pk, 'cdms-pk')
        self.assertEqual(obj.name, 'new name')
        self.assertEqual(obj.modified, modified_on)

    def test_neither_local_nor_cdms_obj_exists(self):
        """
        MyObject.objects.get(cdms_pk=..) when neither local nor cdms obj exists
        should raise MyObject.DoesNotExist.
        """
        self.mocked_cdms_api.get.side_effect = CDMSNotFoundException('not found')

        SimpleObj.objects.skip_cdms().all().delete()
        self.assertEqual(SimpleObj.objects.skip_cdms().count(), 0)

        self.assertRaises(
            SimpleObj.DoesNotExist,
            SimpleObj.objects.get, cdms_pk='cdms-pk'
        )
        self.assertEqual(SimpleObj.objects.skip_cdms().count(), 0)

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': 'cdms-pk'}
        )
        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

class GetByOtherFieldsTestCase(BaseGetTestCase):
    def test(self):
        """
        MyObject.objects.get(other_field=..) should work as with pk or id.
        """
        obj = SimpleObj.objects.get(name='name')
        self.assertEqual(obj.pk, self.obj.pk)

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': self.obj.cdms_pk}
        )
        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

    def test_multiple_objects_returned(self):
        SimpleObj.objects.skip_cdms().create(cdms_pk='cdms-pk1', name='name')
        SimpleObj.objects.skip_cdms().create(cdms_pk='cdms-pk2', name='name')

        self.assertRaises(
            MultipleObjectsReturned,
            SimpleObj.objects.get,
            name='name'
        )

        self.assertNoAPICalled()

class SyncGetTestCase(BaseGetTestCase):
    def test_with_objs_in_sync(self):
        """
        If the cdms obj and local obj are in sync:
            - get obj from local db
            - get cdms_obj from cdms
            - no local changes happen
        """
        self.mocked_cdms_api.get.side_effect = mocked_cdms_get(
            get_data={
                'ModifiedOn': self.obj.modified
            }
        )

        obj = SimpleObj.objects.get(pk=self.obj.pk)
        self.assertEqual(obj.modified, self.obj.modified)

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': self.obj.cdms_pk}
        )

        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

    def test_with_local_more_up_to_date(self):
        """
        If the local obj is more up to date, it means that the last syncronisation didn't
        work as it should have, so we raise ObjectsNotInSyncException.
        """
        modified_on = self.obj.modified - datetime.timedelta(seconds=0.001)

        self.mocked_cdms_api.get.side_effect = mocked_cdms_get(
            get_data={
                'ModifiedOn': modified_on
            }
        )

        self.assertRaises(
            ObjectsNotInSyncException, SimpleObj.objects.get, pk=self.obj.pk
        )

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': self.obj.cdms_pk}
        )

        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

    def test_with_cdms_more_up_to_date(self):
        """
        If the cdms obj includes more recent changes:
            - get obj from local db
            - get cdms_obj from cdms
            - update obj from cdms_obj
        """
        modified_on = self.obj.modified + datetime.timedelta(seconds=1)
        self.mocked_cdms_api.get.side_effect = mocked_cdms_get(
            get_data={
                'ModifiedOn': modified_on,
                'Name': 'new name',
                'DateTimeField': '/Date(1451606400000)/',
                'IntField': 10,
                'FKField': None
            }
        )

        obj = SimpleObj.objects.get(pk=self.obj.pk)
        self.assertEqual(obj.name, 'new name')
        self.assertEqual(obj.dt_field, datetime.datetime(2016, 1, 1).replace(tzinfo=datetime.timezone.utc))
        self.assertEqual(obj.int_field, 10)
        self.assertEqual(obj.modified, modified_on)
        self.assertEqual(obj.created, self.obj.created)

        self.assertAPIGetCalled(
            SimpleObj, kwargs={'guid': self.obj.cdms_pk}
        )

        self.assertAPINotCalled(['list', 'update', 'delete', 'create'])

        # reload obj and check
        obj = SimpleObj.objects.skip_cdms().get(pk=obj.pk)
        self.assertEqual(obj.cdms_pk, 'cdms-pk')
        self.assertEqual(obj.name, 'new name')
        self.assertEqual(obj.modified, modified_on)

    def test_cdms_exception_triggers_exception(self):
        """
        If an exception happens when accessing cdms, the exception is propagated.
        """
        self.mocked_cdms_api.get.side_effect = Exception

        self.assertRaises(
            Exception, SimpleObj.objects.get, pk=self.obj.pk
        )

class GetSkipCDMSTestCase(BaseGetTestCase):
    def test_get_by_any_fields(self):
        """
        Klass.objects.skip_cdms().get(...) should not hit cdms.
        """
        SimpleObj.objects.skip_cdms().get(pk=self.obj.pk)
        self.assertNoAPICalled()

        SimpleObj.objects.skip_cdms().get(cdms_pk=self.obj.cdms_pk)
        self.assertNoAPICalled()

    def test_object_not_found(self):
        """
        Klass.objects.skip_cdms().get(...) should raise DoesNotExist and not hit cdms.
        """
        self.assertRaises(
            SimpleObj.DoesNotExist,
            SimpleObj.objects.skip_cdms().get,
            cdms_pk='invalid'
        )
        self.assertNoAPICalled()


import tkinter
from tkinter import ttk, messagebox
import sqlcommand
import chart_of_accounts

class VatRates(tkinter.Toplevel):

    def __init__(self, parent):
        """Vat rates main window"""
        super().__init__(parent)

        self.title("Vat rates")
        self.resizable(False, False)

        # Create vat rates Frame
        self.vat_rates_frame = tkinter.Frame(self)
        self.vat_rates_frame.grid(column=0, row=0)

        self.vat_rates_treeview()

        # Create options Frame
        self.vat_rates_options = tkinter.Frame(self)
        self.vat_rates_options.grid(column=1, row=0, sticky='n')

        self.add_vat_rate_button = tkinter.Button(self.vat_rates_options, text="Add vat rate",
                                                  command=self.add_vat_rate,
                                                  pady=5, padx=5, width=20)
        self.add_vat_rate_button.grid(column=0, row=0)

        self.delete_vat_rate_button = tkinter.Button(self.vat_rates_options, text="Delete vat rate",
                                                     command=self.delete_vat_rate,
                                                     pady=5, padx=5, width=20)
        self.delete_vat_rate_button.grid(column=0, row=1)

    def vat_rates_treeview(self):
        """Create vat rates treeview"""
        # Connect to sql database to add vat rates
        conn = sqlcommand.SqlCommand()
        execute = conn.sql_execute('''SELECT * FROM vat_rates ORDER BY vat_rate DESC''')

        column_names = execute['column_names']
        self.vat_rates_tree = ttk.Treeview(self.vat_rates_frame, columns=column_names, show='headings', height=10)
        column = 0
        for _ in column_names:
            self.vat_rates_tree.heading(column_names[column], text=f'{column_names[column]}')
            column += 1
        # Adjust column width
        self.vat_rates_tree.column(column_names[0], width=120)
        self.vat_rates_tree.column(column_names[1], width=100)
        self.vat_rates_tree.column(column_names[2], width=100)
        self.vat_rates_tree.column(column_names[3], width=100)

        self.vat_rates_tree.grid(column=0, row=0)

        records = execute['records']
        record = 0
        for _ in records:
            self.vat_rates_tree.insert('', tkinter.END, values=records[record])
            record += 1

    def selected_vat_rate(self):
        selected = self.vat_rates_tree.focus()
        vr = self.vat_rates_tree.item(selected).get('values')
        return vr

    def clicked_button(self, event):
        """Return clicked button"""
        self.clicked_btn = event.widget

    def clicked_right_button(self, event):
        """Return clicked right button"""
        self.clicked_right_btn = event.widget
        self.r_click_menu.tk_popup(event.x_root, event.y_root)

    def add_vat_rate(self):
        """Open new window to add vat rate"""
        self.add_vat_rate_window = tkinter.Toplevel()
        self.add_vat_rate_window.title("Add vat rate")
        self.add_vat_rate_window.grab_set()
        self.add_vat_rate_window.resizable(False, False)

        # Inputs
        self.vat_id_label = tkinter.Label(self.add_vat_rate_window, text="VAT ID", width=25)
        self.vat_id_label.grid(column=0, row=0)
        self.vat_id_entry = tkinter.Entry(self.add_vat_rate_window, width=20)
        self.vat_id_entry.grid(column=1, row=0)

        self.vat_rate_label = tkinter.Label(self.add_vat_rate_window, text="VAT rate", width=25)
        self.vat_rate_label.grid(column=0, row=1)
        self.vat_rate_entry = tkinter.Entry(self.add_vat_rate_window, width=20)
        self.vat_rate_entry.grid(column=1, row=1)

        self.sales_account_num_label = tkinter.Label(self.add_vat_rate_window, text="Sales account number", width=25)
        self.sales_account_num_label.grid(column=0, row=2)
        self.sales_account_num_entry = tkinter.Button(self.add_vat_rate_window, text='',
                                                      command=self.select_account,
                                                      width=25, highlightbackground='grey', borderwidth=1,
                                                      relief='sunken', anchor='w')
        self.sales_account_num_entry.bind('<Button-1>', self.clicked_button)
        self.sales_account_num_entry.grid(column=1, row=2)

        self.purchase_account_num_label = tkinter.Label(self.add_vat_rate_window, text="Purchase account number", width=25)
        self.purchase_account_num_label.grid(column=0, row=3)
        self.purchase_account_num_entry = tkinter.Button(self.add_vat_rate_window, text='',
                                                         command=self.select_account,
                                                         width=25, highlightbackground='grey', borderwidth=1,
                                                         relief='sunken', anchor='w')
        self.purchase_account_num_entry.bind('<Button-1>', self.clicked_button)
        self.purchase_account_num_entry.grid(column=1, row=3)

        self.add_rate_button = tkinter.Button(self.add_vat_rate_window,
                                              text="Add vat rate", command=self.add_vat_rate_command)
        self.add_rate_button.grid(column=1, row=4)

        # Right mouse click menu
        self.r_click_menu = tkinter.Menu(self, tearoff=False)
        self.r_click_menu.add_command(label="Delete", command=self.delete_choice)

        # bind name of widget with function
        self.sales_account_num_entry.bind('<Button-3>', self.clicked_right_button)
        self.purchase_account_num_entry.bind('<Button-3>', self.clicked_right_button)
        self.vat_rate_entry.bind('<Button-3>', self.clicked_right_button)

    def add_vat_rate_command(self):
        """Connect to sql database and add vat rate"""
        try:
            int(self.vat_rate_entry.get())
            sql_command = f"INSERT INTO vat_rates(vat_id, vat_rate, sales_account_num, purchase_account_num) " \
                          f"VALUES" \
                          f"('{self.vat_id_entry.get()}', '{self.vat_rate_entry.get()}'," \
                          f"'{self.sales_account_num_entry['text']}', '{self.purchase_account_num_entry['text']}')"

            # Connect to sql database to add account
            conn = sqlcommand.SqlCommand()
            conn.sql_execute(sql_command)

            self.add_vat_rate_window.destroy()

            # Refresh chart of accounts tree
            self.refresh_vat_rates_tree()
        except ValueError:
            tkinter.messagebox.showerror(title="ERROR", message="Input integer in VAT rate entry",
                                         parent=self.add_vat_rate_window)

    def select_account(self):
        """Open new window with account to choose"""
        self.account_window = chart_of_accounts.ChartOfAccounts(self)
        self.account_window.grab_set()
        self.selected_account_button = self.clicked_btn
        add_account_button = tkinter.Button(self.account_window, text='Select account',
                                             command=self.select_account_command, font=30)
        add_account_button.grid(column=0, row=1, columnspan=2)

    def select_account_command(self):
        """Get selected account from account window"""
        self.acc_details = self.account_window.selected_account()
        self.acc_num = self.account_window.selected_account_num()
        self.selected_account_button.config(text=f"{self.acc_num}")
        self.account_window.destroy()

    def delete_choice(self):
        """Delete choice from button entry widgets"""
        self.r_clicked_button = self.clicked_right_btn
        self.r_clicked_button.config(text='')

    def delete_vat_rate(self):
        """Delete vat rate"""
        try:
            sql_command = f"DELETE FROM vat_rates WHERE vat_id='{self.selected_vat_rate()[0]}'"
            answer = tkinter.messagebox.askyesno(title="WARNING", message=f"Delete {self.selected_vat_rate()[0]}?",
                                                 parent=self)

            if answer:
                deleted_vat_rate = self.selected_vat_rate()[0]
                # Connect to sql database to delete account
                conn = sqlcommand.SqlCommand()
                conn.sql_execute(sql_command)

                # Refresh customers tree
                self.refresh_vat_rates_tree()
                tkinter.messagebox.showinfo(title="INFO", message=f"{deleted_vat_rate} deleted successfully",
                                            parent=self)

        except:
            tkinter.messagebox.showerror(title="ERROR", message="Select vat rate", parent=self)

    def refresh_vat_rates_tree(self):
        """Refresh customer tree"""
        self.vat_rates_tree.delete(*self.vat_rates_tree.get_children())
        self.vat_rates_treeview()


#!/usr/bin/env python2.7
#coding=utf-8

"""
Author:         charliezhao
EMail:          xuechao8086@126.com
Filename:       mcli.py
Create Time:    2015-12-04 21:37
Description:

"""
import time
import os
import random
import socket
import sys
import time

class MemcacheTestCli(object):
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port

    def test_long(self):
        self.s = socket.socket(socket.AF_INET,
                               socket.SOCK_STREAM)
        self.s.connect((self.ip, self.port))
        while True:
            key = "k{}".format(random.randint(1, 19860903))
            value = "v{}".format(random.randint(1, 19860903))
            cmd = "set {} {}\n".format(key, value)

            try:
                self.s.sendall(cmd)
                print(">{}".format(cmd))
                # print(self.s.recv(1024))
            except:
                print("\033[31m set fail\033[0m")

            time.sleep(0.5)

    def test_long2(self):
        self.s = socket.socket(socket.AF_INET,
                               socket.SOCK_STREAM)

        self.s.connect((self.ip, self.port))

        while(True):
            # cmd = "{} {};set {}; get {};".format(
            #       time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            #       os.getpid(),
            #       random.randint(1, 100),
            #       random.randint(1, 100))

            cmd = "set {}k {}v; get k{};".format(random.randint(1, 100),
                                                 random.randint(1, 100),
                                                 random.randint(1, 100));
            try:
                print(cmd)
                self.s.sendall(cmd)
            except:
                print("\033[31m set fail\033[0m")
            time.sleep(1)

    def test_long3(self):
        self.s = socket.socket(socket.AF_INET,
                               socket.SOCK_STREAM)
        self.s.connect((self.ip, self.port))

        rnd = random.randint(1, 19860903);
        cmd = "set {}k {}v; get {}k; set {}k {}{}------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------v;".format(rnd, rnd, rnd, rnd, rnd, rnd)
        try:
            print(cmd)
            self.s.sendall(cmd)
        except:
            print("\033[31m set fail\033[0m")
        cmd = "get {}k".format(rnd)
        try:
            print(cmd)
            self.s.sendall(cmd)
        except:
            print("\033[31m get fail\033[0m")

    def test_long4(self):
        self.s = socket.socket(socket.AF_INET,
                               socket.SOCK_STREAM)
        self.s.connect((self.ip, self.port))

        rnd = random.randint(1, 19860903);

        cmd = "set k{} v{};".format(rnd, rnd)
        try:
            print(cmd)
            self.s.sendall(cmd)
            print(self.s.recv(1024))
        except:
            print("\033[31m set fail\033[0m")

        cmd = "get k{};".format(rnd)
        try:
            print(cmd)
            self.s.sendall(cmd)
            print(self.s.recv(1024))
        except:
            print("\033[31m set fail\033[0m")

    def test_short(self):
        while True:
            s = socket.socket(socket.AF_INET,
                              socket.SOCK_STREAM)
            s.connect((self.ip, self.port))
            key = "k{}".format(random.randint(1, 19860903))
            value = "v{}".format(random.randint(1, 19860903))
            cmd = "set {} {}\n".format(key, value)

            try:
                s.sendall(cmd)
                print(s.recv(1024))
            except:
                print("\033[31m set fail\033[0m")
            time.sleep(1)

def usage():
    print("""{} [1-9]
      1 test_long
      2 test_short
      3 test_long2
      4 test_long3
      5 test_long4""".format(sys.argv[0]))
    sys.exit()

if __name__ == '__main__':
    if len(sys.argv) == 1:
        usage()
    m = MemcacheTestCli('localhost', 11211)
    if sys.argv[1] == '1':
        m.test_long()
    elif sys.argv[1] == '2':
        m.test_short()
    elif sys.argv[1] == '3':
        m.test_long2()
    elif sys.argv[1] == '4':
        m.test_long3()
    elif sys.argv[1] == '5':
        m.test_long4()
    else:
        usage()


import sqlalchemy
import alembic
import alembic.config

from . import models

class DbEngine:
    def __init__(self):
        self._conn = None
        self._session = None

    def initialize(self):
        alembic_args = ['--raiseerr', 'upgrade', 'head']
        alembic.config.main(argv=alembic_args)

        # TODO: relative (to top level) path... asking for trouble.
        c = alembic.config.Config('./alembic.ini')
        url = c.get_main_option('sqlalchemy.url')

        # Connect to the database
        self._conn = sqlalchemy.create_engine(url, connect_args={'check_same_thread': False})

        # Create a configured "Session" class, then instantiate it
        session_factory = sqlalchemy.orm.sessionmaker(bind=self._conn)
        Session = sqlalchemy.orm.scoped_session(session_factory)
        self._session = Session()

    def deinitialize(self):
        self._session.close()
        self._session = None
        self._conn = None

    def add_or_get_season(self, number):
        s = self._session.query(models.Season) \
                         .filter(models.Season.number == number) \
                         .one_or_none()

        if s is None:
            s = models.Season(number=number)
            self._session.add(s)
            self._session.commit()

        return s

    def get_all_seasons(self):
        return self._session.query(models.Season).all()

    def get_all_season_numbers(self):
        ss = self.get_all_seasons()
        return [s.number for s in ss]

    def get_season(self, number):
        return self._session.query(models.Season) \
                            .filter(models.Season.number == number) \
                            .one_or_none()

    def parse_episode_number(self, number):
        """
        Break up an episode number (string) into the season identifier and
        the episode number (int)
        :param number: the full episode number to parse
        :type number: str
        """
        try:
            season = number[:-2]
            ep = number[-2:]
            episode_number = int(ep)
            return (season, episode_number)
        except (ValueError, TypeError) as e:
            logger.Error('Failed to parse {0} as an episode number.'.format(number))
            return None

    def build_episode_number(self, season, episode_number):
        """
        Put together the season string and an episode number (integer)
        into the full episode id
        :param season: the season id string
        :type season: str
        :param episode_number: the number of the episode within the season
        :type episode_number: int
        """
        episode_string = '{:02d}'.format(episode_number)
        return season + episode_string

    def add_episode(self, number, name):
        """
        :param number: the episode number, e.g., 'K07'
        :type number: str
        :param name: the episode name
        :type name: str, e.g., 'Gamera vs. Zigra'
        """
        (season, episode) = self.parse_episode_number(number)
        s = self.add_or_get_season(season)

        e = models.Episode(number=episode, name=name)
        e.season = s

        self._session.add(e)
        self._session.commit()

        return e

    def add_media_set(self, name):
        m = models.MediaSet(name=name)
        self._session.add(m)
        self._session.commit()

        return m

    def add_to_collection(self, episode, media_set):
        m = models.Media()
        m.episode = episode
        m.media_set = media_set
        self._session.add(m)
        self._session.commit()

    def get_episode_list_by_season(self, season_code):
        s = self.get_season(season_code)
        if s:
            return s.episodes

    def get_all_media_sets(self):
        return self._session.query(models.MediaSet) \
                            .order_by(models.MediaSet.id).all()

    def get_episode_by_code(self, code):
        return self._session.query(models.Episode) \
                            .filter(models.Episode.episode_code == code) \
                            .one_or_none()


#!/usr/bin/env python

from __future__ import print_function

import tty
import termios
from time import time
from sys import stdin

def getchar():
    fd = stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(stdin.fileno())
        ch = stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

def addtime(times):
    if type(times) != list:
        raise(TypeError)
    t = time()
    if len(times) == 0:
        tdiff = 0  # initial seed
    else:
        tdiff = t - times[-1][0]
    return (t, tdiff)

def averagetimes(times):
    averagetime = sum([row[1] for row in times])/float(len(times))
    bpm = (1.0/(averagetime/60.0))
    return (averagetime, bpm)

def main():
    print('Tap a key on each beat. Press q to quit.', end='\r')

    times = []
    while True:
        char = getchar()
        if char in ('q', 'Q', '\x1b', '\x03'):  # q, Q, ESC, Control+C
            print()
            quit()

        times.append(addtime(times))
        if len(times) > 1:
            # remove first element if it's either the initial seed
            # or when the list reaches max length
            if times[0][1] == 0 or len(times) > 16:
                del times[0]
            (averagetime, bpm) = averagetimes(times)

            print("\rDetected BPM: %7.3f (Avg time between each: %0.3fs)"
                  % (bpm, averagetime), end='')

if __name__ == '__main__':
    main()


from PyTest import *
##//////////////////// PROBLEM STATEMENT ///////////////////////
## Read 3 integers a, b and c, and print the results when you //
## add all three and also when you multiply all three together//
##//////////////////////////////////////////////////////////////

a = int(input())
b = int(input())
c = int(input())

print(a + b + c, a * b * c)


import math

def get_normalized_rotation_degrees_between_vectors(first_vector, second_vector):
    f_x = first_vector[0]
    f_y = first_vector[1]
    s_x = second_vector[0]
    s_y = second_vector[1]

    radians = math.atan2(-(s_y - f_y), s_x - f_x)
    degrees = math.degrees(radians) - 270

    return degrees

def get_rotation_degrees_between_vectors(first_vector, second_vector):
    f_x = first_vector[0]
    f_y = first_vector[1]
    s_x = second_vector[0]
    s_y = second_vector[1]

    radians = math.atan2(-(s_y - f_y), s_x - f_x)
    degrees = math.degrees(radians)

    return degrees

def get_angle_between_vectors(first_vector, second_vector):
    angle = math.atan2(first_vector[1] - second_vector[1], first_vector[0] - second_vector[0])

    return angle

def get_point_on_circle(circle_center, circle_radius, offset_angle):
    x = circle_center[0] + (circle_radius * math.cos(offset_angle))
    y = circle_center[1] + (circle_radius * math.sin(offset_angle))

    return [x, y]

def get_distance_between_vectors(first_vector, second_vector):
    x_1 = first_vector[0]
    y_1 = first_vector[1]
    x_2 = second_vector[0]
    y_2 = second_vector[1]

    position = math.sqrt(math.pow((x_2 - x_1), 2) + math.pow((y_2 - y_1), 2))

    return position

def check_if_vector_between_two_vectors_on_circle(root_vector, first_vector, second_vector, check_vector):
    result = False

    angle_between_root_and_check = get_rotation_degrees_between_vectors(root_vector, check_vector)
    angle_between_root_and_first_vector = get_rotation_degrees_between_vectors(root_vector, first_vector)
    angle_between_root_and_second_vector = get_rotation_degrees_between_vectors(root_vector, second_vector)

    if angle_between_root_and_first_vector <= angle_between_root_and_check <= angle_between_root_and_second_vector or \
            angle_between_root_and_second_vector <= angle_between_root_and_first_vector <= angle_between_root_and_check or \
            angle_between_root_and_check <= angle_between_root_and_second_vector <= angle_between_root_and_first_vector:

        result = True

    return result


#!/usr/bin/env python
#
# usage: rgb2cmyk.py [-h] [-v] InFile
#
# positional arguments:
#  InFile                Source image file
#
# optional arguments:
#  -h/--help             Show this help message and exit
#  -v/--verbose          Increase output verbosity
#
# Versions:
# - 1.0/2017.11: Initial happy version
#
# TODOs:
# - Support multiple output formats
#
#import argparse
from argparse import ArgumentParser
from argparse import RawTextHelpFormatter
import colortuple
from PIL import Image
from modules.commonlib import warning_msg
from modules.commonlib import error_msg
from modules.commonlib import debug_msg
from modules.commonlib import info_msg
from modules.commonlib import silence_stderr
import os

file_basename = os.path.basename(__file__)
file_version = '1.0|17/11'

def rgb_to_cmyk(r, g, b):
  """
  Convert an RGB color triplet to a CMYK quadruplet.
  """
#  debug_msg( "%d %d %d" % (r, g, b) )
  if r < 3 and g < 3 and b < 3:
    c4 = 0
    m4 = 0
    y4 = 0
    k4 = 100
  else:
    w = max( (r*100)/255, (g*100)/255, (b*100)/255 )
    c4 = ( (w - (r*100)/255)*100 ) / w
    m4 = ( (w - (g*100)/255)*100 ) / w
    y4 = ( (w - (b*100)/255)*100 ) / w
    k4 = 100 - w

  c3 = min(100, (c4*(100 - k4))/100 + k4);
  m3 = min(100, (m4*(100 - k4))/100 + k4);
  y3 = min(100, (y4*(100 - k4))/100 + k4);

  colorC = 255 - (c3*255)/100, 255, 255, 255
  colorM = 255, 255 - (m3*255)/100, 255, 255
  colorY = 255, 255, 255 - (y3*255)/100, 255
  colorK = 255 - (k4*255)/100, 255 - (k4*255)/100, 255 - (k4*255)/100, 255

  return colorC, colorM, colorY, colorK

# Main
def main():

  program_description = "\
 Utility to convert RGB image-files to their CMYK components - v{}\n\
 eg. {} brick-house.png\n\
     {} -h".format(file_version, file_basename, file_basename)

  parser = ArgumentParser(description=program_description, formatter_class=RawTextHelpFormatter)
  parser.add_argument('InFile', type=str, help='input file')
  parser.add_argument('-v', '--verbose', action='store_true', help='increase output verbosity')

  # Read arguments
  args = parser.parse_args()

  # No verbosity by default
  if (not args.verbose):
    silence_stderr()
  else:
    debug_msg("Verbose mode enabled")

  filename_input = args.InFile
  debug_msg( "Input file: '%s'" % (filename_input) )
  format_input = os.path.splitext(filename_input)[1][1:]

  # Main
  debug_msg( "Processing file '%s'..." % (filename_input) )

  img = Image.open(filename_input).convert('RGBA')

  width, height = img.size
  colortuples = img.getcolors()

  imgC = Image.new("RGB", (width, height))
  imgM = Image.new("RGB", (width, height))
  imgY = Image.new("RGB", (width, height))
  imgK = Image.new("RGB", (width, height))

  pix = img.load()
  for x in xrange(0, width):
    for y in xrange(0, height):

      colorC, colorM, colorY, colorK = rgb_to_cmyk(
        pix[x, y][0],
        pix[x, y][1],
        pix[x, y][2]
      )

      imgC.putpixel( (x, y), colorC )
      imgM.putpixel( (x, y), colorM )
      imgY.putpixel( (x, y), colorY )
      imgK.putpixel( (x, y), colorK )

  filename_outputC = filename_input.replace('.' + format_input, '-C.' + format_input)
  debug_msg( "Saving '%s'..." % (filename_outputC) )
  imgC.save( filename_outputC, format_input )

  filename_outputM = filename_input.replace('.' + format_input, '-M.' + format_input)
  debug_msg( "Saving '%s'..." % (filename_outputM) )
  imgM.save( filename_outputM, format_input )

  filename_outputY = filename_input.replace('.' + format_input, '-Y.' + format_input)
  debug_msg( "Saving '%s'..." % (filename_outputY) )
  imgY.save( filename_outputY, format_input )

  filename_outputK = filename_input.replace('.' + format_input, '-K.' + format_input)
  debug_msg( "Saving '%s'..." % (filename_outputK) )
  imgK.save( filename_outputK, format_input )

# Main
if __name__ == '__main__':
  main()


"""
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

给你一个链表，删除链表的倒数第 n 个结点，并且返回链表的头结点。

示例 1：
    输入：head = [1,2,3,4,5], n = 2
    输出：[1,2,3,5]

示例 2：
    输入：head = [1], n = 1
    输出：[]

示例 3：
    输入：head = [1,2], n = 1
    输出：[1]

提示：
    链表中结点的数目为 sz
    1 <= sz <= 30
    0 <= Node.val <= 100
    1 <= n <= sz

进阶：你能尝试使用一趟扫描实现吗？

"""
class ListNode:   # 节点类
    def __init__(self, val = 0, next = None):  # 初始化节点
        self.val = val     # val存放数据元素
        self.next = next   # 保存当前节点中下一个节点的引用
        # 每个节点包含两个部分，一部分存放数据变量的val，另一部分存放下一个节点的位置信息next。

    def __str__(self):
        #测试基本功能，输出字符串
        return str(self.val)

'''根据输入的列表创建链表'''
def listToLinkedList(list):
    head = ListNode(list[0])
    cur = head
    for i in range(1, len(list)):
        cur.next = ListNode(list[i])
        cur = cur.next
    return head

def printLinkedList(head):
    cur = head
    list = []
    while cur:
        list.append(cur.val)
        cur = cur.next
    return list

"""方法一：计算链表长度"""
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        def getLength(head: ListNode) -> int:   # 从头节点开始对链表进行一次遍历，得到链表的长度
            length = 0
            while head:
                length += 1
                head = head.next
            return length

        dummy = ListNode(0, head)
        length = getLength(head)
        cur = dummy
        for i in range(1, length - n + 1):  # 从哑节点开始遍历 L−n+1 个节点
            cur = cur.next                  # 当遍历到第 L-n+1 个节点时，它的下一个节点就是我们需要删除的节点，
        cur.next = cur.next.next            # 把要删除的节点空过去：cur 直接指向 cur.next.next
        return dummy.next

"""方法二：栈"""
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy = ListNode(0, head)
        stack = list()
        cur = dummy
        while cur:
            stack.append(cur)   # 遍历链表的同时将所有节点依次入栈
            cur = cur.next

        for i in range(n):      # 弹出栈的第 n 个节点就是需要删除的节点
            stack.pop()         # 并且目前栈顶的节点就是待删除节点的前驱节点

        prev = stack[-1]        # prev为弹出删除元素后的栈顶
        prev.next = prev.next.next  # 指向跳过原来删除的节点
        return dummy.next

"""方法三：双指针"""
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy = ListNode(0, head)
        first = head    # 使用两个指针 first 和 second 同时对链表进行遍历，初始时 first 和 second 均指向头节点
        second = dummy
        for i in range(n):
            first = first.next

        while first:
            first = first.next
            second = second.next

        second.next = second.next.next
        return dummy.next

if __name__ == "__main__":
    head = listToLinkedList ([1,2,3,4,5])
    n = 2
    sol = Solution()
    result = sol.removeNthFromEnd(head, n)
    print (printLinkedList(result))

0019_删除链表的倒数第N个结点.py


import rospy
from tf.transformations import euler_from_quaternion, quaternion_from_euler
from geometry_msgs.msg import PoseStamped, Twist
from mavros_msgs.msg import State
from mavros_msgs.srv import CommandBool, CommandBoolRequest, SetMode, SetModeRequest, CommandTOL, CommandTOLRequest
from std_msgs.msg import String
import math

# Topics
SETPOINT_POS_PUB = "/mavros/setpoint_position/local"
STATE_SUB = "mavros/state"
COMANDER_POSITION_SUB = '/commands/control_position'
LOCAL_VEL_PUB = "/mavros/setpoint_velocity/cmd_vel_unstamped"
COMANDER_VELOCITY_SUB = '/commands/control_velocity'
LOCAL_POS__SUB = '/mavros/local_position/pose'
MODE_SUB = "/commands/mode"

# Services
ARMING_CLIENT = "/mavros/cmd/arming"
SET_MODE_CLIENT = "/mavros/set_mode"
LAND_CMD_SRV = "/mavros/cmd/land"
TAKE_OFF_CMD_CLIENT = "/mavros/cmd/takeoff"

# Modes
LAND = "LAND"
TAKE_OFF = "TAKE OFF"
POSITION = "POSITION"
VELOCITY = "VELOCITY"

MAX_HEIGH = 2

mode = ""

position = PoseStamped()
value_position = PoseStamped()
current_pos = PoseStamped()

raw = Twist()
value_velocity = Twist()
istakeoff = False

class Drone():
    def __init__(self):
        self.current_state = State()
        self.state_sub = rospy.Subscriber(STATE_SUB, State, callback=self.state_cb)
        self.mode_sub = rospy.Subscriber(MODE_SUB, String, callback=self.control_mode_cb)
        self.local_pos_pub = rospy.Publisher(SETPOINT_POS_PUB, PoseStamped, queue_size=10)
        self.value_position_sub = rospy.Subscriber(COMANDER_POSITION_SUB, PoseStamped, self.get_value_position_cb)
        self.value_velocity_sub = rospy.Subscriber(COMANDER_VELOCITY_SUB, Twist, self.get_value_velocity_cb)
        self.local_raw_pub = rospy.Publisher(LOCAL_VEL_PUB, Twist, queue_size=10)
        self.current_pos_sub = rospy.Subscriber(LOCAL_POS__SUB, PoseStamped, callback=self.current_pos_cb)
        self.orientation_list = []

    def state_cb(self, msg):
        self.current_state = msg

    def check_to_fly(self, offb_set_mode, arm_cmd, last_req, arming_client, set_mode_client):

        '''
        Check before to fly. The dron have a mode offboard and it's should armed before to fly
        '''

        if (self.current_state.mode != "OFFBOARD" and (rospy.Time.now() - last_req) > rospy.Duration(5.0)):
            if (set_mode_client.call(offb_set_mode).mode_sent is True):
                rospy.loginfo("OFFBOARD enabled")

            last_req = rospy.Time.now()

        else:
            if (not self.current_state.armed and (rospy.Time.now() - last_req) > rospy.Duration(5.0)):
                if (arming_client.call(arm_cmd).success is True):
                    rospy.loginfo("Vehicle armed")

                last_req = rospy.Time.now()

    def current_pos_cb(self,pose):

        '''
        Callback, save current position for orientation in control position
        '''
        global current_pos
        current_pos = pose

    def control_mode_cb(self, msg):
        '''
        Callback, save mode: position,velocity,land or take off
        '''
        global mode
        mode = msg.data

    def get_value_position_cb(self, msg):

        '''
        Callback, save value for control position
        '''
        global value_position
        value_position = msg

    def get_value_velocity_cb(self, msg):

        '''
        Callback, save value for control velocity
        '''
        global value_velocity
        value_velocity = msg
    def control_position(self):

        '''
        Control position, position and orientation in radians in exe z (Yaw)

        Only works if the dron is not on the ground
        '''
        if (istakeoff):

            self.orientation_list = [current_pos.pose.orientation.x,
                    current_pos.pose.orientation.y,
                    current_pos.pose.orientation.z,
                    current_pos.pose.orientation.w]

            roll, pitch, yaw = euler_from_quaternion(self.orientation_list)

            quaternion = quaternion_from_euler(roll, pitch, yaw + math.radians(value_position.pose.orientation.z))

            position.pose.orientation.x = quaternion[0]
            position.pose.orientation.y = quaternion[1]
            position.pose.orientation.z = quaternion[2]
            position.pose.orientation.w = quaternion[3]

            position.pose.position.x = value_position.pose.position.x

    def control_velocity(self):

        '''
        Control velocity, velocity lineal and angular in exe z

        Only works if the dron is not on the ground
        '''

        if(istakeoff):
            raw.linear.x = value_velocity.linear.x
            raw.angular.z = math.radians(value_velocity.angular.z)

if __name__ == "__main__":
    rospy.init_node("teleop_node_py")
    drone = Drone()

    rospy.wait_for_service(ARMING_CLIENT)
    arming_client = rospy.ServiceProxy(ARMING_CLIENT, CommandBool)

    rospy.wait_for_service(SET_MODE_CLIENT)
    set_mode_client = rospy.ServiceProxy(SET_MODE_CLIENT, SetMode)

    rospy.wait_for_service(LAND_CMD_SRV)
    land_client = rospy.ServiceProxy(LAND_CMD_SRV, CommandTOL)

    rate = rospy.Rate(20)

    # Wait for Flight Controller connection
    while (not rospy.is_shutdown() and not drone.current_state.connected):
        rate.sleep()

    offb_set_mode = SetModeRequest()
    offb_set_mode.custom_mode = 'OFFBOARD'

    arm_cmd = CommandBoolRequest()
    arm_cmd.value = True

    land_cmd = CommandTOLRequest()
    land_cmd.min_pitch = 0
    land_cmd.yaw = 0
    land_cmd.latitude = 0
    land_cmd.longitude = 0
    land_cmd.altitude = 0

    last_req = rospy.Time.now()

    while (not rospy.is_shutdown()):
        drone.check_to_fly(offb_set_mode, arm_cmd, last_req,
                           arming_client, set_mode_client)

        if(mode == TAKE_OFF):
            position.pose.position.z = MAX_HEIGH
            drone.local_pos_pub.publish(position)
            istakeoff = True

        elif (mode == POSITION):
            drone.control_position()
            drone.local_pos_pub.publish(position)

        elif (mode == VELOCITY):
            drone.control_velocity()
            drone.local_raw_pub.publish(raw)

        elif(mode == LAND):
            if(rospy.Time.now() - last_req) > rospy.Duration(5.0):
                response = land_client.call(land_cmd)
                last_req = rospy.Time.now()

        rate.sleep()


import email.Utils as Utils
import os, logging, time, random
from time import mktime
from datetime import datetime, timedelta
import PyICU
import sys
import sgmllib
from twisted.mail import smtp

#Chandler imports
import application.Globals as Globals
from chandlerdb.util.Lob import Lob
from i18n import ChandlerMessageFactory as _

__all__ = ['log', 'trace', 'disableTwistedTLS', 'getEmptyDate',
           'dateIsEmpty', 'alert', 'alertMailError', 'NotifyUIAsync',
           'datetimeToRFC2822Date', 'RFC2822DateToDatetime', 'createMessageID',
           'hasValue', 'isString', 'dataToBinary', 'binaryToData', 'stripHTML',
           'setStatusMessage', 'callMethodInUIThread']

log = logging.getLogger("MailService")

def trace(printString):
    if printString is not None:
        if isinstance(printString, Exception):
            return log.exception(printString)

        frame = sys._getframe(1)
        """
        Get the package and class name from the frame stack
        """
        caller = frame.f_locals.get('self')

        if caller is not None:
            """
            Strip off the package path and trailing '> on new style classes
            """
            caller = str(caller.__class__).split(".")[-1].rstrip("'>")
            log.debug("[%s] %s " % (caller, printString))
        else:
            log.debug("%s " % printString)

class Counter:
    def __init__(self, val=0):
        self.counter = val

    def nextValue(self):
        self.counter += 1
        return self.counter

def getEmptyDate(view):
    """
    Returns a DateTime object with today's date and the
    current Operating System timezone set to 0 ticks.
    @return: C{datetime} object
    """
    tz = view.tzinfo.default
    return datetime.now(tz).replace(hour=0, minute=0, second=0, microsecond=0)

def dateIsEmpty(date):
    """
    Determines if a C{datetime} is empty (hh:mm:ss == 00:00:00.0).

    @param date: The date to check if it is empty
    @type date: C{datetime}

    @return: C{True} if the date is empty, False otherwise
    """
    if date is None or (date.hour == 0 and date.minute == 0 and
                        date.second == 0 and date.microsecond == 0):
        return True

    return False

def disableTwistedTLS(items, TLSKEY='STARTTLS'):
    """
    Removes TLS from the Capabilities. If TLS is in
    the Capabilities twisted will force a TLS connection
    event if the user specified a non-encypted protocol
    exchange.

    @param TLSKEY: String key to remove from items list
    @type TLSKEY: C{String}
    """

    if items != None and TLSKEY != None:
        try:
            del items[TLSKEY]
        except KeyError:
            pass

    return items

def alert(message, args=None):
    """
    Displays a generic alert dialog.
    """
    if args:
        message = message % args

    NotifyUIAsync(message, cl='alertUser')

def alertMailError(message, account, args=None, helpLinkText=None):
    """
    Displays a mail specific alert dialog with a Edit Account Settings
    button which takes the user to the Account Dialog.
    """
    if args:
        message = message % args

    NotifyUIAsync(message, None, 'displayMailError', account, helpLinkText)

def NotifyUIAsync(message, logger=None, cl='setStatusMessage', *args, **keys):
    if logger is not None:
        logger(message)

    wxApplication = Globals.wxApplication

    if wxApplication is not None: # test framework has no wxApplication
        wxApplication.CallItemMethodAsync("MainView", cl, message, *args, **keys)

def setStatusMessage(message, progressPercentage=-1):
    wxApplication = Globals.wxApplication

    if wxApplication is not None: # test framework has no wxApplication
        wxApplication.CallItemMethodAsync("MainView", "setStatusMessage", message, progressPercentage)

def callMethodInUIThread(method, *args):
    wxApplication = Globals.wxApplication

    if wxApplication is not None: # test framework has no wxApplication
        wxApplication.PostAsyncEvent(method, *args)

ENGLISH_DATE_SYMBOLS = PyICU.DateFormatSymbols(PyICU.Locale.getEnglish())

def datetimeToRFC2822Date(dt):
    """
    Converts a C{datetime} object to a RFC2822 Date String.

    @param dt: a C{datetime} instance
    @type dt: C{datetime}

    @return: RFC2822 Date String
    """
    # we format this ourselves, rather than using strftime because
    # strftime has no way of enforcing English in a thread-safe way,
    # and because it chokes on years before 1900.
    month = ENGLISH_DATE_SYMBOLS.getShortMonths()[dt.month - 1]
    # ICU seems to start with an empty string at array index 0, and
    # then values starting with Sunday. datetime.weekday() has 0<==>Monday.
    icuWeekday = 1 + (dt.weekday() + 1) % 7
    weekday = ENGLISH_DATE_SYMBOLS.getShortWeekdays()[icuWeekday]

    if dt.tzinfo:
        offset = dt.tzinfo.utcoffset(dt) # offset in minutes
        offsetMinutes = offset.seconds / 60 + offset.days * 24 * 60
        offset_part = " %+03d%02d" % (offsetMinutes/60, offsetMinutes%60)
    else:
        offset_part = ""

    return "%s, %02d %s %04d %02d:%02d:%02d%s" % (
                weekday, dt.day, month, dt.year,
                dt.hour, dt.minute, dt.second, offset_part)

def RFC2822DateToDatetime(dateString, tz=None):
    """
    Parses an RFC 2822 date value (e.g. in the Date: header) and
    returns a C{datetime.datetime} value. Uses C{email.utils.parsedate_tz},
    so that a variety of date formats (not all required by the RFC) can
    be parsed.

    @param dateString: Input date value
    @type dateString: C{basestring}

    @param tz: The timezone to use for the return value. If C{None}, and the
               input header specified a timezone offset, the returned
               C{datetime} will be a UTC value. If C{None}, and no timezone
               offset was specified, the returned value will be as parsed.
               If a non-C{None} C{tz} is passed in, the returned datetime will
               have a C{tzinfo} of C{tz}.
    @type tz: C{datetime.tzinfo}

    @rtype: C{datetime.datetime}
    """

    parsed = Utils.parsedate_tz(dateString)

    if parsed is None:
        return None

    result = datetime(*parsed[:6])

    if parsed[9] is not None:

        # i.e. parsed[9] is an offset. Let's convert to UTC
        result -= timedelta(seconds=parsed[9])

        if tz is not None:
            result = result.replace(tzinfo=PyICU.ICUtzinfo.getInstance("UTC"))
            result = result.astimezone(tz)

    else: # (shrug) no tz
        result = result.replace(tzinfo=tz)

    return result

def createMessageID():
    """
    Creates a unique message id.

    @return: String containing the unique message id
    """
    timeval = time.time()
    utcdate = time.strftime('%Y%m%d%H%M%S', time.gmtime(timeval))
    pid = os.getpid()

    randint = random.randrange(100000)

    # The twisted.mail.smtp module
    # contains a cached DNS name. There
    # is a large performance increase in
    # not looking up this value each time a
    # messageID is created.
    idhost = smtp.DNSNAME

    msgid = '<%s.%s.%s@%s>' % (utcdate, pid, randint, idhost)

    return msgid

def hasValue(value):
    """
    This method determines if a String has one or more non-whitespace
    characters. This is useful in checking that a Subject or To address
    field was filled in with a useable value.

    @param value: The String value to check against. The value can be None
    @type value: C{String}
    @return: C{Boolean}
    """
    if isString(value) and len(value.strip()) > 0:
        return True

    return False

def isString(var):
    if isinstance(var, (str, unicode)):
        return True

    return False

def dataToBinary(mailMessage, attribute, data,
                 mimeType="application/octet-stream",
                 compression='bz2', indexed=False):
    """
    Converts non-string data to a C{Lob}.
    """

    contentItem = mailMessage.itsItem
    itemAttributeName = getattr(type(mailMessage), attribute).name

    lobType = contentItem.getAttributeAspect(itemAttributeName, 'type')
    assert lobType.itsName == 'Lob', "The attribute must be of type Lob"

    return lobType.makeValue(data, mimetype=mimeType, indexed=indexed,
                             compression=compression)

def binaryToData(binary):
    """
    Converts a C{Lob} to data.
    """
    assert isinstance(binary, Lob), "Must pass a Lob instance"

    inp = binary.getInputStream()
    data = inp.read()
    inp.close()

    if binary.encoding:
        return unicode(data, binary.encoding)

    return data

class HTMLCleaner(sgmllib.SGMLParser):
    entitydefs={"nbsp": " "}

    def __init__(self):
        sgmllib.SGMLParser.__init__(self)
        self.result = []
        self.title = []

    def do_p(self, *junk):
        self.result.append(u'\n')

    def do_br(self, *junk):
        self.result.append(u'\n')

    def handle_data(self, data):
        tag = self.get_starttag_text()

        if tag != None:
            tag = tag.lower().strip()
        else:
           tag = ""

        if tag.startswith("<title"):
            self.title.append(data)

        elif tag.startswith("<script ") or \
             tag.startswith("<style "):
            pass

        else:
            self.result.append(data)

    def cleaned_text(self):
        txt = u''

        if len(self.title):
            txt += _(u"Title: ")

            for uniText in self.title:
                if isinstance(uniText, str):
                    uniText = unicode(uniText, 'utf-8', 'ignore')

                txt += uniText

            txt += u"\n\n"

        for uniText in self.result:
            if isinstance(uniText, str):
                uniText = unicode(uniText, 'utf-8', 'ignore')

            txt += uniText

        return txt

def stripHTML(text):
    cleaner = HTMLCleaner()
    cleaner.feed(text)
    return cleaner.cleaned_text()


from collections import defaultdict
from collections import Counter
import collections
import enum
from re import A
#import numpy as np

import sys
import argparse
import math
import random
from tkinter import N
# https://www.daleseo.com/python-typing/
from typing import Optional
from typing import Union
from typing import List
from typing import Final
from typing import Dict
from typing import Tuple
from typing import Set

import time

# validPalindrome.py : https://github.com/cheoljoo/problemSolving/tree/master/leetcode

timeFlag = 0
debugFlag = 0
import math

class Solution:
    def validPalindrome(self, s: str) -> bool:
        if len(s) <= 2:
            return True
        start = 0
        end = len(s)-1
        while True:
            if start >= end:
                return True
            if s[start] == s[end]:
                start += 1
                end -= 1
            else:
                if start+1 == end:
                    return True
                if self.isPalindrom(s,start+1,end) or self.isPalindrom(s,start,end-1) :
                    return True
                else :
                    return False

    def isPalindrom(self,s:str,start:int,end:int) -> bool:
        while True:
            if start >= end:
                return True
            if s[start] == s[end]:
                start += 1
                end -= 1
            else :
                return False
        return False

def run(s,expect):
    start = time.time()
    A = Solution()
    r = A.validPalindrome(s)
    print(" total_time1 : ", time.time() - start , "-> ", end="")

    if r == expect:
        print("SUCCESS -> ",end="")
    else :
        print("ERROR(",expect,") -> ",sep="",end="")
    print(r, s , end="")
    print()

if (__name__ == "__main__"):
    parser = argparse.ArgumentParser(
        prog='validPalindrome.py',
        description=
        'validPalindrome'
    )
    parser.add_argument( '--debug', '-d' , action='store_const' , const=1 , help='debug on')

    args = parser.parse_args()
    debug = args.debug
    if not debug:
        debug = 0

    print('validPalindrome problem :')

    run("aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga",True)
    run("aba",True)
    run("a",True)
    run("abc",False)
    run("abca",True)
    run("acba",True)
    run("abcdba",True)
    run("acbbdca",True)
    run("acbcad",True)
    run("ad",True)
    run("add",True)
    run("adf",False)
    run("abffcda",False)


# Given a string, calculate the number of consonants present.

s = "Welcome to Educative!"
v = ["a","e","i","o","u"]

def count_consonants_iter():
    num = 0
    for c in s:
        if c.lower() not in v and c.isalpha():
            num += 1
    return num

def rec(s, i=0):
    if i == len(s):
        return 0
    if s[i].lower() not in v and s[i].isalpha():
        return 1 + rec(s,i+1)
    else:
        return rec(s, i+1)

print(count_consonants_iter())
print(rec(s))