# -*- coding: utf-8 -*-
"""
Created on Wed Apr 22 01:53:45 2020
@author: undiv

This script will gather the latest available DoD R&D spending data for the 50 states
and District of Columbia. The data covers obligations (i.e. contract awards)
that occurred during FY18.

Note: A significant portion of DoD R&D spending is listed as "Undistributed"
in the dataset. This is a result of 1) classified research, and 2) legacy accounting
systems that simply do not provide geographic details for reporting to NSF.
In future years DoD hopes to minimize 'Undistributed' reporting, but for now
this is the best we can do.

Also, the data is from FY18. We would prefer FY19 spending, but these will not
be available until NSF publishes the next volume of its R&D Funds Survey.

We will eventually combine this data with GIS shapefiles to build a map of projected
DoD FY21 R&D spending (after applying a DoD multiplier).
"""
# import pandas as pd and numpy as np

import pandas as pd
import numpy as np

# Display Max Rows so you can see what you're getting as you go

pd.set_option('display.max_rows',None)

# Set up file names: the NSF URL with the .xlsx file,
# and the output file we will write the results into.
# The Excel file contains FY18 DoD geographical spending data.
# We will select data for the 50 states.

excelname = 'https://ncsesdata.nsf.gov/fedfunds/2018/excel/ffs18-dt-tab094.xlsx'
outname = 'DoD_FY18__RD_50_state.csv'

# Also import 'DoD_FY21_Multiplier.csv' and read with pd.read_csv()

dodmulti = 'DoD_FY21_Multiplier.csv'
dodmulti = pd.read_csv(dodmulti)

# Open the desired Excel file from the URL, which is Table 94.
# Read the Excel file using pd.read_excel() with arguments (xl,'Table 94',header=3)

xl = pd.ExcelFile(excelname)
xlf = pd.read_excel(xl,'Table 94', header=3)

# We only want two columns of data: "State or location and agency" and "Total".
# Trim the data to those columns using .iloc[].

trimmed = xlf.iloc[:,[0,1]]

# trim further to include only rows 1-253.

trimmed = trimmed.iloc[1:253]

# We only want the State and the R&D Total, but there are rows in between.
# The state names are in rows 1,6...251 alternating every 5 rows. The R&D Totals
# are in rows 2,7...252 alternating every five rows. Make a list for trimming.
# [If you know of a better way, by all means go for it.]

statelist = [
        1,2,6,7,11,12,16,17,21,22,26,27,31,32,36,37,41,42,46,47,51,52,56,57,61,
        62,66,67,71,72,76,77,81,82,86,87,91,92,96,97,101,102,106,107,111,112,116,
        117,121,122,126,127,131,132,136,137,141,142,146,147,151,152,156,157,161,
        162,166,167,171,172,176,177,181,182,186,187,191,192,196,197,201,202,206,
        207,211,212,216,217,221,222,226,227,231,232,236,237,241,242,246,247,251,252
        ]

# Use .loc[statelist] to trim the data frame.

trimmed = trimmed.loc[statelist]

# Now we need the value of every other row to be switched into the second column.
# Use pd.DataFrame(trimmed.Total.values.reshape(-1,2),columns=['State','Total']) to
# put the values where they should be. Set the Totals to integer datatype.

trimmed = pd.DataFrame(trimmed.Total.values.reshape(-1,2),columns=['State','Total'])
trimmed.Total = trimmed.Total.astype(int)

# This method produced the unintended consequence of replacing the States with
# null values. To resolve the problem, add a list of the States in alphabetical order
# just as in the NSF dataset.

statenames = ['Alabama', 'Alaska', 'Arizona', 'Arkansas',
              'California', 'Colorado', 'Connecticut', 'Delaware',
              'District of Columbia', 'Florida', 'Georgia', 'Hawaii', 'Idaho',
              'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana',
              'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
              'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada',
              'New Hampshire', 'New Jersey', 'New Mexico', 'New York',
              'North Carolina', 'North Dakota',
              'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania',
              'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee',
              'Texas', 'Utah', 'Vermont', 'Virginia',
              'Washington', 'West Virginia', 'Wisconsin', 'Wyoming']

# Replace the null values with the State names, using .drop() to remove the null
# values and replacing with the State names.

n = trimmed.columns[0]
trimmed.drop(n, axis = 1, inplace = True)
trimmed['State'] = statenames

# This method produced an unintended consequence of flipping the columns.
# "Total" is now column [0] and State is column [1].
# To resolve, switch the columns using .head()

trimmed = trimmed[['State','Total']]
trimmed.head()

# The values in the NSF dataset are in $K, so multiply the Totals by 1000
# using .apply(lambda x: x*1000)

trimmed['Total'] = trimmed['Total'].apply(lambda x: x*1000)

# Finally, use the same .apply() command to multiply the Totals by the
# DoD FY21 Multiplier, which is '1.2887570722688233'.
# Use .astype(np.int64) to set the result to integer datatype.
# Print the result.

trimmed['Total'] = trimmed['Total'].apply(lambda x: x*1.2887570722688233)

trimmed['Total'] = trimmed['Total'].astype(np.int64)
print(trimmed)

# Set the index to 'State' for ease of use later.

trimmed.set_index('State',inplace=True)

# Finally, send to the output file

trimmed.to_csv(outname)


import torch
import torch as th
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from scipy.signal import get_window
from torch.utils.tensorboard.writer import SummaryWriter

class GRUC(nn.Module):
    """
    GRU Model
    """

    def __init__(self, input_dim, hidden_dim, output_dim, n_layers, drop_prob=0.2):
        super(GRUC, self).__init__()
        self.hidden_dim = hidden_dim

        self.n_layers = n_layers

        self.gru = nn.GRU(
            input_size=input_dim,
            hidden_size=hidden_dim,
            num_layers=n_layers,
            batch_first=True,
            dropout=drop_prob
        )
        self.linear2 = nn.Linear(hidden_dim, output_dim)
        self.relu = nn.ReLU()

    def forward(self, x):
        out, h = self.gru(x)
        # print(f"out1: {out.size()}")
        out = self.linear2(self.relu(out))
        return out, h

    def init_hidden(self, batch_size):
        weight = next(self.parameters()).data
        hidden = weight.new(self.n_layers, batch_size, self.hidden_dim).zero_()
        return hidden

class NET(nn.Module):
    def __init__(
        self,
        L=20,
        N=256,
        X=8,
        R=4,
        B=256,
        H=512,
        P=3,
        norm="cLN",
        num_spks=1,
        non_linear="relu",
        causal=False
    ):
        super(NET, self).__init__()
        supported_nonlinear = {
            "relu": F.relu,
            "sigmoid": th.sigmoid,
            "softmax": F.softmax
        }
        if non_linear not in supported_nonlinear:
            raise RuntimeError("Unsupported non-linear function: {}",
                               format(non_linear))
        self.non_linear_type = non_linear
        self.non_linear = supported_nonlinear[non_linear]
        # n x S => n x N x T, S = 4s*8000 = 32000
        self.encoder_1d = Conv1D(1, N, L, stride=L // 2, padding=0)
        self.T = (64000 - L) // (L // 2) + 1 # 6399
        self.gru_net = GRUC(
            input_dim=H,
            hidden_dim=H,
            output_dim=B,
            n_layers=2,
            drop_prob=0.2
        )
        # n x N x T => n x N x H
        self.linear1 = nn.Sequential(
            nn.Linear(N, 837),
            nn.ReLU(),
            nn.Linear(837, 637),
            nn.ReLU(),
            nn.Linear(637, H)
        )
        # output 1x1 conv
        # n x B x T => n x N x T
        # NOTE: using ModuleList not python list
        # self.conv1x1_2 = th.nn.ModuleList(
        #     [Conv1D(B, N, 1) for _ in range(num_spks)])
        # n x B x T => n x 2N x T
        self.mask = Conv1D(B, num_spks * N, 1)
        self.linear2 = nn.Sequential(
            nn.Linear(B, 637),
            nn.ReLU(),
            nn.Linear(637, 498),
            nn.ReLU(),
            nn.Linear(498, B),
            nn.ReLU()
        )
        # using ConvTrans1D: n x N x T => n x 1 x To
        # To = (T - 1) * L // 2 + L
        self.decoder_1d = ConvTrans1D(
            N, 1, kernel_size=L, stride=L // 2, bias=True)
        self.num_spks = num_spks

    def forward(self, x):
        # x.size() = torch.Size([16, 64000])
        if x.dim() >= 3:
            raise RuntimeError(
                "{} accept 1/2D tensor as input, but got {:d}".format(
                    self.__name__, x.dim()))
        # when inference, only one utt
        if x.dim() == 1:
            x = th.unsqueeze(x, 0)
        # n x 1 x S => n x N x T
        w = self.encoder_1d(x)  # w.size(): torch.Size([16, 256, 6399])
        # n x N x T => n x T x N
        y = th.transpose(w, 1, 2)
        # n x T x N => n x T x H
        y = th.tanh(self.linear1(y))
        # n x T x H => n x T x B
        y, hidden = self.gru_net(y)

        y = self.linear2(y)

        # n x T x B => n x B x T
        y = th.transpose(y, 1, 2)
        # n x B x T => n x N x T

        e = y * w

        # spks x n x S
        output = self.decoder_1d(e, squeeze=True)  # require torch.Size([16, 64000])
        output = th.unsqueeze(output, 0) # 本框架套用分离框架，第0维表示分离出的说话人，因为为语音增强，只有一个干净语音，所以在第0维加个1，[1,16,257,637]?
        # print("output.size: ".format(output.size()))
        return output

class Conv1D(nn.Conv1d):
    """
    1D conv in GRUC
    """

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

    def forward(self, x, squeeze=False):
        """
        x: N x L or N x C x L
        """
        if x.dim() not in [2, 3]:
            raise RuntimeError("{} accept 2/3D tensor as input".format(
                self.__name__))
        x = super().forward(x if x.dim() == 3 else th.unsqueeze(x, 1))
        if squeeze:
            x = th.squeeze(x)
        return x

class ConvTrans1D(nn.ConvTranspose1d):
    """
    1D conv transpose in ConvTasNet
    """

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

    def forward(self, x, squeeze=False):
        """
        x: N x L or N x C x L
        """
        if x.dim() not in [2, 3]:
            raise RuntimeError("{} accept 2/3D tensor as input".format(
                self.__name__))
        x = super().forward(x if x.dim() == 3 else th.unsqueeze(x, 1))
        if squeeze:
            x = th.squeeze(x)
        return x

# 使用tensorboard工具来可视化查看网络模型
def tensorboard_show_model(model, input=None, model_name=None):
    writer = SummaryWriter(model_name)
    writer.add_graph(model, input)
    writer.close()


# Does not work!

import timeit

# slow
# simple loop
def loop(n):
    t = 0
    for i in range(1, n+1):
        if i % 3 == 0 or i % 5 == 0:
            t += i
    return t

# fast
# calculate each numbers' sum and subtract common multiplier
def calc(n):
    t03 = 3*(n/3)*(n/3+1)/2
    t05 = 5*(n/5)*(n/5+1)/2
    t15 = 15*(n/15)*(n/15+1)/2
    return t03 + t05 - t15


import os
# import rasterio

from . import log

def to_tiff(filename_in, filename_out, format_in, cog=False):
    """
    For accepted formats (in): https://gdal.org/drivers/raster/index.html
    """
    import rasterio

    format_out = 'GTiff'
    format_in = 'ISIS3' if format_in == 'ISIS' else format_in

    try:
        if cog:
            res = tiff2cog(filename_in, filename_out)
        else:
            src = rasterio.open(filename_in, 'r', driver=format_in)
            data = src.read()
            params = src.meta
            params['driver'] = format_out
            dst = rasterio.open(filename_out, 'w', **params)
            dst.write(data)
            dst.close()
            src.close()
    except Exception as err:
        raise err
        return None
    return filename_out

def merge(filenames, output):
    """
    Return filename of merged 'filenames' GeoTIFFs

    Input:
        filenames : list
            List of filenames to merge
        output : string
            Mosaic filename
    """
    import rasterio
    from rasterio.merge import merge as riomerge
    log.debug("Running 'merge' method.")

    with rasterio.open(filenames[0]) as src:
        meta = src.meta.copy()

    # The merge function returns a single array and the affine transform info
    arr, out_trans = riomerge(filenames)

    meta.update({
        "driver": "GTiff",
        "height": arr.shape[1],
        "width": arr.shape[2],
        "transform": out_trans
    })

    # Write the mosaic raster to disk
    with rasterio.open(output, "w", **meta) as dest:
        dest.write(arr)

    return output

def rescale(filename_in, filename_out, factor=0.5):
    """
    Resample data for faster processing. Rescale to HALF the resolution by default.
    """
    import rasterio
    from rasterio.enums import Resampling

    with rasterio.open(filename_in) as src:

        height = int(src.height * factor)
        width = int(src.width * factor)
        transform = src.transform * src.transform.scale(
                    (src.width / width),
                    (src.height / height)
        )

        # resample data to target shape
        data = src.read(
            out_shape=(src.count, height, width),
            resampling=Resampling.bilinear
        )
        data[data<=src.nodata] = src.nodata

        # copy src metadata, update as necessary for 'dst'
        kwargs = src.meta.copy()
        kwargs.update({
            'transform': transform,
            'width': width,
            'height': height
        })

        # reproject "src" to "dst"
        with rasterio.open(filename_out, 'w', **kwargs) as dst:
            for i, band in enumerate(data, 1):
                dst.write(band, i)

        return filename_out

resample = rescale


import random
import time
import os
import sys
import unittest
import mock
import boto3

from tests.ModuleBaseTestCase import ModuleBaseTestCase, MockLumberMill
from lumbermill.input import SQS

class TestSQS(ModuleBaseTestCase):

    def setUp(self):
        if 'TRAVIS' in os.environ and os.environ['TRAVIS'] == 'true':
            raise unittest.SkipTest('At the moment testing sqs services seems to be broken. Checking it.')
        try:
            self.aws_access_key_id = os.environ['AWS_ID']
            self.aws_secret_access_key = os.environ['AWS_KEY']
        except KeyError:
            raise unittest.SkipTest('Skipping test because no aws credentials set. Please set env vars AWS_ID and AWS_KEY.')
        self.queue_name = "%032x%s" % (random.getrandbits(128), os.getpid())
        self.connectToSqsQueue()
        super(TestSQS, self).setUp(SQS.SQS(mock.Mock()))

    def connectToSqsQueue(self):
        try:
            self.sqs_client = boto3.client('sqs', region_name='eu-west-1',
                                                  api_version=None,
                                                  use_ssl=True,
                                                  verify=None,
                                                  endpoint_url=None,
                                                  aws_access_key_id=self.aws_access_key_id,
                                                  aws_secret_access_key=self.aws_secret_access_key,
                                                  aws_session_token=None,
                                                  config=None)
            self.sqs_resource = boto3.resource('sqs', region_name='eu-west-1',
                                                      api_version=None,
                                                      use_ssl=True,
                                                      verify=None,
                                                      endpoint_url=None,
                                                      aws_access_key_id=self.aws_access_key_id,
                                                      aws_secret_access_key=self.aws_secret_access_key,
                                                      aws_session_token=None,
                                                      config=None)
            self.sqs_queue = self.sqs_resource.create_queue(QueueName=self.queue_name)
        except:
            etype, evalue, etb = sys.exc_info()
            print("Could not create sqs queue %s. Exception: %s, Error: %s" % (self.queue_name, etype, evalue))

    def testSQS(self):
        self.test_object.configure({'aws_access_key_id': self.aws_access_key_id,
                                    'aws_secret_access_key': self.aws_secret_access_key,
                                    'region': 'eu-west-1',
                                    'queue': self.queue_name})
        self.checkConfiguration()
        # Send some messages to the test queue.
        for _ in range(0, 100):
            self.sqs_queue.send_message(MessageBody='One thing is for sure, the sheep is not a creature of the air. '
                                                    'They have enormous difficulty in the comparatively simple act of perchin.')
        # Give messages some time to arrive.
        time.sleep(2)
        self.test_object.start()
        event = False
        time.sleep(4)
        counter = 0
        for event in self.receiver.getEvent():
            counter += 1
        self.assertTrue(event != False)
        self.assertEqual(counter, 100)
        self.assertEqual(event['data'], 'One thing is for sure, the sheep is not a creature of the air. '
                                        'They have enormous difficulty in the comparatively simple act of perchin.')

    def tearDown(self):
        self.sqs_client.delete_queue(QueueUrl=self.sqs_queue.url)


import numpy as np
import sys

class Window:
    def __init__(self, size):

        # The data itself
        self.data = {'magnetometer': [], 'barometer': [], 'light': []}

        # The window size, in milliseconds
        self.size = size

        # The first data point
        self.start = None

    def push_point(self, data):
        """
        Add a point to the window and return false if window is full
        """
        sensor_type = data['sensor_type']
        time = data['data']['t']
        if (self.start == None):
            self.start = time
        if (time - self.start > self.size):
            return False
        elif (sensor_type == u"SENSOR_MAGNETOMETER"):
            x = data['data']['x']
            y = data['data']['y']
            z = data['data']['z']
            self.data['magnetometer'].append([time, x, y, z])
            return True
        elif (sensor_type == u"SENSOR_BAROMETER"):
            val = data['data']['value']
            self.data['barometer'].append([time, val])
            return True
        elif (sensor_type == u"SENSOR_LIGHT"):
            val = data['data']['value']
            self.data['light'].append([time, val])
            return True

    def push_slices(self, data):
        """
        Add a slice to the window and return false if the window is full
        Return the data without the slice
        """
        if (self.data != {'magnetometer': [], 'barometer': [], 'light': []} or len(data['magnetometer']) == 0):
            return False
        else:
            def sizeIndex(ls, start, size):
                i = 0
                while(i < len(ls) and ls[i,0] - start < size):
                    i += 1
                return i
            self.start = data['magnetometer'][0,0]
            magIndex = sizeIndex(data['magnetometer'], self.start, self.size)
            barIndex = sizeIndex(data['barometer'], self.start, self.size)
            lightIndex = sizeIndex(data['light'], self.start, self.size)
            self.data['magnetometer'] = data['magnetometer'][:magIndex]
            self.data['barometer'] = data['barometer'][:barIndex]
            self.data['light'] = data['light'][:lightIndex]
            return {'magnetometer': data['magnetometer'][magIndex:], 'barometer': data['barometer'][barIndex:], 'light': data['light'][lightIndex:]}

    def allCheck(self):
        """
        Check if there is enough data
        """
        return 2 <= min([len(self.data['magnetometer']), len(self.data['barometer']), len(self.data['light'])])


import json, re, os
import numpy, numpy as np
from .net import Net
from time import time
import json, zipfile
from io import BytesIO

def read_net(path, debug=False):
    net = Net()
    path = path.replace('.onnx', '')
    if os.path.exists(path+'.pla'):
        with zipfile.ZipFile(path+'.pla') as f:
            path = os.path.split(path)[1]
            body = json.loads(f.read(path+'.json'))
            lay, flw = body['layers'], body['flow']
            inputs, inits = body['input'], body['inits']
            buf = BytesIO(f.read(path+'.npy'))
            weights = np.load(buf)
    elif os.path.exists(path+'.json'):
        with open(path+'.json') as f:
            body = json.load(f)
            lay, flw = body['layers'], body['flow']
            inputs, inits = body['input'], body['inits']
        weights = np.load(path+'.npy')
    elif os.path.exists(path+'.onnx'):
        body, weights = read_onnx(path+'.onnx')
        if body == 'lost': return weights
        lay, flw = body['layers'], body['flow']
        inputs, inits = body['input'], body['inits']
    else:
        return print('model %s not found!'%path)
    net.load_json(inputs, inits, lay, flw, debug)
    net.load_weights(weights)
    return net

types = [None, 'float32', 'uint8', 'int8', 'uint16', 'int16', 'int32', 'int64',
    'str', 'bool', 'float16', 'float64', 'uint32', 'uint64', 'complex64', 'complex128']

def node(attrs, name, k=None, para=None):
    node = None
    for i in attrs:
        if i.name==name: node = i
    if k is None or node is None:
        return node
    rst = getattr(node, k)
    if k=='ints': rst = list(rst)
    if k=='s': rst = rst.decode()
    if not para is None:
        para[name] = rst
    return rst

def read_onnx(path):
    import onnx, onnx.numpy_helper
    graph = onnx.load(path).graph
    input_para = [i.name for i in graph.input]
    layers, inits, weights, flows, values = [], [], [], [], {}
    for i in graph.initializer:
        v = onnx.numpy_helper.to_array(i)
        values[i.name] = len(weights), v.shape
        inits.append([i.name, v.shape, str(v.dtype)])
        if v.ndim==0: v = np.array([v])
        weights.append(v)
    for i in graph.node:
        inpara = [j for j in i.input]
        outpara = [j for j in i.output]

        if len(inpara)==1: inpara = inpara[0]
        if len(outpara)==1: outpara = outpara[0]

        flows.append([inpara, [i.name], outpara])
        # weights.extend([values[i] for i in initpara])
        # print(i.op_type, '===')
        if i.op_type == 'BatchNormalization':
            cur = flows[-1]
            k, b, m, v = [weights[values[cur[0][j]][0]] for j in (1,2,3,4)]
            v_inv = 1/numpy.sqrt(v + 1e-5)
            kmv_inv_b = -k*m*v_inv + b
            kv_inv = k*v_inv
            kmv_inv_b.shape = kv_inv.shape = (1,-1,1,1)

            kname, bname = cur[0][1] + '_invK', cur[0][1] + '_invB'
            values[kname] = len(weights), kv_inv.shape
            values[bname] = len(weights)+1, kmv_inv_b.shape
            inits.append([kname, kv_inv.shape, str(kv_inv.dtype)])
            inits.append([bname, kmv_inv_b.shape, str(kmv_inv_b.dtype)])
            weights.extend([kv_inv, kmv_inv_b])
            cur[0] = [cur[0][0], kname, bname]
            layers.append([i.name, 'batchnorm', {}])
        elif i.op_type == 'Conv':
            # attr, w = i.attribute, values[i.input[1]][1]
            attr = i.attribute
            g = node(attr, 'group', 'i') or 1
            d = node(attr, 'dilations', 'ints')
            p = node(attr, 'pads', 'ints')
            s = node(attr, 'strides', 'ints')
            layers.append([i.name, 'conv', {
                'group':g, 'strides':s, 'dilations':d, 'pads':p}])
        elif i.op_type == 'ConvTranspose':
            attr = i.attribute
            para = {}
            g = node(attr, 'group', 'i', para)
            d = node(attr, 'dilations', 'ints', para)
            p = node(attr, 'pads', 'ints', para)
            s = node(attr, 'strides', 'ints', para)
            op = node(attr, 'output_padding', 'ints', para)
            layers.append([i.name, 'convtranspose', para])
        elif i.op_type == 'Gemm':
            layers.append([i.name, 'dense', {'shp':list(values[i.input[1]][1][::-1])}])
        elif i.op_type == 'MaxPool':
            w = node(i.attribute, 'kernel_shape', 'ints')
            m = node(i.attribute, 'pads', 'ints')
            s = node(i.attribute, 'strides', 'ints')
            layers.append([i.name, 'maxpool', {'w':w, 'pads':m, 'strides':s}])
        elif i.op_type == 'GlobalAveragePool':
            layers.append([i.name, 'gap', {}])
        elif i.op_type == 'Upsample':
            mode = node(i.attribute, 'mode', 's')
            layers.append([i.name, 'upsample', {'mode':mode}])
        elif i.op_type == 'Resize':
            mode = node(i.attribute, 'mode', 's')
            nearest_mode = node(i.attribute, 'nearest_mode', 's')
            trans_mode = node(i.attribute, 'coordinate_transformation_mode', 's')
            layers.append([i.name, 'resize', {'mode':mode, 'nearest_mode':nearest_mode,
                'coordinate_transformation_mode': trans_mode}])
        elif i.op_type == 'Flatten':
            layers.append([i.name, 'flatten', {}])
        elif i.op_type == 'Unsqueeze':
            axis = node(i.attribute, 'axes', 'ints')
            layers.append([i.name, 'unsqueeze', {} if axis is None else {'axes':axis}])
        elif i.op_type == 'Squeeze':
            axis = node(i.attribute, 'axes', 'ints')
            layers.append([i.name, 'squeeze', {} if axis is None else {'axes':axis}])
        elif i.op_type == 'Relu':
            layers.append([i.name, 'relu', {}])
        elif i.op_type == 'LeakyRelu':
            alpha = i.attribute[0].f
            layers.append([i.name, 'leakyrelu', {'alpha':alpha}])
        elif i.op_type == 'HardSigmoid':
            para = {}
            node(i.attribute, 'alpha', 'f', para)
            node(i.attribute, 'beta', 'f', para)
            layers.append([i.name, 'hardsigmoid', para])
        elif i.op_type == 'Add':
            layers.append([i.name, 'add', {}])
        elif i.op_type == 'Sub':
            layers.append([i.name, 'sub', {}])
        elif i.op_type == 'Div':
            layers.append([i.name, 'div', {}])
        elif i.op_type == 'Tile':
            layers.append([i.name, 'tile', {}])
        elif i.op_type == 'MatMul':
            layers.append([i.name, 'matmul', {}])
        elif i.op_type == 'Constant':
            _, _, name = flows.pop(-1)
            dim = i.attribute[0].t.dims
            tp = types[i.attribute[0].t.data_type]

            v = onnx.numpy_helper.to_array(i.attribute[0].t)
            values[name] = len(weights), v.shape
            inits.append([name, v.shape, str(v.dtype)])
            if v.ndim==0: v = np.array([v])
            weights.append(v)
            #layers.append([i.name, 'const', {'value':v, 'dtype':tp}])
        elif i.op_type == 'Identity':
            layers.append([i.name, 'identity', {}])
        elif i.op_type == 'Pow':
            layers.append([i.name, 'pow', {}])
        elif i.op_type == 'ReduceSum':
            para = {}
            node(i.attribute, 'axes', 'ints', para)
            node(i.attribute, 'keepdims', 'i', para)
            layers.append([i.name, 'reducesum', para])
        elif i.op_type == 'ReduceMean':
            para = {}
            node(i.attribute, 'axes', 'ints', para)
            node(i.attribute, 'keepdims', 'i', para)
            layers.append([i.name, 'reducemean', para])
        elif i.op_type == 'ReduceMax':
            para = {}
            node(i.attribute, 'axes', 'ints', para)
            node(i.attribute, 'keepdims', 'i', para)
            layers.append([i.name, 'reducemax', para])
        elif i.op_type == 'ReduceMin':
            para = {}
            node(i.attribute, 'axes', 'ints', para)
            node(i.attribute, 'keepdims', 'i', para)
            layers.append([i.name, 'reducemin', para])
        elif i.op_type == 'Concat':
            layers.append([i.name, 'concat', {'axis':i.attribute[0].i}])
        elif i.op_type == 'Pad':
            para = {}
            node(i.attribute, 'mode', 's', para)
            node(i.attribute, 'constant_value', 'f', para)
            layers.append([i.name, 'pad', para])
        elif i.op_type == 'Sigmoid':
            layers.append([i.name, 'sigmoid', {}])
        elif i.op_type == 'AveragePool':
            w = node(i.attribute, 'kernel_shape', 'ints')
            m = node(i.attribute, 'pads', 'ints')
            s = node(i.attribute, 'strides', 'ints')
            layers.append([i.name, 'averagepool', {'w':w, 'pads':m, 'strides':s}])
        elif i.op_type == 'LSTM':
            para = {'hidden_size': i.attribute[0].i}
            node(i.attribute, 'direction', 's', para)
            layers.append([i.name, 'lstm', para])
        elif i.op_type == 'Shape':
            layers.append([i.name, 'shape', {}])
        elif i.op_type == 'Gather':
            layers.append([i.name, 'gather', {'axis':node(i.attribute, 'axis', 'i') or 0}])
        elif i.op_type == 'Mul':
            layers.append([i.name, 'mul', {}])
        elif i.op_type == 'Reshape':
            layers.append([i.name, 'reshape', {}])
        elif i.op_type == 'Transpose':
            layers.append([i.name, 'transpose', {'axis':node(i.attribute, 'perm', 'ints')}])
        elif i.op_type == 'LogSoftmax':
            layers.append([i.name, 'logsoftmax', {'axis':i.attribute[0].i}])
        elif i.op_type == 'Softmax':
            layers.append([i.name, 'softmax', {'axis':i.attribute[0].i}])
        elif i.op_type == 'ConstantOfShape':
            v = onnx.numpy_helper.to_array(i.attribute[0].t)
            tp, v = str(v.dtype), v.tolist()
            v = v[0] if len(v)==1 else 0
            layers.append([i.name, 'constantofshape', {'value':v, 'dtype':tp}])
        elif i.op_type == 'Greater':
            layers.append([i.name, 'greater', {}])
        elif i.op_type == 'NonZero':
            layers.append([i.name, 'nonzero', {}])
        elif i.op_type == 'GreaterOrEqual':
            layers.append([i.name, 'greaterorequal', {}])
        elif i.op_type == 'TopK':
            para = {}
            node(i.attribute, 'axis', 'i', para)
            node(i.attribute, 'largest', 'i', para)
            node(i.attribute, 'sorted', 'i', para)
            layers.append([i.name, 'topk', para])
        elif i.op_type == 'Split':
            split = node(i.attribute, 'split', 'ints')
            para = {'axis': node(i.attribute, 'axis', 'i')}
            if not split is None: para['split'] = split
            layers.append([i.name, 'split', para])
        elif i.op_type == 'Tanh':
            layers.append([i.name, 'tanh', {}])
        elif i.op_type == 'Exp':
            layers.append([i.name, 'exp', {}])
        elif i.op_type == 'Log':
            layers.append([i.name, 'log', {}])
        elif i.op_type == 'Slice':
            layers.append([i.name, 'slice', {}])
        elif i.op_type == 'Expand':
            layers.append([i.name, 'expand', {}])
        elif i.op_type == 'Equal':
            layers.append([i.name, 'equal', {}])
        elif i.op_type == 'Cast':
            layers.append([i.name, 'cast', {'dtype':types[i.attribute[0].i]}])
        elif i.op_type == 'Range':
            layers.append([i.name, 'range', {}])
        elif i.op_type == 'Where':
            layers.append([i.name, 'where', {}])
        elif i.op_type == 'ScatterND':
            layers.append([i.name, 'scatternd', {}])
        elif i.op_type == 'InstanceNormalization':
            layers.append([i.name, 'instancenormalization', {'epsilon':i.attribute[0].f}])
        elif i.op_type == 'Sqrt':
            layers.append([i.name, 'sqrt', {}])
        elif i.op_type == 'Erf':
            layers.append([i.name, 'erf', {}])
        elif i.op_type=='Reciprocal':
            layers.append([i.name, 'erf', {}])
        elif i.op_type == 'Clip':
            minv = node(i.attribute, 'min', 'f')
            maxv = node(i.attribute, 'max', 'f')
            para = {}
            if minv: para['min']=minv
            if maxv: para['max']=maxv
            layers.append([i.name, 'clip', para])
        else:
            print('lost layer:', i.op_type)
            return 'lost', i

    layers.append(['return', 'return', {}])
    flows.append([[i.name for i in graph.output], ['return'], 'plrst'])
    weights = np.hstack([i.view(dtype=np.uint8).ravel() for i in weights])
    return {'input':input_para, 'inits':inits, 'layers':layers, 'flow':flows}, weights

def onnx2pla(path, zip=True):
    graph, weights = read_onnx(path)
    np.save(path.replace('onnx', 'npy'), weights)
    with open(path.replace('onnx', 'json'), 'w') as f:
        json.dump(graph, f)
    if zip:
        with zipfile.ZipFile(path.replace('onnx', 'pla'), 'w') as f:
            f.write(path[:-4]+'json', os.path.split(path)[1][:-4]+'json')
            f.write(path[:-4]+'npy', os.path.split(path)[1][:-4]+'npy')
        os.remove(path.replace('onnx','json'))
        os.remove(path.replace('onnx','npy'))

if __name__ == '__main__':
    a, b = read_onnx('../demo/yolov3-planer-2/yolov3')


import numpy as np
import matplotlib.pyplot as plt
import time
from IPython import display

# Andrej Wilzcek 880707-7477
# Kildo Alias 971106-7430

# Implemented methods
methods = ['DynProg', 'ValIter']

# Some colours
LIGHT_RED = '#FFC4CC'
LIGHT_GREEN = '#95FD99'
BLACK = '#000000'
WHITE = '#FFFFFF'
LIGHT_PURPLE = '#E8D0FF'
LIGHT_ORANGE = '#FAE0C3'

class Maze:

    # Actions
    # STAY = 0
    # MOVE_LEFT = 1
    # MOVE_RIGHT = 2
    # MOVE_UP = 3
    # MOVE_DOWN = 4
    STAY = 4
    MOVE_LEFT = 0
    MOVE_RIGHT = 1
    MOVE_UP = 2
    MOVE_DOWN = 3

    # Give names to actions
    actions_names = {
        STAY: "stay",
        MOVE_LEFT: "move left",
        MOVE_RIGHT: "move right",
        MOVE_UP: "move up",
        MOVE_DOWN: "move down"
    }

    # Reward values
    STEP_REWARD = -1
    GOAL_REWARD = 0
    IMPOSSIBLE_REWARD = -100

    def __init__(self, maze, weights=None, random_rewards=False, minoStay=False):
        """ Constructor of the environment Maze.
        """
        self.maze = maze
        self.minoStay = minoStay
        self.actions = self.__actions()
        self.minoActions = self.__mino_actions()
        self.states, self.map = self.__states()
        self.n_minoActions = len(self.minoActions)
        self.n_actions = len(self.actions)
        self.n_states = len(self.states)
        self.transition_probabilities = self.__transitions()
        self.rewards = self.__rewards(weights=weights,
                                      random_rewards=random_rewards)

    def __actions(self):
        actions = dict()
        actions[self.STAY] = (0, 0)
        actions[self.MOVE_LEFT] = (0, -1)
        actions[self.MOVE_RIGHT] = (0, 1)
        actions[self.MOVE_UP] = (-1, 0)
        actions[self.MOVE_DOWN] = (1, 0)
        return actions

    def __mino_actions(self):
        minoActions = dict()
        minoActions[self.MOVE_LEFT] = (0, -1)
        minoActions[self.MOVE_RIGHT] = (0, 1)
        minoActions[self.MOVE_UP] = (-1, 0)
        minoActions[self.MOVE_DOWN] = (1, 0)
        if self.minoStay:
            minoActions[self.STAY] = (0, 0)
        return minoActions

    def __states(self):
        states = dict()
        map = dict()
        end = False
        s = 0
        for i in range(self.maze.shape[0]):
            for j in range(self.maze.shape[1]):
                if self.maze[i, j] != 1:
                    for k in range(self.maze.shape[0]):
                        for l in range(self.maze.shape[1]):
                            states[s] = (i, j, k, l)
                            map[(i, j, k, l)] = s
                            s += 1

        return states, map

    def __move(self, state, action, minoAction):
        """ Makes a step in the maze, given a current position and an action.
            If the action STAY or an inadmissible action is used, the agent stays in place.

            :return tuple next_cell: Position (x,y) on the maze that agent transitions to.
        """
        # Compute the future minotaur position given current (state, action)
        minoRow = self.states[state][2] + self.minoActions[minoAction][0]
        minoCol = self.states[state][3] + self.minoActions[minoAction][1]

        try:
            if (self.maze[minoRow, minoCol] == 1):
                minoRow += self.minoActions[minoAction][0]
                minoCol += self.minoActions[minoAction][1]
        except:
            return None

        # Is the future position an impossible one ?
        outside = (minoRow == -1) or (minoRow == self.maze.shape[0]) or \
            (minoCol == -1) or (minoCol ==
                                self.maze.shape[1]) or (self.maze[minoRow, minoCol] == 1)

        if outside:
            return None

        # Compute the future player position given current (state, action)
        row = self.states[state][0] + self.actions[action][0]
        col = self.states[state][1] + self.actions[action][1]
        # Is the future position an impossible one ?
        hitting_maze_walls = (row == -1) or (row == self.maze.shape[0]) or \
            (col == -1) or (col == self.maze.shape[1]) or \
            (self.maze[row, col] == 1)

        # Based on the impossiblity check return the next state.
        if hitting_maze_walls:
            return self.map[(self.states[state][0], self.states[state][1], minoRow, minoCol)]
        else:
            return self.map[(row, col, minoRow, minoCol)]

    def __transitions(self):
        """ Computes the transition probabilities for every state action pair.
            :return numpy.tensor transition probabilities: tensor of transition
            probabilities of dimension S*S*A
        """
        # Initialize the transition probailities tensor (S,S,A)
        dimensions = (self.n_states, self.n_states, self.n_actions)
        transition_probabilities = np.zeros(dimensions)

        # Compute the transition probabilities. Note that the transitions
        # are deterministic.
        for s in range(self.n_states):
            for a in range(self.n_actions):
                nextStates = []
                for ma in range(self.n_minoActions):
                    next_s = self.__move(s, a, ma)
                    if next_s != None:
                        nextStates.append(next_s)
                prob = 1.0/len(nextStates)
                for next_s in nextStates:
                    transition_probabilities[next_s, s, a] = prob
        return transition_probabilities

    def __rewards(self, weights=None, random_rewards=None):

        rewards = np.zeros((self.n_states, self.n_actions))

        # If the rewards are not described by a weight matrix
        if weights is None:
            for s in range(self.n_states):
                for a in range(self.n_actions):
                    nextStates = []
                    for ma in range(self.n_minoActions):
                        next_s = self.__move(s, a, ma)
                        if next_s != None:
                            nextStates.append(next_s)

                    for next_s in nextStates:

                        # Rewrd for hitting a wall
                        if self.states[s][0] == self.states[next_s][0] and self.states[s][1] == self.states[next_s][1] and a != self.STAY:
                            rewards[s, a] += self.IMPOSSIBLE_REWARD
                        # reward for being eaten
                        elif self.states[next_s][0] == self.states[next_s][2] and self.states[next_s][1] == self.states[next_s][3]:
                            rewards[s, a] += self.IMPOSSIBLE_REWARD
                        # Reward for reaching the exit
                        elif self.states[s][0] == self.states[next_s][0] and self.states[s][1] == self.states[next_s][1] and self.maze[self.states[next_s][0], self.states[next_s][1]] == 2:
                            rewards[s, a] += self.GOAL_REWARD
                        # Reward for taking a step to an empty cell that is not the exit
                        else:
                            rewards[s, a] += self.STEP_REWARD
                    rewards[s, a] /= len(nextStates)

        # If the weights are descrobed by a weight matrix
        else:
            for s in range(self.n_states):
                for a in range(self.n_actions):
                    next_s = self.__move(s, a)
                    i, j = self.states[next_s]
                    # Simply put the reward as the weights o the next state.
                    rewards[s, a] = weights[i][j]

        return rewards

    def simulate(self, start, policy, method):
        if method not in methods:
            error = 'ERROR: the argument method must be in {}'.format(methods)
            raise NameError(error)

        path = list()
        if method == 'DynProg':
            # Deduce the horizon from the policy shape
            horizon = policy.shape[1]
            # Initialize current state and time
            t = 0
            s = self.map[start]
            # Add the starting position in the maze to the path
            path.append(start)
            while t < horizon-1:

                while True:
                    randomMove = np.random.randint(0, len(self.minoActions))
                    # Compute the future minotaur position given current (state, action)
                    minoRow = self.states[s][2] + \
                        self.minoActions[randomMove][0]
                    minoCol = self.states[s][3] + \
                        self.minoActions[randomMove][1]
                    try:
                        if (self.maze[minoRow, minoCol] == 1):
                            minoRow += self.minoActions[randomMove][0]
                            minoCol += self.minoActions[randomMove][1]
                    except:
                        continue

                    # Is the future position an impossible one ?
                    outside = (minoRow == -1) or (minoRow == self.maze.shape[0]) or \
                        (minoCol == -1) or (minoCol ==
                                            self.maze.shape[1]) or (self.maze[minoRow, minoCol] == 1)

                    if not outside:
                        break

                # Move to next state given the policy and the current state
                next_s = self.__move(s, policy[s, t], randomMove)
                # Add the position in the maze corresponding to the next state
                # to the path
                path.append(self.states[next_s])
                # Update time and state for next iteration
                t += 1
                s = next_s
        if method == 'ValIter':
            # Initialize current state, next state and time
            t = 1
            s = self.map[start]
            # Add the starting position in the maze to the path
            path.append(start)

            # calculate a random move for the Minotaur
            while True:
                randomMove = np.random.randint(0, len(self.minoActions))
                # Compute the future minotaur position given current (state, action)
                minoRow = self.states[s][2] + \
                    self.minoActions[randomMove][0]
                minoCol = self.states[s][3] + \
                    self.minoActions[randomMove][1]
                try:
                    if (self.maze[minoRow, minoCol] == 1):
                        minoRow += self.minoActions[randomMove][0]
                        minoCol += self.minoActions[randomMove][1]
                except:
                    continue

                # Is the future position an impossible one ?
                outside = (minoRow == -1) or (minoRow == self.maze.shape[0]) or \
                    (minoCol == -1) or (minoCol ==
                                        self.maze.shape[1]) or (self.maze[minoRow, minoCol] == 1)

                if not outside:
                    break

            # Move to next state given the policy and the current state
            next_s = self.__move(s, policy[s], randomMove)

            # Add the position in the maze corresponding to the next state
            # to the path
            path.append(self.states[next_s])
            # Loop while state is not the goal state
            while not (self.states[s][0] == self.states[next_s][0] and self.states[s][1] == self.states[next_s][1] and self.maze[self.states[next_s][0], self.states[next_s][1]] == 2):
                # Update state
                s = next_s
                while True:
                    randomMove = np.random.randint(0, len(self.minoActions))
                    # Compute the future minotaur position given current (state, action)
                    minoRow = self.states[s][2] + \
                        self.minoActions[randomMove][0]
                    minoCol = self.states[s][3] + \
                        self.minoActions[randomMove][1]
                    try:
                        if (self.maze[minoRow, minoCol] == 1):
                            minoRow += self.minoActions[randomMove][0]
                            minoCol += self.minoActions[randomMove][1]
                    except:
                        continue

                    # Is the future position an impossible one ?
                    outside = (minoRow == -1) or (minoRow == self.maze.shape[0]) or \
                        (minoCol == -1) or (minoCol ==
                                            self.maze.shape[1]) or (self.maze[minoRow, minoCol] == 1)
                    if not outside:
                        break
                # Move to next state given the policy and the current state
                next_s = self.__move(s, policy[s], randomMove)
                # Add the position in the maze corresponding to the next state
                # to the path
                path.append(self.states[next_s])
                # Update time and state for next iteration
                t += 1
        return path

    def show(self):
        print('The states are :')
        print(self.states)
        print('The actions are:')
        print(self.actions)
        print('The mapping of the states:')
        print(self.map)
        print('The rewards:')
        print(self.rewards)

def dynamic_programming(env, horizon):
    """ Solves the shortest path problem using dynamic programming
        :input Maze env           : The maze environment in which we seek to
                                    find the shortest path.
        :input int horizon        : The time T up to which we solve the problem.
        :return numpy.array V     : Optimal values for every state at every
                                    time, dimension S*T
        :return numpy.array policy: Optimal time-varying policy at every state,
                                    dimension S*T
    """

    # The dynamic prgramming requires the knowledge of :
    # - Transition probabilities
    # - Rewards
    # - State space
    # - Action space
    # - The finite horizon
    p = env.transition_probabilities
    r = env.rewards
    n_states = env.n_states
    n_actions = env.n_actions
    T = horizon

    # The variables involved in the dynamic programming backwards recursions
    V = np.zeros((n_states, T+1))
    policy = np.zeros((n_states, T+1))
    Q = np.zeros((n_states, n_actions))

    # Initialization
    Q = np.copy(r)
    V[:, T] = np.max(Q, 1)
    policy[:, T] = np.argmax(Q, 1)

    # The dynamic programming bakwards recursion
    for t in range(T-1, -1, -1):
        # Update the value function acccording to the bellman equation
        for s in range(n_states):
            for a in range(n_actions):
                # Update of the temporary Q values
                Q[s, a] = r[s, a] + np.dot(p[:, s, a], V[:, t+1])
        # Update by taking the maximum Q value w.r.t the action a
        V[:, t] = np.max(Q, 1)
        # The optimal action is the one that maximizes the Q function
        policy[:, t] = np.argmax(Q, 1)
    return V, policy

def value_iteration(env, gamma, epsilon):
    """ Solves the shortest path problem using value iteration
        :input Maze env           : The maze environment in which we seek to
                                    find the shortest path.
        :input float gamma        : The discount factor.
        :input float epsilon      : accuracy of the value iteration procedure.
        :return numpy.array V     : Optimal values for every state at every
                                    time, dimension S*T
        :return numpy.array policy: Optimal time-varying policy at every state,
                                    dimension S*T
    """
    # The value itearation algorithm requires the knowledge of :
    # - Transition probabilities
    # - Rewards
    # - State space
    # - Action space
    # - The finite horizon
    p = env.transition_probabilities
    r = env.rewards
    n_states = env.n_states
    n_actions = env.n_actions

    # Required variables and temporary ones for the VI to run
    V = np.zeros(n_states)
    Q = np.zeros((n_states, n_actions))
    BV = np.zeros(n_states)
    # Iteration counter
    n = 0
    # Tolerance error
    tol = (1 - gamma) * epsilon/gamma

    # Initialization of the VI
    for s in range(n_states):
        for a in range(n_actions):
            Q[s, a] = r[s, a] + gamma*np.dot(p[:, s, a], V)
    BV = np.max(Q, 1)

    # Iterate until convergence
    while np.linalg.norm(V - BV) >= tol and n < 200:
        # Increment by one the numbers of iteration
        n += 1
        # Update the value function
        V = np.copy(BV)
        # Compute the new BV
        for s in range(n_states):
            for a in range(n_actions):
                Q[s, a] = r[s, a] + gamma*np.dot(p[:, s, a], V)
        BV = np.max(Q, 1)
        # Show error
        # print(np.linalg.norm(V - BV))

    # Compute policy
    policy = np.argmax(Q, 1)
    # Return the obtained policy
    return V, policy

def draw_maze(maze):

    # Map a color to each cell in the maze
    col_map = {0: WHITE, 1: BLACK,
               2: LIGHT_GREEN, -6: LIGHT_RED, -1: LIGHT_RED}

    # Give a color to each cell
    rows, cols = maze.shape
    colored_maze = [[col_map[maze[j, i]]
                     for i in range(cols)] for j in range(rows)]

    # Create figure of the size of the maze
    fig = plt.figure(1, figsize=(cols, rows))

    # Remove the axis ticks and add title title
    ax = plt.gca()
    ax.set_title('The Maze')
    ax.set_xticks([])
    ax.set_yticks([])

    # Give a color to each cell
    rows, cols = maze.shape
    colored_maze = [[col_map[maze[j, i]]
                     for i in range(cols)] for j in range(rows)]

    # Create figure of the size of the maze
    fig = plt.figure(1, figsize=(cols, rows))

    # Create a table to color
    grid = plt.table(cellText=None,
                     cellColours=colored_maze,
                     cellLoc='center',
                     loc=(0, 0),
                     edges='closed')
    # Modify the hight and width of the cells in the table
    tc = grid.properties()['children']
    for cell in tc:
        cell.set_height(1.0/rows)
        cell.set_width(1.0/cols)
    display.display(fig)
    display.clear_output(wait=True)
    # time.sleep(1)
    plt.show()

def animate_solution(maze, path):

    # Map a color to each cell in the maze
    col_map = {0: WHITE, 1: BLACK,
               2: LIGHT_GREEN, -6: LIGHT_RED, -1: LIGHT_RED}

    # Size of the maze
    rows, cols = maze.shape

    # Create figure of the size of the maze
    fig = plt.figure(1, figsize=(cols, rows))

    # Remove the axis ticks and add title title
    ax = plt.gca()
    ax.set_title('Policy simulation')
    ax.set_xticks([])
    ax.set_yticks([])

    # Give a color to each cell
    colored_maze = [[col_map[maze[j, i]]
                     for i in range(cols)] for j in range(rows)]

    # Create figure of the size of the maze
    fig = plt.figure(1, figsize=(cols, rows))

    # Create a table to color
    grid = plt.table(cellText=None,
                     cellColours=colored_maze,
                     cellLoc='center',
                     loc=(0, 0),
                     edges='closed')

    # Modify the hight and width of the cells in the table
    tc = grid.properties()['children']
    for cell in tc:
        cell.set_height(1.0/rows)
        cell.set_width(1.0/cols)

    # Update the color at each frame
    for i in range(len(path)):
        if i > 0:
            if path[i][0] == path[i][2] and path[i][1] == path[i][3]:
                grid.get_celld()[(path[i][2], path[i][3])
                                 ].set_facecolor(LIGHT_RED)
                grid.get_celld()[(path[i][2], path[i][3])].get_text().set_text(
                    'Player is eaten')
                break

            grid.get_celld()[(path[i-1][0], path[i-1][1])
                             ].set_facecolor(col_map[maze[path[i-1][0], path[i-1][1]]])
            grid.get_celld()[(path[i-1][0], path[i-1][1])
                             ].get_text().set_text('')

            grid.get_celld()[(path[i-1][2], path[i-1][3])
                             ].set_facecolor(col_map[maze[path[i-1][2], path[i-1][3]]])
            grid.get_celld()[(path[i-1][2], path[i-1][3])
                             ].get_text().set_text('')

            grid.get_celld()[(path[i][0], path[i][1])
                             ].set_facecolor(LIGHT_ORANGE)
            grid.get_celld()[(path[i][0], path[i][1])
                             ].get_text().set_text('Player')

            grid.get_celld()[(path[i][2], path[i][3])].set_facecolor(LIGHT_RED)
            grid.get_celld()[(path[i][2], path[i][3])
                             ].get_text().set_text('Minotaur')

            playerLast = grid.get_celld()[(path[i-1][0], path[i-1][1])].xy
            playerNow = grid.get_celld()[(path[i][0], path[i][1])].xy
            deltaX = playerNow[0]-playerLast[0]
            deltaY = playerNow[1]-playerLast[1]

            plt.arrow(playerLast[0] + 0.5/rows, playerLast[1] + 0.5/cols,
                      deltaX, deltaY, width=0.005)

            minoLast = grid.get_celld()[(path[i-1][2], path[i-1][3])].xy
            minoNow = grid.get_celld()[(path[i][2], path[i][3])].xy
            deltaX = minoNow[0]-minoLast[0]
            deltaY = minoNow[1]-minoLast[1]

            plt.arrow(minoLast[0] + 0.25/rows, minoLast[1] + 0.25/cols,
                      deltaX, deltaY, width=0.005, color='red')

            if path[i][0] == path[i-1][0] and path[i][1] == path[i-1][1] and maze[(path[i][0], path[i][1])] == 2:
                print('Vi är i mål')
                grid.get_celld()[(path[i][0], path[i][1])
                                 ].set_facecolor(LIGHT_GREEN)
                grid.get_celld()[(path[i][0], path[i][1])].get_text().set_text(
                    'Player is out')
                break
        else:
            grid.get_celld()[(path[i][0], path[i][1])
                             ].set_facecolor(LIGHT_ORANGE)
            grid.get_celld()[(path[i][0], path[i][1])
                             ].get_text().set_text('Player')

            grid.get_celld()[(path[i][2], path[i][3])].set_facecolor(LIGHT_RED)
            grid.get_celld()[(path[i][2], path[i][3])
                             ].get_text().set_text('Minotaur')

        display.display(fig)
        display.clear_output(wait=True)
        # time.sleep(1)
        plt.draw()
        plt.pause(0.3)
    display.display(fig)
    display.clear_output(wait=True)
    # time.sleep(1)
    plt.show()


import time

from zope import interface
from zope import schema

class INotification(interface.Interface):
    """A notification is a set of useractions sharing the same what/where,
    and linkedd to a specifique user.

    The whos are merged when a useraction sharing the same attributes with an
    unseen one is added. This is made in order to avoid having the same
    notification several times with only the who changing. It allows for more
    notifications shown at the same time."""

    id = schema.ASCIILine(title=u"ID")
    what = schema.ASCIILine(title=u"What")
    where = schema.ASCIILine(title=u"Where")
    when = schema.Datetime(title=u"When")
    who = schema.List(title=u"Who", value_type=schema.ASCIILine())
    info = schema.Dict(title=u"Info",
                       description=u"More info given by the gatherer",
                       key_type=schema.ASCIILine(),
                       value_type=schema.ASCIILine())
    gatherer = schema.ASCIILine(title=u"Gatherer")

    def getId():
        """Get the unique id of the notification"""

    def show():
        """Return a human friendly string explaining the notification."""

class Notification(object):
    interface.implements(INotification)

    def __init__(self, what, where, when, who, user, gatherer,
                 seen=False, info=None):
        self.what = what
        self.where = where
        self.when = when
        self.who = who
        title = "%s" % self.when.strftime("%Y-%m-%d-%H-%M-%S")
        title += "-%s" % self.what.lower()
        title += "-%s" % self.where
        self.id = title
        self.seen = seen
        self.user = user
        self.info = info
        self.gatherer = gatherer

    def getId(self):
        return self.id

    def getWhenTimestamp(self):
        return time.mktime(self.when.timetuple())


def bem_vindo():
    '''Exibe o conteudo inicial'''
    print('''
    ##################################################
    Bem-vindo ao Descubra a Classe do Seu Veículo !

    O programa mostra a classe do veículo com base no
    peso, quantidade de rodas e quantidade de pessoas.
    ##################################################

    ''')

def encerramento():
    '''Exibe o conteúdo final'''
    print('''
    #################################################
    Obrigado. Adeus !
    ################################################''')

def main():
    '''funcao principal'''

    qtd_rodas, peso, qtd_pessoas = 0, 0.0, 0

    bem_vindo() # exibe o conteúdo da função bem_vindo

    # Recebendo dados
    qtd_rodas = int(input('Digite a quantidade de rodas do veículo: '))
    peso = float(input('Digite o peso do veículo em kilogramas: '))
    qtd_pessoas = int(input('Digite quantas pessoas o veículo pode suportar: '))

    # processamento e saída
    if qtd_rodas == 2 or qtd_rodas == 3:
        print('Classe A')
    elif qtd_rodas == 4 and qtd_pessoas <= 8 and peso <= 3500:
        print('Classe B')
    elif qtd_rodas >= 4 and 3500 < peso < 6000:
        print('Classe C')
    elif qtd_rodas >= 4 and qtd_pessoas > 8:
        print('Classe D')
    elif qtd_rodas >= 4 and peso > 6000:
        print('Classe E')
    else:
        print('A classe do veículo não pôde ser identificada')

    encerramento() # mensagem de encerramento

if __name__ == '__main__':
    main()


#coding=utf-8
#Version:python3.6.0
#Tools:Pycharm 2017.3.2
# Author:LIKUNHONG
__date__ = '2018/9/18 12:29'
__author__ = 'likunkun'

from multiprocessing import Process, Manager

def f(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.append(1)
    # print(l)

if __name__ == '__main__':
    d = Manager().dict()  # 生成一个字典，可在多个进程间共享和传递
    l = Manager().list(range(5))  # 列表
    p_list = [] #进程列表
    for i in range(10):
        p = Process(target=f, args=(d, l))  #循环10次每次创建一个进程
        p.start()
        p_list.append(p)    #加入进程列表里
    for res in p_list:  #等所有进程结束
        res.join()
    print(d)
    print(l)


from logzero import logger as log

from forge.entities.base import Base
from requests.exceptions import HTTPError
from alive_progress import alive_bar
from forge.entities.syncplan import SyncPlans

import json

class RepositorySets(Base):
  """Forged RepositorySets object.
  Matches nailgun.entity.RepositorySets

  :param Base: forge.entities.Base
  :type Base: BaseClass
  :return: List of RepositorySets entities
  :rtype: list
  """
  def __init__(self, cfg, org):
    self.entity = "RepositorySet"
    # Caching
    self._repos = {}
    super().__init__(cfg, org)

  def get_by_labels(self, labels, rh_repo=False):
    """ This returns the repo object based on label searched"""
    log.debug(f"Looking for {labels}")
    repos = []
    with alive_bar(len(labels),
      title="Fetching reposets data") as bar:
      for label in labels:
        self.log_bar(f"Looking for {label}", bar)
        if label in self._repos:
          repo = self._repos[label]
        else:
          repo = self.search(None, label=label)
          if len(repo) == 0:
            log.error(f"Repository labeled {label} is not found. Skipping")
            continue
          if not rh_repo:
            self._repos[label] = [r.read() for r in repo[0].repositories]
          else:
            self._repos[label] = repo
        repos.append(self._repos[label][0])
    return repos

  def get_enabled(self):
    self.get_all()
    return list(filter(lambda x: len(x.repositories), self.items))

  def enable_all(self, sync=False):
    sync_plans = SyncPlans(self._cfg, self.org)
    plan_map = sync_plans.get_plan_map("daily")
    planinc = 0

    for section in self._cfg.config:
      if section.startswith("products"):
        self.get_all(True)
        config_keys = dict(self._cfg.config.items(section))
        log.debug(config_keys)
        products = json.loads(config_keys["list"])
        multiplier = 5 if sync else 4
        repos = self.get_by_labels(list(map(lambda x: x["repository_set"],
          products)), True)
        with alive_bar(len(products) * multiplier,
          title="Enabling repo-sets") as bar:
          for i in products:
            self.log_bar(f"Getting reposet {i['repository_set']}", bar)
            filtered_repos = list(filter(lambda x: x.label == i["repository_set"],
              repos))
            log.debug(f"Filtered repos: {filtered_repos}")
            if not len(filtered_repos):
              log.warning(f"Skipping {i['repository_set']}")
              for x in range(multiplier - 1):
                bar("Skipping")
              continue
            repo = filtered_repos[0]
            self.log_bar(f"Looking for repo-set: {repo.label}", bar)
            if len(repo.repositories) == 0:
              attributes = {"basearch": config_keys["arch"],
                            "organization_id": self.org.item.id}
              if "releasever" in i:
                attributes["releasever"] = i["releasever"]
              log.debug(f"Enabling {self.entity} {attributes}")
              try:
                self.log_bar(f"Enabling {repo.label}", bar)
                repo.enable(data=attributes)
              except HTTPError as err:
                if err.response.status_code == 409:
                  log.warning(f"{self.entity} {repo.label} already enabled...")
                else:
                  log.error(f"Error creating {self.entity}: "
                            f"{err.response.status_code} {err.response._content}")
            else:
              log.debug("Repository {repo.label} already enabled")
              self.log_bar(f"Skipped {repo.label}", bar)
            self.log_bar("Updating sync plan", bar)
            if "daily" in i["sync_plan"]:
              planinc += 1
              plan_id = plan_map[planinc % 6]
            else:
              plan_id = sync_plans.get(i["sync_plan"]).id
            repo.product.sync_plan_id = plan_id
            repo.product.update()
            if sync:
              self.log_bar(f"Syncing {repo.label}", bar)
              repo.product.sync(
                synchronous=self._cfg.satellite.getboolean("async_sync"))


'''
Title     : sWAP cASE
Subdomain : Strings
Domain    : Python
Author    : Ahmedur Rahman Shovon
Created   : 15 July 2016
Problem   : https://www.hackerrank.com/challenges/swap-case/problem
'''
__author__ = 'arsho'
def swap_case(s):
    newstring = ""

    for item in s:
        if item.isupper():
            newstring += item.lower()
        else:
            newstring += item.upper()

    return newstring


from django.db import models

NACIONALIDAD = (('mx', 'Mexicana'), ('usa', 'Estadounidense'),
                ('es', 'Española'), ('co', 'Colombia'))

# Create your models here.
class Autor(models.Model):
    nombre = models.CharField(verbose_name='Nombre del autor', max_length=80)
    apellidos = models.CharField(verbose_name='Apellidos', max_length=80)
    pseudonimo = models.CharField(verbose_name='Pseudónimo', max_length=100)
    # nacionalidad = models.CharField(verbose_name='Nacionalidad', max_length=100)
    nacionalidad = models.CharField(choices=NACIONALIDAD, verbose_name='Nacionalidad',
                                    max_length=100, default='mx')
    fechaNacimiento = models.DateField(verbose_name='Fecha de nacimiento')
    fechaFallecimiento = models.DateField(verbose_name='Fecha de fallecimiento', null=True, blank=True)
    foto = models.ImageField(verbose_name='Imagen del autor', upload_to='images/autor/foto')

    def __str__(self):
        return "{0} {1} -- {2}".format(self.nombre, self.apellidos, self.nacionalidad)

    class Meta:
        verbose_name = 'Autor'
        verbose_name_plural = 'Autores'

class Editorial(models.Model):
    nombre = models.CharField(verbose_name='Editorial', max_length=100, unique=True)
    telefono = models.CharField(verbose_name='teléfono', max_length=15, null=True, unique=True)

    def __str__(self):
        return self.nombre

    class Meta:
        verbose_name = 'Editorial'
        verbose_name_plural = 'Editoriales'

class Libro(models.Model):
    titulo = models.CharField(verbose_name="Título del libro", max_length=255)
    autor = models.ForeignKey(Autor, verbose_name='Elija al autor', on_delete=models.SET_NULL, null=True, blank=True)
    editorial = models.ForeignKey(Editorial, verbose_name='Elija la editorial', on_delete=models.SET_NULL, null=True, blank=True)
    sinopsis = models.TextField(verbose_name="Sinopsis", max_length=500)
    portada = models.ImageField(verbose_name="Portada de libro", upload_to='images/libro/portadas/', null=True, blank=True)
    isbn = models.CharField(verbose_name='ISBN', max_length=20, unique=True, null=True, blank=True)

    # def __str__(self):
    #     return "{0} - {1}".format(self.titulo, self.sinopsis)

    class Meta:
        verbose_name = 'Libro'
        verbose_name_plural = 'Libros'


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import math

def cylinder():
    r = float(input("Введите радиус: "))
    h = float(input("Введите высоту: "))
    s_side = 2 * math.pi * r * h

    def circle():
        s_circle = math.pi * r ** 2
        return s_circle

    check = input("Введите Y для бок. площ. или N для всей площ.: ")
    if check == "Y":
        print(f"Бок. площ. цилиндра: {s_side}")
    else:
        full_area = s_side + circle() * 2
        print(f"Полная площ. цилиндра: {full_area}")

if __name__ == "__main__":
    cylinder()


# -*- coding: utf-8 -*-
import scrapy
import json
from COVID_19.items import Covid19Item

class Covid19Spider(scrapy.Spider):
    name = 'covid19'
    allowed_domains = ['https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=317249238170']
    start_urls = ['https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=317249238170/']

    def parse(self, response):
        data = json.loads(response.text)
        item = Covid19Item()
        for country in data['data']['areaTree']:
            item['name']= country['name']
            today_dict = country['today']
            total_dict = country['total']

            item['today_confirm'] = today_dict['confirm'] if (today_dict['confirm'] != None) else 0
            item['today_suspect'] = today_dict['suspect'] if (today_dict['suspect'] != None) else 0
            item['today_heal'] = today_dict['heal'] if (today_dict['heal'] != None) else 0
            item['today_dead'] = today_dict['dead'] if (today_dict['dead'] != None) else 0

            item['total_confirm'] = total_dict['confirm'] if (total_dict['confirm'] != None) else 0
            item['total_suspect'] = total_dict['suspect'] if (total_dict['suspect'] != None) else 0
            item['total_heal'] = total_dict['heal'] if (total_dict['heal'] != None) else 0
            item['total_dead'] = total_dict['dead'] if (total_dict['dead'] != None) else 0
            item['now_confirm'] = item['total_confirm'] - item['total_heal'] - item['total_dead']
            yield item
            # print("国家:" + str(name) + ",今日确诊:" + str(today_confirm) + ",今日疑似:" + str(today_suspect) + ",今日治愈:"
            #       + str(today_heal) + ",今日死亡:" + str(today_dead) + ",累计确诊:" + str(total_confirm) + ",累计疑似:" + str(
            #     total_suspect) +
            #       ",累计治愈:" + str(total_heal) + ",累计死亡:" + str(total_dead) + ",现有确诊:" + str(now_confirm))


from flask import Flask,render_template,request
import datasource
import plotly.express as px
import json
import plotly

app = Flask(__name__)
@app.route("/",methods=['GET','POST'])
def index():
    rows = datasource.get_stockid()
    if request.method == 'POST':
        stock_name = request.form['stock_name']  #1203-味王
        stock_id = stock_name[:4]
        year =  request.form['year']
        stock_dataFrame = datasource.get_stock_data(stockid=stock_id,year=year)
        stock_data = stock_dataFrame.to_numpy().tolist()
        #plotly express
        fig = px.line(stock_dataFrame,x="Date",y="Adj Close",title=f'{stock_name}_{year}')
        graphJSON = json.dumps(fig,cls=plotly.utils.PlotlyJSONEncoder)
        return render_template("form.jinja.html",rows=rows,stock_name=stock_name,year=year,data=stock_data,graphJSON=graphJSON)
    return render_template("form.jinja.html",rows=rows)

@app.route("/features")
def features():

    return render_template("features.jinja.html")

@app.route("/priceing")
def priceing():

    return render_template("priceing.jinja.html")

@app.route("/about")
def about():
    return render_template("about.jinja.html")

@app.route("/form/",methods=['GET', 'POST'])
def form():
    rows = datasource.get_stockid()
    if request.method == 'POST':
        stock_name = request.form['stock_name']  #1203-味王
        stock_id = stock_name[:4]
        stock_data = datasource.get_stock_data(stockid=stock_id)
        year =  request.form['year']
        return render_template("form.jinja.html",rows=rows,stock_name=stock_name,year=year,data=stock_data)

    return render_template("form.jinja.html",rows=rows)

實際案例/歷年股票資訊查詢/app.py


import datetime

x = input("Введите время в формате hh:mm\n")

if not x:
    current_datetime = datetime.datetime.now()
    x = current_datetime.strftime("%H:%M")

x = x.split(':')
hh = int(x[0])
mm = int(x[1])

try:
    if hh < 0 or hh > 23 or mm < 0 or mm > 59:
        raise ValueError
except ValueError:
    print("Ошибка: некорректный формат времени")
    exit()

m1 = {
    1: 'одна', 2: 'две', 3: 'три', 4: 'четыре', 5: 'пять', 6: 'шесть', 7: 'семь', 8: 'восемь', 9: 'девять', 10: 'десять',
    11: 'одиннадцать', 12: 'двенадцать', 13: 'тринадцать', 14: 'четырнадцать', 15: 'пятнадцать', 16: 'шеснадцать',
    17: 'семнадцать', 18: 'восемнадцать', 19: 'девятнадцать', 20: 'двадцать', 21: 'двадцать одна', 22: 'двадцать две',
    23: 'двадцать три', 24: 'двадцать четыре', 25: 'двадцать пять', 26: 'двадцать шесть', 27: 'двадцать семь',
    28: 'двадцать восемь', 29: 'двадцать девять', 31: 'тридцать одна', 32: 'тридцать две', 33: 'тридцать три',
    34: 'тридцать четыре', 35: 'тридцать пять', 36: 'тридцать шесть', 37: 'тридцать семь', 38: 'тридцать восемь',
    39: 'тридцать девять', 40: 'сорок', 41: 'сорок одна', 42: 'сорок две', 43: 'сорок три', 44: 'сорок четыре',
    45: 'пятнадцати', 46: 'четырнадцати', 47: 'тринадцати', 48: 'двенадцати', 49: 'одиннадцати', 50: 'десяти',
    51: 'девяти', 52: 'восьми', 53: 'семи', 54: 'шести', 55: 'пяти', 56: 'четырех', 57: 'трех', 58: 'двух', 59: 'одной'
}

h1 = {
    1: 'второго', 2: 'третьего', 3: 'четвертого', 4: 'пятого', 5: 'шестого', 6: 'седьмого', 7: 'восьмого', 8: 'девятого',
    9: 'десятого', 10: 'одиннадцатого', 11: 'двенадцатого', 12: 'первого', 13: 'второго', 14: 'третьего', 15: 'четвертого',
    16: 'пятого', 17: 'шестого', 18: 'седьмого', 19: 'восьмого', 20: 'девятого', 21: 'десятого', 22: 'одиннадцатого',
    23: 'двенадцатого', 00: 'первого'
}

h2 = {
    00: 'двенадцать', 1: 'один', 2: 'два', 3: 'три', 4: 'четыре', 13: 'один', 14: 'два', 15: 'три', 16: 'четыре',
    17: 'пять', 18: 'шесть', 19: 'семь', 20: 'восемь', 21: 'девять', 22: 'десять', 23: 'одиннадцать', 24: 'двенадцать'
}

if mm == 0 and hh == 1:
    print(f"{h2[hh]} час ровно")
elif mm == 0 and hh == 13:
    print(f"{h2[hh]} час ровно")
elif mm == 0 and hh == 0:
    print(f"{h2[hh]} часов ровно")
elif mm == 0 and 5 <= hh <= 12:
    print(f"{m1[hh]} часов ровно")
elif mm == 0 and 17 <= hh <= 23:
    print(f"{h2[hh]} часов ровно")
elif mm == 0 and 2 <= hh <= 4:
    print(f"{h2[hh]} часа ровно")
elif mm == 0 and 14 <= hh <= 16:
    print(f"{h2[hh]} часа ровно")
elif mm == 30:
    print(f"половина {h1[hh]}")
elif mm == 1 or mm == 21 or mm == 31 or mm == 41:
    print(f"{m1[mm]} минута {h1[hh]}")
elif 2 <= mm <= 4 or 22 <= mm <= 24 or 32 <= mm <= 34 or 42 <= mm <= 44:
    print(f"{m1[mm]} минуты {h1[hh]}")
elif 5 <= mm <= 20 or 25 <= mm <= 29 or 35 <= mm <= 40:
    print(f"{m1[mm]} минут {h1[hh]}")
elif mm == 59 and hh == 0:
    print(f"без {m1[mm]} минуты час")
elif mm == 59 and hh == 12:
    print(f"без {m1[mm]} минуты час")
elif mm >= 45 and (hh == 0 or hh == 12):
    print(f"без {m1[mm]} минут час")
elif mm >= 45 and 5 <= hh <= 11:
    print(f"без {m1[mm]} минут {m1[hh + 1]}")
else:
    print(f"без {m1[mm]} минут {h2[hh + 1]}")


from cProfile import label
from distutils.file_util import write_file
from unicodedata import ucd_3_2_0
import numpy as np
from matplotlib import pyplot

l=2 #in meter

nx=41
dx=(l/(nx-1))

ny=nx
dy=(l/(ny-1))

nt=5
sigma=0.3
dt=sigma * dx

x=np.linspace(0,l,nx)
y=np.linspace(0,l,ny)

u=np.zeros((ny,nx))
v=np.zeros((ny,nx))

un=np.zeros((ny,nx))
vn=np.zeros((ny,nx))

u[int(0.5/dy):int(1/dy+1),int(0.5/dx):int(1/dx+1)]=2  #IC
v[int(0.5/dy):int(1/dy+1),int(0.5/dx):int(1/dx+1)]=2  #IC

un=np.ones(nx)
print(u)

for n in range(nt):
    un=u.copy() #updateing un
    for j in range(1,ny-1):
        for i in range(1,nx-1):
            u[j,i]=un[j,i] - (un[j,i]*dt/dx) * (un[j,i] - un[j,i-1]) -(vn[j,i]*dt/dy) * (un[j,i] - un[j,i-1])
    u[0, :] = 1
    u[-1, :] = 1
    u[:, 0] = 1
    u[:, -1] = 1

    v[0, :] = 1
    v[-1, :] = 1
    v[:, 0] = 1
    v[:, -1] = 1

fig = pyplot.figure(figsize=(11, 7), dpi=100)
ax = fig.gca(projection='3d')
X, Y = np.meshgrid(x, y)

ax.plot_surface(X, Y, u, cmap=cm.viridis, rstride=2, cstride=2)
ax.set_xlabel('$x$')
ax.set_ylabel('$y$');


import functions
import api
from character import Character

def parse_input(inputstr):
    """
    Parse the input
    """
    word_list = inputstr.split()

    if word_list[0] == 'roll':
        functions.roll(word_list[1:])

    elif word_list[0] == 'search':
        api.search(word_list[1:])

    elif word_list[0] == 'load':
        return functions.load_char(word_list[1:])

if __name__ == "__main__":
    loaded_char = None
    inputstr = ""

    while inputstr != "quit":
        inputstr = input("\n\nEnter command: ")
        print("")
        output = parse_input(inputstr)
        if type(output) == Character:
            loaded_char = output