import fcntl
import json
import os
import socket
import select
import struct
import sys
import termios
import threading
import time
import glob
import platform
import traceback
import errno
import re
import logging
import logging.handlers

logger = logging.getLogger('candy_board_qws')
logger.setLevel(logging.INFO)
handler = logging.handlers.SysLogHandler(address='/dev/log')
logger.addHandler(handler)
formatter = logging.Formatter('[candy_board_qws] %(module)s.%(funcName)s: %(message)s')
handler.setFormatter(formatter)

# SerialPort class was imported from John Wiseman's
# https://github.com/wiseman/arduino-serial/blob/master/arduinoserial.py

# Map from the numbers to the termios constants (which are pretty much
# the same numbers).

BPS_SYMS = {
    115200:   termios.B115200,
    460800:   4100,
    # 230400:   termios.B230400,
    # 57600:    termios.B57600,
    # 38400:    termios.B38400,
    # 19200:    termios.B19200,
    # 9600:     termios.B9600,
    # 921600:   4103
    }

# Indices into the termios tuple.

IFLAG = 0
OFLAG = 1
CFLAG = 2
LFLAG = 3
ISPEED = 4
OSPEED = 5
CC = 6

def bps_to_termios_sym(bps):
    return BPS_SYMS[bps]

CGREG_STATS = [
    "Unregistered",
    "Registered",
    "Searching",
    "Denied",
    "Unknown",
    "Roaming"
]

# For local debugging:
# import candy_board_qws
# serial = candy_board_qws.SerialPort("/dev/ttyUSB2", 115200)
# server = candy_board_qws.SockServer(
#     "1.0.0",
#     "/var/run/candy-board-service.sock", serial)
# server.debug = True
# server.apn_ls()

# looking for a modem serial port
# import candy_board_qws
# candy_board_qws.SerialPort.resolve_modem_port()

class SerialPort(object):

    def __init__(self, serialport, bps):
        """Takes the string name of the serial port
        (e.g. "/dev/tty.usbserial","COM1") and a baud rate (bps) and
        connects to that port at that speed and 8N1. Opens the port in
        fully raw mode so you can send binary data.
        """
        self.fd = os.open(serialport, os.O_RDWR | os.O_NOCTTY | os.O_NDELAY)
        attrs = termios.tcgetattr(self.fd)
        bps_sym = bps_to_termios_sym(int(bps))
        # Set I/O speed.
        attrs[ISPEED] = bps_sym
        attrs[OSPEED] = bps_sym

        # 8N1
        attrs[CFLAG] &= ~termios.PARENB
        attrs[CFLAG] &= ~termios.CSTOPB
        attrs[CFLAG] &= ~termios.CSIZE
        attrs[CFLAG] |= termios.CS8
        # No flow control
        attrs[CFLAG] &= ~termios.CRTSCTS

        # Turn on READ & ignore contrll lines.
        attrs[CFLAG] |= termios.CREAD | termios.CLOCAL
        # Turn off software flow control.
        attrs[IFLAG] &= ~(termios.IXON | termios.IXOFF | termios.IXANY)

        # Make raw.
        attrs[LFLAG] &= ~(termios.ICANON | termios.ECHO |
                          termios.ECHOE | termios.ISIG)
        attrs[OFLAG] &= ~termios.OPOST

        # It's complicated--See
        # http://unixwiz.net/techtips/termios-vmin-vtime.html
        attrs[CC][termios.VMIN] = 0
        attrs[CC][termios.VTIME] = 20
        termios.tcsetattr(self.fd, termios.TCSANOW, attrs)

        self.ping()

    def available(self):
        return True

    def read_until(self, until):
        buf = ""
        done = False
        cnt = 0
        while not done:
            try:
                n = os.read(self.fd, 1).decode()
            except UnicodeDecodeError:
                n = '.'
            if n == '':
                if cnt > 200:
                    buf = None
                    break
                cnt = cnt + 1
                # FIXME: Maybe worth blocking instead of busy-looping?
                time.sleep(0.01)
                continue
            buf = buf + n
            if n == until:
                done = True
        return buf

    def read_line(self):
        try:
            return self.read_until("\n").strip()
        except OSError:
            return None

    def write(self, str):
        os.write(self.fd, str.encode())

    def write_byte(self, byte):
        os.write(self.fd, byte)

    def close(self):
        try:
            os.close(self.fd)
        except OSError:
            pass

    def ping(self, loop=3):
        ret = None
        for i in (0, loop):
            self.write("AT\r")
            time.sleep(0.1)
            line = self.read_line()
            if line is None:
                time.sleep(0.1)
                continue
            else:
                ret = ''
                while line is not None:
                    ret = ret + line + '\r'
                    line = self.read_line()
                break
        return ret

    @staticmethod
    def resolve_modem_baudrate(p):
        if platform.system() != 'Linux':
            return None

        for bps in BPS_SYMS.keys():
            port = SerialPort.open_serial_port(p, bps)
            if port is None:
                continue
            ret = port.ping()
            if ret is None:
                port.close()
                continue
            if "OK" in ret:
                port.close()
                return bps
            port.close()

        return None

    @staticmethod
    def open_serial_port(p, bps):
        for i in (0, 3):
            port = None
            try:
                port = SerialPort(p, bps)
                return port
            except Exception:
                if port:
                    try:
                        port.close()
                    except Exception:
                        pass
                port = None
                time.sleep(0.1)
                pass
        return None

    @staticmethod
    def resolve_modem_port(bps=115200):
        if platform.system() != 'Linux':
            return None

        for t in [
                    '/dev/QWS.*.MODEM',
                    '/dev/ttySC1'
                ]:
            for p in sorted(glob.glob(t)):
                port = SerialPort.open_serial_port(p, bps)
                if port is None:
                    continue
                ret = port.ping()
                if ret is None:
                    port.close()
                    continue
                if "OK" in ret:
                    port.close()
                    return p
                port.close()

        return None

class LazySerialPort:
    def __init__(self, serialport, bps):
        self.serial = None
        self.serialport = serialport
        self.bps = bps

    def _serial(self):
        if self.serial is None:
            self.serial = SerialPort(self.serialport, self.bps)
        return self.serial

    def available(self):
        try:
            self._serial()
            return True
        except OSError:
            return False

    def read_line(self):
        return self._serial().read_line()

    def write(self, str):
        return self._serial().write(str)

    def write_byte(self, byte):
        return self._serial().write_byte(byte)

    def close(self):
        if self.serial is None:
            return
        try:
            return self.serial.close()
        finally:
            self.serial = None

class SockServer(threading.Thread):
    def __init__(self, version,
                 sock_path="/var/run/candy-board-service.sock", serial=None):
        super(SockServer, self).__init__()
        self.version = version
        self.sock_path = sock_path
        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.serial = serial
        self.debug = False

    def recv(self, connection, size):
        ready, _, _ = select.select([connection], [], [], 5)
        if ready:
            return connection.recv(size)
        else:
            raise IOError("recv Timeout")

    def run(self):
        self.sock.bind(self.sock_path)
        self.sock.listen(128)
        header_packer = struct.Struct("I")
        print("Listening to the socket[%s]...." % self.sock_path)

        while True:
            try:
                logger.debug("Waiting for an incoming request")
                connection, client_address = self.sock.accept()
                connection.setblocking(0)

                # request
                logger.debug("Request has arrived!")
                header = self.recv(connection, header_packer.size)
                size = header_packer.unpack(header)
                logger.debug("Size:%d" % size)
                unpacker_body = struct.Struct("%is" % size)
                cmd_json = self.recv(connection, unpacker_body.size)
                logger.debug("Body:[%s]" % cmd_json)
                cmd = json.loads(cmd_json)

                # response
                logger.debug("Performing a command")
                message = self.perform(cmd)
                logger.debug("Command done!")
                if message:
                    size = len(message)
                else:
                    size = 0
                packed_header = header_packer.pack(size)
                connection.sendall(packed_header)
                logger.debug("Size:%d" % size)
                if size > 0:
                    packer_body = struct.Struct("%is" % size)
                    packed_message = packer_body.pack(message.encode('utf-8'))
                    logger.debug("Body:[%s]" % message)
                    connection.sendall(packed_message)

            except socket.error as e:
                if isinstance(e.args, tuple):
                    if e[0] == errno.EPIPE:
                        continue
                logger.error("Socket Error: %s" %
                                      (''.join(traceback
                                       .format_exception(*sys.exc_info())[-2:])
                                       .strip().replace('\n', ': '))
                                      )

            except Exception:
                logger.error("Unexpected Error: %s" %
                                      (''.join(traceback
                                       .format_exception(*sys.exc_info())[-2:])
                                       .strip().replace('\n', ': '))
                                      )

            finally:
                if 'connection' in locals():
                    connection.close()

    def perform(self, cmd):
        if self.serial is None or self.serial.available() is False:
            return self.error_message("Modem is not ready")
        try:
            if cmd['category'][0] == '_':
                raise AttributeError()
            m = getattr(self.__class__,
                        "%s_%s" % (cmd['category'], cmd['action']))
            return m(self, cmd)
        except AttributeError:
            return self.error_message("Unknown Command")
        except KeyError:
            return self.error_message("Invalid Args")
        except OSError:  # I/O Error
            return self.error_message("Modem is not ready")
        except Exception:
            return self.error_message("Unexpected error: %s" %
                                      (''.join(traceback
                                       .format_exception(*sys.exc_info())[-2:])
                                       .strip().replace('\n', ': '))
                                      )

    def error_message(self, msg):
        return json.dumps({"status": "ERROR", "result": msg})

    def read_line(self):
        line = self.serial.read_line()
        if self.debug:
            print("[modem:IN] => [%s]" % line)
        return line

    def send_at(self, cmd, ok="OK"):
        line = "%s\r" % cmd
        if self.debug:
            print("[modem:OUT] => [%s]" % line)
        self.serial.write(line)
        time.sleep(0.1)
        result = ""
        status = None
        count = 0
        while True:
            line = self.read_line()
            if line is None:
                if status is not None or count > 650:
                    break
                time.sleep(0.1)
                count = count + 1
            elif line == cmd:
                continue
            elif line == ok or \
                    line == "ERROR" or \
                    line == "NO DIALTONE" or \
                    line == "NO CARRIER" or \
                    line.startswith("+CME ERROR"):
                status = line
            elif line is None:
                status = "UNKNOWN"
            elif line.strip() != "":
                result += line + "\n"
        if self.debug:
            print("cmd:[%s] => status:[%s], result:[%s]" %
                  (cmd, status, result))
        return (status, result.strip())

    def _apn_ls(self):
        status, result = self.send_at("AT+CGDCONT?")
        apn_list = []
        id_name_list = []
        if status == "OK":
            try:
                id_name_list = list(map(lambda e: e[10:].split(",")[0] + "," +
                                   re.sub('"', '', e[10:].split(",")[2]),
                                   result.split("\n")))
                status, result = self.send_at("AT$QCPDPP?")
                creds_list = []
                if status == "OK":
                    def to_user(e):
                        if len(e) > 2:
                            return re.sub('"', '', e[2])
                        return ''
                    creds_list = list(map(lambda e: to_user(e),
                                     list(map(lambda e: e[9:].split(","),
                                         result.split("\n")))))
            except IndexError:
                pass
        for i in range(len(id_name_list)):
                id_name = id_name_list[i].split(",")
                apn = {
                    'apn_id': id_name[0],
                    'apn': id_name[1]
                }
                if len(creds_list) > i:
                    apn['user'] = creds_list[i]
                apn_list.append(apn)
        message = {
            'status': status,
            'result': {
                'apns': apn_list
            }
        }
        return message

    def apn_ls(self, cmd={}):
        return json.dumps(self._apn_ls())

    def apn_set(self, cmd={}):
        (name, user_id, password) = (cmd['name'], cmd['user_id'],
                                     cmd['password'])
        if 'type' in cmd:
            t = cmd['type']
            if t == 'ipv4':
                pdp = 'IP'
            elif t == 'ipv6':
                pdp = 'IPV6'
            else:
                pdp = 'IPV4V6'
        else:
            pdp = 'IP'

        apn_id = "1"
        if 'id' in cmd:
            apn_id = cmd['id']
        status, result = self.send_at(("AT+CGDCONT=%s,\"%s\",\"%s\"," +
                                      ",0,0") % (apn_id, pdp, name))
        if status == "OK":
            status, result = self.send_at(("AT$QCPDPP=%s,3,\"%s\",\"%s\"") %
                                          (apn_id, password, user_id))
        message = {
            'status': status,
            'result': result
        }
        return json.dumps(message)

    def _apn_del(self, apn_id):
        # removes QCPDPP as well
        status, result = self.send_at(("AT+CGDCONT=%s") % apn_id)
        message = {
            'status': status,
            'result': result
        }
        return message

    def apn_del(self, cmd={}):
        apn_id = "1"
        if 'id' in cmd:
            apn_id = cmd['id']
        return json.dumps(self._apn_del(apn_id))

    def network_show(self, cmd={}):
        rssi = ""
        network = "UNKNOWN"
        rssi_desc = ""
        operator = "UNKNOWN"
        status, result = self.send_at("AT+CSQ")
        if status == "OK":
            rssi_level = int(result[5:].split(",")[0])
            if rssi_level == 0:
                rssi = "-113"
                rssi_desc = "OR_LESS"
            elif rssi_level == 1:
                rssi = "-111"
            elif rssi_level <= 30:
                rssi = "%i" % (-109 + (rssi_level - 2) * 2)
            elif rssi_level == 31:
                rssi = "-51"
                rssi_desc = "OR_MORE"
            elif rssi_level == 100:
                rssi = "-116"
                rssi_desc = "OR_LESS"
            elif rssi_level == 101:
                rssi = "-115"
            elif rssi_level <= 190:
                rssi = "%i" % (-114 + (rssi_level - 102))
            elif rssi_level == 191:
                rssi = "-25"
                rssi_desc = "OR_MORE"
            else:
                rssi_desc = "NO_SIGANL"
            status, result = self.send_at("AT+COPS?")
            try:
                operator = result.split(',')[2][1:-1]
            except IndexError:
                operator = "N/A"
            registration = {
                "cs": "N/A",
                "ps": "N/A",
                "eps": "N/A"
            }
            status, result = self.send_at("AT+CREG?")
            try:
                cs = int(result.split(",")[1])
                registration["cs"] = CGREG_STATS[cs]
            except IndexError:
                pass
            status, result = self.send_at("AT+CGREG?")
            try:
                ps = int(result.split(",")[1])
                registration["ps"] = CGREG_STATS[ps]
            except IndexError:
                pass
            status, result = self.send_at("AT+CEREG?")
            try:
                eps = int(result.split(",")[1])
                registration["eps"] = CGREG_STATS[eps]
            except IndexError:
                pass
            access = 'N/A'
            band = 'N/A'
            status, result = self.send_at("AT+QNWINFO")
            if status == 'ERROR':
                status, result = self.send_at("AT+QGBAND")
                try:
                    currentband = int(result.split(': ')[1])
                    if currentband == 1:
                        access, band = 'GSM', 'GSM 900'
                    elif currentband == 2:
                        access, band = 'GSM', 'GSM 1800'
                    elif currentband == 4:
                        access, band = 'GSM', 'GSM 850'
                    elif currentband == 8:
                        access, band = 'GSM', 'GSM 1900'
                    elif currentband == 16:
                        access, band = 'WCDMA', 'WCDMA 2100'
                    elif currentband == 32:
                        access, band = 'WCDMA', 'WCDMA 1900'
                    elif currentband == 64:
                        access, band = 'WCDMA', 'WCDMA 850'
                    elif currentband == 128:
                        access, band = 'WCDMA', 'WCDMA 900'
                    elif currentband == 256:
                        access, band = 'WCDMA', 'WCDMA 800'
                except IndexError:
                    pass
            else:
                try:
                    nwinfo = result.split(': ')[1].split(',')
                    access = nwinfo[0].replace('"', '')
                    band = nwinfo[2].replace('"', '')
                except IndexError:
                    pass
        message = {
            'status': status,
            'result': {
                'rssi': rssi,
                'rssiDesc': rssi_desc,
                'network': 'N/A',
                'operator': operator,
                'registration': registration,
                'access': access,
                'band': band
            }
        }
        return json.dumps(message)

    def network_deregister(self, cmd={}):
        status, result = self.send_at("AT+COPS=2")
        message = {
            'status': status,
            'result': result
        }
        return json.dumps(message)

    def network_register(self, cmd={}):
        operator = None
        if 'operator' in cmd:
            mode = '4' if 'auto' in cmd and cmd['auto'] else '1'
            operator = cmd['operator']
        if operator is None or operator == '':
            mode = '0'
        status, result = self.send_at(
            "AT+COPS=%s,2,%s"
            % (mode, operator))
        message = {
            'status': status,
            'result': {
                'mode': mode
            }
        }
        return json.dumps(message)

    def sim_show(self, cmd={}):
        state = "SIM_STATE_ABSENT"
        msisdn = ""
        imsi = ""
        iccid = ""
        status, result = self.send_at("AT+CIMI")
        if status == "OK":
            imsi = result
            state = "SIM_STATE_READY"
            status, result = self.send_at("AT+CNUM")
            if len(result) > 5:
                msisdn = re.sub('"', '', result[6:].split(",")[1])
            else:
                msisdn = ""
            status, result = self.send_at("AT+QCCID")
            if len(result) > 7:
                iccid = result.split(':')[1].strip()
            else:
                iccid = ""
        message = {
            'status': status,
            'result': {
                'msisdn': msisdn,
                'imsi': imsi,
                'iccid': iccid,
                'state': state
            }
        }
        return json.dumps(message)

    def _counter_show(self):
        """
        - Show TX/RX packet counter
        """
        status, result = self.send_at("AT+QGDCNT?")
        tx = '0'
        rx = '0'
        if status == "OK":
            txrx = result.split(':')[1].strip().split(',')
            tx = txrx[0]
            rx = txrx[1]
        message = {
            'status': status,
            'result': {
                'tx': tx,
                'rx': rx
            }
        }
        return message

    def _counter_reset(self):
        """
        - Reset packet counter
        """
        status, result = self.send_at("AT+QGDCNT=0")
        message = {
            'status': status,
            'result': result
        }
        return message

    def _imei_show(self):
        """
        - Show IMEI
        """
        status, result = self.send_at("AT+GSN")
        message = {
            'status': status,
            'result': result
        }
        return message

    def _timestamp_show(self):
        """
        - Show timestamp
        """
        status, result = self.send_at("AT+CCLK?")
        message = {
            'status': status,
            'result': result
        }
        return message

    def _functionality_show(self):
        """
        - Show phone functionality
        """
        status, result = self.send_at("AT+CFUN?")
        func = "Error"
        if status == "OK":
            func = result.split(':')[1].strip()
            if func == "0":
                func = "Minimum"
            elif func == "1":
                func = "Full"
            elif func == "4":
                func = "Disabled"
            else:
                func = "Anomaly"
        message = {
            'status': status,
            'result': {
                'functionality': func
            }
        }
        return message

    def modem_show(self, cmd={}):
        status, result = self.send_at("ATI")
        man = "UNKNOWN"
        mod = "UNKNOWN"
        rev = "UNKNOWN"
        imei = "UNKNOWN"
        func = "UNKNOWN"
        counter = None
        utc = None
        timezone_hrs = None
        if status == "OK":
            info = result.split("\n")
            man = info[0]
            mod = info[1]
            rev = info[2][10:]
            result = self._imei_show()
            if result['status'] == "OK":
                imei = result['result']
            result = self._counter_show()
            if result['status'] == "OK":
                counter = result['result']
            result = self._timestamp_show()
            if result['status'] == "OK":
                datelen = len(result['result'])
                if datelen == 29:
                    utc = result['result'][8:-4]
                    timezone_hrs = float(result['result'][-4:-1]) / 4
                elif datelen == 26:
                    utc = result['result'][8:-1]
                    timezone_hrs = 0.0
            result = self._functionality_show()
            func = result['result']['functionality']
        message = {
            'status': status,
            'result': {
                'manufacturer': man,
                'model': mod,
                'revision': rev,
                'imei': imei,
                'datetime': utc,
                'timezone': timezone_hrs,
                'functionality': func
            }
        }
        if counter:
            message['result']['counter'] = counter
        return json.dumps(message)

    def _parse_opts(self, cmd={}):
        opts = {}
        if 'opts' in cmd:
            try:
                opts = json.loads(cmd['opts'])
            except Exception:
                try:
                    entries = list(map(lambda e: e.split('='),
                                  cmd['opts'].split(',')))
                    for (k, v) in entries:
                        opts[k.strip()] = v.strip()
                except Exception:
                    pass
        return opts

    def modem_reset(self, cmd={}):
        """
        - opts counter=yes
            - Reset packet counter
        - no-opts or counter!=yes
            - Reset packet counter
            - Remove all APN
            - Reset Phone Functionality
        """
        result = 'counter'
        counter_reset_ret = self._counter_reset()
        status = counter_reset_ret['status']
        opts = self._parse_opts(cmd)
        if 'counter' not in opts or opts['counter'] != 'yes':
            result = ''
            apn_ls_ret = self._apn_ls()
            status = apn_ls_ret['status']
            if apn_ls_ret['status'] == "OK":
                apns = apn_ls_ret['result']['apns']
                for apn in apns:
                    self._apn_del(apn['apn_id'])
            status, qnvw_result = self.send_at(
                'AT+QNVW=4548,0,"0000400C00000210"')
            if status != "OK":
                result = qnvw_result
            status, qnvw_result = self.send_at(
                'AT+QNVW=930,0,"2A39380000030003002A3939000003000300233737370'
                '004000400000000000000000000"')
            if status != "OK":
                result = qnvw_result
            self._modem_clck_unlock(cmd)

        message = {
            'status': status,
            'result': result
        }
        return json.dumps(message)

    def modem_off(self, cmd={}):
        """
        PRIVATE COMMAND (not available from CLI)
        - Power off
        """
        status, result = self.send_at("AT+QPOWD", "POWERED DOWN")
        if status == "POWERED DOWN":
            status = "OK"
            result = ""
        message = {
            'status': status,
            'result': result
        }
        return json.dumps(message)

    def modem_init(self, cmd={}):
        """
        PRIVATE COMMAND (not available from CLI)
        - Enable automatic timezone update with NITZ
          to set modem RTC (if NW is capable)
          Enabled by default.
        - Reset Phone Functionality
        - Set baudrate (optional)
        - Reset packet counter (optional)
        """
        tz_update = "N/A"
        counter_reset_ret = "N/A"
        baudrate_ret = "N/A"
        if 'tz_update' not in cmd or cmd['tz_update'] is True:
            status, result = self.send_at("AT+CTZU?")
            if status == "OK":
                tz_update = "OK"
                for at in ["AT+COPS=2", "AT+CTZU=1", "AT+COPS=0"]:
                    status, result = self.send_at(at)
                    if status != "OK":
                        tz_update = "ERROR"
                        break
        if 'counter_reset' in cmd and cmd['counter_reset']:
            counter_reset_ret = self._counter_reset()['status']
        status, result_qnvw = self.send_at(
            'AT+QNVW=4548,0,"0000400C00000210"')
        if status != "OK":
            message = {
                'status': status,
                'result': result_qnvw,
                'cmd': 'AT+QNVW'
            }
            return json.dumps(message)
        self._modem_clck_unlock(cmd)
        if 'baudrate' in cmd:
            baudrate_ret, result = self.send_at("AT+IPR=%s" % cmd['baudrate'])
            if baudrate_ret != "OK":
                message = {
                    'status': baudrate_ret,
                    'result': result,
                    'cmd': 'baudrate'
                }
                return json.dumps(message)
        message = {
            'status': status,
            'result': {
                'counter_reset': counter_reset_ret,
                'baudrate': baudrate_ret
            }
        }
        return json.dumps(message)

    def _modem_clck_unlock(self, cmd={}):
        if 'pu' not in cmd or cmd['pu'] is False:
            self.send_at(
                'AT+CLCK="PU",0,"12341234"')

    def _gnss_config_uc2x(self, cmd={}):
        glonassenable = '0'
        glonassnmeatype = '0'
        if 'all' in cmd and cmd['all']:
            glonassenable = '1'
            glonassnmeatype = '7'

        status, result = self.send_at('AT+QGPSCFG="glonassenable",%s'
                                      % glonassenable)
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'glonassenable'
            }
            return json.dumps(message)
        status, result = self.send_at('AT+QGPSCFG="glonassnmeatype",%s'
                                      % glonassnmeatype)
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'glonassnmeatype'
            }
            return json.dumps(message)

    def _gnss_config_ec2x(self, cmd={}):
        config = '0'
        glonassnmeatype = '0'
        beidounmeatype = '0'
        galileonmeatype = '0'
        if 'all' in cmd and cmd['all']:
            config = '1'
            glonassnmeatype = '7'
            beidounmeatype = '3'
            galileonmeatype = '1'
        elif 'qzss' in cmd and cmd['qzss']:
            config = '2'
            glonassnmeatype = '7'
            beidounmeatype = '3'

        status, result = self.send_at('AT+QGPSCFG="gnssconfig",%s' % config)
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'gnssconfig'
            }
            return json.dumps(message)
        status, result = self.send_at('AT+QGPSCFG="glonassnmeatype",%s'
                                      % glonassnmeatype)
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'glonassnmeatype'
            }
            return json.dumps(message)
        status, result = self.send_at('AT+QGPSCFG="beidounmeatype",%s'
                                      % beidounmeatype)
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'beidounmeatype'
            }
            return json.dumps(message)
        status, result = self.send_at('AT+QGPSCFG="galileonmeatype",%s'
                                      % galileonmeatype)
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'galileonmeatype'
            }
            return json.dumps(message)

    def _gnss_config(self, cmd={}):
        status, result = self.send_at("ATI")
        if status == "OK":
            info = result.split("\n")
            if info[1] == 'UC20':
                return self._gnss_config_uc2x(cmd)
            else:
                return self._gnss_config_ec2x(cmd)

    def gnss_start(self, cmd={}):
        status, result = self.send_at('AT+QGPSCFG="gpsnmeatype",31')
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'gpsnmeatype'
            }
            return json.dumps(message)
        message_json = self._gnss_config(cmd)
        if message_json is not None:
            return message_json
        status, result = self.send_at('AT+QGPSCFG="nmeasrc",1')
        if status != "OK":
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'nmeasrc'
            }
            return json.dumps(message)
        status, result = self.send_at("AT+QGPS=1,30,50,0,1")
        if status == "OK":
            result = ""
        elif status == "+CME ERROR: 504":
            status = "OK"
        else:
            result = status
            status = "ERROR"
        message = {
            'status': status,
            'result': result,
        }
        return json.dumps(message)

    def gnss_status(self, cmd={}):
        status, result = self.send_at("AT+QGPS?")
        if status == "OK":
            gnssstate = result.split(':')[1].strip()
            if gnssstate == "0":
                session = 'stopped'
            elif gnssstate == "1":
                session = 'started'
        else:
            result = status
            status = "ERROR"
            message = {
                'status': status,
                'result': result,
                'cmd': 'QGPS?'
            }
            return json.dumps(message)

        qzss = 'N/A'
        status, result = self.send_at("ATI")
        if status == "OK":
            info = result.split("\n")
            if info[1] != 'UC20':
                status, result = self.send_at('AT+QGPSCFG="gnssconfig"')
                if status != "OK":
                    result = status
                    status = "ERROR"
                    message = {
                        'status': status,
                        'result': result,
                        'cmd': 'gnssconfig'
                    }
                    return json.dumps(message)
                gnssconfig = result.split(':')[1].split(',')[1].strip()
                if gnssconfig == '1' or gnssconfig == '2':
                    qzss = 'enabled'
                else:
                    qzss = 'disabled'

        message = {
            'status': status,
            'result': {
                'session': session,
                'qzss': qzss
            },
        }
        return json.dumps(message)

    def gnss_stop(self, cmd={}):
        status, result = self.send_at("AT+QGPSEND")
        if status == "OK":
            result = ""
        elif status == "+CME ERROR: 505":
            status = "OK"
        else:
            result = status
            status = "ERROR"
        message = {
            'status': status,
            'result': result,
        }
        return json.dumps(message)

    def gnss_locate(self, cmd={}):
        if 'format' in cmd and cmd['format']:
            format = str(cmd['format'])
        else:
            format = '2'
        status, result = self.send_at("AT+QGPSLOC=%s" % (format))
        if status == "OK":
            csv = result.split(':')[1].strip().split(',')
            if len(csv) < 11:
                message = {
                    'status': 'ERROR',
                    'result': 'Temporary I/O Error',
                }
                return json.dumps(message)
            latitude = csv[1]
            if format == '1':
                latitude = '%s %s' % (latitude, csv[2])
                del csv[2]
            elif format == '0':
                latitude = '%s %s' % (latitude[:-1], latitude[-1])
            longitude = csv[2]
            if format == '1':
                longitude = '%s %s' % (longitude, csv[3])
                del csv[3]
            elif format == '0':
                longitude = '%s %s' % (longitude[:-1], longitude[-1])
            altitude = float(csv[4])
            if format == '2':
                latitude = float(latitude)
                longitude = float(longitude)
            result = {
                'timestamp': '20%s-%s-%sT%s:%s:%s.000Z' %
                (
                    csv[9][4:6], csv[9][2:4], csv[9][0:2],
                    csv[0][0:2], csv[0][2:4], csv[0][4:6]
                ),
                'latitude': latitude,
                'longitude': longitude,
                'hdop': float(csv[3]),
                'altitude': altitude,
                'fix': '%sD' % csv[5],
                'cog': float(csv[6]),
                'spkm': float(csv[7]),
                'spkn': float(csv[8]),
                'nsat': int(csv[10])
            }
        else:
            code = status.split(':')
            if len(code) > 1:
                code = code[1].strip()
                status = "ERROR"
            else:
                code = code[0]
            if code == "516":
                result = "Not fixed yet"
            elif code == "502":
                result = "Invalid format"
            elif code == "505":
                result = "Session not started"
            else:
                result = code
        message = {
            'status': status,
            'result': result,
        }
        return json.dumps(message)

    def service_version(self, cmd={}):
        message = {
            'status': 'OK',
            'result': {
                'version': self.version,
            }
        }
        return json.dumps(message)


from matplotlib.pyplot import *

from numpy import sum, arange, exp, sqrt, pi, inf

import scipy.integrate
import scipy.optimize

clight = 299792458
pmass = 0.938272013e9

def ftoint(u, alpha=1.0, Ax=1.0, Ay=1.0):
    """alpha=theta_c/2 * sqrt(emit/betxstar)
    Ax=sigma_z/betxstar
    Ay=sigma_z/betystar
    """
    dx = 1 + (Ax * u) ** 2
    dy = 1 + (Ay * u) ** 2
    n = exp(-(u**2) * (1 + (alpha * Ax) ** 2 / dx))
    d = sqrt(dx * dy)
    return n / d

def mkint(alpha=290e-6, Ax=1.0, Ay=1.0, debug=True):
    i = scipy.integrate.quad(ftoint, 0, inf, args=(alpha, Ax, Ay))
    if debug:
        print("Integral tolerance: %e" % i[1])
    return 2 / sqrt(pi) * i[0]

def luminosity(
    nb=2808,
    N=1.7e11,
    frev=clight / 26658.8832,
    betx=0.55,
    bety=0.55,
    emit_n=3.75e-6,
    sigma_z=0.0755,
    pc=7e12,
    dsep=10,
    vcrab=0e6,
    r12=24,
    fcrab=400e6,
    debug=True,
):
    brho = pc / clight
    gamma = pc / pmass
    emit = emit_n / gamma
    sigma_x = sqrt(betx * emit)
    sigma_y = sqrt(bety * emit)
    thetac = dsep * sqrt(emit / betx)
    acrab = vcrab / (3e8 * pc) * (4 * pi * r12 * fcrab)
    alpha = (thetac - acrab) / (2 * sqrt(emit / betx))
    L = (nb * N**2 * frev) / (4 * pi * sigma_x * sigma_y)
    Ax = sigma_z / betx
    Ay = sigma_z / bety
    betw = alpha * sigma_z
    factor = mkint(alpha, Ax, Ay, debug=debug)
    LL = L * factor
    Fgeo = 1 / sqrt(1 + ((sigma_z * dsep) / (2 * betx) ** 2))
    if debug:
        print("Head-on Luminosity [cm^-2 s^-1]: %e" % (L / 1e4))
        print("Ext Crossing angle [urad]: %g" % (thetac * 1e6))
        print("Crab Crossing angle [urad]: %g" % (acrab * 1e6))
        print("beta_w: %g" % (alpha * sigma_z))
        print("Piwinski angle: %g" % (betw / betx))
        print("Loss factor : %g" % factor)
        print("Fgeo        : %g" % Fgeo)
        print("Luminosity  [cm^-2 s^-1] : %e" % (LL * 1e-4))
    return LL

def luminosity2(
    nb=2736,
    N=2.2e11,
    betx=0.15,
    bety=0.15,
    emit_n=2.5e-6,
    sigma_z=0.0755,
    pc=7e12,
    thetac=500e-6,
    acrab=380e-6,
    debug=True,
    frev=clight / 26658.8832,
):
    brho = pc / clight
    gamma = pc / pmass
    emit = emit_n / gamma
    sigma_x = sqrt(betx * emit)
    sigma_y = sqrt(bety * emit)
    dsep=thetac/sqrt(emit / betx)
    alpha = (thetac - acrab) / (2 * sqrt(emit / betx))
    L = (nb * N**2 * frev) / (4 * pi * sigma_x * sigma_y)
    Ax = sigma_z / betx
    Ay = sigma_z / bety
    betw = alpha * sigma_z
    factor = mkint(alpha, Ax, Ay, debug=debug)
    LL = L * factor
    Fgeo = 1 / sqrt(1 + ((sigma_z * dsep) / (2 * betx) ** 2))
    if debug:
        print("Head-on Luminosity [cm^-2 s^-1]: %e" % (L / 1e4))
        print("Ext crossing  [signa]: %g" % (dsep))
        print("beta_w: %g" % (alpha * sigma_z))
        print("Piwinski angle: %g" % (betw / betx))
        print("Loss factor : %g" % factor)
        print("Fgeo        : %g" % Fgeo)
        print("Luminosity  [cm^-2 s^-1] : %e" % (LL * 1e-4))
    return LL

def piwibeta(sigma_z=0.0755, bety=0.075, dsep=10):
    def ftomin(x):
        return -luminosity(
            betx=x[0], bety=bety, sigma_z=sigma_z, dsep=dsep, debug=False
        )

    (betx,) = scipy.optimize.fmin(ftomin, [3])
    return betx

def integrated_lumi(
    nb=2808,
    N=1.7e11,
    frev=clight / 26658.8832,
    betx=0.55,
    bety=0.55,
    emit_n=3.75e-6,
    sigma_z=0.0755,
    pc=7e12,
    dsep=10,
    sigma_cross=0.110 * 1e-28,
    vcrab=0e6,
    debug=False,
):
    """cross section
    http://lhc-machine-outreach.web.cern.ch/lhc-machine-outreach/collisions.htm
    * inelastic (sin = 60 mbarn)
    * single diffractive (ssd = 12 mbarn)
    * elastic (sel  = 40 mbarn)
    """
    dt = 1
    level_lumi = 5e38
    lumi = luminosity(
        nb=nb, N=N, betx=betx, bety=bety, emit_n=emit_n, sigma_z=sigma_z, dsep=dsep
    )
    intlumi = 0
    tt = 0
    while N > 0:
        while lumi >= level_lumi and alpha > 5:
            alpha += 0.1
            lumi = luminosity(
                nb=nb,
                N=N,
                betx=betx,
                bety=bety,
                emit_n=emit_n,
                sigma_z=sigma_z,
                alpha=alpha,
                debug=False,
            )
            print(lumi)
        intlumi += lumi * dt
        tt += dt
        burnout = lumi * sigma_cross * dt
        N -= burnout
        print(tt, lumi, N, burnout)

def kfactor(
    betx, bety, dsepA, dsepB, vcrabA, vcrabB, emit_n=3.75e-6, sigma_z=0.0755, pc=7e12
):
    La = luminosity(
        betx=betx,
        bety=bety,
        dsep=dsepA,
        vcrab=vcrabA,
        emit_n=emit_n,
        sigma_z=sigma_z,
        pc=pc,
    )
    Lb = luminosity(
        betx=betx,
        bety=bety,
        dsep=dsepB,
        vcrab=vcrabB,
        emit_n=emit_n,
        sigma_z=sigma_z,
        pc=pc,
    )
    print(La / Lb)

if __name__ == "__main__":
    luminosity()
    luminosity(betx=0.15, bety=0.15)
    luminosity(betx=0.30, bety=0.075)
    luminosity(sigma_z=0.06, betx=0.30, bety=0.075, dsep=13)
    luminosity(sigma_z=0.06, betx=0.36, bety=0.10, dsep=13)
    luminosity(N=1.8e11, sigma_z=0.05, betx=0.25, bety=0.15, dsep=13, emit_n=2.5e-6)
    kfactor(betx=0.15, bety=0.15, dsepA=10, dsepB=10, vcrabA=6e6, vcrabB=-6e6)
    kfactor(betx=0.15, bety=0.15, dsepA=10, dsepB=10, vcrabA=6e6, vcrabB=0e6)
    kfactor(betx=0.15, bety=0.15, dsepA=10, dsepB=10, vcrabA=10e6, vcrabB=-10e6)
    luminosity(N=2.2e11, betx=0.15, bety=0.15, dsep=12.5, emit_n=2.5e-6)
    luminosity(N=3.5e11, nb=1404, betx=0.15, bety=0.15, dsep=11.4, emit_n=3.0e-6)
    luminosity(pc=4e12, N=1.7e11, nb=11390, betx=0.6, bety=0.6, dsep=13, emit_n=2.2e-6)
    luminosity(pc=4e12, N=1.6e11, nb=1390, betx=0.6, bety=0.6, dsep=8, emit_n=2.8e-6)
    luminosity(N=2.2e11, betx=0.15 * 2, bety=0.15 / 2, dsep=12.5 * 1.2, emit_n=2.5e-6)
    luminosity(
        N=3.5e11, nb=1404, betx=0.15 * 2, bety=0.15 / 2, dsep=11.4 * 1.2, emit_n=3.0e-6
    )
    luminosity(
        betx=0.30,
        bety=0.30,
        emit_n=1.54e-6,
        sigma_z=1e-9 * clight / 4,
        dsep=12,
        nb=2592,
        pc=6.5e12,
        N=1.24,
    )

    def plot10():
        clf()
        i = 121
        emit = 2.5
        for dsep in [10, 15]:
            subplot(i)
            for sigma_z, cl in zip([5, 7.5, 10], "rgb"):
                title(r"$N=1.2 \cdot 10^{11}\, d_{\rm sep}=%d \sigma$" % (dsep))
                # for by,ls in zip([0.075,0.10,0.15],['-','--','-.']):
                for by, ls in zip([0.075, 0.10], ["-", "--"]):
                    bx = arange(0.05, 1, 0.01)
                    lumi = [
                        luminosity(
                            betx=bbx,
                            bety=by,
                            emit_n=emit * 1e-6,
                            sigma_z=sigma_z * 1e-2,
                            dsep=dsep,
                            nb=2592,
                            pc=7e12,
                            N=1.2e11,
                        )
                        / 1e38
                        for bbx in bx
                    ]
                    lbl = r"$\sigma_z=%g$ cm, $\beta_{\rm sep}=%g cm$" % (
                        sigma_z,
                        by * 100,
                    )
                    plot(bx * 100, lumi, ls + cl, label=lbl)
                    ylim(0, 8)
                    grid(True)
                legend()
                xlabel(r"$\beta_{\rm cross}$ [cm]")
                ylabel(r"peak luminosity $[10^{34}]$")
            i += 1
        savefig("flat12.png")

    plot10()

    def ftomin(x, by=0.15, emit=1.8, sep=12, bl=1):
        bx = x[0]
        return -luminosity(
            betx=bx,
            bety=by,
            emit_n=emit * 1e-6,
            sigma_z=bl * 1e-9 * clight / 4,
            dsep=sep,
            nb=2592,
            pc=6.5e12,
            N=1.24e11,
        )

# emit=1.54
# out=[]
# for sep in [10,12,13]:
#  for bl in [0.9,1,1.1,1.2]:
#    for by in [0.05,0.10,0.15,0.20,0.25,0.30,0.40]:
#      bx=scipy.optimize.fmin(ftomin,[0.25],args=(by,emit,sep,bl))[0]
#      out.append((bx,by,emit,sep,bl))
#
# for bx,by,emit,sep,bl in out:
#  if by in [0.10,0.20,0.30,0.40] and sep in [10,12]:
#    print ("%5.3g "*4)%(bx,by,bl,sep)
#

import numba
import numpy as np
import scipy
import matplotlib.pyplot as plt

def pdf_normal_2d(mux, muy, sigxx, sigyy, sigxy):
    return numba.njit(
        lambda x, y: 1
        / (2 * np.pi * sigxx * sigyy * sqrt(1 - sigxy**2))
        * np.exp(
            -1
            / (2 * (1 - sigxy**2))
            * (
                (x - mux) ** 2 / sigxx**2
                + (y - muy) ** 2 / sigyy**2
                - 2 * sigxy * (x - mux) * (y - muy) / (sigxx * sigyy)
            )
        )
    )

def int_rho1_rho2(rho1, rho2):
    ftoint = numba.njit(lambda x, y: rho1(x, y) * rho2(x, y))
    return scipy.integrate.dblquad(ftoint, -np.inf, np.inf, -np.inf, np.inf)[0]

rho1 = pdf_normal_2d(0, 0, 1, 1, 0.5)
rho2 = pdf_normal_2d(0, 0, 1, 1, 0.5)

def f1(x):
    rho1 = pdf_normal_2d(x, 0, 1, 1, 0)
    rho2 = pdf_normal_2d(0, 0, 1, 1, 0)
    return int_rho1_rho2(rho1, rho2)


import math
import random
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union

import cv2
import numpy as np
from albumentations import random_utils
from albumentations.augmentations.crops import functional as F
from albumentations.augmentations.geometric import functional as FGeometric
from albumentations.augmentations.utils import (_maybe_process_in_chunks,
                                                preserve_shape)
from albumentations.core.transforms_interface import (DualTransform,
                                                      ImageOnlyTransform)

class _CustomBaseRandomSizedCropNoResize(DualTransform):
    # Base class for RandomSizedCrop and RandomResizedCrop

    def __init__(self, always_apply=False, p=1.0):
        super(_CustomBaseRandomSizedCropNoResize,
              self).__init__(always_apply, p)

    def apply(self,
              img,
              crop_height=0,
              crop_width=0,
              h_start=0,
              w_start=0,
              interpolation=cv2.INTER_LINEAR,
              **params):
        return F.random_crop(img, crop_height, crop_width, h_start, w_start)

    def apply_to_bbox(self,
                      bbox,
                      crop_height=0,
                      crop_width=0,
                      h_start=0,
                      w_start=0,
                      rows=0,
                      cols=0,
                      **params):
        return F.bbox_random_crop(bbox, crop_height, crop_width, h_start,
                                  w_start, rows, cols)

    def apply_to_keypoint(self,
                          keypoint,
                          crop_height=0,
                          crop_width=0,
                          h_start=0,
                          w_start=0,
                          rows=0,
                          cols=0,
                          **params):
        keypoint = F.keypoint_random_crop(keypoint, crop_height, crop_width,
                                          h_start, w_start, rows, cols)
        scale_x = self.width / crop_width
        scale_y = self.height / crop_height
        keypoint = FGeometric.keypoint_scale(keypoint, scale_x, scale_y)
        return keypoint

class CustomRandomSizedCropNoResize(_CustomBaseRandomSizedCropNoResize):
    """Torchvision's variant of crop a random part of the input and rescale it to some size.

    Args:
        scale ((float, float)): range of size of the origin size cropped
        ratio ((float, float)): range of aspect ratio of the origin aspect ratio cropped
        interpolation (OpenCV flag): flag that is used to specify the interpolation algorithm. Should be one of:
            cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4.
            Default: cv2.INTER_LINEAR.
        p (float): probability of applying the transform. Default: 1.

    Targets:
        image, mask, bboxes, keypoints

    Image types:
        uint8, float32
    """

    def __init__(
            self,
            scale=(0.08, 1.0),
            ratio=(0.75, 1.3333333333333333),
            always_apply=False,
            p=1.0,
    ):

        super(CustomRandomSizedCropNoResize,
              self).__init__(always_apply=always_apply, p=p)
        self.scale = scale
        self.ratio = ratio

    def get_params_dependent_on_targets(self, params):
        img = params["image"]
        area = img.shape[0] * img.shape[1]

        for _attempt in range(10):
            target_area = random.uniform(*self.scale) * area
            log_ratio = (math.log(self.ratio[0]), math.log(self.ratio[1]))
            aspect_ratio = math.exp(random.uniform(*log_ratio))

            w = int(round(math.sqrt(target_area *
                                    aspect_ratio)))  # skipcq: PTC-W0028
            h = int(round(math.sqrt(target_area /
                                    aspect_ratio)))  # skipcq: PTC-W0028

            if 0 < w <= img.shape[1] and 0 < h <= img.shape[0]:
                i = random.randint(0, img.shape[0] - h)
                j = random.randint(0, img.shape[1] - w)
                return {
                    "crop_height": h,
                    "crop_width": w,
                    "h_start": i * 1.0 / (img.shape[0] - h + 1e-10),
                    "w_start": j * 1.0 / (img.shape[1] - w + 1e-10),
                }

        # Fallback to central crop
        in_ratio = img.shape[1] / img.shape[0]
        if in_ratio < min(self.ratio):
            w = img.shape[1]
            h = int(round(w / min(self.ratio)))
        elif in_ratio > max(self.ratio):
            h = img.shape[0]
            w = int(round(h * max(self.ratio)))
        else:  # whole image
            w = img.shape[1]
            h = img.shape[0]
        i = (img.shape[0] - h) // 2
        j = (img.shape[1] - w) // 2
        return {
            "crop_height": h,
            "crop_width": w,
            "h_start": i * 1.0 / (img.shape[0] - h + 1e-10),
            "w_start": j * 1.0 / (img.shape[1] - w + 1e-10),
        }

    def get_params(self):
        return {}

    @property
    def targets_as_params(self):
        return ["image"]

    def get_transform_init_args_names(self):
        return "scale", "ratio"

# @TODO: support other native dtype: float, uint16,.. or support higher bit-depth (current 8 bits, LUT size = 256)
# cv2.LUT is tricky and other implementation with higher bit-depth can cause performance (speed) drop
# https://stackoverflow.com/questions/27098831/lookup-table-for-16-bit-mat-efficient-way
# https://stackoverflow.com/questions/71734861/opencv-python-lut-for-16bit-image
# https://stackoverflow.com/questions/28423701/efficient-way-to-loop-through-pixels-of-16-bit-mat-in-opencv
# https://answers.opencv.org/question/206755/lut-for-16bit-image/
@preserve_shape
def move_tone_curve_allow_float_img(img, low_y, high_y):
    """Rescales the relationship between bright and dark areas of the image by manipulating its tone curve.
    Args:
        img (numpy.ndarray): RGB or grayscale image.
        low_y (float): y-position of a Bezier control point used
            to adjust the tone curve, must be in range [0, 1]
        high_y (float): y-position of a Bezier control point used
            to adjust image tone curve, must be in range [0, 1]
    """
    input_dtype = img.dtype

    if low_y < 0 or low_y > 1:
        raise ValueError("low_shift must be in range [0, 1]")
    if high_y < 0 or high_y > 1:
        raise ValueError("high_shift must be in range [0, 1]")

    if input_dtype != np.uint8:
        # raise ValueError("Unsupported image type {}".format(input_dtype))
        assert input_dtype == np.float32
        img = (img * 255).astype(np.uint8)

    t = np.linspace(0.0, 1.0, 256)

    # Defines responze of a four-point bezier curve
    def evaluate_bez(t):
        return 3 * (1 - t)**2 * t * low_y + 3 * (1 - t) * t**2 * high_y + t**3

    evaluate_bez = np.vectorize(evaluate_bez)
    remapping = np.rint(evaluate_bez(t) * 255).astype(np.uint8)

    lut_fn = _maybe_process_in_chunks(cv2.LUT, lut=remapping)
    img = lut_fn(img)
    # convert back to float image in range [0, 1]
    if input_dtype != np.uint8:
        img = (img / 255).astype(np.float32)
    return img

class RandomToneCurveAllowFloatImage(ImageOnlyTransform):
    """Randomly change the relationship between bright and dark areas of the image by manipulating its tone curve.
    Args:
        scale (float): standard deviation of the normal distribution.
            Used to sample random distances to move two control points that modify the image's curve.
            Values should be in range [0, 1]. Default: 0.1
    Targets:
        image
    Image types:
        uint8, float32
    Note: if image in float32 dtype, first convert it to uint8, modify tone curve then convert back to float32.
    """

    def __init__(
        self,
        scale=0.1,
        always_apply=False,
        p=0.5,
    ):
        super(RandomToneCurveAllowFloatImage, self).__init__(always_apply, p)
        self.scale = scale

    def apply(self, image, low_y, high_y, **params):
        return move_tone_curve_allow_float_img(image, low_y, high_y)

    def get_params(self):
        return {
            "low_y":
            np.clip(random_utils.normal(loc=0.25, scale=self.scale), 0, 1),
            "high_y":
            np.clip(random_utils.normal(loc=0.75, scale=self.scale), 0, 1),
        }

    def get_transform_init_args_names(self):
        return ("scale", )


#!/usr/bin/python

# Copyright 2016, Gurobi Optimization, Inc.

# Solve the classic diet model, showing how to add constraints
# to an existing model.

from gurobipy import *

kategorie, minOdzywianie, maxOdzywianie = multidict({
  'kalorie': [1800, 2200],
  'bialko':  [91, GRB.INFINITY],
  'tluszcz':      [0, 65],
  'sod':   [0, 1779] })

jedzenie, koszt = multidict({
  'hamburger': 2.49,
  'kurczak':   2.89,
  'hot dog':   1.50,
  'frytki':     1.89,
  'makaron':  2.09,
  'pizza':     1.99,
  'salata':     2.49,
  'mleko':      0.89,
  'lody': 1.59 })

# Nutrition values for the foods
odzywianieWartosci = {
  ('hamburger', 'kalorie'): 410,
  ('hamburger', 'bialko'):  24,
  ('hamburger', 'tluszcz'):      26,
  ('hamburger', 'sod'):   730,
  ('kurczak',   'kalorie'): 420,
  ('kurczak',   'bialko'):  32,
  ('kurczak',   'tluszcz'):      10,
  ('kurczak',   'sod'):   1190,
  ('hot dog',   'kalorie'): 560,
  ('hot dog',   'bialko'):  20,
  ('hot dog',   'tluszcz'):      32,
  ('hot dog',   'sod'):   1800,
  ('frytki',     'kalorie'): 380,
  ('frytki',     'bialko'):  4,
  ('frytki',     'tluszcz'):      19,
  ('frytki',     'sod'):   270,
  ('makaron',  'kalorie'): 320,
  ('makaron',  'bialko'):  12,
  ('makaron',  'tluszcz'):      10,
  ('makaron',  'sod'):   930,
  ('pizza',     'kalorie'): 320,
  ('pizza',     'bialko'):  15,
  ('pizza',     'tluszcz'):      12,
  ('pizza',     'sod'):   820,
  ('salata',     'kalorie'): 320,
  ('salata',     'bialko'):  31,
  ('salata',     'tluszcz'):      12,
  ('salata',     'sod'):   1230,
  ('mleko',      'kalorie'): 100,
  ('mleko',      'bialko'):  8,
  ('mleko',      'tluszcz'):      2.5,
  ('mleko',      'sod'):   125,
  ('lody', 'kalorie'): 330,
  ('lody', 'bialko'):  8,
  ('lody', 'tluszcz'):      10,
  ('lody', 'sod'):   180 }

# Model
m = Model("diet")

# Create decision variables for the nutrition information,
# which we limit via bounds
odzywianie = m.addVars(kategorie, lb=minOdzywianie, ub=maxOdzywianie, name="odzywianie")

# Create decision variables for the foods to buy
kup = m.addVars(jedzenie, name="kup")

# You could use Python looping constructs and m.addVar() to create
# these decision variables instead.  The following would be equivalent
# to the preceding two statements...
#
# nutrition = {}
# for c in categories:
#   nutrition[c] = m.addVar(lb=minNutrition[c], ub=maxNutrition[c], name=c)
#
# buy = {}
# for f in foods:
#   buy[f] = m.addVar(name=f)

# The objective is to minimize the costs
m.setObjective(kup.prod(koszt), GRB.MINIMIZE)

# Using looping constructs, the preceding statement would be:
#
# m.setObjective(sum(buy[f]*cost[f] for f in foods), GRB.MINIMIZE)

# Nutrition constraints
m.addConstrs(
    (quicksum(odzywianieWartosci[f,c] * kup[f] for f in jedzenie) == odzywianie[c]
     for c in kategorie), "_")

# Using looping constructs, the preceding statement would be:
#
# for c in categories:
#  m.addConstr(
#     sum(nutritionValues[f,c] * buy[f] for f in foods) == nutrition[c], c)

def printSolution():
    if m.status == GRB.Status.OPTIMAL:
        print('\nKoszt: %g' % m.objVal)
        print('\nKup:')
        kupx = m.getAttr('x', kup)
        odzywianiex = m.getAttr('x', odzywianie)
        for f in jedzenie:
            if kup[f].x > 0.0001:
                print('%s %g' % (f, kupx[f]))
        print('\nOdzywianie:')
        for c in kategorie:
            print('%s %g' % (c, odzywianiex[c]))
    else:
        print('Brak rozwiazania')

# Solve
m.optimize()
printSolution()

print('\nDodanie ograniczenia: przynajmniej x porcji nabialu')
m.addConstr(kup.sum(['mleko','lody']) <= 10, "limit_dairy")

# Solve
m.optimize()
printSolution()


from calvin.actor.actor import Actor, manage, condition, stateguard, calvinsys
from calvin.utilities.calvinlogger import get_logger

_log = get_logger(__name__)

class Distance(Actor):

    """
    Measure distance. Takes the period of measurements, in seconds, as input.

    Outputs:
        meters : distance, in meters
    """

    @manage(['period', 'distance', 'timer'])
    def init(self, period):
        self.period = period
        self.distance = calvinsys.open(self, "io.distance")
        self.timer = calvinsys.open(self, "sys.timer.repeating", period=period)

    @stateguard(lambda self: calvinsys.can_read(self.distance))
    @condition([], ['meters'])
    def read_measurement(self):
        value = calvinsys.read(self.distance)
        return (value,)

    @stateguard(lambda self: calvinsys.can_read(self.timer) and calvinsys.can_write(self.distance))
    @condition([], [])
    def start_measurement(self):
        calvinsys.read(self.timer)
        calvinsys.write(self.distance, True)

    action_priority = (read_measurement, start_measurement)
    requires = ['io.distance', 'sys.timer.repeating']

    test_kwargs = {'period': 10}
    test_calvinsys = {'io.distance': {'read': [10, 12, 0, 5],
                                      'write': [True]},
                      'sys.timer.repeating': {'read': ['dummy'],
                                              'write': [10]}}
    test_set = [
        {
            'outports': {'meters': [10, 12, 0, 5]}
        }
    ]


import requests
from lxml import etree
import os
import random

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

url = 'https://www.moer.cn/'

def getthis():
    page_text = requests.get(url=url,headers=headers).text
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//*[@id="feedList"]/li')
    # print(li_list)
    data = []
    for li in li_list:
        title = li.xpath('.//a/text()')[0]
        zhaiyao = li.xpath('./div[1]/p/span/text()')
        author = li.xpath('./div[2]/div[1]/a[2]/text() | ./div[2]/div[1]/a[1]/text()')
        detial_url = li.xpath('./div[1]/a/@href')
        fp=open('摩尔金融数据.json','w')
        for one_url in  detial_url:
            # print('正在采集'+one_url)
            #获取文章ID
            article_id = int(str(one_url).split('=')[-1])
            #浏览量是动态数据
            watched_url = f'https://www.moer.cn/articleCountAndStatus.json?articleId={article_id}'
            watched = requests.get(url=watched_url, headers=headers).json()
            watched_count = watched['result']['authorArticle_browseCount']
            #详情页页面
            detail_page_text = requests.get(url=one_url,headers=headers).text
            one_tree = etree.HTML(detail_page_text)
            #发布时间
            send_time = one_tree.xpath('/html/body/div[1]/div[1]/article/section[1]/p/span[1]/text()')
            #评论数量
            issuce = one_tree.xpath('/html/body/div[1]/div[1]/div[2]/div[2]/ul/li[2]/a/text()')
            #点赞数量
            dianzan = one_tree.xpath('/html/body/div[1]/div[1]/div[2]/div[2]/a/b/text()')
            #构造字典数据结构
            dic2 = {
                '标题':title.rsplit('\n')[0],
                '摘要': zhaiyao[0],
                '作者': author[0],
                '浏览量': str(watched_count),
                 }
            #每循环一次，向字典中添加dic2
            data.append(dic2)
            import json
            # fileobj = json.dumps(data,ensure_ascii=False)
            # fp.write(fileobj)
            # print(dic2,'\n'+'采集成功')
            new_data = json.dumps(data)
            return new_data

爬虫/针对摩尔金融网数据采集.py

针对摩尔金融网数据采集.py


import sys
import ctypes
import re
import unidecode

from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import uic

qtCreatorFile = "GUI.ui"

Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)

alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
m = len(alpha)

def keyControl(keyA, keyB):
    if (keyA == 0):
        return ctypes.windll.user32.MessageBoxW(0, "Kľúč A sa nesmie rovnať 0", "CHYBA", 0)
    if (keyB == 0):
        return ctypes.windll.user32.MessageBoxW(0, "Kľúč B sa nesmie rovnať 0", "CHYBA", 0)
    if (keyA > keyB):
        return ctypes.windll.user32.MessageBoxW(0, "Kľúč A nesmie byť väčší ako kľúč B", "CHYBA", 0)

def euclid(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
    gcd = b
    return gcd, x, y

def mmi(a, m):
    gcd, x, y = euclid(a, m)
    if gcd != 1:
        return ctypes.windll.user32.MessageBoxW(0, "není možné nájsť MMI", "CHYBA", 0)
    else:
        return x % m

def removeDiacritics(text):
    text = unidecode.unidecode(text)
    return text

def removeSpecialChars(text):
    text = numbersCipher(text)
    text = removeDiacritics(text)
    text = re.sub('[^A-Za-z ]+', '', text)
    return text

def numbersCipher(text):
    text = text.replace('0', 'XQW')
    text = text.replace('1', 'XWQ')
    text = text.replace('2', 'QWX')
    text = text.replace('3', 'QWY')
    text = text.replace('4', 'YQW')
    text = text.replace('5', 'WQY')
    text = text.replace('6', 'XWT')
    text = text.replace('7', 'TWX')
    text = text.replace('8', 'WXT')
    text = text.replace('9', 'XQV')
    return text

def numbersDecipher(text):
    text = text.replace('XQW', '0')
    text = text.replace('XWQ', '1')
    text = text.replace('QWX', '2')
    text = text.replace('QWY', '3')
    text = text.replace('YQW', '4')
    text = text.replace('WQY', '5')
    text = text.replace('XWT', '6')
    text = text.replace('TWX', '7')
    text = text.replace('WXT', '8')
    text = text.replace('XQV', '9')
    return text

def splitAt(w,n):
    for i in range(0,len(w),n):
        yield w[i:i+n]

class GUI(QMainWindow, Ui_MainWindow):
    def cipher(self):

        keyA = int(self.keyA.text())
        keyB = int(self.keyB.text())
        keyControl(keyA, keyB)
        text = removeSpecialChars(self.cipherText.toPlainText())
        result = ''.join([ chr((( keyA*(ord(t) - ord('A')) + keyB ) % m)
                + ord('A')) for t in text.upper().replace(' ', 'XMEDZERAX') ])

        result = " ".join(splitAt(result, 5))
        self.cipherResult.setPlainText(str(result))

    def decipher(self):
        keyA = int(self.keyA.text())
        keyB = int(self.keyB.text())
        keyControl(keyA, keyB)
        cipher = numbersDecipher(self.decipherText.toPlainText())
        cipher = cipher.replace(' ', '')
        result = ''.join([ chr(((mmi(keyA, m)*(ord(c) - ord('A') - keyB)) % m)
                  + ord('A')) for c in cipher])
        result = result.replace('XMEDZERAX', ' ')
        self.decipherResult.setPlainText(str(numbersDecipher(result)))

    def __init__(self):
        QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.cipherButton.clicked.connect(self.cipher)
        self.decipherButton.clicked.connect(self.decipher)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = GUI()
    window.show()
    sys.exit(app.exec_())


import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1 import ImageGrid
import os
import torch
import torchvision

# custom weights initialization called on netG and netD
def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        m.weight.data.normal_(0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        m.weight.data.normal_(1.0, 0.02)
        m.bias.data.fill_(0)

# compute the current classification accuracy
def compute_acc(preds, labels):
    correct = 0
    preds_ = preds.data.max(1)[1]
    correct = preds_.eq(labels.data).cpu().sum()
    acc = float(correct) / float(len(labels.data)) * 100.0
    return acc

def sample_image(netG, encoder, batch_size, n_row, batches_done, dataloader, opt):
    """Saves a grid of generated imagenet pictures with captions"""
    target_dir = os.path.join(opt.output_dir, "samples/")
    if not os.path.isdir(target_dir):
        os.makedirs(target_dir)

    device = "cpu"
    if opt.cuda:
        device = "cuda"

    captions = []
    gen_imgs = []
    # get sample captions
    done = False
    while not done:
        for (_, labels_batch, captions_batch) in dataloader:

            eval_noise_ = np.random.normal(0, 1, (batch_size, opt.nz))

            captions += captions_batch
            conditional_embeddings = encoder(labels_batch.to(device), captions_batch)

            embeddings = conditional_embeddings.detach().numpy()
            eval_noise_[np.arange(batch_size), :opt.embed_size] = embeddings[:, :opt.embed_size]
            eval_noise_ = (torch.from_numpy(eval_noise_))

            imgs = netG(eval_noise_.view(batch_size, opt.nz, 1, 1).float().to(device)).cpu()
            gen_imgs.append(imgs)

            if len(captions) > n_row ** 2:
                done = True
                break

    gen_imgs = torch.cat(gen_imgs).detach().numpy()
    gen_imgs = np.clip(gen_imgs, 0, 1)

    fig = plt.figure(figsize=((8, 8)))
    grid = ImageGrid(fig, 111, nrows_ncols=(n_row, n_row), axes_pad=0.2)

    for i in range(n_row ** 2):
        grid[i].imshow(gen_imgs[i].transpose([1, 2, 0]))
        grid[i].set_title(captions[i], fontsize=6)
        grid[i].tick_params(axis='both', which='both', bottom=False, top=False, left=False, right=False, labelbottom=False, labelleft=False)

    save_file = os.path.join(target_dir, "{:013d}.png".format(batches_done))
    plt.savefig(save_file)
    print("saved  {}".format(save_file))
    plt.close()

def sample_image2(netG, encoder, target_n_samples, batch_size, dataloader, opt):
    """Saves a grid of generated imagenet pictures with captions"""
    target_ori_dir = os.path.join(opt.output_dir, "samples_ori/image/")
    target_gen_dir = os.path.join(opt.output_dir, "samples_gen/image/")
    if not os.path.isdir(target_ori_dir):
        os.makedirs(target_ori_dir)
    if not os.path.isdir(target_gen_dir):
        os.makedirs(target_gen_dir)

    device = "cpu"
    if opt.cuda:
        device = "cuda"

    gen_imgs = []
    ori_imgs = []
    n_samples = 0
    done = False
    while not done:
        for (ori_img_batch, labels_batch, captions_batch) in dataloader:
        #for (ori_img_batch, captions_batch) in dataloader:

            eval_noise_ = np.random.normal(0, 1, (batch_size, opt.nz))

            conditional_embeddings = encoder(labels_batch.to(device), captions_batch)
            #print(ori_img_batch.size())
            #print(len(captions_batch))
            #print(captions[0].size())
            #conditional_embeddings = encoder(None, captions_batch[0])

            #print(conditional_embeddings.size())
            #print((batch_size, opt.nz))
            embeddings = conditional_embeddings.detach().numpy()
            eval_noise_[np.arange(batch_size), :opt.embed_size] = embeddings[:, :opt.embed_size]
            eval_noise_ = (torch.from_numpy(eval_noise_))

            gen_img_batch = netG(eval_noise_.view(batch_size, opt.nz, 1, 1).float().to(device)).cpu()
            ori_imgs.append(ori_img_batch)
            gen_imgs.append(gen_img_batch)

            n_samples += batch_size
            if n_samples >= target_n_samples:
                done = True
                break

    ori_imgs = torch.cat(ori_imgs)
    ori_imgs = torch.clamp(ori_imgs, 0, 1)

    gen_imgs = torch.cat(gen_imgs)
    gen_imgs = torch.clamp(gen_imgs, 0, 1)

    for idx, img in enumerate(ori_imgs):
        torchvision.utils.save_image(img, target_ori_dir+'ori_img'+str(idx)+'.png')

    for idx, img in enumerate(gen_imgs):
        torchvision.utils.save_image(img, target_gen_dir+'gen_img'+str(idx)+'.png')

def sample_final_image(netG, encoder, target_n_samples, batch_size, dataloader, opt):
    """Saves a set of generated imagenet pictures as individual files"""
    target_dir = os.path.join(opt.output_dir, "samples_final/")
    if not os.path.isdir(target_dir):
        os.makedirs(target_dir)

    device = "cpu"
    if opt.cuda:
        device = "cuda"
    print("INFO: device is: " + device)

    gen_imgs = []

    done = False
    n_samples = 0
    while not done:
        for (_, labels_batch, captions_batch) in dataloader:

            eval_noise_ = np.random.normal(0, 1, (batch_size, opt.nz))

            conditional_embeddings = encoder(labels_batch.to(device), captions_batch)

            embeddings = conditional_embeddings.detach().numpy()
            eval_noise_[np.arange(batch_size), :opt.embed_size] = embeddings[:, :opt.embed_size]
            eval_noise_ = (torch.from_numpy(eval_noise_))

            imgs = netG(eval_noise_.view(batch_size, opt.nz, 1, 1).float().to(device)).cpu()
            gen_imgs.append(imgs)

            n_samples += batch_size
            if n_samples >= target_n_samples:
                done = True
                break

    gen_imgs = torch.cat(gen_imgs)
    gen_imgs = torch.clamp(gen_imgs, 0, 1)

    for idx, img in enumerate(gen_imgs):
        torchvision.utils.save_image(img, target_dir+'img'+str(idx)+'.png')


import pyautogui
pyautogui.PAUSE = 1
# pyautogui.keyDown('ctrl')
# pyautogui.keyDown('g')
# pyautogui.keyUp('ctrl')
# pyautogui.keyUp('g')

cont = 1
pyautogui.hotkey('alt', 'f2')
while cont < 15:
    pyautogui.typewrite ('EU ESTOU PUTO COM VC')
    pyautogui.press('enter')
    cont += 1

# pyautogui.typewrite('')
# pyautogui.press('enter')

#
# sgf


import time

nums = []
seen = set()

def get_chain_len(n, l):
  global seen
  if n in seen:
    return (0, 0)
  cur = []
  i = n
  broke = False
  leno = 0
  small = 0
  while i not in cur:
    cur.append(i)
    i = nums[i]
    if i > 1000000 or i in seen:
      broke = True
      break
  if not broke:
    ind =  cur.index(i)
    if len(cur) - ind > l:
      small = min(cur[ind:])
      leno = len(cur) - ind
  for el in cur:
    seen.add(el)
  return (leno, small)

def gen_facts_sums(lim):
  r_list = [0]*(lim+1)
  for i in range(1, (lim//2)+1):
    for j in range(2*i, lim+1, i):
      r_list[j] += i
  return r_list

def sol1(lim):
  global nums
  nums = gen_facts_sums(lim)
  longest = 0
  smallest = 1000000000
  for i in range(2, lim + 1):
    leno, sml = get_chain_len(i, longest)
    if leno > longest:
      longest = leno
      smallest = sml
  print('smallest number of the longest ami chain below {} is {}'.format(lim, smallest))

def main():
  lim = 1000000
  a = time.clock()
  sol1(lim)
  b = time.clock()
  print('time taken is {:f}'.format(b-a))

main()


# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import datetime

import pytest

from oas.exceptions import ValidationError
from oas.schema.formats import Formats
from oas.schema.unmarshalers import SchemaUnmarshaler

def test_unmarshal_validation_error():
    schema = {'type': str('string')}
    instance = 123
    message = "123 is not of type 'string'"

    with pytest.raises(ValidationError) as exc_info:
        SchemaUnmarshaler().unmarshal(instance, schema)
    assert exc_info.value.errors[0].message == message

@pytest.mark.parametrize(
    'schema,instance',
    [
        ({'type': 'boolean'}, True),
        ({'type': 'boolean'}, False),
        ({'type': 'number'}, 0.0),
        ({'type': 'number'}, 2.0),
        ({'type': 'integer'}, 0),
        ({'type': 'integer'}, 2),
        ({'type': 'string'}, 'foo'),
    ],
)
def test_unmarshal_primitive(schema, instance):
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == instance

def test_unmarshal_primitive_format():
    schema = {'type': 'string', 'format': 'date'}
    instance = '2018-01-02'
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == datetime.date(2018, 1, 2)

def test_unmarshal_primitive_without_formats():
    schema = {'type': 'string', 'format': 'date'}
    instance = '2018-01-02'
    unmarshaled = SchemaUnmarshaler(formats=Formats()).unmarshal(
        instance, schema
    )
    assert unmarshaled == instance

def test_unmarshal_primitive_enum():
    schema = {'type': 'string', 'enum': ['a', 'b']}
    instance = 'a'
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == 'a'

def test_unmarshal_array():
    schema = {'type': 'array', 'items': {'type': 'string', 'format': 'date'}}
    instance = ['2018-01-02', '2018-02-03', '2018-03-04']
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == [
        datetime.date(2018, 1, 2),
        datetime.date(2018, 2, 3),
        datetime.date(2018, 3, 4),
    ]

def test_unmarshal_object():
    schema = {
        'type': 'object',
        'properties': {
            'id': {'type': 'integer'},
            'date': {'type': 'string', 'format': 'date'},
            'date-default': {
                'type': 'string',
                'format': 'date',
                'default': '2020-01-01',
            },
        },
    }
    instance = {'date': '2018-01-02'}
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == {
        'date': datetime.date(2018, 1, 2),
        'date-default': datetime.date(2020, 1, 1),
    }

@pytest.mark.parametrize(
    'properties,additional_properties,instance,expected',
    [
        (
            None,
            None,
            {'x': 'foo', 'y': '2020-01-02'},
            {'x': 'foo', 'y': '2020-01-02'},
        ),
        (
            None,
            True,
            {'x': 'foo', 'y': '2020-01-02'},
            {'x': 'foo', 'y': '2020-01-02'},
        ),
        (
            None,
            {},
            {'x': 'foo', 'y': '2020-01-02'},
            {'x': 'foo', 'y': '2020-01-02'},
        ),
        (
            None,
            {'type': 'string', 'format': 'date'},
            {'y': '2020-01-02'},
            {'y': datetime.date(2020, 1, 2)},
        ),
        (
            {'x': {'type': 'string'}},
            None,
            {'x': 'foo', 'y': '2020-01-02'},
            {'x': 'foo', 'y': '2020-01-02'},
        ),
        (
            {'x': {'type': 'string'}},
            True,
            {'x': 'foo', 'y': '2020-01-02'},
            {'x': 'foo', 'y': '2020-01-02'},
        ),
        ({'x': {'type': 'string'}}, False, {'x': 'foo'}, {'x': 'foo'}),
        (
            {'x': {'type': 'string'}},
            {'type': 'string', 'format': 'date'},
            {'x': 'foo', 'y': '2020-01-02'},
            {'x': 'foo', 'y': datetime.date(2020, 1, 2)},
        ),
    ],
)
def test_unmarshal_object_properties_and_additional_properties(
    properties, additional_properties, instance, expected
):
    schema = {'type': 'object'}
    if properties is not None:
        schema['properties'] = properties
    if additional_properties is not None:
        schema['additionalProperties'] = additional_properties

    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == expected

def test_unmarshal_all_of():
    schema = {
        'allOf': [
            {
                'type': 'object',
                'properties': {'from': {'type': 'string', 'format': 'date'}},
            },
            {'type': 'object', 'properties': {'from': {'type': 'string'}}},
            {'type': 'object', 'properties': {'to': {'type': 'string'}}},
            {
                'type': 'object',
                'properties': {'to': {'type': 'string', 'format': 'date'}},
            },
        ]
    }
    instance = {'from': '2018-01-02', 'to': '2018-01-03'}
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == {
        'from': datetime.date(2018, 1, 2),
        'to': datetime.date(2018, 1, 3),
    }

def test_unmarshal_all_of_required_only():
    schema = {
        'allOf': [
            {'type': 'object', 'properties': {'id': {'type': 'integer'}}},
            {'type': 'object', 'required': [str('id')]},
        ]
    }
    instance = {}
    with pytest.raises(ValidationError) as exc_info:
        SchemaUnmarshaler().unmarshal(instance, schema)
    assert exc_info.value.errors[0].message == "'id' is a required property"

def test_unmarshal_all_of_array():
    schema = {
        'allOf': [
            {'type': 'array', 'items': {'type': 'number'}},
            {'type': 'array', 'items': {'type': 'integer'}},
        ]
    }
    instance = [1, 2]
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == instance

def test_unmarshal_all_of_array_min_items():
    schema = {
        'allOf': [
            {'type': 'array', 'items': {'type': 'number'}},
            {'type': 'array', 'items': {}, 'minItems': 2},
        ]
    }
    instance = [1]
    with pytest.raises(ValidationError) as exc_info:
        SchemaUnmarshaler().unmarshal(instance, schema)
    assert exc_info.value.errors[0].message == '[1] is too short'

def test_unmarshal_all_of_primitive_number_integer():
    schema = {'allOf': [{'type': 'number'}, {'type': 'integer'}]}
    instance = 1
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == instance

def test_unmarshal_all_of_primitive_string_pattern():
    schema = {
        'allOf': [
            {'type': 'string'},
            {'type': 'string', 'pattern': '^[a-z]+$'},
        ]
    }
    instance = 'abc'
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == instance

def test_unmarshal_all_of_primitive_string_enum():
    schema = {
        'allOf': [{'type': 'string'}, {'type': 'string', 'enum': ['a', 'b']}]
    }
    instance = 'a'
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == instance

@pytest.mark.parametrize('schema_type', ['oneOf', 'anyOf'])
def test_unmarshal_one_of_or_any_of(schema_type):
    schema = {
        schema_type: [
            {'type': 'integer'},
            {'type': 'string', 'format': 'date'},
        ]
    }
    instance = '2018-01-02'
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled == datetime.date(2018, 1, 2)

@pytest.mark.parametrize(
    'schema',
    [
        {'type': 'string', 'nullable': True},
        {'type': 'array', 'nullable': True},
        {'type': 'object', 'nullable': True},
        {'type': 'string', 'format': 'date', 'nullable': True},
        {'type': 'string', 'enum': ['a', 'b'], 'nullable': True},
    ],
)
def test_unmarshal_nullable(schema):
    instance = None
    unmarshaled = SchemaUnmarshaler().unmarshal(instance, schema)
    assert unmarshaled is None


# 846. Hand of Straights
# Same as 1296

# Array / Ordered Map

# running time: faster than 23.49%
class Solution1:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        cnt = collections.Counter(hand)

        while cnt:
            m = min(cnt)
            for k in range(m, m+W):
                v = cnt[k]
                if not v:
                    return False
                if v == 1:
                    del cnt[k]
                else:
                    cnt[k] -= 1

        return True

# https://blog.csdn.net/fuxuemingzhu/article/details/82530857
# Same as solution1, but with sorting
# running time: faster than 98.19%
class Solution2:
    def isNStraightHand(self, hand: List[int], W: int) -> bool:
        cnt = collections.Counter(hand)
        for i in sorted(cnt):
            if cnt[i] > 0:
                for j in range(W)[::-1]:
                    if i + j not in cnt:
                        return False
                    cnt[i+j] -= cnt[i]
                    if cnt[i+j] < 0:
                        return False
        return True


'''

Receive a number between 0 and 1,000,000,000 from the user.
Use while loop to find the number - when the number is found exit the loop and print the number to the console.

'''

i = int(input("Give me a number between 0 and 1,000,000,000: "))

n = 0
while n < 1000000000:
    if n != i:
        n += 1
    else:
        print(n)
        break


# 그리디 알고리즘 기출문제 Q2. 곱하기 혹은 더하기

# 문자열 입력 받기
s = input()

# 결과를 문자열의 첫번째 숫자로 초기화
res = int(s[0])

# 숫자 하나씩 확인
for i in range(1, len(s)):

    # 문자열의 숫자 저장
    n = int(s[i])

    # 곱하거나 더한 수 중, 큰 값 저장
    res = max(res * n, res + n)

print(res)

Book-이것이코테다/1. 그리디/Q2. 곱하기 혹은 더하기.py

Q2. 곱하기 혹은 더하기.py


import check_objectives
from . import BaseState
from entities import Ball
from pyxit.vec import Vec

class BallAnimationState(BaseState):
    def __init__(self, game, pushing):
        super(BallAnimationState, self).__init__(game)
        self.pushing = pushing

    def enter(self):
        create = self.game.animation.create
        a = create(300, self.shake_current_row, self.end_shake)
        a = a.chain(300, None)
        a = a.chain(300, self.move_falling_ball,
                    self.change_to_check_condition_state)

    def shake_current_row(self, percent):
        import math

        balls = self.game.model_matcher.get_current_row_balls()

        for e in self.game.entities:
            if isinstance(e, Ball) and e.ref in balls:
                if e.old_pos_x is None:
                    e.old_pos_x = e.pos.x
                e.pos.x = e.old_pos_x + math.sin(percent * 100) * 3

    def end_shake(self):
        moving_ball = self.game.model_matcher.sniffer.get_ball_from_table()
        bs = []
        mb = None
        for e in self.game.entities:
            if isinstance(e, Ball):
                if e.ref != moving_ball:
                    if e.old_pos_x is not None:
                        e.old_pos_x = None
                        bs.append(e)
                else:
                    e.old_pos_x = None
                    mb = e

        self.game.model_matcher.update_ball_positions(bs)

        if self.game.model.currently_left:
            is_left = True
        else:
            is_left = False
        if self.pushing:
            is_left = not is_left

        if is_left:
            h_pos = 16 * 5
        else:
            h_pos = 16 * 15

        mb.move(Vec(h_pos,
                    mb.pos.y))

    def move_falling_ball(self, percent):
        pass

    def change_to_check_condition_state(self):
        s = check_objectives.CheckObjectivesState(self.game)
        self.game.state_machine.change_state(s)


# Quick example showing how to translate a QUBO matrix into
# D-Wave code.
#
# The matrix in this problem is of the format
#
# | -5  2   4  0 |
# | 2  -3   1  0 |
# | 4   1  -8  5 |
# | 0   0   5 -6 |
#
# and encodes the optimization of the quadratic -5x1 + -3x2 + -8x3 + -6x4 + 4x1x2 + 8x1x3 + 2x2x3 + 10x3x4
# as described at https://arxiv.org/pdf/1811.11538.pdf

from dwave_qbsolv import *

q = {
        (0,0): -5,
        (1,1): -3,
        (2,2): -8,
        (3,3): -6,
        (0,1): 4,
        (0,2): 8,
        (1,2): 2,
        (2,3): 10
    }
response = QBSolv().sample_qubo(q)
print(response)


import requests
from pandas import json_normalize
import pandas as pd

def baseline(years_selected, config):
    """
    Fetches baseline data for a given year from the FDRS API.
    """
    try:
        code = requests.get(f"{config['BASE_URL']}entities/ns/?apiKey={config['API_KEY_PUBLIC']}").json()
        df_code = json_normalize(data=code)[["KPI_DON_code", "NSO_DON_name", "NSO_ZON_name", "iso_3"]]

        dfs = [df_code.assign(KPI_Year=float(year)) for year in years_selected]
        df_baseline = pd.concat(dfs, ignore_index=True)
        df_baseline["KPI ID"] = df_baseline["KPI_DON_code"] + df_baseline["KPI_Year"].astype(str)

        return df_baseline
    except requests.RequestException as e:
        print(f"Error fetching baseline data: {e}")
        return pd.DataFrame()

def fetch_data(years, kpi_code, config, endpoint):
    df_temp = pd.DataFrame()
    df = pd.DataFrame()

    for kpi_codes in kpi_code:
        for year in years:
            try:
                url = f"{config['BASE_URL']}{endpoint}?kpicode={kpi_codes}&year={year}&apiKey={config['API_KEY_PUBLIC']}&showunpublished=true"
                results = requests.get(url).json()
                df_temp = json_normalize(data=results).assign(KPI_Year=float(year), KPI_Code=kpi_codes)
                df = df._append(df_temp, ignore_index=True)
            except requests.RequestException as e:
                print(f"Error fetching data for {kpi_codes} in {year}: {e}")

    return df

def pivot_data(df, df_baseline):
    df_pivoted = df.pivot_table(index=['doncode', 'KPI_Year'], columns='KPI_Code', values='value', aggfunc='first').reset_index()

    # Convert specific columns to float
    for col in df_pivoted.columns:
        if col not in ['doncode']:
            df_pivoted[col] = df_pivoted[col].astype(float, errors='ignore')

    df_final = df_baseline.merge(df_pivoted, left_on=["KPI_DON_code", "KPI_Year"], right_on=["doncode", "KPI_Year"], how="outer")
    return df_final.drop("doncode", axis=1)

def api_function(years, kpi_code, config):
    df_data = fetch_data(years, kpi_code, config, 'KpiValue')
    df_baseline = baseline(years, config)
    return pivot_data(df_data, df_baseline)

def api_function_imputed(years, kpi_code, config):
    df_data = fetch_data(years, kpi_code, config, 'KpiImputedValue')
    df_baseline = baseline(years, config)
    return pivot_data(df_data, df_baseline)


import numpy as np
import importlib
import pandas as pd
import os
import  subprocess
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

data = pd.read_csv("Results_500.csv")

boolList = list()
for i in range(data.shape[0]):
    if (data["Problem"])[i] in ["prob1", "prob2", "prob3", "prob4", "prob5"]:
        boolList.append(True)
    else:
        boolList.append(False)

data = data[boolList]

data = data.reset_index()

new_data = pd.DataFrame(columns=["Problem", "Nb_Features", "Taken_Feat_Ratio", "Test_accuracy", "Model", "Algo"])

previous = "prob4"
i = 0

while i < len(data["Problem"]):
    best = dict()
    current = -float("inf")
    while (data["Problem"])[i] == previous:
        previous = (data["Problem"])[i]
        if (data["Test Accuracy"])[i] > current and (data["Technique"])[i] != "ga2":
            current = (data["Test Accuracy"])[i]
            cntFeat = 0
            cntTaken = 0
            for j in data.columns:
                if "feature_" in j:
                    if (data[j])[i] == 0.0:
                        cntFeat = cntFeat + 1
                    elif (data[j])[i] == 1.0:
                        cntFeat = cntFeat + 1
                        cntTaken = cntTaken + 1
            best = {"Problem":(data["Problem"])[i], "Nb_Features": cntFeat, "Taken_Feat_Ratio": cntTaken/cntFeat,
                "Test_accuracy":(data["Test Accuracy"])[i] , "Model": (data["model"])[i], "Algo": (data["Technique"])[i]}
        i = i + 1
        if i >= len(data["Problem"]):
            break

    if i < data.shape[0]:
        previous = (data["Problem"])[i]
    print(best)
    new_data = new_data.append(best, ignore_index=True)

print(new_data)

frequences = pd.DataFrame(data=0,columns=["ambs", "tpe", "ga1", "pso1", "Models Frequencies"], index=["randomForestRegressor", "kneighborsRegressor", "nnRegressor", "Methods Frequencies"])
print(frequences)

k = 0
for i in new_data["Algo"]:
    j = new_data["Model"][k]
    frequences.loc[j , i] = frequences.loc[j , i] + 1
    k = k + 1

sum = np.zeros((len(frequences["ambs"])))
for i in range(len(frequences.loc["randomForestRegressor", :])):
    sum = frequences.iloc[:, i] + sum

frequences["Models Frequencies"] = sum

sum = np.zeros((len(frequences.loc["randomForestRegressor", :])))
for i in range(len(frequences.loc[:, "ambs"])):
    sum = frequences.iloc[i, :] + sum

frequences.loc["Methods Frequencies", :] = sum

frequences = frequences/len(new_data)

frequences.to_csv("frequenciesReg.csv")
"""

print(new_data["Nb_Features"].drop(19))

plt.scatter(new_data["Taken_Feat_Ratio"], new_data["Test_accuracy"])
plt.xlabel("Leprechauns")
plt.ylabel("Gold")
plt.legend(loc='upper left')
plt.show()
plt.savefig('scatter')

colors = ["c","red","green","blue"]
algo = ["ambs", "tpe", "ga1", "pso1"]

ambsD =

for i in new_data["Algo"]:
    c.append(colors[algo.index(i)])

fig, ax = plt.subplots()

k = 0
for color in c:
    ax.scatter(new_data["Taken_Feat_Ratio"][k], new_data["Test_accuracy"][k], c=color,  label=new_data["Algo"][k])
    k = k + 1

ax.legend()
plt.savefig('scatter')
"""


from django import forms
from projects.models import Project

class FilesForm(forms.ModelForm):
	class Meta:
		model = Project
		fields = ['img','anexo']
		labels = {
		'img':'Imagen, relacionada al proyecto (opcional)',
		'anexo':'¿Tienes algún archivo que complemente el proyecto?'
		}


# Given an n-ary tree, return the postorder traversal of its nodes' values.

# For example, given a 3-ary tree:

#             1
#     3       2       4

# 5       6

# Return its postorder traversal as: [5,6,3,2,4,1].

# Definition for a Node.
class Node(object):
    def __init__(self, val, children):
        self.val = val
        self.children = children

class Solution(object):
    def postorder(self, root):
        """
        :type root: Node
        :rtype: List[int]
        """
        #if(root is None):
         #   return
        if(len(root.children)==0):
            return [root.val]
        else:
            result=[]

            for i in root.children:
                #print(root.val)
                result =result+ (self.postorder(i))
            result.append(root.val)
            return result

def createRoot(data):
    # Read data of children and val
    # Call Create root for each children

    val=data["val"]
    children=[]
    for item in data["children"]:
        children.append(createRoot(item))
    return Node(val,children)

s=Solution()
#print(s.postorder(None))
a=createRoot({"$id":"1",
"children":[
    {"$id":"2","children":[
        {"$id":"5","children":[],"val":5},
        {"$id":"6","children":[],"val":6}],
        "val":3},
    {"$id":"3","children":[],"val":2},
    {"$id":"4","children":[],"val":4}
    ],
"val":1})
print(s.postorder(a))


from django.shortcuts import render
import json
from urllib import parse
import urllib.request, urllib.parse
from god.forms import fanyiForm

# Create your views here.
def youdaofanyi(request):
    '''
    有道翻译功能
    '''

    query = {}  # 定义需要翻译的文本
    fanyi = request.POST.get('fanyi_content', '')
    query['q'] = fanyi  # 输入要翻译的文本
    url = 'http://fanyi.youdao.com/openapi.do?keyfrom=11pegasus11&key=273646050&type=data&doctype=json&version=1.1&' + parse.urlencode(
        query)  # 有道翻译api
    response = urllib.request.urlopen(url, timeout=5)
    # 编码转换
    try:
        html = response.read().decode('utf-8')
        d = json.loads(html)
        explains = d.get('basic').get('explains')  # 翻译后输出
        a1 = d.get('basic').get('uk-phonetic')  # 英式发音
        a2 = d.get('basic').get('us-phonetic')  # 美式发音
        explains_list = []
        for result in explains:
            explains_list.append(result)
        # 输出
        fanyi_dict = {
            'q': query['q'],
            'yinshi': a1,
            'meishi': a2,
            'explains_list': set(explains_list + d['translation']),
        }
        return fanyi_dict
    except Exception:
        try:
            fanyi_dict = {
                'q': query['q'],
                'explains_list': d['translation'],
            }
            return fanyi_dict
        except Exception as e:
            print(e)

def listblogs(request):
    '''
    翻译页面
    :param request:
    :return:
    '''
    fanyi_dict = {}
    fanyi_form = fanyiForm()
    if request.method == 'POST':
        fanyi_form = fanyiForm(request.POST)
        if fanyi_form.is_valid():
            fanyi_dict = youdaofanyi(request)

    bloglist = {
        'fanyi_form': fanyi_form,  # 翻译的表单
        'fanyi_dict': fanyi_dict,  # 翻译出来的文本
    }
    return render(request, 'fanyi.html', bloglist)


#import http.client
import httplib
from time import sleep, localtime, strftime
import sys

ARDUINO_NOT_READY = -9999

ip_addr = '192.168.1.182'
port = 80
timeout = 5
retry = 5

def main():
	while 1:
		temp = getArduinoTemp(ip_addr, port, timeout, retry)
		if (temp != None):
			print (strftime("[%H:%M:%S]: ", localtime()) + "Arduino Temp\t" + str(temp))

		sleep(5)

def getArduinoTemp(ip_addr, port, timeout, retry):
	for i in range(retry):
		try:
			#conn = http.client.HTTPConnection(ip_addr, port, timeout)
			conn = httplib.HTTPConnection(ip_addr, port, timeout)
			conn.request("GET", "/temp")
			conn.sock.settimeout(timeout)
			r1 = conn.getresponse()
			if (r1.status == 200):
				lines = r1.read()
				line = lines.split('\n')
				temp = None
				if (len(lines.split()) == 3):
					temp = float(line[2])
				if (temp == ARDUINO_NOT_READY):
					temp = None
				else:
					break
			else:
				print (r1.status, r1.reason)
				temp = None

		except:
			print (strftime("[%H:%M:%S]: EXCEPTION ", localtime()) + str(sys.exc_info()[0]))
			temp = None
			sleep(2)	#wait for device to get ready again

	conn.close()

	return temp

if __name__ == "__main__":
	main()


#!/usr/bin/env python3
#அச்சிடு வரையறு - பின் வரும் நிரல்களில் அச்சிடு பயன்படுத்தலாம்.
def அச்சிடு(*வாதங்கள்,பிரி=" ",முடி='\n',கோப்பு=None,பறிப்பு=False):
    print(*வாதங்கள், sep=பிரி,end=முடி, file=கோப்பு,flush=பறிப்பு)

# உள்ளீடு வரையறு - பின் வரும் நிரல்களில் அச்சிடு பயன்படுத்தலாம்.
def உள்ளீடு(*வாதங்கள்):
    அ = input (*வாதங்கள்)
    return அ

import sqlite3

def முதன்மை ():
    அச்சிடு('connect')
    db = sqlite3.connect('db-api.db')
    cur = db.cursor()
    அச்சிடு('create')
    cur.execute("DROP TABLE IF EXISTS test")
    cur.execute("""
        CREATE TABLE test (
            id INTEGER PRIMARY KEY, string TEXT, number INTEGER
        )
        """)
    அச்சிடு('insert row')
    cur.execute("""
        INSERT INTO test (string, number) VALUES ('one', 1)
        """)
    அச்சிடு('insert row')
    cur.execute("""
        INSERT INTO test (string, number) VALUES ('two', 2)
        """)
    அச்சிடு('insert row')
    cur.execute("""
        INSERT INTO test (string, number) VALUES ('three', 3)
        """)
    அச்சிடு('commit')
    db.commit()
    அச்சிடு('count')
    cur.execute("SELECT COUNT(*) FROM test")
    count = cur.fetchone()[0]
    அச்சிடு(f'there are {count} rows in the table.')
    அச்சிடு('read')
    for row in cur.execute("SELECT * FROM test"):
        அச்சிடு(row)
    அச்சிடு('drop')
    cur.execute("DROP TABLE test")
    அச்சிடு('close')
    db.close()

if __name__ == '__main__': முதன்மை ()


cmd = input().split('-')
contacts = {}

while len(cmd)>1:
    contacts[cmd[0]] = cmd[1]
    cmd = input().split('-')

cmd = int(cmd[0])

for _ in range(cmd):
    lookup = input()
    if lookup not in contacts.keys():
        print(f'Contact {lookup} does not exist.')
    else:
        print(f'{lookup} -> {contacts[lookup]}')