"""
This serves to compare fixed mu and random mu
"""

import dan2_fixed_mu as dan2_f
import dan2 as dan2
import numpy as np
import pickle
import sys
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

def load_file(path):
    with open(path, 'rb') as f:

        file = pickle.load(f)

        if type(file) is not np.ndarray:
            file = np.array(file)

        return file

def save_file(path, model):
    with open(path + '.pk', 'wb') as save_file:
        pickle.dump(model, save_file)

def test_fit_and_predict(training_preds, testing_preds):
    return np.array_equal(training_preds, testing_preds)

def main(X, X_test, y_train, y_test, depth):
    clf = dan2.DAN2Regressor(depth=depth)
    tr_pred = clf.fit(X_train, y_train)
    path = clf.name
    save_file(path, clf)
    print(clf.coef_)
    y_pred = clf.predict(X_test)
    mse = np.sum((y_pred - y_test)**2) / X_test.shape[0]
    perc_error=sum(np.abs((y_pred-y_test)/y_test))/(3264*0.3)
    return perc_error, mse,y_pred

def main_2(X, X_test, y_train, y_test, depth):
    clf = dan2_f.DAN2Regressor(depth=depth)
    tr_pred = clf.fit(X_train, y_train)
    path = clf.name
    save_file(path, clf)
    print(clf.coef_)
    y_pred = clf.predict(X_test)
    mse = np.sum((y_pred - y_test)**2) / X_test.shape[0]
    perc_error=sum(np.abs((y_pred-y_test)/y_test))/(3264*0.3)
    return perc_error, mse,y_pred

if __name__ == '__main__':
    # X = load_file(sys.argv[1])
    # y = load_file(sys.argv[2])
    X = load_file(r'/Users/sushenzhang/Documents/phd/second_year_code/X_values.pkl')
    y = load_file(r'/Users/sushenzhang/Documents/phd/second_year_code/Y_values.pkl')
    X = (X-X.min())/(X.max()-X.min())
    y= (y-y.min())/(y.max()-y.min())
    # X = (X-np.mean(X,axis=0))/np.std(X,axis=0)
    # y = (y-np.mean(y,axis=0))/np.std(y,axis=0)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=42)
    X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.30, random_state=42)

    y_train = y_train[:,1]
    y_test = y_test[:,1]
    y_train = y_train.reshape(len(y_train), 1)
    y_test = y_test.reshape(len(y_test),1)

    mse_list =[]

    perc_error, mse, y_pred=main_2(X_train, X_test, y_train,y_test,50)
    perc_error_f, mse_f, y_pred_f = main(X_train, X_test, y_train,y_test,50)
    perc_error_f_1, mse_f_1, y_pred_f_1 = main(X_train, X_test, y_train,y_test,50)
    perc_error_f_2, mse_f_2, y_pred_f_2 = main(X_train, X_test, y_train,y_test,50)
    mse_list.append(mse)

    plt.plot(y_pred-y_test,lw=0.5,c='b',label='Predicted Values with Fixed μ')
    plt.plot(y_pred_f-y_test,lw=0.5,c='g',label='Predicted Values with Random μ (Set 1)')
    plt.plot(y_pred_f_1-y_test,lw=0.5,c='r',label='Predicted Values with Random μ (Set 2)')
    plt.plot(y_pred_f_2-y_test,lw=0.5,c='m',label='Predicted Values with Random μ(Set 3)')
    plt.legend()
    plt.title('The Effect of Fixed and Random μ')
    plt.xlabel('Testing Dataset')
    plt.ylabel('Recovery Rate (%)')
    plt.show()
    print('avg error is:',np.sum(np.abs((y_pred-y_test)/y_test))/3264*0.3)
    print ('error',mse, perc_error)
    print('fixed error', mse_f, perc_error_f)
    print('fixed error 1', mse_f_1, perc_error_f_1)
    print('fixed error 2', mse_f_2,perc_error_f_2)
    # print(X.min(),X.max())
    print(y_test.max(),y_test.min())
    # print(np.mean(X,axis=0),np.std(X,axis=0,dtype = np.float32))
    # print(np.mean(y,axis=0),np.std(y,axis=0,dtype = np.float32))
'''
print('model_weights', clf.model['weights'])
print('model_intercepts', clf.model['intercept'])
print('model_mu', clf.model['mu'])
'''


class Position:
    def __init__(self, state=-1, x=-1, y=-1):
        self.state = state
        self.x = x
        self.y = y

    @staticmethod
    def from_dict(data):
        ret = Position()
        ret.state = data["state"]
        ret.x = data["x"]
        ret.y = data["y"]
        return ret

    def to_dict(self):
        return {
            "state": self.state,
            "x": self.x,
            "y": self.y
        }

def same_point(point1, point2):
    return point1[0] == point2[0] and point1[1] == point2[1]

# 0-lack of corner
# 1-can be placed
# 2-occupied or share edge with same color or illegal or out of board
lack_of_corner = 0
can_be_placed = 1
illegal = 2

# 0 - share_corner
# 1 - share_edge
# 2 - occupy
share_corner = 0
share_edge = 1
occupy = 2

# 维护单个棋子(包括八个状态）在棋盘的各个位置上的状态
class Piece:
    def __init__(self, piece_shape_set, player_id, initialize_position=None):
        self.shape_set = piece_shape_set
        self.cell_num = 0 if len(piece_shape_set) == 0 else len(piece_shape_set[0])

        self.possible_position = []
        if initialize_position is None:
            for state in range(8):
                self.possible_position.append(
                    self._generate_piece_initialize_legal_position(
                        self.shape_set[state],
                        player_id
                    )
                )
        else:
            self.possible_position = initialize_position

        self.action = []
        for state in range(8):
            self.action.append(
                self._action_generate(
                    self.shape_set[state]
                )
            )
        self.is_drop = False

        self.state_update_table = [
            [[0, 1, 2],
             [0, 1, 2],
             [2, 2, 2]],

            [[1, 1, 2],
             [2, 2, 2],
             [2, 2, 2]]
        ]

    def try_drop(self, position):
        if self.is_drop:
            return False
        if not self.is_possible_position(position):
            return False
        self.is_drop = True
        return True

    def is_possible_position(self, position):
        if 0 > position.state or position.state > 8:
            return False
        if 0 > position.x or 20 < position.x:
            return False
        if 0 > position.y or 20 < position.y:
            return False
        return self.possible_position[position.state][position.x][position.y] == can_be_placed

    def get_one_possible_position(self):
        if self.is_drop:
            return Position()
        for state in range(8):
            for x in range(20):
                for y in range(20):
                    if self.possible_position[state][x][y] == 1:
                        return Position(state, x, y)
        return Position()

    def update_possible_position(self, piece_shape, position, is_same_player):
        for state in range(8):
            for one_cell in piece_shape:
                for act in self.action[state]:
                    self._update_one_position(
                        state,
                        one_cell[0] + position.x + act[0],
                        one_cell[1] + position.y + act[1],
                        act[2],
                        is_same_player
                    )

    def _update_one_position(self, state, x, y, action, is_same_player):
        if x < 0 or x >= 20:
            return
        if y < 0 or y >= 20:
            return
        self.possible_position[state][x][y] = self.state_update_table[is_same_player][action][self.possible_position[state][x][y]]

    def _action_generate(self, piece_shape):
        irrelevant = -1
        def get_act(x, y, ano_pos):
            dx = abs(x + ano_pos[0])
            dy = abs(y + ano_pos[1])
            if dx + dy == 0:
                return occupy
            if dx <= 1 and dy <= 1:
                if dx + dy == 2:
                    return share_corner
                else:
                    return share_edge
            return irrelevant

        res_action = []
        for x in range(-5, 6):
            for y in range(-5, 6):
                action = irrelevant
                for ano_pos in piece_shape:
                    action = max(action, get_act(x, y, ano_pos))
                    if action == occupy:
                        break
                if action == irrelevant:
                    continue
                res_action.append((x, y, action))
        return res_action

    def get_state(self):
        return {
            "is_drop": self.is_drop,
        }

    def _generate_piece_initialize_legal_position(self, piece_shape, player_id):

        def can_place(piece_set, coordinate_x, coordinate_y):
            for piece_point in piece_set:
                if piece_point[0] + coordinate_x >= 20 or piece_point[1] + coordinate_y >= 20:
                    return False
            return True

        def occupied(act_pos, ano_pos):
            for actp in act_pos:
                for anop in ano_pos:
                    if same_point(actp, anop):
                        return True
            return False

        def share_edge(act_pos, ano_pos):
            if same_point((act_pos[0] + 1, act_pos[1]), ano_pos):
                return True
            if same_point((act_pos[0] - 1, act_pos[1]), ano_pos):
                return True
            if same_point((act_pos[0], act_pos[1] + 1), ano_pos):
                return True
            if same_point((act_pos[0], act_pos[1] - 1), ano_pos):
                return True
            return False

        def share_corner(act_pos, ano_pos):
            if same_point((act_pos[0] + 1, act_pos[1] + 1), ano_pos):
                return True
            if same_point((act_pos[0] - 1, act_pos[1] - 1), ano_pos):
                return True
            if same_point((act_pos[0] - 1, act_pos[1] + 1), ano_pos):
                return True
            if same_point((act_pos[0] + 1, act_pos[1] - 1), ano_pos):
                return True
            return False

        begin_point = [(-1, -1), (-1, 20), (20, 20), (20, -1)]
        dir_point = [(-1, -1), (-1, 1), (1, 1), (1, -1)]
        begin_position = [[0 for j in range(20)] for i in range(20)]
        for i in range(20):
            for j in range(20):
                legal_place = can_place(piece_shape, i, j)
                if legal_place == 0:
                    begin_position[i][j] = 2
                    continue
                if begin_position[i][j] == 2:
                    continue
                can_be_placed = 0
                for point in piece_shape:
                    if same_point((i + point[0] + dir_point[player_id][0], j + point[1] + dir_point[player_id][1]), begin_point[player_id]):
                        can_be_placed = 1
                        break
                begin_position[i][j] = can_be_placed
        return begin_position


from typing import List
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        for i in range(len(nums)):
            #每个i位置上放第i+1个正数
            #0<=nums[i]-1<len(nums) 如果该位置上数比0小或者超出长度范围，不算
            #nums[nums[i]-1]!=nums[i] 如果该位置上的数不是第i+1个数 nums[i]-1:该数应该去的位置
            while 0<=nums[i]-1<len(nums) and nums[nums[i]-1]!=nums[i]:
                tmp=nums[i]-1
                nums[i],nums[tmp]=nums[tmp],nums[i]
        for i in range(len(nums)):
            if nums[i]!=i+1:
                return i+1
        return len(nums)+1

x = Solution()
a = x.firstMissingPositive([7,8,9,11,12])
print(a)


# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 Esteban J. Garcia Gabancho.
# Copyright (C) 2020 Mojib Wali.
#
# invenio-shibboleth is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""Temporary file for, IMHO, Invenio-Accounts code."""
from invenio_accounts import __version__ as ACCOUNTS_VERSION
from invenio_accounts.models import User
from invenio_db import db
from pkg_resources import DistributionNotFound, get_distribution, parse_version
from sqlalchemy_utils import Timestamp

HAS_USER_IDENTITY = True
if parse_version(ACCOUNTS_VERSION) < parse_version("1.2.0"):
    HAS_USER_IDENTITY = False

try:
    get_distribution("invenio-oauthclient")
    from invenio_oauthclient import __version__ as OAUTHCLIENT_VERSION

    if parse_version(OAUTHCLIENT_VERSION) < parse_version("1.2.0"):
        HAS_USER_IDENTITY = True
except DistributionNotFound:
    pass

if HAS_USER_IDENTITY:
    from invenio_oauthclient.models import UserIdentity

    __all__ = ()
else:

    class UserIdentity(db.Model, Timestamp):
        """Represent a UserIdentity record."""

        __tablename__ = "accounts_useridentity"

        id = db.Column(db.String(255), primary_key=True, nullable=False)
        method = db.Column(db.String(255), primary_key=True, nullable=False)
        id_user = db.Column(db.Integer(), db.ForeignKey(User.id), nullable=False)

        user = db.relationship(User, backref="external_identifiers")

        __table_args__ = (
            db.Index("useridentity_id_user_method", id_user, method, unique=True),
        )

    __all__ = ("UserIdentity",)


class Patient:  #base class
    pat_count=0
    def __init__(self,name,email): #default constructor
          self.name=name
          self.email=email
          Patient.pat_count+=1
    def DisplayDetails(self):
        print("Name: ",self.name,"Email: ",self.email)
    def DispCount(self):
        print("Total count of patients: ",Patient.pat_count)

class Doctor(Patient):#Inheritance Usage
    def __init__(self,Doc_name,email,Doctor_id): #default init constructor
        Patient.__init__(self,Doc_name,email)
        self.Doctor_id=Doctor_id
    def DisplayDetails(self):
        Patient.DisplayDetails(self)
        print("Doctor_ID: ",self.Doctor_id)

class Clerk(Doctor): #inheritance
    def __init__(self,name,email,emp_id,Doc_name,d_email,Doctor_id,time,date): #default Init constructor
        super().__init__(name,email,Doctor_id)   #usage of super call
        self.emp_id=emp_id
        self.name=name
        self.email=email
        self.dname=Doc_name
        self.demail=d_email
        self.did=Doctor_id
        self.time=time
        self.date=date
    def DisplayDetails(self):
        Patient.DisplayDetails(self)
        print("Emp ID:", self.emp_id)
        print("The aappointment time is: ",self.time)
        print("The appointment date is: ",self.date)

class Book():
    def __init__(self,pat_name,blood_pressure, sugar_level): #default init constructor
        self.patient_name=pat_name
        self.blood=blood_pressure
        self.sugar=sugar_level
    def DisplayDetaails(self):
        print("Patient_name: ",self.patient_name,"Blood pressure: ",self.blood,"Sugar level: ",self.sugar)

class Nurse(Patient,Book): #multiple Inheritance
    def __init__(self,name,email,pat_name,blood_pressure,sugar_level): #default init constructor
        # super().__init__(name,email)
        Patient.__init__(self,name,email)
        Book.__init__(self,pat_name,blood_pressure, sugar_level)

    def DisplayDetails(self):
        Book.DisplayDetaails(self)
        Patient.DisplayDetails(self)

#creation of instances for above classes

patient1=Patient('Akhila','akhila.atluri@gmail.com')
patient2=Patient('Kamal','kamaltej@gmail.com')
Doctor1=Doctor('Harish','harishc88@gmail.com','16262845')
Doctor2=Doctor('vinay','vinaymaturi@gmail.com','1645458')
Book1=Book('Akhila','180/60','normal')
Book2=Book('Kamal','140/50','normal')
print("##Patient Count##")
Patient.DispCount(Patient)

#nurse attending patients
Nurse1=Nurse('akhila atluri','akhila.atluri@gmail.com','Akhila','180/60', 'normal')
Nurse2=Nurse('kamal tej','kamtej@gmail.com','kamal','110/50','normal')

print("###Doctor Details###")
Doctor1.DisplayDetails();
Doctor2.DisplayDetails();

print("##Patient Details##")
patient1.DisplayDetails();
patient2.DisplayDetails();

print("##Book Details##")
Book1.DisplayDetaails();
Book2.DisplayDetaails();

print("#Nurse attending patient details")
Nurse1.DisplayDetaails();

clerk1=Clerk("rahul","rahu2g@gmail.com","162625252","Dr Harish","harishjoshi@gmail.com","12345","9 40 PM","16 JUNE")
print("clerk Issuing Appointments")
clerk1.DisplayDetails()

clerk2=Clerk("kunal","kunakrathod@gmail.com","990909876","Dr kavya","kavyajoshi@gmail.com","898976","8 00 AM","21 JUNE")
print("clerk Issuing Appointments")
clerk2.DisplayDetails()


"""
A hash table.
"""

class HashTable(object):
    """
    This class defines a HashTable.
    """
    def __init__(self, table_size):
        self.size = table_size
        self.slots = [None] * table_size
        self.data = [None] * table_size

    def _my_hash(self, val):
        """
        It takes a value and returns its hash value.
        """
        table_size = self.size

        # Hash value for a string.
        if isinstance(val, str):
            value = 0
            for character in val:
                value += ord(character)
            return value % table_size

        # Hash value for other types.
        else:
            return ((int(val) % table_size) ** 2) % table_size

    def _rehash(self, position):
        """
        Rehash when collisions occur.
        """
        return (position + 1) % self.size

    def put(self, val, data):
        """
        Put a new (key, value) pair into our table.
        """

        # First try to find the hashed key.
        key = self._my_hash(val)

        # If taken then rehash.
        while self.slots[key] is not None:

            # Repeated Keys.
            if self.slots[key] == val:
                self.data[key] = data
                break
            key = self._rehash(key)
        else:
            self.slots[key] = val
            self.data[key] = data

    def get(self, val):
        """
        Get the data with value = val.
        """
        key = self._my_hash(val)
        while self.slots[key] != val:
            key = self._rehash(key)
        return self.data[key]


#!/usr/bin/python

from __future__ import print_function

import sys
from getopt import getopt

from cherrypick import CherryPick

def usage(msg=None, command=None):
    if msg:
        print(msg)
        print()

    if command is None:
        print('USAGE: gitrocity COMMAND')
        print('\tCOMMAND\tCurrently only cherrypick is supported')
    elif command == 'cherrypick':
        print('USAGE: gitrocity cherrypick [-h | --help] -d GIT_REPO_PATH')
        print('       -b BRANCH1~NUM_COMMITS [-b BRANCH2~NUM_COMMITS ...]')
        print('       --diffcommit=BASE_COMMIT --newbranch=NEWBRANCH')
        print()
        print('-h | --help \t\t\tPrint help')
        print('-d GIT_REPO_PATH\t\tThe path to the git repo for which to generate the patch')
        print('-b BRANCH~NUM_COMMITS\t\tThe branch from which to cherry pick the commit that')
        print('                     \t\tis NUM_COMMITS behind HEAD')
        print('--diffcommit=BASE_COMMIT\tThe commit off of which NEWBRANCH will be created')
        print('--newbranch=NEWBRANCH\t\tThe branch to which the cherry picked commits will be added')

    sys.exit(1)

def main():
    repo_path = None
    diffcommit = None
    branches = []
    newbranch = None

    if len(sys.argv) < 2:
        usage(msg='Requires at least two arguments')

    command = sys.argv[1]
    opts, args = getopt(sys.argv[2:], 'd:b:h', ['diffcommit=', 'newbranch=', 'help'])
    for a, o in opts:
        if a == '-d':
            if repo_path is None:
                repo_path = o
            else:
                usage(msg='Only one git repo path is allowed', command=command)
        elif a == '--diffcommit':
            if diffcommit is None:
                diffcommit = o
            else:
                usage(msg='Only one commit is allowed', command=command)
        elif a == '-b':
            branches.append(o)
        elif a == '--newbranch':
            if newbranch is None:
                newbranch = o
            else:
                usage(msg='Only one custom build branch can be specified', command=command)
        elif a in ['-h', '--help']:
            usage(command=command)
    if command == 'cherrypick':
        if repo_path is None or diffcommit is None or not branches or newbranch is None:
            usage(msg='Please supply necessary parameters', command=command)

        cp = CherryPick(repo_path)
        cp.merge_branches(diffcommit, branches, new_branch=newbranch)
        cp.generate_diff(diffcommit)
    else:
        usage(msg='Unrecognized command')

if __name__ == '__main__':
    main()


import youtube_dl
def start():
    print("Welcome to the song downloader")
    url = input("Please insert url of the video: ")
    ydl_opts = {
        'format': 'bestaudio',
        'outtmpl': u'%(title)s.%(ext)s',
        'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'mp3',
        'preferredquality': '192',
}]
}
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        ydl.download([url])

start()