from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from os import environ
import json
import os
# import amqp_setup

from invokes import invoke_http

monitorBindingKey='*.notifications'

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = environ.get('dbURL')
#app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqlconnector://is213@localhost:3306/notifications'

# to fix the kong bug
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {'pool_recycle': 299}

db = SQLAlchemy(app)

CORS(app)

class Notifications(db.Model):
    __tablename__ = 'notifications'

    notification_id = db.Column(db.Integer, primary_key=True)
    message = db.Column(db.String(1000), nullable=False)
    account_type = db.Column(db.String(10), nullable=False)
    facility_name = db.Column(db.String(64), nullable=False)

    def __init__(self, message, account_type, facility_name):

        self.message = message
        self.account_type = account_type
        self.facility_name = facility_name

    def json(self):
        return {"notification_id": self.notification_id, "message": self.message, "account_type": self.account_type, "facility_name": self.facility_name}

# def receiveNotifications ():
#     amqp_setup.check_setup()

#     #queue_name = "User" and "Admin"
#     # set up a consumer and start to wait for coming messages
#     amqp_setup.channel.basic_consume(queue="Admin", on_message_callback=callback, auto_ack=True)
#     amqp_setup.channel.basic_consume(queue="User", on_message_callback=callback, auto_ack=True)

#     amqp_setup.channel.start_consuming() # an implicit loop waiting to receive messages;
#     #it doesn't exit by default. Use Ctrl+C in the command window to terminate it.

# def callback(channel, method, properties, body): # required signature for the callback; no return
#     print("\nReceived a message by " + __file__)
#     processNotifications(body)
#     print()

# def processNotifications(notificationMsg):

#     print("Printing the notification:")
#     try:
#         notification = json.loads(notificationMsg)
#         print("--JSON:", notification)

#         #call the invoke(create_noti + admin/user, post, json=data)
#         receiver = notification["data"]["receiver"]
#         invoke_http("http://localhost:5007/notifications/" + receiver, method='POST', json=notification["data"])

#     except Exception as e:
#         print("--NOT JSON:", e)
#         print("--DATA:", notificationMsg)
#     print()

#retrieve all user/admin notification
#limit by 5 only
@app.route("/notifications/<string:account_type>", methods=['GET'])
def get_notifications(account_type):
    notificationList = Notifications.query.filter_by(account_type = account_type).order_by(Notifications.notification_id.desc()).limit(5).all()

    if len(notificationList):
        return jsonify(
            {
                "code": 200,
                "data": {
                    "notifications": [notifications.json() for notifications in notificationList]
                }
            }
        )
    return jsonify(
        {
            "code": 404,
            "message": "There are no such notifications."
        }
    ), 404

# #insert into notification
@app.route("/notifications/<string:account_type>", methods=['POST'])
def create_notification(account_type):

    data = request.get_json()

    message = data['message']
    facility_name = data['facility_name']
    print("ACCOUNT_TYPE HERE: " + str(account_type))
    print("DATA HERE: " + str(message))
    notifications = Notifications(account_type = account_type, message = message, facility_name = facility_name)

    try:
        db.session.add(notifications)
        db.session.commit()

    except Exception as e:
        print (e)
        return jsonify(
            {
                "code": 500,
                "data": {
                    "account_type": account_type
                },
                "message": "An error occurred creating the notifications."
            }
        ), 500

    return jsonify(
        {   #SUCCESS
            "code": 201,
            "data": notifications.json()
        }
    ), 201

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=5007, debug=True)
    #app.port = 5007
    # print("\nThis is " + os.path.basename(__file__), end='')
    # print(": monitoring routing key '{}' in exchange '{}' ...".format(monitorBindingKey, amqp_setup.exchangename))
    # receiveNotifications()


"""
Fields and methods used by the LMS and Studio.
BASICALLY CRIBBED BY @jbau from the edx-ora2 project at
https://raw.githubusercontent.com/edx/edx-ora2/master/apps/openassessment/xblock/lms_mixin.py
"""

from xblock.fields import String, Float, Scope, DateTime

class LmsCompatibilityMixin(object):
    """
    Extra fields and methods used by LMS/Studio.
    """
    # Studio the default value for this field to show this XBlock
    # in the list of "Advanced Components"
    display_name = String(
        default="js-parsons problem", scope=Scope.settings,
        help="Display name"
    )

    start = DateTime(
        default=None, scope=Scope.settings,
        help="ISO-8601 formatted string representing the start date of this assignment."
    )

    due = DateTime(
        default=None, scope=Scope.settings,
        help="ISO-8601 formatted string representing the due date of this assignment."
    )

    weight = Float(
        display_name="Problem Weight",
        help="Defines the number of points this problem is worth.",
        values={"min": 0, "step": .1},
        default=1.0,
        scope=Scope.settings
    )

    def has_dynamic_children(self):
        """Do we dynamically determine our children? No, we don't have any.

        The LMS wants to know this to see if it has to instantiate our module
        and query it to find the children, or whether it can just trust what's
        in the static (cheaper) children listing.
        """
        return False

    @property
    def has_score(self):
        """Are we a scored type (read: a problem). Yes.

        For LMS Progress page/grades download purposes, we're always going to
        have a score, even if it's just 0 at the start.
        """
        return True

    @property
    def icon_class(self):
        return 'problem'

    def max_score(self):
        """The maximum raw score of our problem.
        """
        return self.weight


#we compute deltaB and make plots of Bx, By, Bx, |B| vs x
#for the 4/03 data

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd

#import off data
fileOff = "/Users/alexandraklipfel/Desktop/senior_thesis/data_4-14/off/averaged_off_rot-Z.txt"
datOff = np.loadtxt(fileOff)

#import on data
fileOn = "/Users/alexandraklipfel/Desktop/senior_thesis/data_4-14/on/averaged_on_rot-Z.txt"
datOn = np.loadtxt(fileOn)

#Again, there are no intervals, so everything is much simpler

plusX = 4050
minX = -3950
plusY = 8050
minY = 50

V1 = -58654

T0 = -100 #need to verify

#get data
z = (15.2 / 50000) * (datOn[:, 2] - V1)
print(z)
dBx = datOn[:, 3] - datOff[:, 3]
dBy = datOn[:, 5] - datOff[:, 5]
dBz = datOn[:, 7] - datOff[:, 7]

B = np.sqrt(np.square(dBx) + np.square(dBy) + np.square(dBz))

#dBx vs z
plt.scatter(z, dBx, color="maroon")
plt.plot(z, dBx, color="maroon")

plt.xlabel("z (cm)")
plt.ylabel("Bx (mG)")
plt.title("delta Bx (along B0) vs z: off")
plt.savefig("Bx_z-deltaB_tcorr.png", dpi=500)
plt.show()

#dBy vs z
plt.scatter(z, dBy, color="maroon")
plt.plot(z, dBy, color="maroon")

plt.xlabel("z (cm)")
plt.ylabel("By (mG)")
plt.title("delta  By vs z: off")
plt.savefig("By_z-deltaB_tcorr.png", dpi=500)
plt.show()

#dBz vs z
plt.scatter(z, dBz, color="maroon")
plt.plot(z, dBz, color="maroon")

plt.xlabel("z (cm)")
plt.ylabel("Bz (mG)")
plt.title("delta  Bz vs z: off")
plt.savefig("Bz_z-deltaB_tcorr.png", dpi=500)
plt.show()

#dB vs z
plt.scatter(z, B, color="maroon")
plt.plot(z, B, color="maroon")

plt.xlabel("z (cm)")
plt.ylabel("|B| (mG)")
plt.title("delta  |B| vs z: off")
plt.savefig("B_z-deltaB_tcorr.png", dpi=500)
plt.show()


import os
import sqlite3
from urllib.request import urlopen
import csv
import io
from intellistock.data import data

ARCHIVE_BASE_URL = "http://hunyadym.hu/stock"
ARCHIVE_LIST = "list.php"

def setup_database():
    if os.path.isfile(data.DB_PATH):
        data.conn = sqlite3.connect(data.DB_PATH)
        return

    global conn
    data.conn = sqlite3.connect(data.DB_PATH)
    data.conn.execute('''CREATE TABLE StockData (
                    id INTEGER PRIMARY KEY,
                    paper_name TEXT,
                    datetime INTEGER,
                    close REAL,
                    volume INTEGER);''')

    data.conn.execute('''CREATE TABLE Stocks (
                    paper_name TEXT);''')
    data.conn.commit()
    initialize_database()

    persist_stocks()

    data.conn.commit()

def initialize_database():
    urlpath = urlopen(ARCHIVE_BASE_URL + "/" + ARCHIVE_LIST)

    files = urlpath.read().decode('utf-8').split()

    for f in files:
        print("loading " + f)
        load_from_csv(f)

def load_from_csv(csv_path):
    global stocks

    urlpath = urlopen(ARCHIVE_BASE_URL + "/" + csv_path)

    file = urlpath.read().decode('ISO-8859-1')

    csv_reader = csv.reader(io.StringIO(file))
    next(csv_reader) #skip header

    for row in csv_reader:
        try:
            paper_name = row[0]
            date = int(row[2])
            time = int(row[3])
            close = float(row[4])
            volume = int(row[5])

            data.conn.execute("INSERT INTO StockData VALUES (?, ?, ?, ?, ?)",
                     (None, paper_name, date * 1000000 + time, close, volume))

            if paper_name not in data.stocks:
                data.stocks.add(paper_name)

        except ValueError:
            continue

def persist_stocks():
    for stock in data.stocks:
        data.conn.execute("INSERT INTO Stocks VALUES (?)", [stock])

setup_database()


# This file defines all the pruning functions that main.py will use.
# and the method of building a (pretrained) ResNet-18 model
import torch
import torch.nn as nn
import torch.nn.functional as fct
from torch.hub import load_state_dict_from_url
import math
import numpy as np
import pickle

# get pretrained parameters
model_urls = {
    'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
}

def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
    """3x3 convolution with padding"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
                     padding=dilation, groups=groups, bias=False, dilation=dilation)

def conv1x1(in_planes, out_planes, stride=1):
    """1x1 convolution"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)

class BasicBlock(nn.Module):
    expansion = 1
    # copy all the prev_model in, out channels to rebuild the new model if prev_model is not None
    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
                 base_width=64, dilation=1, norm_layer=None, prev_model=None):
        super(BasicBlock, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        if groups != 1 or base_width != 64:
            raise ValueError('BasicBlock only supports groups=1 and base_width=64')
        if dilation > 1:
            raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
        # Both self.conv1 and self.downsample layers downsample the input when stride != 1
        self.conv1 = conv3x3(inplanes, planes, stride)
        self.bn1 = norm_layer(planes)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = conv3x3(planes, planes)
        self.bn2 = norm_layer(planes)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

def resnet18(pretrained=False, progress=True, **kwargs):
    r"""ResNet-18 model from
    `"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
    Args:
        pretrained (bool): If True, returns a model pre-trained on ImageNet
        progress (bool): If True, displays a progress bar of the download to stderr
    """
    return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress, **kwargs)

def _resnet(arch, block, layers, pretrained, progress, **kwargs):
    model = ResNet(block, layers, **kwargs)
    if pretrained:
        state_dict = load_state_dict_from_url(model_urls[arch],
                                              progress=progress)
        model.load_state_dict(state_dict)
    return model

class ResNet(nn.Module):
    #block = Basicblock, layers=[2,2,2,2]
    def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,
                 groups=1, width_per_group=64, replace_stride_with_dilation=None,
                 norm_layer=None):
        super(ResNet, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        self._norm_layer = norm_layer

        self.inplanes = 64
        self.dilation = 1
        self.compute_metric_on = ["conv_1"] + [f"conv_{subnet_id}_{i}_{j}" for subnet_id in range(2, 6)
                                               for i in range(1, 3)
                                               for j in range(1, 3)]
        self.all_layers = self.compute_metric_on +["fc"] + [f"downsample{i}" for i in range(2, 5)]

        # init model parameters
        self.n_channels = [64, 128, 256, 512]  # channel sizes
        self.drop_rate = 0.0
        self.perf_table = None
        self.num_classes = 1000
        self.total_cost = 0 # us->s
        self.to_prune = (['conv_2_1_1'] + ['conv_2_2_1']
                   + ['conv_3_1_1'] + ['conv_3_2_1']
                   + ['conv_4_1_1'] + ['conv_4_2_1']
                   + ['conv_5_1_1'] + ['conv_5_2_1']
			       )

        if replace_stride_with_dilation is None:
            # each element in the tuple indicates if we should replace
            # the 2x2 stride with a dilated convolution instead
            replace_stride_with_dilation = [False, False, False]
        if len(replace_stride_with_dilation) != 3:
            raise ValueError("replace_stride_with_dilation should be None "
                             "or a 3-element tuple, got {}".format(replace_stride_with_dilation))
        self.groups = groups
        self.base_width = width_per_group
        self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
                               bias=False)
        self.bn1 = norm_layer(self.inplanes)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(block, 64, layers[0], layer_id=1)
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
                                       dilate=replace_stride_with_dilation[0], layer_id=2)
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
                                       dilate=replace_stride_with_dilation[1], layer_id=3)
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
                                       dilate=replace_stride_with_dilation[2], layer_id=4)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(512 * block.expansion, num_classes)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

        # Zero-initialize the last BN in each residual branch,
        # so that the residual branch starts with zeros, and each residual block behaves like an identity.
        # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
        if zero_init_residual:
            for m in self.modules():
                if isinstance(m, Bottleneck):
                    nn.init.constant_(m.bn3.weight, 0)
                elif isinstance(m, BasicBlock):
                    nn.init.constant_(m.bn2.weight, 0)

    #_make_layer = make_subnetwork
    # block=BasicBlock(in "make_subnetwork" for loop),
	# planes=self.n_channels[x], blocks=n_blocks_per_subnet,
	# stride=stride, dilate=???, layer_id=1~4
    def _make_layer(self, block, planes, blocks, layer_id, stride=1, dilate=False):
        norm_layer = self._norm_layer
        downsample = None
        previous_dilation = self.dilation
        if dilate:
            self.dilation *= stride
            stride = 1
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                conv1x1(self.inplanes, planes * block.expansion, stride),
                norm_layer(planes * block.expansion),
            )

        layers = []
        # small block 1
        layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
                            self.base_width, previous_dilation, norm_layer))
        # inplanes = [64, 64, 128, 256]
        self.inplanes = planes * block.expansion

        # small block 2~N
        for _ in range(1, blocks): # blocks = 2 if resnet18
            layers.append(block(self.inplanes, planes, groups=self.groups,
                                base_width=self.base_width, dilation=self.dilation,
                                norm_layer=norm_layer))

        return nn.Sequential(*layers)

    def _forward_impl(self, x):
        # See note [TorchScript super()]
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)

        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.fc(x)

        return x

    def forward(self, x):
        return self._forward_impl(x)

    def choose_num_channels(self, layer_name, cost_red_obj, allow_small_prunings):
        """chooses how many channels to remove
        :param layer_name: layer at which we remove channels
        :param cost_red_obj: the given cost reduction objective (to attain or approach as much as possible)
        :param allow_small_prunings: allows to prune layers for which we cannot achieve the reduction objective
        :returns: the number of channels to prune and achieved cost reduction or None, None if (we cannot achieve
        cost_red_obj and allow_small_prunings is set to False) or the Layer was pruned away"""
        layer = self.layer1[0].conv2
        if layer_name == 'conv_2_1_1':
            layer = self.layer1[0].conv1
        elif layer_name == 'conv_2_1_2':
            layer = self.layer1[0].conv2
        elif layer_name == 'conv_2_2_1':
            layer = self.layer1[1].conv1
        elif layer_name == 'conv_2_2_2':
            layer = self.layer1[1].conv2
        elif layer_name == 'conv_3_1_1':
            layer = self.layer2[0].conv1
        elif layer_name == 'conv_3_1_2':
            layer = self.layer2[0].conv2
        elif layer_name == 'conv_3_2_1':
            layer = self.layer2[1].conv1
        elif layer_name == 'conv_3_2_2':
            layer = self.layer2[1].conv2
        elif layer_name == 'conv_4_1_1':
            layer = self.layer3[0].conv1
        elif layer_name == 'conv_4_1_2':
            layer = self.layer3[0].conv2
        elif layer_name == 'conv_4_2_1':
            layer = self.layer3[1].conv1
        elif layer_name == 'conv_4_2_2':
            layer = self.layer3[1].conv2
        elif layer_name == 'conv_5_1_1':
            layer = self.layer4[0].conv1
        elif layer_name == 'conv_5_1_2':
            layer = self.layer4[0].conv2
        elif layer_name == 'conv_5_2_1':
            layer = self.layer4[1].conv1
        elif layer_name == 'conv_5_2_2':
            layer = self.layer4[1].conv2

        if layer is None:
            print(f"{layer_name} has been pruned away")
            return None, None

        init_nbr_out_channels = layer.out_channels
        print(f"{layer_name} has {init_nbr_out_channels} output channels")
        #print(f'start get_cost_array layername={layer_name}')
        costs_array = self._get_cost_array(layer_name)
        #print('end get_cost_array')
        # determines the number of filters
        prev_cost = costs_array[init_nbr_out_channels - 1]
        minimum_channel_per_layer = 10
        for rem_channels in range(init_nbr_out_channels - 1, minimum_channel_per_layer-1, -1):  # could not be made O(log(n)) instead because cost
            # table not strictly monotonic
            cost_diff = prev_cost - costs_array[rem_channels - 1]  # -1 because we are directly accessing a cost_array
            if cost_diff > cost_red_obj:
                return init_nbr_out_channels - rem_channels, cost_diff
        print(f"{layer_name} cannot be pruned anymore")
        return None, None

    def load_table(self, name):
        """loads the pickle file coresponding to table and prints the total cost of the network"""
        with open(name, 'rb') as file:
            self.perf_table = pickle.load(file)

        self._compute_total_cost()

        print(f"the total cost of the model is: {self.total_cost/1000000 :.3f}s according to the perf table")

    def _get_cost_array(self, layer_name):
        """returns the costs array corresponding to the layer named laryer_name, the difference between cost_array[a]
        and cost_array[b] is the performance gain according to the perf_tables when pruning from a to b channels in the
        layer named laryer_name"""
        '''now prune conv_x_y_1 only.'''
        #else:  # layer_name = Conv_x_y_1, we only influence Conv_x_y_2
        # since we got here, Conv_x_y_1 cannot be none
        layer_name_table = f"No_Stride_{int(layer_name[5])-1}"
        next_layer = layer_name[:9] + "2"
        subnet_layer_name = f"layer{int(layer_name[5])-1}"
        layer1_in_channels = getattr(self, subnet_layer_name)[int(layer_name[7])-1].conv1.in_channels
        layer2_out_channels = getattr(self, subnet_layer_name)[int(layer_name[7])-1].conv2.out_channels

        costs_array = self.get_cost(layer_name_table, layer1_in_channels, None) + \
            self.get_cost(layer_name_table, None, layer2_out_channels)

        return costs_array

    def get_cost(self, layer_name, in_channel, out_channel):
        """ get the cost of layer layer_name when it has in_channel and out_channel channels, None means we return all
        input channels"""
        if in_channel is None:
            if out_channel is None:
                return self.perf_table[layer_name][:, :]
            else:
                return self.perf_table[layer_name][:, out_channel - 1]
        elif out_channel is None:
            return self.perf_table[layer_name][in_channel - 1, :]
        else:
            return self.perf_table[layer_name][in_channel - 1, out_channel - 1]

    def _compute_total_cost(self):
        """computes the total cost of the network by adding the costs of the channels in the perf_table"""
        self.total_cost = 0
        for layer_name in self.all_layers: # TODO
            if layer_name == "fc":
                self.total_cost += self.get_cost("FC", self.fc.in_features, 1)
            elif layer_name[:10] == "downsample": #self.layerx[0].downsample[0].in_channels
                subnet_layer_name = "layer" + layer_name[10]
                din = getattr(self, subnet_layer_name)[0].downsample[0].in_channels
                dout = getattr(self, subnet_layer_name)[0].downsample[0].out_channels
                self.total_cost += self.get_cost(f"DownSampling_{layer_name[10]}", din, dout)
            elif layer_name == 'conv_1':
                self.total_cost += self.get_cost("Conv_1", self.conv1.in_channels, self.conv1.out_channels)
            else:
                layer = self.layer1[0].conv2
                if layer_name == 'conv_2_1_1':
                    layer = self.layer1[0].conv1
                elif layer_name == 'conv_2_1_2':
                    layer = self.layer1[0].conv2
                elif layer_name == 'conv_2_2_1':
                    layer = self.layer1[1].conv1
                elif layer_name == 'conv_2_2_2':
                    layer = self.layer1[1].conv2
                elif layer_name == 'conv_3_1_1':
                    layer = self.layer2[0].conv1
                elif layer_name == 'conv_3_1_2':
                    layer = self.layer2[0].conv2
                elif layer_name == 'conv_3_2_1':
                    layer = self.layer2[1].conv1
                elif layer_name == 'conv_3_2_2':
                    layer = self.layer2[1].conv2
                elif layer_name == 'conv_4_1_1':
                    layer = self.layer3[0].conv1
                elif layer_name == 'conv_4_1_2':
                    layer = self.layer3[0].conv2
                elif layer_name == 'conv_4_2_1':
                    layer = self.layer3[1].conv1
                elif layer_name == 'conv_4_2_2':
                    layer = self.layer3[1].conv2
                elif layer_name == 'conv_5_1_1':
                    layer = self.layer4[0].conv1
                elif layer_name == 'conv_5_1_2':
                    layer = self.layer4[0].conv2
                elif layer_name == 'conv_5_2_1':
                    layer = self.layer4[1].conv1
                elif layer_name == 'conv_5_2_2':
                    layer = self.layer4[1].conv2
                else:
                    layer = None

                if layer is not None:
                    if layer_name.endswith("_1_1"):#conv_5_1_1 = self.layer4[0].conv1
                        layer_name_table = f"Stride_{int(layer_name[5])-1}"
                    else:
                        layer_name_table = f"No_Stride_{int(layer_name[5])-1}"

                    self.total_cost += self.get_cost(layer_name_table, layer.in_channels, layer.out_channels)

    def remove_from_in_channels(self, layer_name, remaining_channels):
        """removes the input channels to the layer
        :param layer_name: the name of the layer that will be pruned
        :param remaining_channels: the offsets of the remaining channels"""
        # get attribute
        #print(f'Hello from rfinchannels! layer_name = {layer_name}')
        layer = self.layer1[0].conv2
        if layer_name == 'conv_2_1_1':
            layer = self.layer1[0].conv1
        elif layer_name == 'conv_2_1_2':
            layer = self.layer1[0].conv2
        elif layer_name == 'conv_2_2_1':
            layer = self.layer1[1].conv1
        elif layer_name == 'conv_2_2_2':
            layer = self.layer1[1].conv2
        elif layer_name == 'conv_3_1_1':
            layer = self.layer2[0].conv1
        elif layer_name == 'conv_3_1_2':
            layer = self.layer2[0].conv2
        elif layer_name == 'conv_3_2_1':
            layer = self.layer2[1].conv1
        elif layer_name == 'conv_3_2_2':
            layer = self.layer2[1].conv2
        elif layer_name == 'conv_4_1_1':
            layer = self.layer3[0].conv1
        elif layer_name == 'conv_4_1_2':
            layer = self.layer3[0].conv2
        elif layer_name == 'conv_4_2_1':
            layer = self.layer3[1].conv1
        elif layer_name == 'conv_4_2_2':
            layer = self.layer3[1].conv2
        elif layer_name == 'conv_5_1_1':
            layer = self.layer4[0].conv1
        elif layer_name == 'conv_5_1_2':
            layer = self.layer4[0].conv2
        elif layer_name == 'conv_5_2_1':
            layer = self.layer4[1].conv1
        elif layer_name == 'conv_5_2_2':
            layer = self.layer4[1].conv2
        else:
            raise Exception('Error from "remove_from_in_channels"')
        num_remaining_channels = remaining_channels.size(0)
        if layer_name == "FC":
            new_layer = nn.Linear(num_remaining_channels, self.num_classes)
            new_layer.weight.data = layer.weight.data[:, remaining_channels]
            new_layer.bias.data = layer.bias.data
        else:
            new_layer = nn.Conv2d(in_channels=num_remaining_channels, out_channels=layer.out_channels,
                                  kernel_size=layer.kernel_size, stride=layer.stride, padding=layer.padding,
                                  dilation=layer.dilation, groups=layer.groups, bias=layer.bias is not None)
            new_layer.weight.data = layer.weight.data[:, remaining_channels, :, :]  # out_ch * in_ch * height * width
            if new_layer.bias is not None:
                new_layer.bias.data = layer.bias.data
        # set attribute
        if layer_name == 'conv_2_1_1':
            self.layer1[0].conv1 = new_layer
        elif layer_name == 'conv_2_1_2':
            self.layer1[0].conv2 = new_layer
        elif layer_name == 'conv_2_2_1':
            self.layer1[1].conv1 = new_layer
        elif layer_name == 'conv_2_2_2':
            self.layer1[1].conv2 = new_layer
        elif layer_name == 'conv_3_1_1':
            self.layer2[0].conv1 = new_layer
        elif layer_name == 'conv_3_1_2':
            self.layer2[0].conv2 = new_layer
        elif layer_name == 'conv_3_2_1':
            self.layer2[1].conv1 = new_layer
        elif layer_name == 'conv_3_2_2':
            self.layer2[1].conv2 = new_layer
        elif layer_name == 'conv_4_1_1':
            self.layer3[0].conv1 = new_layer
        elif layer_name == 'conv_4_1_2':
            self.layer3[0].conv2 = new_layer
        elif layer_name == 'conv_4_2_1':
            self.layer3[1].conv1 = new_layer
        elif layer_name == 'conv_4_2_2':
            self.layer3[1].conv2 = new_layer
        elif layer_name == 'conv_5_1_1':
            self.layer4[0].conv1 = new_layer
        elif layer_name == 'conv_5_1_2':
            self.layer4[0].conv2 = new_layer
        elif layer_name == 'conv_5_2_1':
            self.layer4[1].conv1 = new_layer
        elif layer_name == 'conv_5_2_2':
            self.layer4[1].conv2 = new_layer

    def remove_from_out_channels(self, layer_name, remaining_channels):
        """removes the output channels to the layer and adapts the corresponding batchnorm layers (in the case of
        Skip_x, Conv_x_0_2_bn is left unchanged)
        :param layer_name: the name of the layer that will be pruned
        :param remaining_channels: the offsets of the remaining channels"""
        layer =  self.layer1[0].conv1 # conv_2_1_1
        if layer_name == 'conv_2_1_1':
            layer = self.layer1[0].conv1
        elif layer_name == 'conv_2_1_2':
            layer = self.layer1[0].conv2
        elif layer_name == 'conv_2_2_1':
            layer = self.layer1[1].conv1
        elif layer_name == 'conv_2_2_2':
            layer = self.layer1[1].conv2
        elif layer_name == 'conv_3_1_1':
            layer = self.layer2[0].conv1
        elif layer_name == 'conv_3_1_2':
            layer = self.layer2[0].conv2
        elif layer_name == 'conv_3_2_1':
            layer = self.layer2[1].conv1
        elif layer_name == 'conv_3_2_2':
            layer = self.layer2[1].conv2
        elif layer_name == 'conv_4_1_1':
            layer = self.layer3[0].conv1
        elif layer_name == 'conv_4_1_2':
            layer = self.layer3[0].conv2
        elif layer_name == 'conv_4_2_1':
            layer = self.layer3[1].conv1
        elif layer_name == 'conv_4_2_2':
            layer = self.layer3[1].conv2
        elif layer_name == 'conv_5_1_1':
            layer = self.layer4[0].conv1
        elif layer_name == 'conv_5_1_2':
            layer = self.layer4[0].conv2
        elif layer_name == 'conv_5_2_1':
            layer = self.layer4[1].conv1
        elif layer_name == 'conv_5_2_2':
            layer = self.layer4[1].conv2
        else:
            layer = None

        num_remaining_channels = remaining_channels.size(0)

        # conv layer
        new_layer = nn.Conv2d(in_channels=layer.in_channels, out_channels=num_remaining_channels,
                              kernel_size=layer.kernel_size, stride=layer.stride, padding=layer.padding,
                              dilation=layer.dilation, groups=layer.groups, bias=layer.bias is not None)

        new_layer.weight.data = layer.weight.data[remaining_channels, :, :, :]  # out_ch * in_ch * height * width
        if new_layer.bias is not None:
            new_layer.bias.data = layer.bias.data[remaining_channels]

        # set attribute
        if layer_name == 'conv_2_1_1':
            self.layer1[0].conv1 = new_layer
        elif layer_name == 'conv_2_1_2':
            self.layer1[0].conv2 = new_layer
        elif layer_name == 'conv_2_2_1':
            self.layer1[1].conv1 = new_layer
        elif layer_name == 'conv_2_2_2':
            self.layer1[1].conv2 = new_layer
        elif layer_name == 'conv_3_1_1':
            self.layer2[0].conv1 = new_layer
        elif layer_name == 'conv_3_1_2':
            self.layer2[0].conv2 = new_layer
        elif layer_name == 'conv_3_2_1':
            self.layer2[1].conv1 = new_layer
        elif layer_name == 'conv_3_2_2':
            self.layer2[1].conv2 = new_layer
        elif layer_name == 'conv_4_1_1':
            self.layer3[0].conv1 = new_layer
        elif layer_name == 'conv_4_1_2':
            self.layer3[0].conv2 = new_layer
        elif layer_name == 'conv_4_2_1':
            self.layer3[1].conv1 = new_layer
        elif layer_name == 'conv_4_2_2':
            self.layer3[1].conv2 = new_layer
        elif layer_name == 'conv_5_1_1':
            self.layer4[0].conv1 = new_layer
        elif layer_name == 'conv_5_1_2':
            self.layer4[0].conv2 = new_layer
        elif layer_name == 'conv_5_2_1':
            self.layer4[1].conv1 = new_layer
        elif layer_name == 'conv_5_2_2':
            self.layer4[1].conv2 = new_layer

        # batchnorm layer # If I prune some channels of self.layer1[0].conv1(conv2_1_1), self.layer1[0].bn1(conv2_1_1_bn) should be modified at the same time.
        bn_layer = self.layer1[0].bn1 # initialize bn_layer
        if layer_name[:4] != "Skip":
            # get attribute of batchnorm layer (bn)
            if layer_name == 'conv_2_1_1':
                bn_layer = self.layer1[0].bn1
            elif layer_name == 'conv_2_1_2':
                bn_layer = self.layer1[0].bn2
            elif layer_name == 'conv_2_2_1':
                bn_layer = self.layer1[1].bn1
            elif layer_name == 'conv_2_2_2':
                bn_layer = self.layer1[1].bn2
            elif layer_name == 'conv_3_1_1':
                bn_layer = self.layer2[0].bn1
            elif layer_name == 'conv_3_1_2':
                bn_layer = self.layer2[0].bn2
            elif layer_name == 'conv_3_2_1':
                bn_layer = self.layer2[1].bn1
            elif layer_name == 'conv_3_2_2':
                bn_layer = self.layer2[1].bn2
            elif layer_name == 'conv_4_1_1':
                bn_layer = self.layer3[0].bn1
            elif layer_name == 'conv_4_1_2':
                bn_layer = self.layer3[0].bn2
            elif layer_name == 'conv_4_2_1':
                bn_layer = self.layer3[1].bn1
            elif layer_name == 'conv_4_2_2':
                bn_layer = self.layer3[1].bn2
            elif layer_name == 'conv_5_1_1':
                bn_layer = self.layer4[0].bn1
            elif layer_name == 'conv_5_1_2':
                bn_layer = self.layer4[0].bn2
            elif layer_name == 'conv_5_2_1':
                bn_layer = self.layer4[1].bn1
            elif layer_name == 'conv_5_2_2':
                bn_layer = self.layer4[1].bn2

            new_bn_layer = nn.BatchNorm2d(num_remaining_channels, eps=bn_layer.eps, momentum=bn_layer.momentum,
                                          affine=bn_layer.affine, track_running_stats=bn_layer.track_running_stats)
            if new_bn_layer.affine:
                new_bn_layer.weight.data = bn_layer.weight.data[remaining_channels]
                new_bn_layer.bias.data = bn_layer.bias.data[remaining_channels]

            if new_bn_layer.track_running_stats:
                new_bn_layer.running_mean.data = bn_layer.running_mean.data[remaining_channels]
                new_bn_layer.running_var.data = bn_layer.running_var.data[remaining_channels]
                new_bn_layer.num_batches_tracked.data = bn_layer.num_batches_tracked.data
            # set attribute of batchnorm layer (bn)
            if layer_name == 'conv_2_1_1':
                self.layer1[0].bn1 = new_bn_layer
            elif layer_name == 'conv_2_1_2':
                self.layer1[0].bn2 = new_bn_layer
            elif layer_name == 'conv_2_2_1':
                self.layer1[1].bn1 = new_bn_layer
            elif layer_name == 'conv_2_2_2':
                self.layer1[1].bn2 = new_bn_layer
            elif layer_name == 'conv_3_1_1':
                self.layer2[0].bn1 = new_bn_layer
            elif layer_name == 'conv_3_1_2':
                self.layer2[0].bn2 = new_bn_layer
            elif layer_name == 'conv_3_2_1':
                self.layer2[1].bn1 = new_bn_layer
            elif layer_name == 'conv_3_2_2':
                self.layer2[1].bn2 = new_bn_layer
            elif layer_name == 'conv_4_1_1':
                self.layer3[0].bn1 = new_bn_layer
            elif layer_name == 'conv_4_1_2':
                self.layer3[0].bn2 = new_bn_layer
            elif layer_name == 'conv_4_2_1':
                self.layer3[1].bn1 = new_bn_layer
            elif layer_name == 'conv_4_2_2':
                self.layer3[1].bn2 = new_bn_layer
            elif layer_name == 'conv_5_1_1':
                self.layer4[0].bn1 = new_bn_layer
            elif layer_name == 'conv_5_1_2':
                self.layer4[0].bn2 = new_bn_layer
            elif layer_name == 'conv_5_2_1':
                self.layer4[1].bn1 = new_bn_layer
            elif layer_name == 'conv_5_2_2':
                self.layer4[1].bn2 = new_bn_layer
            #else:
                # error
    def choose_which_channels(self, layer_name, num_channels):
        """chooses which channels remains after the pruning
        :param layer_name: layer at which we remove filters
        :param num_channels: the number of channels to remove
        :returns: the id of the channels that survives the pruning"""
        pruning_score = self.get_pruning_score(layer_name)
        #print(f'From choose_which_channels: {self.layer1[0].conv1}')

        # get the channels with biggest score
        _, remaining_channels = torch.topk(pruning_score, k=pruning_score.size(0) - num_channels, largest=True, dim=0)

        remaining_channels, _ = torch.sort(remaining_channels)

        return remaining_channels

    def get_pruning_score(self, layer_name):
        """get the pruning score (the bigger the less interesting to prune) associated with each channel of the layer
        :param layer_name: name of the concerned layer
        :returns: the pruning_score associated with each channel"""
        # initialize weights as weights of conv_2_1_1
        #weights = getattr(self, layer_name).weight.data  # out_ch * in_ch * height * width
        weights = self.layer1[0].conv1.weight.data # conv_2_1_1
        if layer_name == 'conv_2_1_1':
            weights = self.layer1[0].conv1.weight.data
        elif layer_name == 'conv_2_1_2':
            weights = self.layer1[0].conv2.weight.data
        elif layer_name == 'conv_2_2_1':
            weights = self.layer1[1].conv1.weight.data
        elif layer_name == 'conv_2_2_2':
            weights = self.layer1[1].conv2.weight.data
        elif layer_name == 'conv_3_1_1':
            weights = self.layer2[0].conv1.weight.data
        elif layer_name == 'conv_3_1_2':
            weights = self.layer2[0].conv2.weight.data
        elif layer_name == 'conv_3_2_1':
            weights = self.layer2[1].conv1.weight.data
        elif layer_name == 'conv_3_2_2':
            weights = self.layer2[1].conv2.weight.data
        elif layer_name == 'conv_4_1_1':
            weights = self.layer3[0].conv1.weight.data
        elif layer_name == 'conv_4_1_2':
            weights = self.layer3[0].conv2.weight.data
        elif layer_name == 'conv_4_2_1':
            weights = self.layer3[1].conv1.weight.data
        elif layer_name == 'conv_4_2_2':
            weights = self.layer3[1].conv2.weight.data
        elif layer_name == 'conv_5_1_1':
            weights = self.layer4[0].conv1.weight.data
        elif layer_name == 'conv_5_1_2':
            weights = self.layer4[0].conv2.weight.data
        elif layer_name == 'conv_5_2_1':
            weights = self.layer4[1].conv1.weight.data
        elif layer_name == 'conv_5_2_2':
            weights = self.layer4[1].conv2.weight.data
        #else:
            # error

        weights_norm = torch.norm(weights.view(weights.size()[0], -1), p=2, dim=1)
        num_layers = 1
        pruning_score = weights_norm.div(num_layers)

        return pruning_score

    def prune_channels(self, layer_name, remaining_channels): # TODO: try to implement pruning every layer
        """modifies the structure of self so as to remove the given channels at the given layer
        :param layer_name: the name of the layer that will be pruned
        :param remaining_channels: the offsets of the remaining channels"""
        # name == conv_x_y_1, we only influence conv_x_y_2
        next_layer_name = layer_name[:9] + "2"
        if remaining_channels.size(0) != 0:
            self.remove_from_out_channels(layer_name, remaining_channels)
            self.remove_from_in_channels(next_layer_name, remaining_channels)
        else:
            # set attribute
            if layer_name == 'conv_2_1_1':
                self.layer1[0].conv1 = None
            elif layer_name == 'conv_2_1_2':
                self.layer1[0].conv2 = None
            elif layer_name == 'conv_2_2_1':
                self.layer1[1].conv1 = None
            elif layer_name == 'conv_2_2_2':
                self.layer1[1].conv2 = None
            elif layer_name == 'conv_3_1_1':
                self.layer2[0].conv1 = None
            elif layer_name == 'conv_3_1_2':
                self.layer2[0].conv2 = None
            elif layer_name == 'conv_3_2_1':
                self.layer2[1].conv1 = None
            elif layer_name == 'conv_3_2_2':
                self.layer2[1].conv2 = None
            elif layer_name == 'conv_4_1_1':
                self.layer3[0].conv1 = None
            elif layer_name == 'conv_4_1_2':
                self.layer3[0].conv2 = None
            elif layer_name == 'conv_4_2_1':
                self.layer3[1].conv1 = None
            elif layer_name == 'conv_4_2_2':
                self.layer3[1].conv2 = None
            elif layer_name == 'conv_5_1_1':
                self.layer4[0].conv1 = None
            elif layer_name == 'conv_5_1_2':
                self.layer4[0].conv2 = None
            elif layer_name == 'conv_5_2_1':
                self.layer4[1].conv1 = None
            elif layer_name == 'conv_5_2_2':
                self.layer4[1].conv2 = None

            if next_layer_name == 'conv_2_1_1':
                self.layer1[0].conv1 = None
            elif next_layer_name == 'conv_2_1_2':
                self.layer1[0].conv2 = None
            elif next_layer_name == 'conv_2_2_1':
                self.layer1[1].conv1 = None
            elif next_layer_name == 'conv_2_2_2':
                self.layer1[1].conv2 = None
            elif next_layer_name == 'conv_3_1_1':
                self.layer2[0].conv1 = None
            elif next_layer_name == 'conv_3_1_2':
                self.layer2[0].conv2 = None
            elif next_layer_name == 'conv_3_2_1':
                self.layer2[1].conv1 = None
            elif next_layer_name == 'conv_3_2_2':
                self.layer2[1].conv2 = None
            elif next_layer_name == 'conv_4_1_1':
                self.layer3[0].conv1 = None
            elif next_layer_name == 'conv_4_1_2':
                self.layer3[0].conv2 = None
            elif next_layer_name == 'conv_4_2_1':
                self.layer3[1].conv1 = None
            elif next_layer_name == 'conv_4_2_2':
                self.layer3[1].conv2 = None
            elif next_layer_name == 'conv_5_1_1':
                self.layer4[0].conv1 = None
            elif next_layer_name == 'conv_5_1_2':
                self.layer4[0].conv2 = None
            elif next_layer_name == 'conv_5_2_1':
                self.layer4[1].conv1 = None
            elif next_layer_name == 'conv_5_2_2':
                self.layer4[1].conv2 = None


import requests
import time
from pytz import utc
from datetime import datetime
from pymongo import MongoClient
from apscheduler.schedulers.blocking import BlockingScheduler
import logging

client = MongoClient()
database = client['predictor']
collection = database['gdax']
tickCount = 0;

logging.basicConfig()

def tick():
    global tickCount
    start = time.clock()
    ticker = requests.get('https://api.pro.coinbase.com/products/BTC-USD/ticker').json()
    depth = requests.get('https://api.pro.coinbase.com/products/BTC-USD/book?level=2').json()
    request_time = time.clock() - start
    date = datetime.now()
    price = float(ticker['price'])
    v_bid = sum([float(bid[1]) for bid in depth['bids']])
    v_ask = sum([float(ask[1]) for ask in depth['asks']])
    collection.insert({'date': date, 'price': price, 'v_bid': v_bid, 'v_ask': v_ask})
    tickCount += 1;
    print("point: {} req_time: {} date: {} price: {} v_bid: {} v_ask: {}".format(tickCount, request_time, date, price, v_bid, v_ask))

def main():
    """Run tick() at the interval of every ten seconds."""
    scheduler = BlockingScheduler(timezone=utc)
    scheduler.add_job(tick, 'interval', seconds=30)
    scheduler.start()

if __name__ == '__main__':
    main()


import networkx as nx

def transport(cost, supply, demand):
    N = len(cost)
    G = nx.DiGraph()
    G.add_node('s', demand=-sum(supply))
    G.add_node('t', demand=sum(demand))
    # G.add_edge('t', 's', weight=0, capacity=sum(r))
    for i in range(N):
        G.add_edge('s', 's_' + str(i), weight=0, capacity=supply[i])
        G.add_edge('t_' + str(i), 't', weight=0, capacity=demand[i])
        for j in range(N):
            if cost[i][j] < float("inf"):
                G.add_edge('s_' + str(i), 't_' + str(j), weight=cost[i][j], capacity=float('inf'))
    flowCost, flowDict = nx.capacity_scaling(G)
    flowXprime = {}
    for u in flowDict:
        for v in flowDict[u]:
            if "_" in u and "_" in v and flowDict[u][v] > 0:
                i, j = int(u[2:]), int(v[2:])
                flowXprime[(i, j)] = flowDict[u][v]
    return flowCost, flowXprime


#coding:utf-8
from django.conf.urls import url
from jiahuaApp import jsonViews,callbackViews
urlpatterns = [

    #url(r'^/$', views.get),#地址：www.*/oneApp/get?id=*
    url(r'^order/create/$', jsonViews.orderCreate),#订单创建
    url(r'^order/query/$', jsonViews.orderQuery),#订单查询
    url(r'^order/update/$', jsonViews.orderUpdate),#订单修改
    url(r'^order/batchUpdate/$', jsonViews.orderBatchUpdate),#订单批量修改
    url(r'^order/delete/$', jsonViews.orderDelete),#订单删除,发送id键
    url(r'^order/delbydate/$',jsonViews.deleteOrder),#按日期删除订单
    url(r'^order/count/$', jsonViews.orderCount),#订单统计，发送createTime键

    url(r'^order/batch/insert/$', jsonViews.batchCreate),#批处理导入订单
    url(r'^order/batch/query/$', jsonViews.batchQuery),#查询历史导入订单

    #url(r'^cat/query/$', jsonViews.queryCat),#车辆查询
    url(r'^cat/department/$', jsonViews.departmentList),#部门列表
    url(r'^cat/query/$', jsonViews.getDriver),#车辆查询
    url(r'^cat/create/$', jsonViews.createCat),#车辆创建
    url(r'^cat/update/$', jsonViews.updateCat),#车辆修改
    url(r'^cat/delete/$', jsonViews.deleteCat),#车辆删除

    url(r'^client/query/$', jsonViews.queryClient),#客户查询
    url(r'^client/create/$', jsonViews.createClient),#客户创建
    url(r'^client/update/$', jsonViews.updateClient),#客户修改
    url(r'^client/delete/$', jsonViews.deleteClient),#客户删除

    url(r"^postCat/$", jsonViews.postCat),#指派车辆功能
    url(r"^batchPostCat/$", jsonViews.batchPostCat),#指派车辆功能#批量指派
    url(r"^getCat/$", jsonViews.getCat),#查询所有车牌号
    url(r"^postCat/$", jsonViews.postCat),#订单按车次派送,{"userid":1,"plateNum:"鄂A12312","orderList":[..... ]}

    url(r'^operateHistory/$', jsonViews.operateHistory),#查询操作历史
    url(r'^activeTimeout/$', jsonViews.activeTimeout),#查询取卸超时
    url(r'^deleteActiveTimeout/$', jsonViews.deleteActiveTimeout),#删除取卸超时

    url(r'^location/$', jsonViews.location),#获取位置

]


import numpy as np
import torch
from captum.attr import (IntegratedGradients, LayerActivation,
                         LayerConductance, NeuronConductance, Occlusion)

from ..model import MyDataset
from . import TorchModel

def get_neurons_activation(model: TorchModel, data: MyDataset, only_prunable=True, **kwargs):
    """https://captum.ai/tutorials/Titanic_Basic_Interpret"""
    model.cuda()
    layers = model.prunable if only_prunable else tuple(model.layers.children())
    ig = LayerActivation(model, layers)
    X = model.safe_cast_input(data.X)
    X.requires_grad_()
    attr = ig.attribute(X)
    model.cpu()
    return dict(zip(layers, attr))

def get_neurons_importance(model: TorchModel, data: MyDataset, only_prunable=True, n_steps=1, **kwargs):
    model.cuda()
    layers = model.prunable if only_prunable else tuple(model.layers.children())
    X = model.safe_cast_input(data.X)
    ret = {}
    for l in layers:
        cond = LayerConductance(model, l)
        ret[l] = np.mean(cond.attribute(X, target=1, n_steps=n_steps).detach().cpu().numpy(), axis=0)
    model.cpu()
    return ret

def get_learned_features_per_neuron(model: TorchModel, data: MyDataset, only_prunable=True, n_steps=2, **kwargs):
    model.cuda()
    layers = model.prunable if only_prunable else tuple(model.layers.children())
    X = model.safe_cast_input(data.X)
    ret = {}
    for l in layers:
        neuron_cond = NeuronConductance(model, l)
        ret[l] = np.mean(neuron_cond.attribute(X, neuron_selector=1,
                         target=1, n_steps=n_steps).detach().cpu().numpy(), axis=0)
    model.cpu()
    return ret

def rank_gradient_captum(model: TorchModel, data: MyDataset, current_features, n_steps=1, **_):
    """Compute feature importance with integrated gradient method using captum"""
    model.cuda()
    positions = [i for i, x in enumerate(data.X.columns.values) if x in current_features]
    ig = IntegratedGradients(model)
    X = model.safe_cast_input(data.X)
    X.requires_grad_()
    attr = ig.attribute(X, target=1, n_steps=n_steps)
    attr = attr.detach().numpy()
    importances = np.mean(attr, axis=0)
    model.cpu()
    return dict(zip(current_features, [importances[i] for i in positions]))

def rank_perturbation_captum(model: TorchModel, data: MyDataset, current_features, **_):
    model.cuda()
    positions = [i for i, x in enumerate(data.X.columns.values) if x in current_features]
    occlusion = Occlusion(model)

    attributions_occ = occlusion.attribute(torch.tensor(data.X.values, device=model.device),
                                           target=1,
                                           sliding_window_shapes=(1,),
                                           baselines=0)
    attr = attributions_occ.detach().cpu().numpy()
    importances = np.mean(attr, axis=0)
    model.cpu()
    return dict(zip(current_features, [importances[i] for i in positions]))


#!/usr/bin/env python3
import subprocess
import tempfile
import os
import os.path
import collections
import json
import sys
import multiprocessing
import struct

ProcessedTrack = collections.namedtuple("ProcessedTrack", ["dfpwm_file", "metadata"])

def convert_wav_dfpwm(infile, outfile):
    subprocess.run(["java", "-jar", "LionRay.jar", infile, outfile])

def convert_any_wav(infile, outfile):
    subprocess.run(["ffmpeg", "-hide_banner", "-i", infile, "-ar", "48000", "-ac", "1", outfile], stderr=subprocess.PIPE)

def read_meta(path):
    proc = subprocess.run(["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", path], stdout=subprocess.PIPE)
    data = json.loads(proc.stdout)
    meta = {}
    # These are the two locations I've found tags in in my not very thorough testing
    try:
        meta.update(data["format"]["tags"])
    except KeyError: pass
    try:
        meta.update(data["streams"][0]["tags"])
    except KeyError: pass
    # lowercase all keys because in Opus files these seem to be uppercase sometimes
    return { k.lower(): v for k, v in meta.items() }

def process_file(filename):
    meta = read_meta(filename)
    wav_dest = tempfile.mktemp(".wav")
    convert_any_wav(filename, wav_dest)
    dfpwm_dest = tempfile.mktemp(".dfpwm")
    convert_wav_dfpwm(wav_dest, dfpwm_dest)
    os.remove(wav_dest)
    print(filename)
    return ProcessedTrack(dfpwm_dest, {
        "title": meta["title"],
        "artist": meta.get("artist", None) or meta.get("artists", None),
        "album": meta.get("album", None)
    })

def read_binary(filename):
    with open(filename, "rb") as f:
        return f.read()

def process_dir(dirname):
    files = list(map(lambda file: os.path.join(dirname, file), os.listdir(dirname)))
    with multiprocessing.Pool(8) as p:
        tracks = p.map(process_file, files)
    tape_image = b""
    tracks_meta = []
    for track in tracks:
        track.metadata["start"] = len(tape_image)
        data = read_binary(track.dfpwm_file)
        os.remove(track.dfpwm_file)
        track.metadata["end"] = track.metadata["start"] + len(data)
        tape_image += data
        tracks_meta.append(track.metadata)
    # dump in a compact format to save space
    meta = json.dumps({ "tracks": tracks_meta }, separators=(',', ':')).encode("utf-8")
    assert(len(meta) < 65536)
    # new format - 0x54 marker byte, then metadata length as 2-byte big endian integer, then metadata, then concatenated DFPWM files
    # start is now not an absolute position but just how far after the metadata it is
    tape_image = b"\x54" + struct.pack(">H", len(meta)) + meta + tape_image
    with open("tape.bin", "wb") as f:
        f.write(tape_image)
    # Tape lengths are measured in minutes. 6000 bytes are played per second because they use a 48000Hz sample rate and DFPWM is somehow 1 bit per sample.
    length_minutes = len(tape_image) / (6000*60)
    print(length_minutes, "minute tape required")

process_dir(sys.argv[1])


from Genocchi import genocchi
from fractions import Fraction as frac

"""Bernoulli numbers A164555/A027642
"""

# #@

def Bernoulli(n: int) -> frac:
    if n < 2: return frac(1, n + 1)
    if n % 2 == 1: return frac(0, 1)
    g = genocchi(n // 2 - 1)[-1]
    f = frac(g, 2 ** (n + 1) - 2)
    return -f if n % 4 == 0 else f

if __name__ == "__main__":

    print([Bernoulli(n) for n in range(10)])

    from timeit import default_timer as timer
    start = timer()
    [Bernoulli(n) for n in range(1000)]
    end = timer()
    print(end - start)


from flask import Flask ,render_template, request ,redirect, session
from datetime import datetime
import pdfkit

app=Flask(__name__)
@app.route("/")
def index():
    return render_template("index.html")

muz=(' ','Onze', 'Douze', 'Treize',
          'Quatorze', 'Quinze', 'Seize', 'Dix-Sept', 'Dix-Huit', 'Dix-Neuf' )

to_19_fr = ( 'Zéro',  'Un',   'Deux',  'Trois', 'Quatre',   'Cinq',   'Six',
          'Sept', 'Huit', 'Neuf', 'Dix',   'Onze', 'Douze', 'Treize',
          'Quatorze', 'Quinze', 'Seize', 'Dix-Sept', 'Dix-Huit', 'Dix-Neuf' )
tens_fr  = ( 'Vingt', 'Trente', 'Quarante', 'Cinquante', 'Soixante', 'Soixante-Dix', 'Quatre-Vingt', 'Quatre-Vingt Dix')
denom_fr = ( '',
          'Mille',     'Million(s)',         'Milliards',       'Billions',       'Quadrillions',
          'Quintillion',  'Sextillion',      'Septillion',    'Octillion',      'Nonillion',
          'Décillion',    'Undecillion',     'Duodecillion',  'Tredecillion',   'Quattuordecillion',
          'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Icosillion', 'Vigintillion' )

def _convert_nn_fr(val):
    """ convertion des valeurs < 100 en Français
    """
    if val < 20:
        return to_19_fr[val]
    for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_fr)):
          if dval + 10 > val:
                if val % 10:
                      if(val>70 and val <= 79):
                           dcap='Soixante'
                           return dcap + '-' +muz[val % 10]

                      if(val>90 and val <=99 ):
                            dcap='Quatre-vingt'
                            return dcap + '-' +muz[val % 10]
                      else:
                              return dcap + '-' +to_19_fr[val % 10]

                return dcap
def _convert_nnn_fr(val):
    """ convert a value < 1000 to french

        special cased because it is the level that kicks
        off the < 100 special case.  The rest are more general.  This also allows you to
        get strings in the form of 'forty-five hundred' if called directly.
    """
    word = ''
    (mod, rem) = (val % 100, val // 100)
    b = val // 100
    if rem > 0:
         if b == 1 :
               word= 'Cent'
         else:
               word = to_19_fr[rem] + ' Cent'
    if mod > 0:
            word += ' '
    if mod > 0:
        word += _convert_nn_fr(mod)
    return word

def french_number(val):
    if val < 100:
        return _convert_nn_fr(val)
    if val < 1000:
         return _convert_nnn_fr(val)
    for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_fr))):
        if dval > val:
            mod = 1000 ** didx
            l = val // mod
            r = val - (l * mod)
            if (l ==1 ) and (denom_fr[didx] == 'Mille'):
                ret = denom_fr[didx]
            else:
                  ret = _convert_nnn_fr(l) + ' ' + denom_fr[didx]
            if r > 0:
                ret = ret + ' ' + french_number(r)
            return ret

def amount_to_text_fr(number):
    import math
    number = '%.2f' % number
    units_name = ' '
    list = str(number).split('.')
    muzamil=(french_number(abs(int(list[0]))))
    start_word = muzamil
    end_word =''
    #french_number(int(list[1]))
    cents_number = int(list[1])
    cents_name = (cents_number > 1) and ' dirhams' or ' dirhams'
    final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
    return final_result
@app.route("/data",methods=['POST','GET'])
def data():
    if request.method=="POST":
        if request.form["nom"] and request.form["ice"] and request.form["qte"] and request.form["puht"] and request.form["adress"] and request.form["desi"] and request.form["dtf"]:
            total=int(request.form["qte"])*int(request.form["puht"])
            ttc=total*1.2
            return render_template("data.html",nom=request.form["nom"],ice=request.form["ice"],qte=request.form["qte"],puht=request.form["puht"],total=total,tva=(total*20)/100,ttc=ttc,adress=request.form["adress"],desi=request.form["desi"],date=str(datetime.now().strftime('%Y-%m-%d')),dtf=request.form["dtf"],nbch=amount_to_text_fr(ttc))

@app.route("/pdf")
def pdf():
    pdfkit.from_file(data(), 'out.pdf')
    return res

if __name__== "__main__":
    app.run(debug=True)


"""main URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin

from django.contrib.auth import views as auth_views
import app.views as app_views

from channels.routing import route

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', app_views.index),
    url(r'^login/$', auth_views.login, {'template_name': 'login.html'}),
    url(r'^logout/$', auth_views.logout, {'template_name': 'logout.html'}),
    url(r'^home/$', app_views.home),
    url(r'^uploads/$', app_views.uploads),
    url(r'^downloads/$', app_views.downloads),
]

channel_routing = [
    route("websocket.connect", app_views.ws_connect),
    route("websocket.receive", app_views.ws_receive),
    route("websocket.disconnect", app_views.ws_disconnect),
]


import os

import pytest
import tomli
from affctrllib.affetto import Affetto, Chain

CONFIG_DIR_PATH = os.path.join(os.path.dirname(__file__), "config")

CHAIN_LINK_EXAMPLE_01 = (
    # link configuration
    [
        {"name": "link#00", "jointtype": "fixed"},
        {"name": "link#01", "jointtype": "revolute", "parent": "link#00"},
        {"name": "link#02", "jointtype": "revolute", "parent": "link#01"},
    ],
    # dof
    2,
)
CHAIN_LINK_EXAMPLE_02 = (
    # link configuration
    [
        {"name": "link#00", "jointtype": "fixed"},
        {"name": "link#01", "jointtype": "prismatic", "parent": "link#00"},
    ],
    # dof
    1,
)
CHAIN_LINK_EXAMPLE_03 = (
    # link configuration
    [
        {"name": "link#00", "jointtype": "fixed"},
        {"name": "link#01", "jointtype": "revolute", "parent": "link#00"},
        {"name": "link#02", "jointtype": "revolute", "parent": "link#01"},
        {"name": "link#03", "jointtype": "revolute", "parent": "link#02"},
        {"name": "link#04", "jointtype": "revolute", "parent": "link#03"},
        {"name": "link#05", "jointtype": "revolute", "parent": "link#04"},
        {"name": "link#06", "jointtype": "revolute", "parent": "link#05"},
    ],
    # dof
    6,
)

class TestChain:
    def test_init(self) -> None:
        chain = Chain()
        assert isinstance(chain, Chain)

    @pytest.mark.parametrize(
        "linkchain",
        [
            CHAIN_LINK_EXAMPLE_01,
            CHAIN_LINK_EXAMPLE_02,
            CHAIN_LINK_EXAMPLE_03,
        ],
    )
    def test_init_with_config(self, linkchain) -> None:
        c = {"link": linkchain[0]}
        chain = Chain(c)
        assert chain.dof == linkchain[1]

    @pytest.mark.parametrize(
        "linkchain",
        [
            CHAIN_LINK_EXAMPLE_01,
            CHAIN_LINK_EXAMPLE_02,
            CHAIN_LINK_EXAMPLE_03,
        ],
    )
    def test_load(self, linkchain) -> None:
        c = {"link": linkchain[0]}
        chain = Chain()
        chain.load(c)
        assert chain.dof == linkchain[1]

    @pytest.mark.parametrize("cfile,dof", [("chain1.toml", 2), ("chain2.toml", 6)])
    def test_load_from_file(self, cfile, dof) -> None:
        cpath = os.path.join(CONFIG_DIR_PATH, cfile)
        with open(cpath, "rb") as f:
            config = tomli.load(f)
        chain = Chain(config["chain"])
        assert chain.dof == dof

class TestAffetto:
    def test_init(self) -> None:
        affetto = Affetto()
        assert isinstance(affetto, Affetto)

    def test_init_with_config_path(self) -> None:
        cpath = os.path.join(CONFIG_DIR_PATH, "default.toml")
        affetto = Affetto(cpath)
        assert str(affetto.config_path) == cpath
        assert affetto.name == "affetto"
        assert affetto.dof == 13

    def test_load_config(self) -> None:
        cpath = os.path.join(CONFIG_DIR_PATH, "default.toml")
        affetto = Affetto()
        affetto.load_config_path(cpath)
        assert str(affetto.config_path) == cpath
        assert affetto.name == "affetto"
        assert affetto.dof == 13

    def test_set_config_error(self) -> None:
        affetto = Affetto()
        with pytest.raises(KeyError) as excinfo:
            affetto.load_config({})
        assert "'affetto'" == str(excinfo.value)

    def test_set_config_warning(self) -> None:
        affetto = Affetto()
        with pytest.warns(UserWarning) as record:
            affetto.load_config({"affetto": {}})
        assert "'chain' field is not defined" == str(record[0].message)

    @pytest.mark.parametrize(
        "linkchain",
        [
            CHAIN_LINK_EXAMPLE_01,
            CHAIN_LINK_EXAMPLE_02,
            CHAIN_LINK_EXAMPLE_03,
        ],
    )
    def test_load_chain(self, linkchain) -> None:
        c = {"chain": {"link": linkchain[0]}}
        affetto = Affetto()
        affetto.load_chain(c)
        assert affetto.dof == linkchain[1]

    def test_dof_default(self) -> None:
        affetto = Affetto()
        assert affetto.dof == 13


import torch
import cv2
import numpy as np
import time
import audio

def yolo():
    # Model
    model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)

    start_time = time.time()

    audio.say('I CAN SEE A...')

    lst = []
    cap = cv2.VideoCapture(0)
    while time.time() - start_time < 25:
        ret, frame = cap.read()

        # Make detections
        results = model(frame)
        cv2.imshow('YOLO', np.squeeze(results.render()))

        df = results.pandas().xyxy[0]

        for i in df['name']:
            if i not in lst:
                lst.append(i)
                new_label = i
                time.sleep(2)
                confidence = df[df['name'] == new_label]['confidence'].max().item()

                print(new_label)

                if confidence >= 0.35:
                    # Determine direction based on object's bounding box center
                    bbox_center_x = (df[df['name'] == new_label]['xmax'].iloc[0] + df[df['name'] == new_label]['xmin'].iloc[0]) / 2
                    bbox_center_y = (df[df['name'] == new_label]['ymax'].iloc[0] + df[df['name'] == new_label]['ymin'].iloc[0]) / 2
                    frame_center_x = frame.shape[1] / 2
                    frame_center_y = frame.shape[0] / 2

                    if bbox_center_x > frame_center_x:
                        direction_x = "to your right"
                    else:
                        direction_x = "to your left"

                    if bbox_center_y < frame_center_y: # Flip the comparison for vertical direction
                        direction_y = "above you" # Flip the direction description
                    else:
                        direction_y = "below you" # Flip the direction description

                    words = f'{new_label} {direction_x} {direction_y}'

                    print(words)
                    audio.say(words)

    cap.release()

    cv2.destroyAllWindows()


import numpy.random as random
import numpy as np
import matplotlib
matplotlib.use('pdf') # required to compile on MCS over SSH
import matplotlib.pyplot as plt
import time

s = np.pi / 8

def integrand(input):
    return np.sin(np.sum(input)) * 10 ** 6

def estimate_average_f(N):
    # Uses Monte-Carlo routine to randomly sample f
    # Initiate pythonic list to store sampled values of the integrand, more efficient than np array here.
    f_list = []
    for i in range(N):
        # initiate 1D array of random values in range [0,s]
        inputs = random.rand(8) * s
        f = integrand(inputs)
        f_list.append(f)

    # Convert f_list to numpy array f_array for vectorisation
    f_array = np.array(f_list)
    f_squared_array = f_array ** 2
    average_f = (1 / N) * np.sum(f_array)
    average_f_squared = (1 / N) * np.sum(f_squared_array)
    return average_f, average_f_squared

def plot_errors(results_list):
    # Plot a graph of sampled error against N
    Ns = [dic.get("N") for dic in results_list]
    errors = [dic.get("sampled_error") for dic in results_list]
    fig, ax1 = plt.subplots()
    ax1.set_yscale("log")
    ax1.set_xscale("log")
    ax1.set_ylabel("log(Sampled Error /No Units)")
    ax1.set_xlabel("log(N /No Units)")
    ax1.set_title("Plot of sampled error against N")
    ax1.plot(Ns, errors, label="Sampled error")

    # Calculate normalisation value to match expected relationship to results
    normalisation_k = errors[0] / Ns[0] ** -0.5
    ax1.plot(Ns, normalisation_k * np.power(Ns, -1 / 2), label="Theoretical relationship", linestyle="dashed")
    ax1.legend()
    plt.savefig("core_one_error_plot.pdf")

def plot_theoretical_error(results_list):
    Ns = [dic.get("N") for dic in results_list]
    errors = [dic.get("sampled_error") for dic in results_list]
    theoretical_errors = [dic.get("theoretical_error") for dic in results_list]
    fig, ax1 = plt.subplots()
    ax1.set_ylabel("Error /No Units")
    ax1.set_xlabel("N /No Units")
    ax1.plot(Ns, theoretical_errors, label="Theoretical error")
    ax1.plot(Ns, errors, label="Sampled error")
    ax1.set_title("Plot of theoretical and sampled error against N")
    ax1.legend()
    plt.savefig("supplementary_one_plot.pdf")

def main_loop(N_list, N_t=25):
    # Estimates the integral using Monte-Carlo techniques, by taking N samples, and repeating this process n_t times. This process is applied to each value N in N_list
    results_list = []
    volume = s ** 8

    for N in N_list:
        estimates_list = []
        theoretical_error_list = []
        for i in range(N_t):
            average_f, average_f_squared = estimate_average_f(N)
            estimate = average_f * volume
            theoretical_error = volume * ((average_f_squared - average_f ** 2) / N) ** (1 / 2)
            theoretical_error_list.append(theoretical_error)
            estimates_list.append(estimate)
        estimates_array = np.array(estimates_list)
        mean = np.mean(estimates_array)
        theoretical_error_mean = np.mean(theoretical_error_list)

        # RMS error in mean, from estimates
        sampled_error = np.std(estimates_array)
        results_list.append(
            {"N": N, "mean": mean, "sampled_error": sampled_error, "theoretical_error": theoretical_error_mean})
    return results_list

if __name__ == "__main__":
    N_list = np.arange(10, 400, 4, dtype=int).tolist()

    # Prove N^(-1/2) relationship
    print("Beginning error calculation.")
    results_list = main_loop(N_list, N_t=25)
    plot_errors(results_list)

    # Supplementary task one
    plot_theoretical_error(results_list)
    print("Finished error calculation.")

    # Estimate integral for N=20000, n_t=25
    N = 20000
    print(f"Estimating integral for N={N}.")
    t_start = time.time()
    results_list = main_loop([N], N_t=25)
    estimated_value = results_list[0].get("mean")
    sampled_error = results_list[0].get("sampled_error")
    print(
        f"Integral estimated to be {estimated_value} +/- {sampled_error} for N={N} in {round(time.time()-t_start, 3)}s.")


import streamlit as st
from PIL import Image
import ultralytics
from ultralytics import YOLO

st.title('Aloe Vera Plant Disease Analyser')

col1,col2=st.columns(2)
upload_stat=0
with col1:

    input_image=st.file_uploader('Upload The Image File Here',type=['jpg','png'])

    confirmation=st.button('Submit')
    if confirmation==True:
        st.image(input_image)
        upload_stat=1

with col2:
    st.subheader('Detection:')
    if upload_stat==1:
        image_new=Image.open(input_image)
        model=YOLO('best_new_v2.pt')
        results= model(image_new)

        for r in results:
            im_array = r.plot()  # plot a BGR numpy array of predictions
            im = Image.fromarray(im_array[..., ::-1])  # RGB PIL image
            st.image(im)  # show image


"""
Given a sorted array of distinct integers and a target value, return the index if the
target is found. If not, return the index where it would be if it were inserted in order.

You must write an algorithm with O(log n) runtime complexity.

Example 1:

Input: nums = [1,3,5,6], target = 5
Output: 2
Example 2:

Input: nums = [1,3,5,6], target = 2
Output: 1
Example 3:

Input: nums = [1,3,5,6], target = 7
Output: 4

Constraints:

1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums contains distinct values sorted in ascending order.
-104 <= target <= 104
"""
from typing import List

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        nums.sort()
        i = 0
        for n in nums:
            if n == target:
                return i
            elif n > target:
                return i
            i += 1
        return i

def main():
    nums = [1, 3, 5, 6]
    target = 5
    print(Solution().searchInsert(nums, target))
    nums = [1, 3, 5, 6]
    target = 2
    print(Solution().searchInsert(nums, target))
    nums = [1, 3, 5, 6]
    target = 7
    print(Solution().searchInsert(nums, target))
    nums = [1, 3, 5, 6]
    target = 0
    print(Solution().searchInsert(nums, target))
    nums = [-1, -3, -5, -6]
    target = -4
    print(Solution().searchInsert(nums, target))

if __name__ == '__main__':
    main()


from django.shortcuts import render,HttpResponse
from django.contrib.auth.decorators import login_required
from crm import forms
from crm import models
from crm import admin
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
from PerfectCRM import settings
import os,json,time
# Create your views here.

@login_required
def my_courses(request):
    '''每个学员的课程列表'''
    return render(request,"stu/my_courses.html")

@login_required
def my_grade(request):
    return render(request,'stu/my_grade.html')

@login_required
def my_homeworks(request,enroll_id):

    enroll_obj = models.Enrollment.objects.get(id=enroll_id)
    return render(request,'stu/homeworks.html',{'enroll_obj':enroll_obj})

def get_uploaded_fileinfo(file_dic,upload_dir):
    for filename in os.listdir(upload_dir):
        abs_file = '%s/%s' % (upload_dir, filename)
        file_create_time = time.strftime("%Y-%m-%d %H:%M:%S",
                                         time.gmtime(os.path.getctime(abs_file)))
        file_dic['files'][filename] = {'size': os.path.getsize(abs_file) / 1000,
                                           'ctime': file_create_time}

@login_required
def homework_detail(request,customer_id,course_record_id):
    course_record_obj = models.CourseRecord.objects.get(id=course_record_id)
    upload_dir = "%s%s/%s/%s" % (settings.BASE_HOMEWORK_DIR,
                                 customer_id,
                                 course_record_obj.course.id,
                                 course_record_id)
    # print("upload dir",upload_dir)
    if not os.path.isdir(upload_dir):
        os.makedirs(upload_dir, exist_ok=True)

    response_dic = {'files':{}}

    if request.method == "POST":
        if request.FILES:

            print("files:",request.FILES)

            for k,file_obj in request.FILES.items():
                if len(os.listdir(upload_dir)) < 6:
                    with open('%s/%s' %(upload_dir,file_obj.name), 'wb+') as destination:
                        for chunk in file_obj.chunks():
                            destination.write(chunk)
                else:
                    response_dic['error'] = "can only upload no more than 5 files."
            # for filename in os.listdir(upload_dir):
            #     abs_file = '%s/%s' %(upload_dir,filename)
            #     file_create_time = time.strftime("%Y-%m-%d %H:%M:%S" ,
            #                                      time.gmtime(os.path.getctime(abs_file)))
            #     response_dic['files'][filename] = {'size':os.path.getsize(abs_file)/1000,
            #                                    'ctime':file_create_time}
            #
            get_uploaded_fileinfo(response_dic, upload_dir)

            return HttpResponse(json.dumps(response_dic))

    study_record_obj = models.StudyRecord.objects.filter(student_id=customer_id,course_record_id=course_record_id)

    #get uploaded file dic
    get_uploaded_fileinfo(response_dic, upload_dir)

    if study_record_obj:
        study_record_obj = study_record_obj[0]
    else: #此时这个学生还没有本节课的学习记录,但需要学习记录方能交作业,所以在这里创建一条学习纪录为他
        study_record_obj = models.StudyRecord(
            student_id = customer_id,
            course_record_id = course_record_id,
            record='checked',
            score = 0
        )
        study_record_obj.save()

    return render(request,'stu/homework_detail.html',
                  {'study_record_obj':study_record_obj,
                   'course_record_obj':course_record_obj,
                   'uploaded_files':response_dic})

@login_required
def delete_file(request,customer_id,course_record_id):
    response = {}
    if request.method == "POST":
        course_record_obj = models.CourseRecord.objects.get(id=course_record_id)
        upload_dir = "%s%s/%s/%s" % (settings.BASE_HOMEWORK_DIR,
                                     customer_id,
                                     course_record_obj.course.id,
                                     course_record_id)
        filename = request.POST.get('filename')
        file_abs = "%s/%s" %(upload_dir,filename.strip())
        if os.path.isfile(file_abs):
            os.remove(file_abs)
            response['msg'] = "file '%s' got deleted " % filename
        else:
            response["error"] = "file '%s' does not exist on server"% filename
    else:
        response['error'] = "only supoort POST method..."
    return HttpResponse(json.dumps(response))


import numpy as np
import dxfgrabber
import sys
if '/opt/ros/kinetic/lib/python2.7/dist-packages' in sys.path:
    sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')
sys.path.append("..")
import cv2
from config.config import cfg
from src.Coordinate_Transformation import Coordinate_Transformation
import math
import argparse
from src.utils import check_collision, ray_trace
import os

def getMinXY(shapes):
    minX, minY = 99999, 99999
    for shape in shapes:
        if shape.dxftype == 'LINE':
            minX = min(minX, shape.start[0], shape.end[0])
            minY = min(minY, shape.start[1], shape.end[1])
        elif shape.dxftype == 'ARC':
            minX = min(minX, shape.center[0])
            minY = min(minY, shape.center[1])

    return minX, minY

def getMaxXY(shapes):
    maxX, maxY = -99999, -99999
    for shape in shapes:
        if shape.dxftype == 'LINE':
            maxX = max(maxX, shape.start[0], shape.end[0])
            maxY = max(maxY, shape.start[1], shape.end[1])
        elif shape.dxftype == 'ARC':
            maxX = max(maxX, shape.center[0])
            maxY = max(maxY, shape.center[1])

    return maxX, maxY

def FillHole(mask):
    contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    len_contour = len(contours)

    for i in range(len_contour):
        if contours[i].shape[0] < 800:
            mask = cv2.drawContours(mask, contours, i, (255, 255, 255), -1)

    return mask

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    flag_parser = parser.add_mutually_exclusive_group(required=False)
    flag_parser.add_argument('--Generate_RC_data', dest='Generate_RC_data', action='store_true')
    flag_parser.add_argument('--no-Generate_RC_data', dest='Generate_RC_data', action='store_false')
    parser.set_defaults(Generate_RC_data=True)
    flag_parser = parser.add_mutually_exclusive_group(required=False)
    flag_parser.add_argument('--Testing', dest='Testing', action='store_true')
    flag_parser.add_argument('--no-Testing', dest='Testing', action='store_false')
    parser.set_defaults(Testing=False)
    flag_parser = parser.add_mutually_exclusive_group(required=False)
    flag_parser.add_argument('--Generate_GT_data', dest='Generate_GT_data', action='store_true')
    flag_parser.add_argument('--no-Generate_GT_data', dest='Generate_GT_data', action='store_false')
    parser.set_defaults(Testing=False)
    args = parser.parse_args()

    """
        Generate image of environment with dxf file.
    """
    Bicocca_dxf = dxfgrabber.readfile(cfg.Bicocca_dxf_path)
    shapes = Bicocca_dxf.entities.get_entities()
    x_min, y_min = getMinXY(shapes)
    x_max, y_max = getMaxXY(shapes)
    Bicocca_Coordinate_Transformation = Coordinate_Transformation(x_max, x_min, y_max, y_min)

    shapes = Bicocca_dxf.entities.get_entities()
    env_size = Bicocca_Coordinate_Transformation.get_env_size()
    env_size = Bicocca_Coordinate_Transformation.img2array(env_size,cfg.Bicocca_resolution)

    env = np.zeros((env_size[0],env_size[1],3), np.uint8)
    for shape in shapes:
        if shape.dxftype == 'LINE':
            start = shape.start[0:2]
            end = shape.end[0:2]
            x_start, y_start = Bicocca_Coordinate_Transformation.ori2array(start,cfg.Bicocca_resolution)
            x_end, y_end = Bicocca_Coordinate_Transformation.ori2array(end,cfg.Bicocca_resolution)

            env = cv2.line(env, (y_start,x_start), (y_end,x_end), (255,255,255), 1)
        elif shape.dxftype == 'ARC':
            center = shape.center
            x_center , y_center = Bicocca_Coordinate_Transformation.ori2array(center,cfg.Bicocca_resolution)
            radius = int(shape.radius / cfg.Bicocca_resolution)
            if (shape.start_angle > 180) and (shape.end_angle < shape.start_angle):
                env = cv2.ellipse(env, (y_center,x_center), (radius, radius), 180, int(shape.start_angle) - 180, 180 + int(shape.end_angle), (255,255,255), 1)
            else:
                env = cv2.ellipse(env, (y_center,x_center), (radius, radius), 0, int(360 - shape.start_angle), int(360 - shape.end_angle), (255,255,255), 1)

        elif shape.dxftype == 'POLYLINE':
            points = shape.points
            for i in range(len(points)-1):
                start = points[i][0:2]
                end = points[i+1][0:2]
                x_start, y_start = Bicocca_Coordinate_Transformation.ori2array(start, cfg.Bicocca_resolution)
                x_end, y_end = Bicocca_Coordinate_Transformation.ori2array(end, cfg.Bicocca_resolution)

            env = cv2.line(env, (y_start, x_start), (y_end, x_end), (255,255,255), 1)
    env = cv2.cvtColor(env, cv2.COLOR_BGR2GRAY)
    env = FillHole(env)
    env = cv2.cvtColor(env, cv2.COLOR_GRAY2BGR)
    """
        If we do not want to generate ray casting data set
    """
    if args.Testing:
        """
            Map laser scan onto image with ground truth pose.
        """
        Bicocca_gt_trajectory = np.loadtxt(cfg.Bicocca_gt_trajectory_path,
                                           delimiter=',')
        Bicocca_laser_scan = np.loadtxt(cfg.Bicocca_laser_scan_path,
                                        delimiter=',')
        index_laser = 0
        x_img_start, y_img_start, x_img_end, y_img_end = cfg.Bicocca_crop[0]
        for i in range(Bicocca_gt_trajectory.shape[0]-1):
            env_ = env.copy()
            time_stamp_now = Bicocca_gt_trajectory[i, 0]
            time_stamp_next = Bicocca_gt_trajectory[i + 1, 0]
            while (Bicocca_laser_scan[index_laser, 0] < time_stamp_now):
                index_laser += 1
            time_stamp_laser = Bicocca_laser_scan[index_laser, 0]

            pose_now = Bicocca_gt_trajectory[i,1:]
            x_now , y_now, theta_now = Bicocca_Coordinate_Transformation.Bicocca_trajectory2ori(pose_now)
            x_now , y_now= Bicocca_Coordinate_Transformation.ori2array((x_now , y_now), cfg.Bicocca_resolution)

            pose_next = Bicocca_gt_trajectory[i+1, 1:]
            x_next, y_next, theta_next = Bicocca_Coordinate_Transformation.Bicocca_trajectory2ori(pose_next)
            x_next, y_next = Bicocca_Coordinate_Transformation.ori2array((x_next, y_next), cfg.Bicocca_resolution)

            x = x_now + (x_next - x_now) / (time_stamp_next - time_stamp_now) * (time_stamp_laser - time_stamp_now)
            y = y_now + (y_next - y_now) / (time_stamp_next - time_stamp_now) * (time_stamp_laser - time_stamp_now)
            theta = theta_now + (theta_next - theta_now) / (time_stamp_next - time_stamp_now) * (time_stamp_laser - time_stamp_now)

            laser_scan = Bicocca_laser_scan[index_laser,1:]

            for j in range(len(laser_scan)):
                if laser_scan[j] < 30:
                    scan_theta_now = cfg.Bicocca_st_angle + j * cfg.Bicocca_angle_step
                    delta_x_axis_base = math.cos(scan_theta_now) * laser_scan[j] / cfg.Bicocca_resolution
                    delta_y_axis_base = math.sin(scan_theta_now) * laser_scan[j] / cfg.Bicocca_resolution
                    delta_x_axis_base_rot = delta_x_axis_base * math.cos(theta) - delta_y_axis_base * math.sin(theta)
                    delta_y_axis_base_rot = delta_x_axis_base * math.sin(theta) + delta_y_axis_base * math.cos(theta)

                    delta_x_axis_map = -1 * delta_y_axis_base_rot
                    delta_y_axis_map = delta_x_axis_base_rot

                    x_scan = int(x + delta_x_axis_map)
                    y_scan = int(y + delta_y_axis_map)

                    env_[x_scan, y_scan, 2] = 255
                    env_[x_scan, y_scan, 1] = 0
                    env_[x_scan, y_scan, 0] = 255

            if x > x_img_start and x < x_img_end and y > y_img_start and y < y_img_end:

                cv2.imwrite('/Users/chenrj/Desktop/1.png',env_)
                cv2.imshow('scan',env_)
                cv2.waitKey()
    elif args.Generate_RC_data:
        """
            Generate ray casting data set with the map.
            * First crop the map into submaps.
            * Generate ray casting data on submaps.
        """
        for i in range(len(cfg.Bicocca_crop)):
            env_crop = env.copy()
            x_img_start, y_img_start, x_img_end, y_img_end = cfg.Bicocca_crop[i]
            env_crop = env_crop[x_img_start:x_img_end,y_img_start:y_img_end]
            path = cfg.Bicocca_dataset_root_path + 'Data_Transformed_'+ cfg.Bicocca_dataset + '/' + str(i+1)
            map_env = env_crop

            count = 0

            for p in range(20):
                map_env_with_ob = map_env.copy()
                X , Y = map_env_with_ob.shape

                for j in range(60):
                    x = int(np.random.uniform(low=5, high=X - 5))
                    y = int(np.random.uniform(low=5, high=Y - 5))
                    cv2.rectangle(map_env_with_ob, (y, x), (y + 1, x + 1), (255), -1)
                    x = int(np.random.uniform(low=5, high=X - 5))
                    y = int(np.random.uniform(low=5, high=Y - 5))
                    cv2.circle(map_env_with_ob, (y, x), 1, (255), -1, 0)

                cv2.imwrite(path + '/map_ob_'+str(p+1)+'.png', map_env_with_ob)
                cv2.imwrite(path + '/map_.png', map_env)

                for XX in range(5, X-5, 2):
                    for YY in range(5, Y-5, 2):

                        if check_collision(XX, YY, map_env_with_ob):
                            pmap = np.zeros((X, Y))
                            pmap[XX, YY] = 255
                            pmap = cv2.GaussianBlur(pmap, (7, 7), 3)
                            cv2.normalize(pmap, pmap, 0, 255, cv2.NORM_MINMAX)

                            for k in range(10):
                                degree = np.random.uniform(low=cfg.rad_min, high=cfg.rad_max)
                                scan = ray_trace(XX, YY, map_env_with_ob, degree, cfg.Bicocca_laser_max_range / cfg.Bicocca_resolution,cfg.Bicocca_st_angle,cfg.Bicocca_scan_steps,cfg.Bicocca_angle_step)

                                if len(np.where(scan == 255)) > 0:
                                    cv2.imwrite(path + '/scan/' + str(count) + '.png', scan)
                                    cv2.imwrite(path + '/pmap/' + str(count) + '.png', pmap)
                                    cv2.imwrite(path + '/map/' + str(count) + '.png', map_env)
                                    np.savetxt(path + '/rotation/' + str(count) + '.txt', np.array([degree]))

                                    count += 1

                                    print(str(p+1) + 'th scene ---- ' + str(count) + ' in total')
    elif args.Generate_GT_data:
        """
            Generate ground truth data (odometry, observation and pose) with the map.
            * First crop the map into submaps.
            * Generate ray casting data on submaps.
        """
        Bicocca_gt_trajectory = np.loadtxt(cfg.Bicocca_gt_trajectory_path,
                                           delimiter=',')
        Bicocca_laser_scan = np.loadtxt(cfg.Bicocca_laser_scan_path,
                                        delimiter=',')

        for i in range(len(cfg.Bicocca_crop)):
            env_crop = env.copy()
            x_img_start, y_img_start, x_img_end, y_img_end = cfg.Bicocca_crop[i]
            env_crop = env_crop[x_img_start:x_img_end, y_img_start:y_img_end]
            gt_pose=[]
            laser=[]
            odo = []
            for j in range(Bicocca_gt_trajectory.shape[0]-1):
                index_laser = 0
                time_stamp_now = Bicocca_gt_trajectory[j, 0]
                time_stamp_next = Bicocca_gt_trajectory[j + 1, 0]
                pose_now = Bicocca_gt_trajectory[j, 1:]
                x_now, y_now, theta_now = Bicocca_Coordinate_Transformation.Bicocca_trajectory2ori(pose_now)
                x_now, y_now = Bicocca_Coordinate_Transformation.ori2array((x_now, y_now), cfg.Bicocca_resolution)
                pose_next = Bicocca_gt_trajectory[j + 1, 1:]
                x_next, y_next, theta_next = Bicocca_Coordinate_Transformation.Bicocca_trajectory2ori(pose_next)
                x_next, y_next = Bicocca_Coordinate_Transformation.ori2array((x_next, y_next),
                                                                             cfg.Bicocca_resolution)

                if x_now > x_img_start and x_now < x_img_end and y_now > y_img_start and y_now < y_img_end \
                        and  x_next > x_img_start and x_next < x_img_end and y_next > y_img_start and y_next < y_img_end:

                    while (Bicocca_laser_scan[index_laser, 0] < time_stamp_now):
                        index_laser += 1
                    time_stamp_laser = Bicocca_laser_scan[index_laser, 0]

                    x = x_now + (x_next - x_now) / (time_stamp_next - time_stamp_now) * (
                                time_stamp_laser - time_stamp_now)
                    y = y_now + (y_next - y_now) / (time_stamp_next - time_stamp_now) * (
                                time_stamp_laser - time_stamp_now)
                    theta = theta_now + (theta_next - theta_now) / (time_stamp_next - time_stamp_now) * (
                                time_stamp_laser - time_stamp_now)

                    laser_scan = Bicocca_laser_scan[index_laser, 1:]
                    count_laser_inside = 0
                    for j in range(len(laser_scan)):
                        if laser_scan[j] < 30:
                            scan_theta_now = cfg.Bicocca_st_angle + j * cfg.Bicocca_angle_step
                            delta_x_axis_base = math.cos(scan_theta_now) * laser_scan[j] / cfg.Bicocca_resolution
                            delta_y_axis_base = math.sin(scan_theta_now) * laser_scan[j] / cfg.Bicocca_resolution
                            delta_x_axis_base_rot = delta_x_axis_base * math.cos(theta) - delta_y_axis_base * math.sin(
                                theta)
                            delta_y_axis_base_rot = delta_x_axis_base * math.sin(theta) + delta_y_axis_base * math.cos(
                                theta)

                            delta_x_axis_map = -1 * delta_y_axis_base_rot
                            delta_y_axis_map = delta_x_axis_base_rot

                            x_scan = int(x + delta_x_axis_map)
                            y_scan = int(y + delta_y_axis_map)

                            if x_scan > x_img_start and x_scan < x_img_end and y_scan > y_img_start and y_scan < y_img_end:
                                count_laser_inside += 1
                            else:
                                laser_scan[j] = math.nan
                        else:
                            laser_scan[j] = math.nan
                    x = x - x_img_start
                    y = y - y_img_start
                    if count_laser_inside > 10:
                        laser.append(laser_scan)
                        gt_pose.append((x,y,theta))
                        if len(gt_pose)>1:
                            odo.append(np.array(gt_pose[-1])-np.array(gt_pose[-2]))

            laser = np.array(laser)
            gt_pose = np.array(gt_pose)
            odo = np.array(odo)
            path = cfg.Bicocca_dataset_root_path + 'Data_Transformed_' + cfg.Bicocca_dataset + '/Test_MCL/' + str(i + 1) + '/'
            os.makedirs(path,exist_ok=True)
            np.savetxt(path + 'laser.txt', laser)
            np.savetxt(path + 'gt_pose.txt', gt_pose)
            np.savetxt(path + 'odo.txt', odo)
            cv2.imwrite(path + 'global_map.png',env_crop)


import pytest
from pacific_atlantic_water_flow import Solution

@pytest.mark.parametrize('heights, expected', [
    ([
        [1,2,2,3,5],
        [3,2,3,4,4],
        [2,4,5,3,1],
        [6,7,1,4,5],
        [5,1,1,2,4]
    ], [
        [0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]
    ]),
    ([[1]], [[0, 0]]),
    ([
        [2,1],
        [1,2]
    ], [
        [0,0],[0,1],[1,0],[1,1]
    ]),
])
def test_solution(heights, expected):
    actual = Solution().pacificAtlantic(heights)
    expected = map(tuple, expected)
    assert set(actual) == set(expected)


from asyncpg import UniqueViolationError
from utils.database_api.schemas.user import User
from utils.database_api.schemas.publicplace_base import PubliPlace
from utils.database_api.db_publicplaces import db

async def add_pp(pp_id: int, pp_name: str, ph_number: str,
                 loc: str, atl: str, wt: str, ct: str, ph: str,
                 link: str, rating: float):
    try:
        pp = PubliPlace(pp_id=pp_id, pp_name=pp_name, phone_number=ph_number,
                        location=loc,atl=atl,work_time=wt,category=ct,photo=ph,
                        link=link, rating=rating)
        await pp.create()
    except UniqueViolationError:
        print('Общественное место не добавлено')

async def add_user(user_id: int, name: str):
    try:
        user = User(user_id=user_id, name=name)
        await user.create()
    except UniqueViolationError:
        print('Пользователь не добавлен')

async def select_all_users():
    users = await User.query.gino.all()
    return users

async def count_users():
    count = await db.func.count(User.user_id).gino.scalar()
    return count

async def select_user(user_id):
    user = await User.query.where(User.user_id == user_id).gino.first()
    return user

async def delete_user(user_id):
    user_del = await select_user(user_id)
    await user_del.delete()

async def update_user(user_id, new_name):
    upd_user = await select_user(user_id)
    await upd_user.update(name=new_name).apply()