from bucket import Bucket
import utils

MAX_SIZE = 10000000
THRESHOLD = 200000
SPLIT_SIZE = 100
abc_frequency_dict = {'a': 1.7, 'b': 4.4, 'c': 5.2, 'd': 3.2, 'e': 2.8, 'f': 4, 'g': 1.6, 'h': 4.2, 'i': 7.3, 'j': 7.3,
                      'k': 0.86, 'l': 2.4, 'm': 3.8, 'n': 2.3, 'o': 7.6, 'p': 4.3, 'q': 0.22, 'r': 2.8, 's': 6.7,
                      't': 16, 'u': 1.2, 'v': 0.82, 'w': 5.5, 'x': 0.045, 'y': 0.76, 'z': 0.045}

class PostingsHandler:
    """
    A class for managing posting files for terms and entities in memory, and writing them to the disk when they
    get too big (controlled via the MAX_SIZE and THRESHOLD constants).
    """

    def __init__(self, config, number_of_buckets=6, first_bucket_index=0, contains="terms"):
        if contains == "terms":
            number_of_buckets = config.get_number_of_term_buckets()
        elif contains == "entities":
            number_of_buckets = config.get_number_of_entities_buckets()
            first_bucket_index = config.get_entities_index()
        self.buckets = []
        self.letters_dict = {}  # mapping between a letter and a bucket number
        self.size = 0
        # self.config = config
        self.__equal_width_buckets(number_of_buckets)
        self.buckets_mapping = {}  # mapping between bucket in memory to a bucket index on the disk
        self.initialize_buckets(number_of_buckets, first_bucket_index)

    def initialize_buckets(self, num_of_buckets, first_bucket_index=0):
        """
        Creates the bucket files on the disk and saves a mapping for their indices
        """
        for i in range(num_of_buckets):
            utils.save_obj([], "bucket" + str(first_bucket_index + i))
            self.buckets_mapping[i] = first_bucket_index + i

    def __flush_bucket(self, inverted_idx, bucket_index):
        """
        Writes a bucket to the disk. If it already has data saved on the disk it first loads and extends the data
        with the new data in the memory and only then saves it again.
        """
        new_posting = utils.load_obj("bucket" + str(self.buckets_mapping[bucket_index]))
        for term in self.buckets[bucket_index].get_dict_terms():
            if inverted_idx[term][1][1] < 0:  # update the inverted index pointer if needed
                new_posting.append([])
                inverted_idx[term][1] = (self.buckets_mapping[bucket_index], len(new_posting) - 1)
            new_posting[inverted_idx[term][1][1]].extend(self.buckets[bucket_index].get_term_posting(term))
        self.size -= self.buckets[bucket_index].get_size()
        self.buckets[bucket_index].clean_bucket()
        utils.save_obj(new_posting, "bucket" + str(self.buckets_mapping[bucket_index]))

    def __equal_width_buckets(self, number_of_buckets):
        for key in abc_frequency_dict.keys():
            self.letters_dict[key] = (ord(key) - ord('a')) % number_of_buckets
        for i in range(number_of_buckets):
            new_bucket = Bucket()
            self.buckets.append(new_bucket)

    def __find_the_biggest_bucket(self):
        max_size_bucket = 0
        for i in range(1, len(self.buckets)):
            if max_size_bucket < self.buckets[i].get_size():
                max_size_bucket = i
        return max_size_bucket

    def append_term(self, term, tweet_id, frequency, inverted_idx):
        """"
        This function gets posting tuple data for term posting file and insert the tuple in term bucket
        If after the insertion the total size of all the buckets is bigger then MAX_SIZE so each bucket
        with size bigger then THRESHOLD will be flush.
        :param term is a term in the corpus
        :param tweet_id
        :param frequency of term in tweet_id
        :param inverted_idx for update pointer if needed or find bucket in the disk
        """
        if len(term) == 0 or not term[0].isalpha():
            if len(term) > 1 and term[1].isalpha():
                self.buckets[self.letters_dict[term[1].lower()]].append_term(term, tweet_id, frequency)
            else:
                self.buckets[-1].append_term(term, tweet_id, frequency)
        else:
            self.buckets[self.letters_dict[term[0].lower()]].append_term(term, tweet_id, frequency)
        self.size += 1
        if self.size > MAX_SIZE:
            for i in range(len(self.buckets)):
                if self.buckets[i].get_size() > THRESHOLD:
                    self.__flush_bucket(inverted_idx, i)

    def change_term_case(self, old_term, new_term):
        self.buckets[self.letters_dict[old_term[0].lower()]].rename_key(old_term, new_term)

    def finish_indexing(self, inverted_idx):  # flush all the buckets
        for i in range(len(self.buckets)):
            if self.buckets[i].get_size != 0:
                self.__flush_bucket(inverted_idx, i)

    def split_postings(self, inverted_idx):  # split the posting files after the building
        buckets = {}
        for entry in inverted_idx.items():
            if not entry[1][1][0] in buckets.keys():
                buckets[entry[1][1][0]] = []
            buckets[entry[1][1][0]].append(entry[0])
        for bucket in buckets.items():
            self.__split_bucket(bucket, inverted_idx)

    def __split_bucket(self, bucket, inverted_index):  # split file
        self.buckets
        posting = utils.load_obj("bucket" + str(bucket[0]))
        counter = 0
        new_posting = []
        split_index = 0
        for term in bucket[1]:
            if counter == 0:
                new_posting = []
                new_posting_index = str(inverted_index[term][1][0]) + "." + str(split_index)
                split_index += 1
            new_posting.append(posting[inverted_index[term][1][1]])
            inverted_index[term][1] = (new_posting_index, len(new_posting) - 1)
            counter += 1
            if counter == SPLIT_SIZE:
                counter = 0
                utils.save_obj(new_posting, "bucket" + new_posting_index)
        utils.save_obj(new_posting, "bucket" + new_posting_index)


from lib.calculations import *
from lib import matrices

class Triangle:
    def __init__(self, vertex_array, colour_array):
        self.vertices = np.array(vertex_array, dtype=np.float32)
        self.colours = np.array(colour_array, dtype=np.float32)

    def change_vertex(self, i, vertex):
        self.vertices[i] = vertex

    def change_vertex_colour(self, i, colour):
        self.colours[i] = colour

class Cube:
    def __init__(self, vertex_array, colour_array):
        self.vertices = np.array(vertex_array, dtype=np.float32)
        self.colours = np.array(colour_array, dtype=np.float32)
        self.trans_mat = np.empty((4, 4), dtype=np.float32)

    def change_vertex(self, i, vertex):
        self.vertices[i] = vertex

    def change_vertex_colour(self, i, colour):
        self.colours[i] = colour

class Sphere:
    def __init__(self, center, radius, colour,spec_intensity,spec_power,vertices=None,indices=None):
        if vertices is None:
            self.vertices = self.gen_vertices()
            self.indices = self.gen_indices()
            self.subdivide(2)
        else:
            self.vertices = vertices
            self.indices = indices
        self.colour = np.array(colour,dtype=np.float32)
        self.center = center
        self.radius = radius
        self.normals = self.vertices
        self.trans_mat = self.gen_trans_mat()
        self.spec_intensity = np.array([spec_intensity],np.float32)
        self.spec_power = np.array([spec_power], np.float32)

    def gen_vertices(self):
        X = .525731112119133606 ## these numbers make sure that the vertices of the Icosahedron all lie at distance 1 off
        Z = .850650808352039932 ## the origin.
        return np.array([[-X, 0, Z], [X, 0, Z], [-X, 0, -Z], [X, 0, -Z],
                         [0, Z, X], [0, Z, -X], [0, -Z, X], [0, -Z, -X],
                         [Z, X, 0], [-Z, X, 0], [Z, -X, 0], [-Z, -X, 0]], np.float32)

    def gen_indices(self):
        return np.array([[1, 4, 0], [4, 9, 0], [4, 5, 9], [8, 5, 4], [1, 8, 4],
                         [1, 10, 8], [10, 3, 8], [8, 3, 5], [3, 2, 5], [3, 7, 2],
                         [3, 10, 7], [10, 6, 7], [6, 11, 7], [6, 0, 11], [6, 1, 0],
                         [10, 1, 6], [11, 0, 9], [2, 11, 9], [5, 2, 9], [11, 2, 7]],np.uint32)

    def gen_colours(self):
        colours = np.empty((0,3),np.float32)

        for index in range(len(self.indices)):
            colour = np.array([np.random.random(),np.random.random(),np.random.randn()],np.float32)
            colours = np.vstack((colours,colour))

        return colours

    def gen_trans_mat(self):
        scale_mat = matrices.get_scale_matrix([self.radius,self.radius,self.radius])
        tot_mat = matrices.get_translation_matrix(self.center,matrix=scale_mat)
        return tot_mat

    def subdivide(self,depth):

        while depth > 0:
            new_indices = np.empty((0,3),np.uint32)
            for i in range(len(self.indices)):
                i1 = self.indices[i,0]
                i2 = self.indices[i,1]
                i3 = self.indices[i, 2]
                v1 = self.vertices[i1]
                v2 = self.vertices[i2]
                v3 = self.vertices[i3]

                v4 = (v1+v2)/2
                v5 = (v2+v3)/2
                v6 = (v1+v3)/2

                v4/=norm(v4)
                v5 /= norm(v5)
                v6 /= norm(v6)
                sub_indices = np.array([[i1,len(self.vertices),len(self.vertices)+2],
                                        [len(self.vertices),len(self.vertices)+1,len(self.vertices)+2],
                                        [len(self.vertices),i2,len(self.vertices)+1],
                                        [len(self.vertices)+1,i3,len(self.vertices)+2]],np.uint32)
                new_indices = np.vstack((new_indices,sub_indices))
                self.vertices = np.vstack((self.vertices,v4,v5,v6))
            self.indices = new_indices
            depth -=1
            self.subdivide(depth)
        for vertex in reversed(self.vertices):
            swap_index = np.where(np.all(self.vertices== vertex,axis=1))
            if np.size(swap_index) > 1:
                self.vertices = np.delete(self.vertices, swap_index[0][1], axis=0)
                indices = np.where(self.indices == swap_index[0][1])
                for i1,i2 in zip(indices[0],indices[1]):
                    self.indices[i1,i2]=swap_index[0][0]
                indices2 = np.where(self.indices>swap_index[0][1])
                for i1, i2 in zip(indices2[0], indices2[1]):
                    self.indices[i1,i2]-=1

class Cylinder:
    def __init__(self,v1,v2,radius,colour,spec_intensity,spec_power):

        self.vertices,self.indices,self.normals = self.read_object()

        self.colour = np.array(colour,dtype=np.float32)
        self.spec_intensity = np.array([spec_intensity],np.float32)
        self.spec_power = np.array([spec_power],np.float32)
        self.trans_mat = self.gen_trans_mat(v1,v2,radius)

    def gen_trans_mat(self,v1,v2,radius):
        vr = v2-v1
        l = norm(vr)
        angle = 180/pi * acos(vr[2]/l)
        scale_mat = matrices.get_scale_matrix([radius, radius, l])
        rot_ax = norm_cross_product(np.array([0,0,1],np.float32),vr)
        if norm(rot_ax)>0:
            rot_mat = matrices.get_rotation_matrix(rot_ax,angle,scale_mat)
            tot_mat = matrices.get_translation_matrix(v2,matrix=rot_mat)
        else:
            tot_mat = matrices.get_translation_matrix(v2,scale_mat)
        return tot_mat

    def read_object(self):
        obj = ObjReader()
        return obj.read_file("/Users/louisponet/PycharmProjects/pyopenglTut/lib/objects/cylinder.obj")

class OldCylinder:
    ##USE EVEN DIVISIONS!!
    def __init__(self, v1, v2, radius, colour, divisions):
        self.divisions = divisions
        self.vertices = self.gen_vertices(v1, v2, radius)
        self.indices = self.gen_indices()
        self.colour = np.array(colour, dtype=np.float32)
        self.normals = self.gen_normals()
        self.trans_mat = self.gen_trans_mat(v1, v2)
        print(self.normals, self.vertices)

    def gen_vertices(self, v1, v2, radius):
        vertices = np.array([[0, 0, 0], [0, 0, norm(v2 - v1)]], np.float32)
        i = 0
        while i < 2 * pi:
            vertices = np.vstack((vertices, np.array([radius * cos(i), radius * sin(i), 0], np.float32)))
            i += 2 * pi / self.divisions
        i = 0
        while i < 2 * pi:
            vertices = np.vstack((vertices, np.array([radius * cos(i), radius * sin(i), norm(v2 - v1)], np.float32)))
            i += 2 * pi / self.divisions
        vertices = np.vstack((vertices, vertices[2:]))
        return vertices

    def gen_indices(self):
        indices = np.empty((0, 3), np.uint32)
        i = 2
        while i < self.divisions + 1:
            indices = np.vstack((indices, np.array([i + 1, i, 0], np.uint32)))
            indices = np.vstack((indices, np.array([1, i + self.divisions, i + self.divisions + 1], np.uint32)))
            i += 1
        indices = np.vstack((indices,
                             np.array([[0, 2, self.divisions + 1], [2 * self.divisions + 1, self.divisions + 2, 1]],
                                      np.uint32)))
        i = 2
        while i < self.divisions + 1:
            indices = np.vstack((indices, np.array(
                [[i + 1, i + self.divisions, i], [self.divisions + i, i + 1, i + self.divisions + 1]], np.uint32)))
            i += 1
        indices = np.vstack((indices, np.array([[self.divisions + 2, 2 * self.divisions + 1, self.divisions + 1],
                                                [self.divisions + 1, 2, self.divisions + 2]], np.uint32)))
        indices = np.vstack((indices, indices))
        return indices

    def gen_colours(self):
        colours = np.empty((0, 3), np.float32)
        for i in range(len(self.vertices)):
            colours = np.vstack(
                (colours, np.array([np.random.random(), np.random.random(), np.random.random()], np.float32)))
        return colours

    def gen_trans_mat(self, v1, v2):
        vr = v2 - v1
        l = norm(vr)
        angle = 180 / pi * acos(vr[2] / l)

        rot_ax = norm_cross_product(np.array([0, 0, 1], np.float32), vr)
        if norm(rot_ax) > 0:
            rot_mat = matrices.get_rotation_matrix(rot_ax, angle)
            tot_mat = matrices.get_translation_matrix(v2, matrix=rot_mat)
        else:
            tot_mat = matrices.get_translation_matrix(v2)
        return tot_mat

    def gen_normals(self):
        normals = np.empty((0, 3), dtype=np.float32)
        normals = np.vstack((normals, [0, 0, -1]))
        # for vertex in self.vertices[2:1+2*self.divisions]:
        #     normals = np.vstack((normals,vertex))
        # else:

        # normals=np.vstack((normals,np.array([vertex[0],vertex[1],0],dtype=np.float32)))
        # for vertex in range(len(self.vertices[2+2*self.divisions:2+3*self.divisions])):
        #     normals = np.vstack((normals,np.array([0,0,-1],np.float32)))
        # for vertex in range(len(self.vertices[2+3*self.divisions:])):
        #     normals = np.vstack((normals,np.array([0,0,1],np.float32)))
        return normals

class ObjReader:
    def __init__(self):
        pass

    def read_file(self,filename):
        vertices = np.empty((0,3),dtype=np.float32)
        normals = np.empty((0,3),dtype=np.float32)
        indices = np.empty((0,3),dtype=np.uint32)
        norm_indices = np.empty((0,3),dtype=np.uint32)
        for line in open(filename, "r"):
            if line.startswith('#'): continue
            values = line.split()
            if not values: continue
            if values[0] == 'v':
                v = np.array(values[1:4],dtype=np.float32)
                vertices = np.vstack((vertices,v))
            elif values[0] == 'vn':
                v = np.array(values[1:4], dtype=np.float32)
                normals = np.vstack((normals,v))

            elif values[0] == 'f':
                w1 = values[1].split('/')
                w2 = values[2].split('/')
                w3 = values[3].split('/')
                index = np.array([int(w1[0])-1,int(w2[0])-1,int(w3[0])-1],np.uint32)
                norm_index = np.array([int(w1[-1])-1,int(w2[-1])-1,int(w3[-1])-1],np.uint32)
                indices = np.vstack((indices,index))
                norm_indices = np.vstack((norm_indices,norm_index))

        out_normals = np.empty(np.shape(normals),np.float32)
        for index, n_index in zip(indices,norm_indices):
            i1 = index[0]
            i2 = index[1]
            i3 = index[2]
            n1 = n_index[0]
            n2 = n_index[1]
            n3 = n_index[2]
            out_normals[i1] = normals[n1]
            out_normals[i2] = normals[n2]
            out_normals[i3] = normals[n3]
        return vertices,indices,out_normals


#!/bin/python3
"""
# Time Complexity:
    1. Best case: O(n)
    2. Average case: O(n2)
    3. Worst case: O(n2)
# Space complexity: O(1)
# Stable & In place sorting algorithm.
# Slow sorting algorithm but better than selection sort.

"""

# bubble_sort function to find number of swap, first element & last element.
def bubble_sort(a, n):
    swap_count = 0
    for i in range(n):
        flag = False
        for j in range(n - i - 1):
            if a[j] > a[j + 1]:
                flag = True
                swap_count += 1
                a[j], a[j + 1] = a[j + 1], a[j]
        if flag == False: break
    return a, swap_count, a[0], a[-1]

if __name__ == '__main__':
    n = int(input())
    a = list(map(int, input().rstrip().split()))
    # a = [int(i) for i in input().strip().split(" ")]
    a, swap_count, first_element, last_element = bubble_sort(a, n)
    print("Sorted array is {}.".format(a))
    print("Array is sorted in {} swaps.".format(swap_count))
    print("First Element: {}".format(first_element))
    print("Last Element: {}".format(last_element))


from django.db.models import Sum, Q, Count
from .models import ReadDetail
from django.utils import timezone
from article.models import Article
from django.contrib.contenttypes.models import ContentType
import datetime

def get_hot_article(type_=0, type=0):
    today = timezone.now().date()
    search_ = Q(data=today)
    for i in range(1, 4):
        search_ = search_ | Q(data=today - datetime.timedelta(days=i))
    ct = ContentType.objects.get_for_model(Article)
    readdetail = ReadDetail.objects.filter(search_).filter(content_type=ct)
    hot_article = readdetail.values('object_id').annotate(hot_nums=Sum('hot_num')).order_by('-hot_nums')
    if type_ == 0:
        hot_article = hot_article[:12]
    articles = []
    for art in hot_article:
        try:
            article = Article.objects.get(pk=art['object_id'])
            if type == 0 or article.type.pk == type:
                articles.append(article)
        except Exception:
            pass
    return articles

def get_jing_article(type=0):
    today = timezone.now().date()
    search_ = Q(data=today)
    for i in range(1, 4):
        search_ = search_ | Q(data=today - datetime.timedelta(days=i))
    ct = ContentType.objects.get_for_model(Article)
    readdetail = ReadDetail.objects.filter(search_).filter(content_type=ct)
    jing_article = readdetail.values('object_id').annotate(jing_nums=Sum('comment_num')).order_by('-jing_nums')
    articles = []
    for art in jing_article:
        try:
            article = Article.objects.get(pk=art['object_id'])
            if type == 0 or article.type.pk == type:
                articles.append(article)
        except Exception:
            pass
    return articles


class Solution:
    def countPrimes(self, n: int) -> int:
        def is_primes(c):
            """
            判断c是否为质数
            """
            for i in range(2, int(pow(c, 0.5)) + 1):
                if c % i == 0:
                    return False
            return True

        ans = 0
        for j in range(2, n):
            if is_primes(j):
                ans += 1
        return ans

if __name__ == "__main__":
    print(Solution().countPrimes(10))  # 4


# -*- coding:utf-8 -*-
import re
from django.contrib.auth import authenticate
from django.contrib.auth.signals import user_login_failed

def my_clean_credentials(credentials):
    SENSITIVE_CREDENTIALS = re.compile('api|token|key|secret|password|signature', re.I)
    CLEANSED_SUBSTITUTE = '********************'
    for key in credentials:
        if SENSITIVE_CREDENTIALS.search(key):
            credentials[key] = CLEANSED_SUBSTITUTE
    return credentials

def my_authenticate(**credentials):
    if 'the_backend' in credentials:
        the_backend = credentials['the_backend']
        try:
            user = the_backend.authenticate(**credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            user = None
        if user is  not None:
        # Annotate the user object with the path of the backend.
            user.backend = "%s.%s" % (the_backend.__module__, the_backend.__class__.__name__)
            return user
    else:
        return authenticate(**credentials)

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__, credentials=my_clean_credentials(credentials))


__author__ = 'Tyler LaBerge'
from Agent import Agent
from Web import Web
from Overseer import Overseer
import time
from Clock import Clock
from random import Random

def ExpectedResults(agents, sim_time):
    print("Expected results")
    for agent in agents:
        page_time = (agent.pageTime)
        site_time = (agent.homeTime)
        lifespan = (agent.lifespan)
        spawn_time = agent.spawn_time

        death_time =  (spawn_time) + (lifespan)
        if death_time > sim_time:
            death_time = sim_time

        life_time = death_time - spawn_time

        if site_time % page_time == 0:
            page_per_site = int((site_time/page_time))
        else:
            page_per_site = int((site_time/page_time)+1)

        homesites = int((life_time/site_time))
        base_sites = homesites * page_per_site
        remainder = life_time - (homesites*site_time)
        remaining_sites = (remainder/page_time)
        final_sites = base_sites+remaining_sites
        forms = 0
        for key in agent.forms_filled:
            if agent.forms_filled[key] == True:
                forms+=1

        print(agent.name +  ": " + "Approximately " + str(int(final_sites+1+(agent.mistake_sites * 2)+agent.typo_mistakes+forms)) + " visited sites")

def webErrorTesting():
    testAgent = Agent(["http://www.yahoo.com/"],10,25,"testAgent",60)
    url = "hfdahefl"
    testAgent.changeURL(url)
    testAgent.web.Update(testAgent,testAgent.rando)

def overseerTest():
    overseer_test = Overseer(1,["http://www.youtube.com","http://www.yahoo.com","http://www.cnn.com"],"overseertest")
    overseer_test.origin = time.time()
    overseer_test.run_overseer()

def typo_test():
    clock = Clock()
    test_agent = Agent(clock.get_time_passed(),["http://www.youtube.com","http://www.cnn.com","http://www.yahoo.com"],10,25,"Test Agent",65)
    mistake = test_agent.make_typo_mistake()
    print(mistake)

def glasshammers_form_test():
    rando = Random()
    name = "DJdjango"
    email = "DJdjango@dj.com"
    phone = "1230984756"
    inquiries = ["Customer Support","Commission","Questions","Comments"]
    reason = rando.choice(inquiries)
    message = "callllvinnnn!!"

    web = Web()
    web.glass_hammers_form(name,email,phone,reason,message)


from election_analysis import *
from matplotlib import cm

attribs = [
            'GOP2012',

            'Turnout2012',

            'Population2016',
            'Population2012',
            'Population2009',
            'Population1980',
            'PopulationDensity2016',

            'White2015',
            'Black2015',
            'Hispanic2015',
            'Asian2015',
            'Indian2015',
            'Youth2015',
            'White2009',
            'Black2009',
            'Hispanic2009',
            'Asian2009',
            'Indian2009',
            'Youth2009',

            'Unemployment2016',
            'Unemployment2011',
            'Unemployment2007',

            'MedianAge',
            'Bachelors',
            'CommuteTime',
            'FoodStamps',
            'Homeownership',
            'IncomeInequality',

            'Businesses2016',
            'Businesses2009',

            'RentBurdened2015',
            'RentBurdened2010',

            'EvangelicalProtestant',
            'MainlineProtestant',
            'BlackProtestant',
            'Catholic',
            'Jewish',
            'Muslim',
            'Mormon',

            'ClimateChange',

            'Corn',
            'Cotton',
            'Soybeans',
            'WinterWheat',
            'MedianIncome',

            'DrugPoisoning'
               ]
linearModel = ElectionAnalysis(attribs=attribs, regressionType='Linear', numDivisions=50, reloadData = True)
print(linearModel.data.index)
print(linearModel.data.iloc[0]['GOP2016'])
input('wait for key')
linearModel.makePipeline(demographicsChanges=True, economicChanges=True)

#Figure 3- National vote residuals
for i in range(50):
    print("i = " + str(i))
    linearModel.splitTestTrain(technique='hash', i=i)
    linearModel.prepData(labelName = 'GOP2016')
    linearModel.trainModel()
    linearModel.predictModel()
    linearModel.residModel()
    linearModel.concatenateResiduals()

print("RMS Elastic = " + str(100.0*linearModel.rmsModel()) + "%")
linearModel.countyPlot(pd.Series(index=linearModel.data.index, data=linearModel.results),dataMin=-0.2, dataMax=0.2, vMin=-20.0, vMax=20.0,cMap = cm.seismic, cLabel = 'GOP Vote Share Residual', pltTitle='test')

#Figure 4: Ensemble residuals
linearModel.bubblePlot(yValues = linearModel.results, xValues = linearModel.data['GOP2016'], sValues = linearModel.data['Population2016']/3400.0, cValues = linearModel.data['GOP2016'], fileName = 'test2', xLabel = 'GOP Vote Share', yLabel = 'GOP Vote Residual', minXValue = 0.0, minYValue = -0.2, maxXValue = 1.0, maxYValue = 0.2, cMap = cm.seismic)

#Drug poisoning GIF code
input('wait for key')

drugpoisoning = pd.read_csv('data_spreadsheets/drug_poisoning.csv').pivot(index='FIPS',columns='Year',values='Estimated Age-adjusted Death Rate, 16 Categories (in ranges)')
for column in drugpoisoning.columns:
    drugpoisoning[column] = drugpoisoning[column].str.split('-')
drugpoisoning = drugpoisoning.dropna()
for fips in drugpoisoning.index:
    for column in drugpoisoning.columns:
        drugpoisoning[column][fips] = float(drugpoisoning[column][fips][0].replace('>',''))

#Initialize the analysis object
for i in range(1999, 2016):
    print(i)
    linearModel.countyPlot(pd.Series(index=drugpoisoning.index, data=drugpoisoning[i]),dataMin=0.0, dataMax=30.0, vMin=0.0, vMax=30.0, cMap = cm.inferno, cLabel = 'Drug Poisoning Deaths per 100,000 per year', pltTitle='drugPoisoning'+str(i), pltSupTitle = str(i))


import tensorflow as tf
import numpy as np

# Hyperparameters
learning_rate = 0.0001
training_epochs = 100000
display_step = 1000
batch_size = 128
beta = 0.01

count_up_to = 100

# Network parameters
n_hidden_1 = 128
n_hidden_2 = 128
n_hidden_3 = 128
n_input = 1                  # 0-9
n_output = count_up_to       # 0-1 but as 1-hot vector. 2 = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

# Placeholders
x = tf.placeholder("float", [None, n_input], name="Input")
y = tf.placeholder("float", [None, n_output], name="Output")

def multilayer_perceptron(nn_input, weights, biases):
    layer_1 = tf.add(tf.matmul(nn_input, weights["h1"]), biases["b1"])
    layer_1 = tf.nn.sigmoid(layer_1)
    layer_2 = tf.add(tf.matmul(layer_1, weights["h2"]), biases["b2"])
    layer_2 = tf.nn.sigmoid(layer_2)
    layer_3 = tf.add(tf.matmul(layer_2, weights["h3"]), biases["b3"])
    layer_3 = tf.nn.sigmoid(layer_3)
    out_layer = tf.add(tf.matmul(layer_3, weights["out"]), biases["out"])
    return out_layer

def create_batch(batch_size):
    # We want to learn it how to coint: 0->1, 1->2, 2->3 .. 9->0
    xs = np.random.randint(0, count_up_to, batch_size)
    ys = [(t + 1) % count_up_to for t in xs]

    # But we need to create batches of observation input variables and response.
    # Format it into something tensorflow understands (shit).
    # The shape of batch_x has to be (batch_size, 1) as there is 64 observations of 1 value
    # The shape of batch_y has to be (batch_size, 10) as there is 64 observations of 1-hot vectors corresponding
    # to correct answer e.g. 2 = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

    batch_x = np.array([[t] for t in xs])

    # https://stackoverflow.com/questions/38592324/one-hot-encoding-using-numpy
    targets_y = np.array([ys]).reshape(-1)
    batch_y = np.eye(n_output)[targets_y]

    return batch_x, batch_y

# Weights and bias
weights = {
    'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
    'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'h3': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_3])),
    'out': tf.Variable(tf.random_normal([n_hidden_3, n_output]))
}
biases = {
    'b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'b3': tf.Variable(tf.random_normal([n_hidden_3])),
    'out': tf.Variable(tf.random_normal([n_output]))
}

# Construct model
nn_out = multilayer_perceptron(x, weights, biases)

# Define loss and optimizer
regularizer = tf.nn.l2_loss(weights["h1"]) + tf.nn.l2_loss(weights["h2"])
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=nn_out, labels=y) + regularizer * beta)
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)

init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    # Train
    for epoch in range(training_epochs):

        train_x, train_y = create_batch(batch_size)

        _, c = sess.run([optimizer, cost], feed_dict={x: train_x, y: train_y})

        if epoch % display_step == 0:
            print("Epoch {}".format(epoch))

    print("Training finished")

    # Test model
    pairs = []
    for test_value in range(count_up_to):
        test_x = np.zeros(1)
        test_x[0] = test_value
        test_x = test_x.reshape(1, 1)

        nn_out_softmax = tf.nn.softmax(nn_out)
        classification = sess.run(nn_out_softmax, {x: test_x})
        # print("sum: {}".format(np.sum(classification, 1)))
        # print("classifications: {}".format(classification))
        predicted_number = np.argmax(classification)
        print("predicted next number from {} is {}".format(test_value, predicted_number))

        pairs.append((test_value, predicted_number))

    correct = len(list(filter(lambda t: t[0] != (t[1]+1) % count_up_to, pairs)))
    print("Correct: {} out of: {}, percentage: {}".format(correct, count_up_to, (correct/count_up_to)*100))


from datetime import timedelta
import pandas as pd
import numpy as np

def smooth_with_rolling_average(
    series: pd.Series, window: int = 7, include_trailing_zeros: bool = True
):
    """Smoothes series with a min period of 1.

    https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.rolling.html

    Port of Projections.ts:
    https://github.com/covid-projections/covid-projections/blob/master/src/common/models/Projection.ts#L715

    Args:
        series: Series to smooth.
        window: Sliding window to average.
        include_trailing_zeros: Whether or not to NaN out trailing zeroes.

    Returns:
        Smoothed series.
    """
    rolling_average = series.rolling(window, min_periods=1).mean()
    if include_trailing_zeros:
        return rolling_average
    last_valid_index = series.replace(0, np.nan).last_valid_index()

    if last_valid_index:
        rolling_average[last_valid_index + 1 :] = np.nan
        return rolling_average
    else:  # entirely empty series:
        return series

def interpolate_stalled_values(series: pd.Series) -> pd.Series:
    """Interpolates periods where values have stopped increasing,

    Args:
        series: Series

    """
    series = series.copy()
    start, end = series.first_valid_index(), series.last_valid_index()
    series_with_values = series.loc[start:end]

    series_with_values[(series_with_values.diff() == 0)] = None
    # Use the index to determine breaks between data (so
    # missing data is not improperly interpolated)
    series.loc[start:end] = series_with_values.interpolate(method="index").round()

    return series


#
# Copyright (c) 2013, Arista Networks
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
#   Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
#   Redistributions in binary form must reproduce the above copyright notice, this
#   list of conditions and the following disclaimer in the documentation and/or
#   other materials provided with the distribution.
#
#   Neither the name of the {organization} nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import unittest
import os

import ztpserver.repository

class TestNode(unittest.TestCase):

    def test_create_node(self):
        headers = {
            'X-Arista-Softwarereversion': '4.12.0',
            'X-Arista-Architecture': 'i386',
            'X-Arista-Modelname': 'vEOS',
            'X-Arista-Systemmac': '00:0c:29:f5:d2:7d',
            'X-Arista-Serialnumber': '1234567890'
        }

        obj = ztpserver.repository.create_node(headers)
        self.assertEqual(obj.softwarereversion, '4.12.0')
        self.assertEqual(obj.architecture, 'i386')
        self.assertEqual(obj.modelname, 'vEOS')
        self.assertEqual(obj.systemmac, '00:0c:29:f5:d2:7d')
        self.assertEqual(obj.serialnumber, '1234567890')

class TestFileObject(unittest.TestCase):

    def test_create_file_object_with_path(self):
        path = os.path.join(os.getcwd(), 'test')
        fn = 'test_repository.py'
        obj = ztpserver.repository.FileObject(fn, path)

        self.assertEqual(repr(obj), 'FileObject(name=%s, type=%s)' %
            (os.path.join(path, fn), 'text/x-python'))

    def test_create_file_object_without_path(self):
        path = os.path.join(os.getcwd(), 'test', 'test_repository.py')
        obj = ztpserver.repository.FileObject(path)
        self.assertEqual(repr(obj), 'FileObject(name=%s, type=%s)' %
            (path, 'text/x-python'))

class TestFileStore(unittest.TestCase):

    def test_create_file_store(self):
        name = 'test'
        path = os.path.join(os.getcwd(), name)

        obj = ztpserver.repository.create_file_store(name, os.getcwd())
        self.assertEqual(repr(obj), "FileStore(path=%s)" % path)

    def test_get_file_valid(self):
        filestore = 'test'
        filename = 'test_repository.py'
        path = os.path.join(os.getcwd(), filestore, filename)
        fspath = os.path.join(os.getcwd(), filestore)

        obj = ztpserver.repository.create_file_store(filestore, basepath=os.getcwd())
        fobj = obj.get_file(filename)
        self.assertEqual(repr(fobj), 'FileObject(name=%s, type=%s)' %
            (path, 'text/x-python'))

    def test_get_file_invalid(self):
        obj = ztpserver.repository.create_file_store('test', os.getcwd())
        self.assertRaises(ztpserver.repository.FileObjectNotFound,
                          obj.get_file,
                          'invalid_filename')

if __name__ == '__main__':
    unittest.main()


#calss header
class _EMETIC():
	def __init__(self,):
		self.name = "EMETIC"
		self.definitions = [u'a substance, especially a medicine, that causes vomiting']

		self.parents = []
		self.childen = []
		self.properties = []
		self.jsondata = {}

		self.specie = 'nouns'

	def run(self, obj1 = [], obj2 = []):
		return self.jsondata


"""

Write a function that returns the **smallest N-digit number** which is a
**multiple** of the specified value.

### Examples

    smallest(3, 8) ➞ 104
    # Smallest 3-digit integer that is a multiple of 8

    smallest(5, 12) ➞ 10008

    smallest(7, 1) ➞ 1000000

    smallest(2, 3) ➞ 12

### Notes

N/A

"""

def smallest(d, v):

    x = int("1" + "0" * (d-1))
    while x>1:
        if x%v==0:
            return(x)
            break
        else:
            x+=1


import csv
from django.db.models import BooleanField, Case, Count, When, Value
from django.utils.functional import cached_property

from company.models import Company
from supplier.models import Supplier

class SSOUser:
    def __init__(self, id, email):
        self.id = id
        self.email = email

    @property
    def pk(self):
        return self.id

    @cached_property
    def supplier(self):
        try:
            return Supplier.objects.get(sso_id=self.id)
        except Supplier.DoesNotExist:
            return None

def generate_suppliers_csv(file_object, queryset):
    csv_excluded_fields = (
        'id',
        'company',
        'created',
        'modified',
        'company__collaboratorrequest',
        'company__company_type',
        'company__supplier_case_studies',
        'company__suppliers',
        'company__users',
        'company__verification_code',
        'company__messages',
        'supplieremailnotification',
        'company__ownershipinvite',
        'ownershipinvite',
        'company__collaboratorinvite',
        'collaboratorinvite'
    )
    fieldnames = [field.name for field in Supplier._meta.get_fields()
                  if field.name not in csv_excluded_fields]
    fieldnames += ['company__' + field.name
                   for field in Company._meta.get_fields()
                   if 'company__' + field.name
                   not in csv_excluded_fields]
    fieldnames.extend([
        'company__has_case_study',
        'company__number_of_case_studies'
    ])
    suppliers = queryset.select_related('company').all().annotate(
        company__has_case_study=Case(
            When(company__supplier_case_studies__isnull=False,
                 then=Value(True)
                 ),
            default=Value(False),
            output_field=BooleanField()
        ),
        company__number_of_case_studies=Count(
            'company__supplier_case_studies'
        ),
    ).values(*fieldnames)
    fieldnames.append('company__number_of_sectors')
    fieldnames = sorted(fieldnames)
    writer = csv.DictWriter(file_object, fieldnames=fieldnames)
    writer.writeheader()

    for supplier in suppliers:

        sectors = supplier.get('company__sectors')
        if sectors:
            supplier['company__number_of_sectors'] = len(sectors)
            supplier['company__sectors'] = ','.join(sectors)
        else:
            supplier['company__number_of_sectors'] = '0'
            supplier['company__sectors'] = ''

        writer.writerow(supplier)


import numpy as np
from scipy import sparse, linalg
import osqp
import pdb

#from compatibility_lib.cleaned_LMPC.local_linearization import PredictiveModel
import copy
from matplotlib import pyplot as plt

class MPCUtil():
    '''
    General purpose MPC utility. Can be used for MPC, LMPC, ATV_MPC, etc...

    '''

    def __init__(self, N, dim_x, dim_u, num_ss = 50):
        #support for non-LMPC is not yet implemented
        self.N = N
        self.dim_x = dim_x
        self.dim_u = dim_u
        self.num_ss = num_ss
        self.num_lambda = self.num_ss
        self.num_eps = self.N
        self.num_mu = self.dim_x

        self.last_output = np.zeros((self.dim_u,1))

        #TODO: These are currently placeholders and may not work if changed
        self.use_ss = True
        self.use_terminal_slack = True
        self.use_lane_slack = True
        self.use_affine = True
        self.use_time_varying = False
        return

    def set_model_matrices(self, A ,B ,C = None):
        assert A.shape[1] == A.shape[0]
        assert A.shape[1] == self.dim_x
        assert B.shape[0] == self.dim_x
        assert B.shape[1] == self.dim_u

        if C is None: C = np.zeors((self.dim_x, 1))
        assert C.shape[0] == self.dim_x
        assert C.shape[1] == 1

        self.A = A
        self.B = B
        self.C = C
        return

    def set_state_costs(self, Q, P, R, dR):
        assert Q.shape[0] == Q.shape[1]
        assert Q.shape[0] == self.dim_x
        assert P.shape[0] == P.shape[1]
        assert P.shape[0] == self.dim_x
        assert R.shape[0] == R.shape[1]
        assert R.shape[0] == self.dim_u
        assert dR.shape[0] == dR.shape[1]
        assert dR.shape[0] == self.dim_u

        self.Q = Q   # intermediate state cost
        self.P = P   # terminal state cost
        self.R = R   # output state cost
        self.dR = dR # output rate cost
        return

    def set_slack_costs(self, Q_mu, Q_eps, b_eps):
        assert Q_mu.shape[0] == Q_mu.shape[1]
        assert Q_mu.shape[0] == self.num_mu
        assert Q_eps.shape[0] == Q_eps.shape[1]
        assert Q_eps.shape[0] == self.num_eps
        assert b_eps.shape[0] == self.num_eps
        assert b_eps.shape[1] == 1

        self.Q_mu = Q_mu
        self.Q_eps = Q_eps
        self.b_eps = b_eps
        return

    def set_state_constraints(self,Fx, bx_u, bx_l, Fu, bu_u, bu_l, E, max_lane_slack = 1):
        assert Fx.shape[1] == self.dim_x
        assert Fx.shape[0] == bx_u.shape[0]
        assert Fx.shape[0] == bx_l.shape[0]
        assert bx_u.shape[1] == 1
        assert bx_l.shape[1] == 1
        assert Fu.shape[1] == self.dim_u
        assert Fu.shape[0] == bu_u.shape[0]
        assert Fu.shape[0] == bu_l.shape[0]
        assert bu_u.shape[1] == 1
        assert bu_l.shape[1] == 1
        assert E.shape[0] == Fx.shape[0]
        assert E.shape[1] == 1

        self.Fx = Fx
        self.bx_u = bx_u
        self.bx_l = bx_l
        self.Fu = Fu
        self.bu_u = bu_u
        self.bu_l = bu_l
        self.E = E
        self.max_lane_slack = max_lane_slack
        return

    def set_ss(self,ss_vecs, ss_q):
        assert ss_vecs.shape[0] == self.dim_x
        assert ss_vecs.shape[1] == self.num_ss
        assert ss_q.shape[0] == self.num_ss
        assert ss_q.shape[1] == 1

        self.ss_terminal_q = ss_q
        self.ss_terminal_vecs = ss_vecs
        return

    def set_x0(self,x0, xf = None):
        if xf is None:
            xf = np.zeros(x0.shape)
        assert x0.shape[0] == self.dim_x
        assert x0.shape[1] == 1
        assert xf.shape[0] == self.dim_x
        assert xf.shape[1] == 1
        self.x0 = x0
        self.xf = xf

        return

    def build_cost_matrix(self):

        Mx = sparse.block_diag((*([self.Q]*self.N), self.P))
        Mu = sparse.kron(sparse.eye(self.N, k = -1), -self.dR)  +\
             sparse.kron(sparse.eye(self.N, k =  1), -self.dR)  +\
             sparse.kron(sparse.eye(self.N), self.R+2*self.dR)
        M = 2*sparse.block_diag([Mx, Mu])

        #q = np.zeros((self.num_x,1))
        if self.use_ss:
            q = np.vstack([np.kron(np.ones((self.N,1)), -self.Q @ self.ss_terminal_vecs[:,-1:]), self.P @ self.ss_terminal_vecs[:,-1:]])
        else:
            q = np.vstack([np.kron(np.ones((self.N,1)), -self.Q @ self.xf), self.P @ self.xf])

        #q = np.vstack([q, np.zeros((self.num_u,1))])
        for i in range(self.N):                             #TODO: prior output cost should go here
            q = np.vstack([q, np.array([[0],[0],[-14]])])

        #q = np.vstack([q, -2 * self.dR @ self.last_output])         # untested (thomasfork)
        #q = np.vstack([q, np.zeros((self.dim_u * (self.N-1),1))])

        if self.use_ss:
            M = sparse.block_diag([M, sparse.csc_matrix((self.num_lambda, self.num_lambda))])
            q = np.vstack([q, self.ss_terminal_q])

        if self.use_terminal_slack:
            M = sparse.block_diag([M, 2*self.Q_mu])
            q = np.vstack([q, np.zeros((self.dim_x,1))])

        if self.use_lane_slack:
            M = sparse.block_diag([M, 2*self.Q_eps])
            q = np.vstack([q, self.b_eps])

        self.osqp_P = sparse.csc_matrix(M)
        self.osqp_q = q

        return

    def build_constraint_matrix(self):
        #more info on the constraints for OSQP can be found at https://osqp.org
        # in particular, https://osqp.org/docs/examples/mpc.html provides a great MPC example

        #more info on the constraints for the berkeley car can be found at a location coming soon.

        #Equality constraints:
        # state constraints - x_k+1 = A*x_k + B*u_k
        # except x_0 = self.x0
        Ax = sparse.kron(sparse.eye(self.N+1),sparse.eye(self.dim_x)) + \
             sparse.kron(sparse.eye(self.N+1, k=-1), -self.A)                #TODO: Time varying case would be implemented here
        Au = sparse.kron(sparse.vstack([sparse.csc_matrix((1, self.N)), sparse.eye(self.N)]), -self.B)
        Aeq = sparse.hstack([Ax, Au])
        leq = np.vstack([self.x0, np.tile(self.C.T,self.N).T])

        # safe set constraints:
        #  terminal point must be a weighted sum of safe set points and slack:
        #  weights must also sum to zero
        if self.use_ss:
            temp_Aeq_height = Aeq.shape[0]
            if self.use_terminal_slack:

                A_lambda = np.vstack((np.hstack((self.ss_terminal_vecs, -np.eye(self.dim_x))), np.hstack((np.ones((1,self.num_ss)), np.zeros((1,self.dim_x))))))
            else:
                A_lambda = sparse.vstack([self.ss_terminal_vecs, np.ones((1,self.num_ss))])

            Aeq = sparse.block_diag((Aeq,A_lambda))
            Aeq = sparse.lil_matrix(Aeq)
        #  finish terminal point constraint - sum of weights and slack variables must equal x_N
            Aeq[temp_Aeq_height: temp_Aeq_height + self.dim_x, self.dim_x * self.N: self.dim_x * (self.N+1)] = -sparse.eye(self.dim_x)

        #  update leq, ueq with terminal constraints
            leq = np.vstack([leq, np.zeros((self.dim_x, 1)), 1])

        # otherwise add terminal constraint
        else:
            tmp = np.zeros((1,self.N + 1))
            tmp[0,self.N] = 1
            A_terminal = sparse.kron(tmp, sparse.eye(self.dim_x))
            A_terminal = sparse.hstack([A_terminal, sparse.csc_matrix((self.dim_x, self.num_u))])
            Aeq = sparse.vstack([Aeq, A_terminal])

            leq = np.vstack([leq, self.xf])
        # upper and lower constraints are identical for equality constraints
        ueq = copy.copy(leq)

        # no equality constraints for lane slack but need to add columns of zeros
        if self.use_lane_slack:
            Aeq = sparse.hstack((Aeq, sparse.csc_matrix((Aeq.shape[0],  self.num_eps))))

        assert Aeq.shape[0] == ueq.shape[0]

        #Inequality constraints:
        # state constraints
        '''if self.use_ss:
            #  no state constraint for x_N since it is handleded by safe set constraint
            Aineq = sparse.block_diag(([self.Fx]*self.N))  #, sparse.csc_matrix((self.dim_x,self.dim_x))))
            Aineq = sparse.hstack([Aineq, sparse.csc_matrix((Aineq.shape[0],self.dim_x))])

        else:'''

        Aineq = sparse.block_diag(([self.Fx]*(self.N+1)))
        lineq = np.kron(np.ones((self.N+1,1)), self.bx_l)
        uineq = np.kron(np.ones((self.N+1,1)), self.bx_u)

        # generate upper and lower bounds
        '''if self.use_ss:
            lineq = np.kron(np.ones((self.N,1)), self.bx_l)
            uineq = np.kron(np.ones((self.N,1)), self.bx_u)
        else:'''

        assert Aineq.shape[0] == lineq.shape[0]

        # add output constraints
        Aineq = sparse.block_diag((Aineq,*([self.Fu]*self.N)))
        lineq = np.vstack((lineq, *([self.bu_l]*self.N)))
        uineq = np.vstack((uineq, *([self.bu_u]*self.N)))

        # force safe set weighting terms (lamda) to be positive
        #   note: upper bound is 1 not inf since their sum must be 1
        if self.use_ss:
            Aineq = sparse.block_diag((Aineq,sparse.eye(self.num_ss)))
            lineq = np.vstack([lineq,  np.zeros((self.num_ss,1))])
            uineq = np.vstack([uineq,  np.ones((self.num_ss,1))])

        assert Aineq.shape[0] == lineq.shape[0]

        # zero pad if terminal slack is used (no constriants on terminal slack)
        if self.use_terminal_slack:
            Aineq = sparse.hstack([Aineq,sparse.csc_matrix((Aineq.shape[0], self.dim_x))])

        # add effect on state constraints if lane slack is added.
        #    note: does not effect terminal state
        if self.use_lane_slack:
            slack_matrix = sparse.block_diag(([self.E]*self.N))
            Aineq = sparse.block_diag([Aineq, sparse.eye(self.num_eps)])
            Aineq = sparse.lil_matrix(Aineq)
            Aineq [0:slack_matrix.shape[0],-slack_matrix.shape[1]:] = slack_matrix

            #force lane slack to less than max_lane_slack (+/- since slack can act on either side of the lane)

            lineq = np.vstack([lineq, -np.ones((self.E.shape[1]*self.N,1))*self.max_lane_slack])
            uineq = np.vstack([uineq, np.ones((self.E.shape[1]*self.N,1))*self.max_lane_slack])

        assert Aineq.shape[0] == lineq.shape[0]

        # - OSQP constraints
        A = sparse.vstack([Aeq, Aineq], format='csc')
        l = np.vstack([leq, lineq])
        u = np.vstack([ueq, uineq])

        self.osqp_A = sparse.csc_matrix(A)
        self.osqp_l = l
        self.osqp_u = u

        return

    def setup(self):
        self.num_x =         (self.N + 1) * self.dim_x
        self.num_u =         self.N * self.dim_u

        self.index_x =       0
        self.index_u =       self.index_x + self.num_x
        self.index_lambda =  self.index_u + self.num_u
        self.index_mu =      self.index_lambda + self.num_lambda
        self.index_eps =     self.index_mu + self.num_mu

        self.use_ss = True
        self.use_terminal_slack = False
        self.use_lane_slack = False

        self.build_cost_matrix()
        self.build_constraint_matrix()

        self.solver = osqp.OSQP()
        self.solver.setup(P=self.osqp_P, q=self.osqp_q, A=self.osqp_A, l=self.osqp_l, u=self.osqp_u, verbose=True, polish=True)
        return

    def setup_MPC(self):
        self.num_x =         (self.N + 1) * self.dim_x
        self.num_u =         self.N * self.dim_u
        self.index_x =       0
        self.index_u =       self.index_x + self.num_x

        self.use_ss = False
        self.use_terminal_slack = False
        self.use_lane_slack = False

        self.build_cost_matrix()
        self.build_constraint_matrix()

        self.solver = osqp.OSQP()
        self.solver.setup(P=self.osqp_P, q=self.osqp_q, A=self.osqp_A, l=self.osqp_l, u=self.osqp_u, verbose=True, polish=True)
        return

    def update(self):
        self.update_ss()
        self.update_x0()
        self.update_model_matrices()
        self.solver.update(q = self.osqp_q, Ax = self.osqp_A.data, l = self.osqp_l ,u = self.osqp_u)
        return

    def update_ss(self):
        if not self.use_ss:
            return
        num_x = self.dim_x * (self.N + 1)
        num_u = self.dim_u * self.N
        self.osqp_q[num_x + num_u: num_x + num_u + self.num_ss] = self.ss_terminal_q
        self.osqp_A = sparse.lil_matrix(self.osqp_A)
        self.osqp_A[num_x + num_u :num_x+num_u + self.dim_x, num_x+num_u : num_x+num_u + self.num_ss] = self.ss_terminal_vecs
        self.osqp_A = sparse.csc_matrix(self.osqp_A)
        return

    def update_x0(self):
        self.osqp_l[0:self.dim_x] = self.x0
        self.osqp_u[0:self.dim_x] = self.x0
        return

    def update_model_matrices(self):
        Ax = sparse.kron(sparse.eye(self.N+1),sparse.eye(self.dim_x)) + \
             sparse.kron(sparse.eye(self.N+1, k=-1), -self.A)                #TODO: Implement time varying case
        Au = sparse.kron(sparse.vstack([sparse.csc_matrix((1, self.N)), sparse.eye(self.N)]), -self.B)
        Aeq = sparse.hstack([Ax, Au])

        self.osqp_A[0:Aeq.shape[0], 0:Aeq.shape[1]] = Aeq
        return

    def solve(self, init_vals = None):
        if init_vals is not None:
            self.solver.warm_start(x=init_vals)

        z0 = np.vstack([self.x0, self.ss_terminal_vecs[:,0:self.N].reshape(-1,1)])
        z0 = np.vstack([z0, np.zeros((self.osqp_P.shape[0] - z0.shape[0],1))])
        self.solver.warm_start(x = z0)

        res = self.solver.solve()
        self.osqp_feasible = res.info.status_val == 1

        if self.osqp_feasible:
            self.unpack_results(res)
        else:
            print('Ineasible OSQP')
        return

    def unpack_results(self,res):
        num_x = self.dim_x * (self.N + 1)
        num_u = self.dim_u * self.N
        self.predicted_x = np.reshape(res.x[self.index_x:self.index_x + self.num_x], (self.N+1, self.dim_x))
        self.predicted_u = np.reshape(res.x[self.index_u:self.index_u + self.num_u], (self.N, self.dim_u))

        if self.use_ss:
            self.predicted_lambda = res.x[self.index_lambda:self.index_lambda + self.num_lambda]
        else:
            self.predicted_lambda = np.nan
        if self.use_terminal_slack:
            self.predicted_mu = res.x[self.index_mu:self.index_mu + self.num_mu]
        else:
            self.predicted_mu = np.nan
        if self.use_lane_slack:
            self.predicted_eps = res.x[self.index_eps:self.index_eps + self.num_eps]
        else:
            self.predicted_eps = np.nan

        return

def main():
    N = 5
    dim_x = 2
    dim_u = 1
    dim_mu = dim_x
    dim_eps = N
    dim_ss = 4

    A = np.array([[1,0.1],[0,.9]])
    B = np.array([[0],[1]])
    C = np.array([[0.0],[0]])

    x0 = np.ones((dim_x,1)) * 4

    Q = sparse.eye(dim_x) * 10
    P = sparse.eye(dim_x) * 100
    R = sparse.eye(dim_u) * 10
    dR = sparse.eye(dim_u) * 0
    Q_mu = sparse.eye(dim_mu) * 10000
    Q_eps = sparse.eye(dim_eps) * 100
    b_eps = np.ones((dim_eps,1)) * 0

    ss_vecs = np.ones((dim_x,dim_ss))
    ss_vecs[1,:] = 0
    ss_q    = np.zeros((dim_ss,1))

    #Fx = np.array([[0,0,0,0,0,1]])
    #bx_u = np.array([[0.8]])
    #bx_l =  np.array([[-0.8]])

    #Fu = np.eye(2)
    #bu_u = np.array([[10],[0.5]])
    #bu_l = np.array([[-10],[-0.5]])

    Fx = np.eye(2)
    bx_u = np.array([[10],[10]])
    bx_l = np.array([[-10],[-10]])

    Fu = np.eye(1)
    bu_u = np.array([[1]])
    bu_l = np.array([[-1]])

    E = np.array([[1],[1]])

    m = MPCUtil(N, dim_x, dim_u, num_ss = dim_ss)
    m.set_model_matrices(A,B,C)
    m.set_x0(x0)
    m.set_state_costs(Q, P, R, dR)
    m.set_slack_costs(Q_mu, Q_eps, b_eps)
    m.set_ss(ss_vecs, ss_q)
    m.set_state_constraints(Fx, bx_u, bx_l, Fu, bu_u, bu_l, E)

    m.setup()

    assert m.osqp_P.shape[0] == dim_x  *(N+1) + N*dim_u + dim_eps + dim_mu + dim_ss
    assert m.osqp_P.shape[0] == m.osqp_P.shape[1]

    assert m.osqp_A.shape[1] == m.osqp_A.shape[1]
    assert m.osqp_A.shape[0] == m.osqp_l.shape[0]
    assert m.osqp_A.shape[0] == m.osqp_u.shape[0]
    assert m.osqp_l.shape[1] == 1
    assert m.osqp_u.shape[1] == 1
    m.solve()

    print('LMPC u: %s'%str(m.predicted_u[0]))
    print('avg. terminal point: %f'%np.sum(m.predicted_lambda * np.arange(m.num_ss)))
    print('terminal slack: %f'%np.linalg.norm(m.predicted_mu))
    print('lane slack: %f'%np.linalg.norm(m.predicted_eps))

    plt.figure()

    x = x0.copy()
    xlist = [x]
    ulist = []
    for j in range(150):
        m.set_x0(x)
        m.update() #setup()
        m.solve()
        u = m.predicted_u[0:1]
        print(u)
        x = A @ x + B @ u + C
        for i in range(dim_x):
            plt.subplot(2,2,i*2+1)
            plt.plot(range(j,j+N+1), m.predicted_x[:,i],'--')
        for i in range(dim_u):
            plt.subplot(2,2,i*2+2)
            plt.plot(range(j,j+N), m.predicted_u[:,i],'--')
        xlist.append(x)
        ulist.append(u)
    xlist = np.array(xlist)
    ulist = np.array(ulist)
    for i in range(dim_x):
        plt.subplot(2,2,i*2+1)
        plt.plot(xlist[:,i,0],'-')
    for i in range(dim_u):
        plt.subplot(2,2,i*2+2)
        plt.plot(ulist[:,i,0],'-')

    plt.show()

    #pdb.set_trace()

    return

if __name__ == '__main__':
    main()


from __future__ import absolute_import
import wx
from utils.date_time import wxDefaultDateTime
from wx.lib import masked

class CorrectionPanelUI(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, id=wx.ID_ANY,
                          pos=wx.DefaultPosition,
                          size=wx.Size(760, 280), style=wx.TAB_TRAVERSAL)

        bSizer1 = wx.BoxSizer(wx.HORIZONTAL)

        self.m_splitter1 = wx.SplitterWindow(self, wx.ID_ANY,
                                             wx.DefaultPosition,
                                             wx.DefaultSize, wx.SP_3D)
        #self.m_splitter1.Bind(wx.EVT_IDLE, self.m_splitter1OnIdle)

        self.rightPanel = wx.Panel(self.m_splitter1, wx.ID_ANY,
                                   wx.DefaultPosition, wx.DefaultSize,
                                   wx.TAB_TRAVERSAL)
        bSizer2 = wx.BoxSizer(wx.VERTICAL)

        self.lc_correctionList = wx.ListCtrl(self.rightPanel, wx.ID_ANY,
                                             wx.DefaultPosition,
                                             wx.DefaultSize, wx.LC_REPORT)
        self.lc_correctionList.InsertColumn(0, "Correction Id", width=20)
        self.lc_correctionList.InsertColumn(1, "Episode Id", width=50)
        self.lc_correctionList.InsertColumn(2, "User Id", width=50)
        self.lc_correctionList.InsertColumn(3, "Complain Date", width=60)
        self.lc_correctionList.InsertColumn(4, "Timecode", width=50)
        self.lc_correctionList.InsertColumn(5, "Error Description", width=80)
        self.lc_correctionList.InsertColumn(6, "Editor Id", width=40)
        self.lc_correctionList.InsertColumn(7, "Correction Date", width=40)
        self.lc_correctionList.InsertColumn(8, "Correction Status", width=40)
        bSizer2.Add(self.lc_correctionList, 1, wx.ALL | wx.EXPAND, 5)

        self.rightPanel.SetSizer(bSizer2)
        self.rightPanel.Layout()
        bSizer2.Fit(self.rightPanel)
        self.m_splitter1.Initialize(self.rightPanel)
        bSizer1.Add(self.m_splitter1, 1, wx.EXPAND, 5)

        self.m_splitter2 = wx.SplitterWindow(self, wx.ID_ANY,
                                             wx.DefaultPosition,
                                             wx.DefaultSize, wx.SP_3D)
        #self.m_splitter2.Bind(wx.EVT_IDLE, self.m_splitter2OnIdle)

        self.leftPanel = wx.ScrolledWindow(self.m_splitter2, wx.ID_ANY,
                                           wx.DefaultPosition,
                                           wx.DefaultSize,
                                           wx.HSCROLL | wx.VSCROLL)
        self.leftPanel.SetScrollRate(5, 5)
        fgSizer1 = wx.FlexGridSizer(0, 2, 0, 0)
        fgSizer1.AddGrowableCol(1)
        fgSizer1.AddGrowableRow(4)
        fgSizer1.SetFlexibleDirection(wx.BOTH)
        fgSizer1.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)

        self.st_userID = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                       u"User Name", wx.DefaultPosition,
                                       wx.DefaultSize, 0)
        self.st_userID.Wrap(-1)
        fgSizer1.Add(self.st_userID, 0, wx.ALL, 5)

        self.tc_userID = wx.TextCtrl(self.leftPanel, wx.ID_ANY,
                                     wx.EmptyString, wx.DefaultPosition,
                                     wx.DefaultSize, 0)
        self.tc_userID.Enable(False)

        fgSizer1.Add(self.tc_userID, 1, wx.ALL | wx.EXPAND, 5)

        self.st_complain_date = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                              u"Complaint Date",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.st_complain_date.Wrap(-1)
        fgSizer1.Add(self.st_complain_date, 0, wx.ALL, 5)

        self.dp_complain_date = wx.DatePickerCtrl(self.leftPanel, wx.ID_ANY,
                                                  wxDefaultDateTime(),
                                                  wx.DefaultPosition,
                                                  wx.DefaultSize, wx.DP_DEFAULT)
        fgSizer1.Add(self.dp_complain_date, 0, wx.ALL, 5)

        self.st_complain_Time = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                              u"Complaint Time",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.st_complain_Time.Wrap(-1)
        fgSizer1.Add(self.st_complain_Time, 0, wx.ALL, 5)

        complaintSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.tc_compTime = masked.TimeCtrl(self.leftPanel, wx.ID_ANY,
                                           wx.EmptyString, wx.DefaultPosition,
                                           wx.DefaultSize,
                                           display_seconds=False,
                                           oob_color="White")
        complaintSizer.Add(self.tc_compTime, 1, wx.ALL | wx.EXPAND, 5)
        self.spin_compTime = wx.SpinButton(self.leftPanel, wx.ID_ANY,
                                           wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        self.tc_compTime.BindSpinButton(self.spin_compTime)
        complaintSizer.Add(self.spin_compTime, 0, wx.ALL, 5)

        fgSizer1.Add(complaintSizer, 1, wx.EXPAND, 5)

        self.st_timecode = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                         u"Time Code", wx.DefaultPosition,
                                         wx.DefaultSize, 0)
        self.st_timecode.Wrap(-1)
        fgSizer1.Add(self.st_timecode, 0, wx.ALL, 5)

        self.tc_timecode = masked.TextCtrl(self.leftPanel, wx.ID_ANY,
                                           wx.EmptyString, wx.DefaultPosition,
                                           wx.DefaultSize,
                                           mask='##:##:##:##',
                                           defaultValue='00:00:00:00')
        fgSizer1.Add(self.tc_timecode, 0, wx.ALL | wx.EXPAND, 5)

        self.st_desc = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                     u"Description", wx.DefaultPosition,
                                     wx.DefaultSize, 0)
        self.st_desc.Wrap(-1)
        fgSizer1.Add(self.st_desc, 0, wx.ALL, 5)

        self.tc_desc = wx.TextCtrl(self.leftPanel, wx.ID_ANY,
                                   wx.EmptyString, wx.DefaultPosition,
                                   wx.DefaultSize, wx.TE_MULTILINE)
        self.tc_desc.SetMaxLength(255)
        self.tc_desc.SetMinSize(wx.Size(-1, 70))

        fgSizer1.Add(self.tc_desc, 1, wx.ALL | wx.EXPAND, 5)

        self.st_editorName = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                           u"Editor Name", wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        self.st_editorName.Wrap(-1)
        fgSizer1.Add(self.st_editorName, 0, wx.ALL, 5)

        self.tc_editorName = wx.TextCtrl(self.leftPanel, wx.ID_ANY,
                                         wx.EmptyString, wx.DefaultPosition,
                                         wx.DefaultSize, 0)
        self.tc_editorName.Enable(False)

        fgSizer1.Add(self.tc_editorName, 0, wx.ALL | wx.EXPAND, 5)

        self.st_correctionDate = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                               u"Correction Date",
                                               wx.DefaultPosition,
                                               wx.DefaultSize, 0)
        self.st_correctionDate.Wrap(-1)
        fgSizer1.Add(self.st_correctionDate, 0, wx.ALL, 5)

        self.dp_correctionDate = wx.DatePickerCtrl(self.leftPanel, wx.ID_ANY,
                                                   wxDefaultDateTime(),
                                                   wx.DefaultPosition,
                                                   wx.DefaultSize,
                                                   wx.DP_DEFAULT)
        fgSizer1.Add(self.dp_correctionDate, 0, wx.ALL, 5)

        self.st_correction_Time = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                                u"Correction Time",
                                                wx.DefaultPosition,
                                                wx.DefaultSize, 0)
        self.st_correction_Time.Wrap(-1)
        fgSizer1.Add(self.st_correction_Time, 0, wx.ALL, 5)

        correctionSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.tc_corrTime = masked.TimeCtrl(self.leftPanel, wx.ID_ANY,
                                           wx.EmptyString, wx.DefaultPosition,
                                           wx.DefaultSize,
                                           display_seconds=False,
                                           oob_color="White")
        correctionSizer.Add(self.tc_corrTime, 1, wx.ALL | wx.EXPAND, 5)

        self.spin_corrTime = wx.SpinButton(self.leftPanel, wx.ID_ANY,
                                           wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        self.tc_corrTime.BindSpinButton(self.spin_corrTime)
        correctionSizer.Add(self.spin_corrTime, 0, wx.ALL, 5)

        fgSizer1.Add(correctionSizer, 1, wx.EXPAND, 5)

        self.st_correctionStatus = wx.StaticText(self.leftPanel, wx.ID_ANY,
                                                 u"Correction Status",
                                                 wx.DefaultPosition,
                                                 wx.DefaultSize, 0)
        self.st_correctionStatus.Wrap(-1)
        fgSizer1.Add(self.st_correctionStatus, 0, wx.ALL, 5)

        self.cb_correction = wx.CheckBox(self.leftPanel, wx.ID_ANY,
                                         u"Completed!", wx.DefaultPosition,
                                         wx.DefaultSize, 0)
        fgSizer1.Add(self.cb_correction, 0, wx.ALL, 5)

        self.btn_NewCorrection = wx.Button(self.leftPanel, wx.ID_ANY,
                                           u"Add New Correction",
                                           wx.DefaultPosition,
                                           wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_NewCorrection, 0, wx.ALL, 5)

        self.btn_UpdateCorrection = wx.Button(self.leftPanel, wx.ID_ANY,
                                              u"Update Correction",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_UpdateCorrection, 0, wx.ALL, 5)

        self.btn_GetCorrections = wx.Button(self.leftPanel, wx.ID_ANY,
                                            u"Get Correction List",
                                            wx.DefaultPosition,
                                            wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_GetCorrections, 0, wx.ALL, 5)

        self.btn_DeleteCorrection = wx.Button(self.leftPanel, wx.ID_ANY,
                                              u"Delete Correction",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        self.btn_DeleteCorrection.Enable(False)

        fgSizer1.Add(self.btn_DeleteCorrection, 0, wx.ALL, 5)

        self.btn_Now = wx.Button(self.leftPanel, wx.ID_ANY, u"Now",
                                 wx.DefaultPosition, wx.DefaultSize, 0)
        fgSizer1.Add(self.btn_Now, 0, wx.ALL, 5)

        self.leftPanel.SetSizer(fgSizer1)
        self.leftPanel.Layout()
        fgSizer1.Fit(self.leftPanel)
        self.m_splitter2.Initialize(self.leftPanel)
        bSizer1.Add(self.m_splitter2, 1, wx.EXPAND, 5)

        self.SetSizer(bSizer1)
        self.Layout()

        # Connect Events
        self.lc_correctionList.Bind(wx.EVT_LIST_ITEM_ACTIVATED,
                                    self.CorrectionSelected)
        self.dp_complain_date.Bind(wx.EVT_DATE_CHANGED,
                                   self.ComplainDate_Entered)
        self.tc_compTime.Bind(wx.EVT_TEXT, self.ComplaintTime_Entered)
        self.tc_timecode.Bind(wx.EVT_TEXT, self.TimeCode_Entered)
        self.tc_desc.Bind(wx.EVT_TEXT, self.Description_Entered)
        self.dp_correctionDate.Bind(wx.EVT_DATE_CHANGED,
                                    self.CorrectionDate_Entered)
        self.tc_corrTime.Bind(wx.EVT_TEXT, self.correctionTime_Entered)
        self.cb_correction.Bind(wx.EVT_CHECKBOX, self.CorrectionStatus_Entered)
        self.btn_NewCorrection.Bind(wx.EVT_BUTTON, self.AddCorrection)
        self.btn_UpdateCorrection.Bind(wx.EVT_BUTTON, self.UpdateCorrection)
        self.btn_GetCorrections.Bind(wx.EVT_BUTTON, self.GetCorrection)
        self.btn_DeleteCorrection.Bind(wx.EVT_BUTTON, self.DeleteCorrection)
        self.btn_Now.Bind(wx.EVT_BUTTON, self.Now)
        # --
        self.dp_complain_date.Bind(wx.EVT_DATE_CHANGED,
                                   self.ComplainDateChanged)
        self.tc_compTime.Bind(wx.lib.masked.EVT_TIMEUPDATE,
                              self.ComplainDateChanged)
        self.complain_date = None
        self.dp_correctionDate.Bind(wx.EVT_DATE_CHANGED,
                                    self.CorrectionDateChanged)
        self.tc_corrTime.Bind(wx.lib.masked.EVT_TIMEUPDATE,
                              self.CorrectionDateChanged)
        self.correction_date = None
        self.complain_timecode = '00:00:00:00'
        self.correction_id = None

    def __del__(self):
        pass

    # Virtual event handlers, overide them in your derived class
    def ComplaintTime_Entered(self, event):
        event.Skip()

    def correctionTime_Entered(self, event):
        event.Skip()

    def ComplainDateChanged(self, event):
        event.Skip()

    def CorrectionDateChanged(self, event):
        event.Skip()

    def Now(self, event):
        event.Skip()

    def CorrectionSelected(self, event):
        event.Skip()

    def ComplainDate_Entered(self, event):
        event.Skip()

    def TimeCode_Entered(self, event):
        event.Skip()

    def Description_Entered(self, event):
        event.Skip()

    def CorrectionDate_Entered(self, event):
        event.Skip()

    def CorrectionStatus_Entered(self, event):
        event.Skip()

    def AddCorrection(self, event):
        event.Skip()

    def UpdateCorrection(self, event):
        event.Skip()

    def GetCorrection(self, event):
        event.Skip()

    def DeleteCorrection(self, event):
        event.Skip()


import os
import base64
from Crypto.Cipher import AES

from rest_framework import status
from rest_framework.decorators import api_view
from django.http import HttpResponse
from users_data.models import Purchases, Devices
from books.models import Book
from player.models import Player
from restrictions.models import *

@api_view(['POST'])
def read_book(request):
    book_id = request.POST.get('book_id')

    if not request.user.is_authenticated():
        return HttpResponse("User not logged in", status=status.HTTP_403_FORBIDDEN)

    if book_id==None or book_id=="":
        return HttpResponse("Invalid book_id", status=status.HTTP_400_BAD_REQUEST)

    book = Book.objects.get(ebook_id=book_id)

    if book is None:
        return HttpResponse("Book doesn't exists", status=status.HTTP_400_BAD_REQUEST)

    p = Purchases.objects.all().filter(user=request.user, book_id=book)

    if len(p) == 0:
        return HttpResponse("User hasn't bought the book", status=status.HTTP_403_FORBIDDEN)

    response = HttpResponse("restrictions sent", status=status.HTTP_200_OK)

    response["book_id"] = ""
    response["device_key"] = ""
    response["player_version"] = ""
    response["location"] = ""
    response["so"] = ""
    response["time"] = ""

    return response

# consulted code from: http://eli.thegreenplace.net/2010/06/25/aes-encryption-of-files-in-python-with-pycrypto
# consulted code from http://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256

@api_view(['POST'])
def validate(request):
    book_id = request.POST.get('book_id')
    device_key = request.POST.get('device_key')
    player_version = request.POST.get('player_version')
    location = request.POST.get('location')
    so = request.POST.get('so')
    time = request.POST.get('time')

    # Validating reading restrictions

    if not request.user.is_authenticated():
        return HttpResponse("User not logged in", status=status.HTTP_403_FORBIDDEN)

    if book_id==None or book_id=="":
        return HttpResponse("Invalid book_id", status=status.HTTP_400_BAD_REQUEST)

    book = Book.objects.get(ebook_id=book_id)

    if book is None:
        return HttpResponse("Book doesn't exists", status=status.HTTP_400_BAD_REQUEST)

    if device_key==None or device_key=="":
        return HttpResponse("Invalid device key", status=status.HTTP_400_BAD_REQUEST)

    device = Devices.objects.get(device_key=device_key)

    if device is None:
        return HttpResponse("Device is not registered", status=status.HTTP_400_BAD_REQUEST)

    if player_version==None or player_version=="":
        return HttpResponse("Invalid player key", status=status.HTTP_400_BAD_REQUEST)

    player = Player.objects.get(player_version=player_version)
    player_key = player.player_key

    if player is None:
        return HttpResponse("Player doesn't exist", status=status.HTTP_400_BAD_REQUEST)

    if location==None or location=="":
        return HttpResponse("Invalid location", status=status.HTTP_400_BAD_REQUEST)

    country = Countries.objects.get(country=location)

    if country is None:
        return HttpResponse("User not allowed to read the book in the country he's in", status=status.HTTP_403_FORBIDDEN)

    if so==None or so=="":
        return HttpResponse("Invalid operating system", status=status.HTTP_400_BAD_REQUEST)

    system = OperatingSystem.objects.get(so=so)

    if system is None:
        return HttpResponse("User not allowed to read the book with his operating system", status=status.HTTP_403_FORBIDDEN)

    if time==None or time=="" or len(time.split(':')) != 3:
        return HttpResponse("Invalid time", status=status.HTTP_400_BAD_REQUEST)

    hour = time.split(':')[0]

    if int(hour) < 0 or int(hour) > 24:
        return HttpResponse("User not allowed to read the book at this time", status=status.HTTP_403_FORBIDDEN)

    # End of validating reading restrictions

    # Ciphering the book for the user

    random = Purchases.objects.all().filter(user=request.user, book_id=book)[0].random
    user_key = request.user.user_key.user_key

    IV = os.urandom(16)

    random = base64.b64decode(random)
    user_key = base64.b64decode(user_key)

    # cipher random with player key
    aes = AES.new(player_key, AES.MODE_CBC, IV)
    key1 = aes.encrypt(random)

    # cipher previous key with user_key
    aes = AES.new(user_key, AES.MODE_CBC, IV)
    key2 = aes.encrypt(key1)

    # cipher previous key with device_key
    aes = AES.new(device_key, AES.MODE_CBC, IV)
    file_key = aes.encrypt(key2)

    # end result is cipher(device_key, cipher(user_key, cipher(player_key, random)))

    # starting to cipher file using file key

    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

    file_path = os.path.join(BASE_DIR, book.text_file)
    cipher_file_path = file_path.replace("books", "cipher_books")

    with open(file_path, 'rb') as book_file:
        with open(cipher_file_path, 'w+') as cipher_file:
            block_size = 16
            bytes_read = 0
            data = book_file.read()
            length = 16 - (len(data) % 16)
            data += chr(length)*length
            size = len(data)

            aes = AES.new(file_key, AES.MODE_CBC, IV)
            while bytes_read < size:
                block = data[0:block_size]
                data = data[block_size:]
                bytes_read += block_size

                ciphered_block = aes.encrypt(block)

                cipher_file.write(ciphered_block)

    response = HttpResponse("Successfully ciphered", status=status.HTTP_200_OK)

    response['random'] = base64.b64encode(random)
    response['iv'] = base64.b64encode(IV)

    return response

@api_view(['POST'])
def get_file(request):
    book_id = request.POST.get('book_id')

    if not request.user.is_authenticated():
        return HttpResponse("User not logged in", status=status.HTTP_403_FORBIDDEN)

    if book_id==None or book_id=="":
        return HttpResponse("Invalid book_id", status=status.HTTP_400_BAD_REQUEST)

    book = Book.objects.get(ebook_id=book_id)

    if book is None:
        return HttpResponse("Book doesn't exists", status=status.HTTP_400_BAD_REQUEST)

    file_path = "media/cipher_books/pg" + book_id + ".txt"

    cipher_file = open(file_path, 'rb')

    cipher_content = cipher_file.read()

    cipher_file.close()

    os.remove(file_path)

    return HttpResponse(base64.b64encode(cipher_content), content_type='text/plain', status=status.HTTP_200_OK)

@api_view(['POST'])
def decrypt(request):
    key = request.POST.get('Key')
    key= base64.b64decode(key)

    IV = request.POST.get('iv')
    IV= base64.b64decode(IV)

    if not request.user.is_authenticated():
        return HttpResponse("User not logged in", status=status.HTTP_403_FORBIDDEN)

    user_key = request.user.user_key.user_key

    user_key = base64.b64decode(user_key)

    aes = AES.new(user_key, AES.MODE_CBC, IV)
    encryptedKey = aes.encrypt(key)

    response = HttpResponse("Successfully ciphered 2", status=status.HTTP_200_OK)
    response['encryptedKey'] = base64.b64encode(encryptedKey)
    return response


# -*- coding: utf-8 -*- {{{
#
# Your license here
# }}}

import sys
from datetime import datetime
from dateutil import parser
import pandas as pd
import matplotlib.pyplot as plt
from os.path import dirname, abspath, join

sys.path.insert(0, dirname(dirname(dirname(abspath(__file__)))))

from fleet_factory import create_fleet
from service_factory import create_service

def integration_test(service_name, fleet_name, **kwargs):
    # Create test service
    service = create_service(service_name)
    if service is None:
        raise 'Could not create service with name ' + service_name

    grid_type = 2

    # Create test fleet
    fleet = create_fleet(fleet_name, grid_type, **kwargs)
    if fleet is None:
        raise 'Could not create fleet with name ' + fleet_name

    # Assign test fleet to test service to use
    service.fleet = fleet
    assigned_fleet_name = service.fleet.__class__.__name__

    start_time = kwargs['start_time']

    # Run test
    if service_name == 'DistributionVoltageService':
        fleet_responses, fleet_requests = service.request_loop()

    else:
        pass

if __name__ == '__main__':
    # Full test
    # services = ['Regulation', 'Reserve', 'ArtificialInertia' 'DistributionVoltageService']
    # fleets = ['BatteryInverter', 'ElectricVehicle', 'PV', 'WaterHeater', 'Electrolyzer', 'FuelCell', 'HVAC', 'Refridge' ]
    # kwargs = {'autonomous': True}  # This is for later use

    # Dev test
    services = ['DistributionVoltageService']
    fleets = ['PV']
    start_time = parser.parse('8/1/17 16:00')

    kwargs = {}
    kwargs['start_time'] = start_time

    for service in services:
        for fleet in fleets:
            if service == 'ArtificialInertia':
                kwargs['autonomous'] = 'autonomous'
            integration_test(service, fleet, **kwargs)


# Databricks notebook source
dbutils.widgets.text("Sender_List", "")
dbutils.widgets.get("Sender_List")
Sender_List=getArgument("Sender_List")
print(Sender_List)

dbutils.widgets.text("Subject", "")
dbutils.widgets.get("Subject")
Subject=getArgument("Subject")
print(Subject)

dbutils.widgets.text("Body", "")
dbutils.widgets.get("Body")
Body=getArgument("Body")
print(Body)

dbutils.widgets.text("Blob_Location", "N")
dbutils.widgets.get("Blob_Location")
Blob_Location=getArgument("Blob_Location")
print(Blob_Location)

dbutils.widgets.text("Att_Name", "N")
dbutils.widgets.get("Att_Name")
Att_Name=getArgument("Att_Name")
print(Att_Name)

subscription_key = dbutils.secrets.get(scope="eim-dbrx", key="api-email-sub-key")

# COMMAND ----------

if Blob_Location != 'N' and Att_Name != 'N':
  Att_Flg='Y'
else:
  Att_Flg='N'
print(Att_Flg)

# COMMAND ----------

#Send EMail
import requests, json

url = "https://api.columbia.com/eim-azure-notification/manual/paths/invoke"
headers = {
    "Ocp-Apim-Subscription-Key": subscription_key,
    "Content-Type": "application/json",
    "cache-control": "no-cache"
    }

payload = {
    "Att_Flg": Att_Flg,
    "Att_Name": Att_Name,
    "Blob_Location": Blob_Location,
    "Body": Body,
    "Subject": Subject,
    "User": Sender_List
}

response_decoded_json = requests.post(url, data=json.dumps(payload), headers=headers, timeout=None)
print(response_decoded_json)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 18 09:40:22 2019

@author: gabin
"""

import pickle
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import time
from scipy.signal import savgol_filter

#dico=pickle.load(open('Shots','rb'))

def shot_type(row):
    if row['Time_to_shoot']>-2:
        return('catch-and-shoot')
    else :
        return('pull-up')

def shooting_efficiency_inferior(data):

    ### getting the data ###
    D_CLOSEST_PLAYER=data['D_CLOSEST_DEF']
    T_CLOSEST_PLAYER=data['T_CLOSEST_DEF']
    TIME=data['TIME_ABSCISSE']
    TIME_TO_SHOOT=data['TIME_TO_SHOOT']

    ### differentiating catch-and-shoot, pull-up shots and success and fails ###
    D_CLOSEST_PLAYER1=[]
    D_CLOSEST_PLAYER2=[]
    T_CLOSEST_PLAYER1=[]
    T_CLOSEST_PLAYER2=[]
    TIME1=[]
    TIME2=[]

    for k in range(len(D_CLOSEST_PLAYER)):
        ## success ##
        if D_CLOSEST_PLAYER[k][0]==1:

            # all shots #
            D_CLOSEST_PLAYER1.append(D_CLOSEST_PLAYER[k][1])
            T_CLOSEST_PLAYER1.append(T_CLOSEST_PLAYER[k][1])
            TIME1.append(np.array(TIME[k][1]))

        ## fails ##
        else :

            # all shots #
            D_CLOSEST_PLAYER2.append(D_CLOSEST_PLAYER[k][1])
            T_CLOSEST_PLAYER2.append(T_CLOSEST_PLAYER[k][1])
            TIME2.append(np.array(TIME[k][1]))

    print(len(D_CLOSEST_PLAYER1)/(len(D_CLOSEST_PLAYER2)+len(D_CLOSEST_PLAYER1)))
    closest1=[]
    pos1=[]
    closest2=[]
    pos2=[]
    for i in range(len(D_CLOSEST_PLAYER1)):
        min1=0
        min2=0
        for j in range(len(D_CLOSEST_PLAYER1[i])):
            if -0.04<TIME1[i][j]<0.04:
                if T_CLOSEST_PLAYER1[i][j]>min1:
                    min1=T_CLOSEST_PLAYER1[i][j]
                if D_CLOSEST_PLAYER1[i][j]>min2:
                    min2=D_CLOSEST_PLAYER1[i][j]
        closest1.append(min1)
        pos1.append(min2)

    for i in range(len(D_CLOSEST_PLAYER2)):
        min1=np.inf
        min2=np.inf
        for j in range(len(D_CLOSEST_PLAYER2[i])):
            if -0.04<TIME2[i][j]<0.04:
                if T_CLOSEST_PLAYER2[i][j]<min1:
                    min1=T_CLOSEST_PLAYER2[i][j]
                if D_CLOSEST_PLAYER2[i][j]<min2:
                    min2=D_CLOSEST_PLAYER2[i][j]
        closest2.append(min1)
        pos2.append(min2)

    inferior_values=[]
    time_abs=[0.02*i+0.2 for i in range(60)]
    S1=[]
    T1=[]
    for i in range(60):
        success=0
        fails=0
        for j in range(len(closest1)):
            if not np.isinf(closest1[j]):
                if closest1[j]<time_abs[i]:
                    success+=1
        for j in range(len(closest2)):
            if not np.isinf(closest2[j]):
                if closest2[j]<time_abs[i]:
                    fails+=1
        S1.append(success/len(closest1))
        T1.append(fails/len(closest2))

        #print('inf to :', i)
        #print(success,fails)

        inferior_values.append(success/(fails+success)*100)

    fig,ax1=plt.subplots()
    plt.plot(time_abs,inferior_values)
    plt.xlabel(r'$\delta_{t}^*(0)$ inferior to [s]')
    plt.ylabel('Three point shooting percentage')
    plt.vlines(time_abs[15], inferior_values[0], inferior_values[15], linestyle="dashed",lw=0.5)
    plt.hlines(inferior_values[15], time_abs[0], time_abs[15], linestyle="dashed",lw=0.5)
    plt.xlim(time_abs[0],time_abs[-1])
    plt.ylim(inferior_values[0],inferior_values[-1]+1)
    ax1.tick_params(direction='in')
    plt.show()
#    plt.plot(time_abs2,inferior_values2)
    #plt.figure(2)
    #plt.plot(time_abs,S1)
    #plt.plot(time_abs,T1)

    d_abs=[0.1*i+3 for i in range(140)]
    inferior_values=[]
    S=[]
    T=[]
    for i in range(140):
        success=0
        fails=0
        for j in range(len(pos1)):
            if not np.isinf(pos1[j]):
                if pos1[j]<d_abs[i]:
                    success+=1
        for j in range(len(pos2)):
            if not np.isinf(pos2[j]):
                if pos2[j]<d_abs[i]:
                    fails+=1
        S.append(success/len(pos1))
        T.append(fails/len(pos2))

        #print('inf to :', i*0.2)
        #print(success,fails)
        #print(round(success/len(pos1),2),round(fails/len(pos2),2),round(success/(fails+success),2)*100)

        inferior_values.append(success/(fails+success)*100)

    print(inferior_values[10],inferior_values[50])

#    d_abs2=[0.2*i+1 for i in range(120)]
#    inferior_values2=[]
#    for i in range(120):
#        success=0
#        fails=0
#        for j in range(len(pos3)):
#            if not np.isinf(pos3[j]):
#                if pos3[j]<d_abs2[i]:
#                    success+=1
#        for j in range(len(pos4)):
#            if not np.isinf(pos4[j]):
#                if pos4[j]<d_abs2[i]:
#                    fails+=1
#        #print('inf to :', i*0.2)
#        #print(success,fails)
#        #print(round(success/len(pos1),2),round(fails/len(pos2),2),round(success/(fails+success),2)*100)
#
#        inferior_values2.append(success/(fails+success)*100)

    fig,ax2=plt.subplots()
    plt.plot(d_abs,inferior_values)
    plt.xlabel(r'$\delta_{d}^*(0)$ inferior to [feet]')
    plt.ylabel('Three point shooting percentage')
    ax2.tick_params(direction='in')
    plt.xlim(d_abs[0],d_abs[-1])
    plt.ylim(min(inferior_values),inferior_values[-1]+1)
    plt.vlines(d_abs[10], inferior_values[0], inferior_values[10], linestyle="dashed",lw=0.5)
    plt.hlines(inferior_values[10], d_abs[0], d_abs[10], linestyle="dashed",lw=0.5)
    plt.vlines(d_abs[50], inferior_values[0], inferior_values[50], linestyle="dashed",lw=0.5)
    plt.hlines(inferior_values[50], d_abs[0], d_abs[50], linestyle="dashed",lw=0.5)
    plt.show()
#    plt.plot(d_abs2,inferior_values2)
    #fig = plt.figure(4)
    #sns.kdeplot(np.array(pos1),bw=0.2)
    #sns.kdeplot(np.array(pos2),bw=0.2)
   # plt.show()
    #plt.plot(S, label='success')
    #plt.plot(T, label='fails')
    #plt.legend()

def restructure_data(data):

    ### getting the data ###
    D_CLOSEST_PLAYER=data['D_CLOSEST_DEF']
    T_CLOSEST_PLAYER=data['T_CLOSEST_DEF']
    TIME=data['TIME_ABSCISSE']
    TIME_TO_SHOOT=data['TIME_TO_SHOOT']

    ### only the second column because the first one contains if it is a succes or a miss ###
    D_CLOSEST_PLAYER_bis=[]
    T_CLOSEST_PLAYER_bis=[]
    TIME_bis=[]
    TIME_TO_SHOOT_bis=[]
    SUCCESS=[]
    nb_catch_and_shoot=0
    nb_pull_up=0
    nb_success=0
    nb_missed=0
    nb_cns_success=0
    nb_cns_missed=0
    nb_pull_up_success=0
    nb_pull_up_missed=0
    for k in range(len(D_CLOSEST_PLAYER)):
        unique,count=np.unique(np.array(TIME[k][1]).round(2), return_counts=True)
        if list(count)==[1]*len(count): # we don't take shots where values of time are repeated, because in the data, sometimes the values of time doesn't change so stay on the same second but we count the evolution on this second
            if D_CLOSEST_PLAYER[k][0]==0:
                nb_missed+=1
                if TIME_TO_SHOOT[k][1]>-2:
                    nb_catch_and_shoot+=1
                    nb_cns_missed+=1
                else :
                    nb_pull_up+=1
                    nb_pull_up_missed+=1
            else :
                nb_success+=1
                if TIME_TO_SHOOT[k][1]>-2:
                    nb_catch_and_shoot+=1
                    nb_cns_success+=1
                else :
                    nb_pull_up+=1
                    nb_pull_up_success+=1
            D_CLOSEST_PLAYER_bis.append(D_CLOSEST_PLAYER[k][1])
            T_CLOSEST_PLAYER_bis.append(T_CLOSEST_PLAYER[k][1])
            TIME_bis.append(np.array(TIME[k][1]).round(2)) # round to 0.01 second
            TIME_TO_SHOOT_bis.append([TIME_TO_SHOOT[k][1]]*len(TIME[k][1]))
            SUCCESS.append([TIME_TO_SHOOT[k][0]]*len(TIME[k][1]))

    print('number of valid shot:',len(D_CLOSEST_PLAYER_bis))
    print('number of success :',nb_success)
    print('number of miss :',nb_missed)
    print('percentage of success:',nb_success/(nb_success+nb_missed)*100)
    print('percentage of catch-and-shoot shots :',nb_catch_and_shoot/(nb_pull_up+nb_catch_and_shoot)*100)
    print('percentage of catch-and-shoot success:',nb_cns_success/(nb_cns_missed+nb_cns_success)*100)
    print('percentage of pull-up success:',nb_pull_up_success/(nb_pull_up_missed+nb_pull_up_success)*100)

    ### we concatenate all the data
    TIME_bis=np.concatenate(np.array(TIME_bis))
    D_CLOSEST_PLAYER_bis=np.concatenate(np.array(D_CLOSEST_PLAYER_bis))
    T_CLOSEST_PLAYER_bis=np.concatenate(np.array(T_CLOSEST_PLAYER_bis))
    TIME_TO_SHOOT_bis=np.concatenate(np.array(TIME_TO_SHOOT_bis))
    SUCCESS=np.concatenate(np.array(SUCCESS))

    ### put the data into a dataframe ###
    df=pd.DataFrame({'D':D_CLOSEST_PLAYER_bis,'T':T_CLOSEST_PLAYER_bis,'Time':TIME_bis,'Time_to_shoot':TIME_TO_SHOOT_bis,'Shot result':SUCCESS})

    ## only evolution between 3.2 seconds before shot and 0.8 second after. (It is because there are some errors in the data) ##
    df=df.query('Time>-3.2 and Time<0.8').copy()

    return(df)