import pandas as pd
import matplotlib.pyplot as plt
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from sklearn.cluster import KMeans, DBSCAN
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import silhouette_score, silhouette_samples
import numpy as np
import matplotlib.cm as cm
from sklearn.decomposition import PCA
import seaborn as sns

def textPreprocessing(df):
    stop = stopwords.words('english')
    df['text'] = df['text'].str.replace('[^\w\s]', '')
    df['text'] = df['text'].apply(lambda x: " ".join(x for x in x.split() if x not in stop))
    df['text'] = df['text'].apply(lambda x: " ".join(x.lower() for x in x.split()))
    stemmer = PorterStemmer()

    df['text'] = df['text'].apply(lambda x: " ".join([stemmer.stem(word) for word in x.split()]))
    df['text'] = df['text'].apply(lambda x: " ".join(x for x in x.split() if x not in stop))

    return df

def TFIDFtransformer(df):
    tfidf = TfidfVectorizer(max_features=100, analyzer='word', ngram_range=(1, 3), stop_words='english')
    tfidfDF = pd.DataFrame(tfidf.fit_transform(df['text']).toarray())
    cols = tfidf.get_feature_names()
    return tfidfDF, cols

# elbow rule plot
def optimalK_SSE(data):
    sum_of_squared_distances = []
    K = range(2, 11)
    for k in K:
        km = KMeans(n_clusters=k)
        km = km.fit(data)
        sum_of_squared_distances.append(km.inertia_)

    plt.plot(K, sum_of_squared_distances, 'bx-')
    plt.xlabel('k')
    plt.ylabel('Sum_of_squared_distances')
    plt.title('Elbow Method For Optimal k')
    plt.show()

def optimalK_Silouhette(data):
    silhouette_scores = []
    K = range(2, 11)
    for k in K:
        km = KMeans(n_clusters=k)
        cluster_labels = km.fit_predict(data)
        silhouette_avg = silhouette_score(data, cluster_labels)
        silhouette_scores.append(silhouette_avg)

    plt.plot(K, silhouette_scores, 'bx-')
    plt.xlabel('k')
    plt.ylabel('Silhouette Scores')
    plt.title('Silhouette For Optimal k')
    plt.show()

def plotSilouhette(X):
    range_n_clusters = range(2, 11)

    for n_clusters in range_n_clusters:
        # Create a subplot with 1 row and 2 columns
        fig, (ax1, ax2) = plt.subplots(1, 2)
        fig.set_size_inches(18, 7)

        # The 1st subplot is the silhouette plot
        # The silhouette coefficient can range from -1, 1 but in this example all
        # lie within [-0.1, 1]
        ax1.set_xlim([-0.1, 1])
        # The (n_clusters+1)*10 is for inserting blank space between silhouette
        # plots of individual clusters, to demarcate them clearly.
        ax1.set_ylim([0, len(X) + (n_clusters + 1) * 10])

        # Initialize the clusterer with n_clusters value and a random generator
        # seed of 10 for reproducibility.
        clusterer = KMeans(n_clusters=n_clusters, random_state=10)
        cluster_labels = clusterer.fit_predict(X)

        # The silhouette_score gives the average value for all the samples.
        # This gives a perspective into the density and separation of the formed
        # clusters
        silhouette_avg = silhouette_score(X, cluster_labels)
        print("For n_clusters =", n_clusters,
              "The average silhouette_score is :", silhouette_avg)

        # Compute the silhouette scores for each sample
        sample_silhouette_values = silhouette_samples(X, cluster_labels)

        y_lower = 10
        for i in range(n_clusters):
            # Aggregate the silhouette scores for samples belonging to
            # cluster i, and sort them
            ith_cluster_silhouette_values = \
                sample_silhouette_values[cluster_labels == i]

            ith_cluster_silhouette_values.sort()

            size_cluster_i = ith_cluster_silhouette_values.shape[0]
            y_upper = y_lower + size_cluster_i

            color = cm.nipy_spectral(float(i) / n_clusters)
            ax1.fill_betweenx(np.arange(y_lower, y_upper),
                              0, ith_cluster_silhouette_values,
                              facecolor=color, edgecolor=color, alpha=0.7)

            # Label the silhouette plots with their cluster numbers at the middle
            ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))

            # Compute the new y_lower for next plot
            y_lower = y_upper + 10  # 10 for the 0 samples

        ax1.set_title("The silhouette plot for the various clusters.")
        ax1.set_xlabel("The silhouette coefficient values")
        ax1.set_ylabel("Cluster label")

        # The vertical line for average silhouette score of all the values
        ax1.axvline(x=silhouette_avg, color="red", linestyle="--")

        ax1.set_yticks([])  # Clear the yaxis labels / ticks
        ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])

        # 2nd Plot showing the actual clusters formed
        colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
        ax2.scatter(X.iloc[:, 0], X.iloc[:, 1], marker='.', s=30, lw=0, alpha=0.7,
                    c=colors, edgecolor='k')

        # Labeling the clusters
        centers = clusterer.cluster_centers_
        # Draw white circles at cluster centers
        ax2.scatter(centers[:, 0], centers[:, 1], marker='o',
                    c="white", alpha=1, s=200, edgecolor='k')

        for i, c in enumerate(centers):
            ax2.scatter(c[0], c[1], marker='$%d$' % i, alpha=1,
                        s=50, edgecolor='k')

        ax2.set_title("The visualization of the clustered data.")
        ax2.set_xlabel("Feature space for the 1st feature")
        ax2.set_ylabel("Feature space for the 2nd feature")

        # plt.suptitle(("Silhouette analysis for KMeans clustering on sample data "
        #               "with n_clusters = %d" % n_clusters),
        #              fontsize=14, fontweight='bold')

    plt.show()

def intepretationWithVariance():

    print()

if __name__ == '__main__':

    # load reviews csv
    # df = pd.read_csv('/home/andreas/Documents/Notebooks/TripAdvisor/reviews.csv')
    # print(df.head())
    # print(df.dtypes)
    #
    # # keep ony text
    # df = df[['username', 'text']]
    #
    # # group by username & merge reviews text to a unified corpus
    # df = df.groupby('username').agg({
    #     'text': lambda x: ' '.join(x)
    # }).reset_index()
    #
    # # Text Pre-Processing
    # df = textPreprocessing(df)
    #
    # # Text Vectorization using TFIDF
    # df, cols = TFIDFtransformer(df)
    # df.columns = cols
    # print(df.head())
    #
    # df.to_csv('tfidf.csv', index=False)
    df = pd.read_csv('tfidf.csv')

    # print('before outliers:', len(df))
    # remove outliers
    # from scipy import stats
    # df = df[(np.abs(stats.zscore(df)) < 3).all(axis=1)]
    # print('after outliers:', len(df))

    pca = PCA(n_components=2)
    pcadf = pd.DataFrame(pca.fit_transform(df))

    print(pca.explained_variance_ratio_)

    # df.to_csv('pcaDF.csv', index=False)

    # pcadf = pd.read_csv('pcaDF.csv')

    # Clustering Evaluation
    optimalK_SSE(pcadf)
    optimalK_Silouhette(pcadf)
    # plotSilouhette(pcadf)

    # dbscan = DBSCAN(eps=1, min_samples=2).fit(df)
    # print('DBSCAN: {}'.format(silhouette_score(df, dbscan.labels_,
    #                                            metric='cosine')))

    km = KMeans(n_clusters=3).fit(pcadf)
    # cluster_labels = km.fit_predict(df)

    from sklearn.preprocessing import MinMaxScaler

    scaler = MinMaxScaler()
    df_scaled = pd.DataFrame(scaler.fit_transform(df))
    df_scaled['cluster_id'] = km.labels_
    df_mean = df_scaled.groupby('cluster_id').mean()
    # df_mean.columns  = df.columns

    results = pd.DataFrame(columns=['Variable', 'Var'])
    for column in df_mean.columns:
        print(column)
        results.loc[len(results), :] = [column, np.var(df_mean[column])]
    selected_columns = list(results.sort_values(
        'Var', ascending=False,
    ).head(15).Variable.values) + ['cluster_id']
    tidy = df_scaled[selected_columns].melt(id_vars='cluster_id')
    tidy['variable'] = tidy['variable'].apply(lambda x: df.columns[x])
    # clrs = ['grey' if (x < max(tidy['value'])) else 'red' for x in tidy['value']]
    sns.barplot(x='cluster_id', y='value', hue='variable', data=tidy)
    plt.legend(bbox_to_anchor=(1.01, 1),
               borderaxespad=0)
    plt.title('Interpretation with feature variance')
    plt.show()

    # for i in selected_columns:
    #     print(str(i) + ': ' + str(df.columns[i]))

    from sklearn.ensemble import RandomForestClassifier

    X, y = df_scaled.iloc[:, :-1], df_scaled.iloc[:, -1]
    clf = RandomForestClassifier(n_estimators=100).fit(X, y)
    data = np.array([clf.feature_importances_, X.columns]).T
    columns = list(pd.DataFrame(data, columns=['Importance', 'Feature'])
                   .sort_values("Importance", ascending=False)
                   .head(15).Feature.values)
    tidy = df_scaled[columns + ['cluster_id']].melt(id_vars='cluster_id')
    tidy['variable'] = tidy['variable'].apply(lambda x: df.columns[x])
    sns.barplot(x='cluster_id', y='value', hue='variable', data=tidy)
    plt.legend(bbox_to_anchor=(1.01, 1),
               borderaxespad=0)
    plt.title('Interpretation with feature importance')
    plt.show()


import numpy as np
from exceptions import *

def simulation(positions, num_trials):
    '''
    Define a simulation function that takes postions and number of trials as inputs and returns the revenue rate of every trial.
    '''

    # use simulationResult to store the final simulation result
    simulationResult = {}

    # for every position in the positions list generate a simulation
    for position in positions:
        simulationResult[position] = []

        for trial in range(num_trials):
            position_value = 1000 / position

            # generate a random number which is in (0, 1) and find whether it is more than 0.49.
            result = np.random.uniform(0, 1, size=position) > 0.49

            daily_ret = (result * position_value * 2).sum() / 1000.0 - 1
            simulationResult[position].append(daily_ret)

    return simulationResult

def parseInputPositions(positionInput):
    '''
    parse the positions the user input and return a list contains these numbers.
    '''

    # delete all the space in the inputs
    positionInput = ''.join(positionInput.split())

    positions = []

    # check whether the user' input is correct.'
    if positionInput[0] != '[' or positionInput[-1] != ']':
        raise InvalidPositions('The positions you input does not fit the criterion that the input requests!')
    else:
        try:
            positionstr = positionInput[1:-1].split(',')
            for item in positionstr:
                positions.append(int(item))
        except:
            raise InvalidPositions("The positions you input are incorrect!")

    return positions


import threading

""" Global parameters """
UNUSED = 0
REQUEST = 1
COMMAND = 1
VERSION = 2
TTL = 225
RESPONSE = 2
ROUTE_TAG = 0
RIP_PORT = 520
RIPv2_VERSION = 2
ADDRESS_FAMILY = 2
IP_ADDRESS = 'addr'
SUBNET_MASK = 'netmask'
INFINITY_HOP_COUNT = 16
NEXT_HOP_ZERO = "0.0.0.0"
MAX_NUMBER_OF_ENTRIES = 25
UPDATE_TIME_INTERVAL_SECONDS = 30
LISTEN_ALL_INTERFACES = "0.0.0.0"
IP_MULTI_CAST_ADDRESS = "224.0.0.9"
IPV4_ADDRESS_FAMILY_IDENTIFIER = 2
MAX_NUMBER_OF_RECEIVED_BYTES = 504
INVALID_TIMER_DEFAULT_SECONDS = 35
DEFAULT_TIME_FOR_LOCAL_INTERFACES = 0
SCANNING_INTERFACE_STRING_LENGTH = 40
IGNORE_NETWORK = ("127.0.0.0", "255.0.0.0")

logging_lock = threading.Lock()
routing_table_lock = threading.Lock()
neighbours_lock = threading.Lock()


import copy
from math import cos, sin
import simple_draw as sd

martix_ident = [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
]

matrix = copy.deepcopy(martix_ident)

def vec_mul_matrix(vec, matrix):
    x = (vec[0] * matrix[0][0] +
         vec[1] * matrix[0][1] +
         vec[2] * matrix[0][2] +
         matrix[0][3]
         )
    y = (vec[0] * matrix[1][0] +
         vec[1] * matrix[1][1] +
         vec[2] * matrix[1][2] +
         matrix[1][3]
         )
    z = (vec[0] * matrix[2][0] +
         vec[1] * matrix[2][1] +
         vec[2] * matrix[2][2] +
         matrix[2][3]
         )
    return [x, y, z]

def matrix_mul_matrix(matrix1, matrix2):
    _matrix = copy.deepcopy(martix_ident)
    _matrix[0][0] = matrix1[0][0] * matrix2[0][0] + matrix1[0][1] * matrix2[1][0] + matrix1[0][2] * matrix2[2][0] + \
                    matrix1[0][3] * matrix2[3][0]
    _matrix[0][1] = matrix1[0][0] * matrix2[0][1] + matrix1[0][1] * matrix2[1][1] + matrix1[0][2] * matrix2[2][1] + \
                    matrix1[0][3] * matrix2[3][1]
    _matrix[0][2] = matrix1[0][0] * matrix2[0][2] + matrix1[0][1] * matrix2[1][2] + matrix1[0][2] * matrix2[2][2] + \
                    matrix1[0][3] * matrix2[3][2]
    _matrix[0][3] = matrix1[0][0] * matrix2[0][3] + matrix1[0][1] * matrix2[1][3] + matrix1[0][2] * matrix2[2][3] + \
                    matrix1[0][3] * matrix2[3][3]

    _matrix[1][0] = matrix1[1][0] * matrix2[0][0] + matrix1[1][1] * matrix2[1][0] + matrix1[1][2] * matrix2[2][0] + \
                    matrix1[1][3] * matrix2[3][0]
    _matrix[1][1] = matrix1[1][0] * matrix2[0][1] + matrix1[1][1] * matrix2[1][1] + matrix1[1][2] * matrix2[2][1] + \
                    matrix1[1][3] * matrix2[3][1]
    _matrix[1][2] = matrix1[1][0] * matrix2[0][2] + matrix1[1][1] * matrix2[1][2] + matrix1[1][2] * matrix2[2][2] + \
                    matrix1[1][3] * matrix2[3][2]
    _matrix[1][3] = matrix1[1][0] * matrix2[0][3] + matrix1[1][1] * matrix2[1][3] + matrix1[1][2] * matrix2[2][3] + \
                    matrix1[1][3] * matrix2[3][3]

    _matrix[2][0] = matrix1[2][0] * matrix2[0][0] + matrix1[2][1] * matrix2[1][0] + matrix1[2][2] * matrix2[2][0] + \
                    matrix1[2][3] * matrix2[3][0]
    _matrix[2][1] = matrix1[2][0] * matrix2[0][1] + matrix1[2][1] * matrix2[1][1] + matrix1[2][2] * matrix2[2][1] + \
                    matrix1[2][3] * matrix2[3][1]
    _matrix[2][2] = matrix1[2][0] * matrix2[0][2] + matrix1[2][1] * matrix2[1][2] + matrix1[2][2] * matrix2[2][2] + \
                    matrix1[2][3] * matrix2[3][2]
    _matrix[2][3] = matrix1[2][0] * matrix2[0][3] + matrix1[2][1] * matrix2[1][3] + matrix1[2][2] * matrix2[2][3] + \
                    matrix1[2][3] * matrix2[3][3]

    _matrix[3][0] = matrix1[3][0] * matrix2[0][0] + matrix1[3][1] * matrix2[1][0] + matrix1[3][2] * matrix2[2][0] + \
                    matrix1[3][3] * matrix2[3][0]
    _matrix[3][1] = matrix1[3][0] * matrix2[0][1] + matrix1[3][1] * matrix2[1][1] + matrix1[3][2] * matrix2[2][1] + \
                    matrix1[3][3] * matrix2[3][1]
    _matrix[3][2] = matrix1[3][0] * matrix2[0][2] + matrix1[3][1] * matrix2[1][2] + matrix1[3][2] * matrix2[2][2] + \
                    matrix1[3][3] * matrix2[3][2]
    _matrix[3][3] = matrix1[3][0] * matrix2[0][3] + matrix1[3][1] * matrix2[1][3] + matrix1[3][2] * matrix2[2][3] + \
                    matrix1[3][3] * matrix2[3][3]
    return _matrix

def translate(vec):
    _matrix = copy.deepcopy(martix_ident)
    _matrix[0][3] = vec[0]
    _matrix[1][3] = vec[1]
    _matrix[2][3] = vec[2]
    return _matrix

def scale(vec):
    _matrix = copy.deepcopy(martix_ident)
    _matrix[0][0] = vec[0]
    _matrix[1][1] = vec[1]
    _matrix[2][2] = vec[2]
    return _matrix

def rotateX(angle):
    _matrix = copy.deepcopy(martix_ident)
    _matrix[1][1] = cos(angle)
    _matrix[2][1] = -sin(angle)
    _matrix[1][2] = sin(angle)
    _matrix[2][2] = cos(angle)
    return _matrix

def rotateY(angle):
    _matrix = copy.deepcopy(martix_ident)
    _matrix[0][0] = cos(angle)
    _matrix[0][2] = sin(angle)
    _matrix[2][0] = -sin(angle)
    _matrix[2][2] = cos(angle)
    return _matrix

def rotateZ(angle):
    _matrix = copy.deepcopy(martix_ident)
    _matrix[0][0] = cos(angle)
    _matrix[0][1] = -sin(angle)
    _matrix[1][0] = sin(angle)
    _matrix[1][1] = cos(angle)
    return _matrix

def length_line(a, b):
    """Длина линии между двумя точками"""
    return ((a.x - b.x) ** 2 + (a.y - b.y) ** 2) ** 0.5

def get_point_line(a, b, percent=0.5):
    vector = (b.x - a.x, b.y - a.y)
    vector_2 = (vector[0] * percent, vector[1] * percent)
    point_end = sd.get_point(x=a.x + vector_2[0], y=a.y + vector_2[1])
    return point_end

class Mesh:

    def __init__(self, vertices, polygons):
        self.vertices = []
        self.polygons = polygons
        self.angle = 0
        self.origin = sd.get_point(0, 0)
        self._prepare_vertices(vertices)
        self._calculate_origin()

    def _prepare_vertices(self, vertices):
        for vertex in vertices:
            self.vertices.append([vertex[0], vertex[1], 0])

    def _calculate_origin(self):
        left_x = min([vert[0] for vert in self.vertices])
        right_x = max([vert[0] for vert in self.vertices])
        top_y = min([vert[1] for vert in self.vertices])
        bottom_y = max([vert[1] for vert in self.vertices])
        x = (left_x + right_x) // 2
        y = (top_y + bottom_y) // 2
        self.origin = sd.get_point(x, y)

    def move_to(self, point):
        dx = point.x - self.origin.x
        dy = point.y - self.origin.y
        for vertex in self.vertices:
            vertex[0] += dx
            vertex[1] += dy
        self.origin = point

    def scale(self, scaleXY):
        mat_scale = scale([scaleXY[0], scaleXY[1], 1])
        mat_trans = translate([-self.origin.x, -self.origin.y, 0])
        mat = matrix_mul_matrix(mat_trans, mat_scale)
        self.apply_matrix(mat)
        old_origin = self.origin
        self._calculate_origin()
        self.move_to(old_origin)

    def rotate(self, angle_deg):
        mat_trans = translate([-self.origin.x, -self.origin.y, 0])
        mat_rot = rotateZ(6.30 * angle_deg / 360)
        mat = matrix_mul_matrix(mat_trans, mat_rot)
        self.apply_matrix(mat)
        old_origin = self.origin
        self._calculate_origin()
        self.move_to(old_origin)

    def rotateY(self, angle_deg):
        mat_trans = translate([-self.origin.x, -self.origin.y, 0])
        mat_rot = rotateY(6.30 * angle_deg / 360)
        mat = matrix_mul_matrix(mat_trans, mat_rot)
        self.apply_matrix(mat)
        old_origin = self.origin
        self._calculate_origin()
        self.move_to(old_origin)

    def apply_matrix(self, matrix):
        for idx, vertex in enumerate(self.vertices):
            self.vertices[idx] = vec_mul_matrix(vertex, matrix)

    def render(self, color, color_back=None, need_edge=False):
        for polygon in self.polygons:
            _color = copy.deepcopy(color)
            if self._check_polygon(polygon):
                if color_back is None:
                    continue
                else:
                    _color = copy.deepcopy(color_back)

            points_array = []
            changed_color = copy.deepcopy(_color)
            for vert_idx in polygon:
                vertex = self.vertices[vert_idx]
                points_array.append(sd.get_point(x=int(vertex[0]), y=int(vertex[1])))
                if vertex[2] != 0 and changed_color == _color:
                    changed_color = [int(col * .9) for col in _color]

            sd.polygon(point_list=points_array, width=0, color=changed_color)
            if need_edge:
                sd.polygon(point_list=points_array, width=1, color=sd.COLOR_BLACK)

    def _check_polygon(self, polygon):
        p1 = self.vertices[polygon[0]]
        p2 = self.vertices[polygon[1]]
        p3 = self.vertices[polygon[2]]
        dx1 = p2[0] - p1[0]
        dx2 = p3[0] - p2[0]
        dy1 = p2[1] - p1[1]
        dy2 = p3[1] - p2[1]
        r = dx1 * dy2 - dx2 * dy1
        if r >= 0:
            return True
        else:
            return False


# JobProcessor.py

try:
   import cPickle as pickle
except:
   import pickle

import os
import glob
import time

from Job import Job
from Job_SPEAKTEXT import Job_SPEAKTEXT
from Job_PLAYMP3   import Job_PLAYMP3

class JobProcessor:
	def __init__(self, jobs_dir):
		self.jobs_dir = jobs_dir

	def getNextJob(self):
		files = glob.glob(self.jobs_dir + '/*')
		files_sorted = sorted(files)
		if (len(files_sorted) > 0):
			return files_sorted[0]
		else:
			return ""

	def start(self):
		self.exit_processor_loop = False
		while True:
			if (self.exit_processor_loop == True):
				break
			time.sleep(1)
			j = self.getNextJob()
			if (j):
				self.processJob(j)

	def stop(self):
		self.exit_processor_loop = True

	def processJob(self, jobfile):
		inf = open(jobfile)
		job_obj = pickle.load(inf)
		inf.close();
		os.remove(jobfile)
		job_obj.execute()


import numpy as np
import phase as phase

class BasisGenerator():

    def __init__(self, phaseGenerator, numBasis = 10):

        self.numBasis = numBasis
        self.phaseGenerator = phaseGenerator

    def basis(self):

        return None

    def basisMultiDoF(self, time, numDoF):
        #print('time in=', time)
        basisSingleDoF = self.basis(time)  # get a sampled basis function for a single DoF, is the one in NormalizedRBFBasisGenerator(BasisGenerator) class, is 1 dim if time is 1dim and basissingle is nb of basis/dof x nb of samples (time samples0)
        #print('basisSingleDoF_dim=', basisSingleDoF.shape) # 1x5
        basisMultiDoF = np.zeros((basisSingleDoF.shape[0] * numDoF, basisSingleDoF.shape[1] * numDoF)) # basisSingleDoF.shape[0] gives number of basis fns for 1 dof, and shape[1] gives nb of basis/time samples ? basisMultiDoF is a block diag matrix, to sum up it's 3x15

        for i in range(numDoF): # 0, 1, 2
            rowIndices = slice(i * basisSingleDoF.shape[0], (i + 1) * basisSingleDoF.shape[0]) # indices from start to stop
            columnIndices = slice(i * basisSingleDoF.shape[1], (i + 1) * basisSingleDoF.shape[1])

            basisMultiDoF[rowIndices, columnIndices] = basisSingleDoF
        return basisMultiDoF

class DMPBasisGenerator(BasisGenerator):

    def __init__(self, phaseGenerator, numBasis = 10, duration = 1, basisBandWidthFactor = 3):
        BasisGenerator.__init__(self, phaseGenerator, numBasis)

        self.basisBandWidthFactor = basisBandWidthFactor

        timePoints = np.linspace(0, duration, self.numBasis)
        self.centers = self.phaseGenerator.phase(timePoints)

        tmpBandWidth = np.hstack((self.centers[1:]-self.centers[0:-1], self.centers[-1] - self.centers[- 2]))

        # The Centers should not overlap too much (makes w almost random due to aliasing effect).Empirically chosen
        self.bandWidth = self.basisBandWidthFactor / (tmpBandWidth ** 2)

    def basis(self, time):

        phase = self.phaseGenerator.phase(time)

        diffSqr = np.array([((x - self.centers) ** 2) * self.bandWidth for x in phase])
        basis = np.exp(- diffSqr /  2)

        sumB = np.sum(basis, axis=1)
        basis = [column * phase / sumB for column in basis.transpose()]
        return np.array(basis).transpose()

class NormalizedRBFBasisGenerator(BasisGenerator):

    def __init__(self, phaseGenerator, numBasis = 10, duration = 1, basisBandWidthFactor = 3, numBasisOutside = 0):
        BasisGenerator.__init__(self, phaseGenerator, numBasis)

        self.basisBandWidthFactor = basisBandWidthFactor
        self.numBasisOutside = numBasisOutside
        basisDist = duration / (self.numBasis - 2 * self.numBasisOutside - 1)  # dist between 2 consecutive basis in temporal space, numBasis provided is total including the nb outside the duration (1s) range and is the number on a one side of that duration (right or left)

        timePoints = np.linspace(-self.numBasisOutside * basisDist, duration + self.numBasisOutside * basisDist, self.numBasis)  # time for the center points of the basis to generate
        self.centers = self.phaseGenerator.phase(timePoints)

        tmpBandWidth = np.hstack((self.centers[1:]-self.centers[0:-1], self.centers[-1] - self.centers[- 2]))  # ???

        # The Centers should not overlap too much (makes w almost random due to aliasing effect).Empirically chosen
        self.bandWidth = self.basisBandWidthFactor / (tmpBandWidth ** 2) # bandwidth is the spatial scale of the Basis functions

    def basis(self, time):

        if isinstance(time, (float, int)):
            time = np.array([time])

        phase = self.phaseGenerator.phase(time)  # z(t)

        diffSqr = np.array([((x - self.centers) ** 2) * self.bandWidth for x in phase])
        basis = np.exp(- diffSqr / 2) # gaussian basis functions , h = given here as 1 / basiswidth

        sumB = np.sum(basis, axis=1) # axis = 1  --- > column
        basis = [column / sumB for column in basis.transpose()]
        return np.array(basis).transpose()  # each basis generate dat this level is along column, each basis is sampled along 1 column

class NormalizedRhythmicBasisGenerator(BasisGenerator):

    def __init__(self, phaseGenerator,  numBasis = 10, duration = 1, basisBandWidthFactor = 3):

        BasisGenerator.__init__(self, phaseGenerator, numBasis)

        self.numBandWidthFactor = basisBandWidthFactor
        self.centers = np.linspace(0, 1, self.numBasis)

        tmpBandWidth = np.hstack((self.centers[1:]-self.centers[0:-1], self.centers[-1] - self.centers[- 2]))

        # The Centers should not overlap too much (makes w almost random due to aliasing effect).Empirically chosen
        self.bandWidth = self.basisBandWidthFactor / (tmpBandWidth ** 2)

    def basis(self):

        phase = self.getInputTensorIndex(0)

        diff = np.arraay([np.cos((phase - self.centers) * self.bandWidth * 2 * np.pi)])
        basis = np.exp(diff)

        sumB = np.sum(basis, axis=1)
        basis = [column / sumB for column in basis.transpose()]
        return np.array(basis).transpose()

if __name__ == "__main__":
    import matplotlib.pyplot as plt
    import numpy as np

    phaseGenerator = phase.LinearPhaseGenerator()
    basisGenerator = NormalizedRBFBasisGenerator(phaseGenerator, numBasis = 10, duration = 1, basisBandWidthFactor = 3, numBasisOutside = 1)

    time = np.linspace(0, 1, 100)
    basis = basisGenerator.basis(time)
    basisMultiDoF = basisGenerator.basisMultiDoF(time, 3)

    plt.figure()
    plt.plot(time, basis)

    plt.show()

    print('done')


import numpy as np
import scipy
import math
import matplotlib.pyplot as plt
from scipy import special
from scipy.fftpack import fft, ifft

#   http://www.satbroadcasts.com/DVB-S_Bitrate_and_Bandwidth_Calculator.html

symrate = 27500.0
symdur = 1/symrate
poi_per_sym = 100
k = 10.0/symdur

#zero_zero = np.sinc(k*(n-symdur*0.125)) #time domain
#zero_one = np.sinc(k*(n-symdur*0.375))
#one_zero = np.sinc(k*(n-symdur*0.625))
#one_one = np.sinc(k*(n-symdur*0.875))

h=[]

f = np.linspace(-1e4,1e4,int(poi_per_sym))
Ts = 1e-2 # what values should be taken  ?
fn = 1/(2*Ts)
alpha = 0.35

def func(x,alpha):
	if abs(x) < fn*(1-alpha) :
		return 1
	elif abs(x) > fn*(1+alpha) :
		return 0
	else:
		return np.sqrt(0.5+0.5*(math.sin((math.pi/(2*fn))*((fn-abs(x))/alpha))))

def genh(alpha):
	for i in range(0,int(poi_per_sym)):
		h.append(func(f[i],alpha))

genh(alpha)

noof_symbols = 30

n = np.linspace(0,noof_symbols*symdur,noof_symbols*poi_per_sym)

xbinary = np.random.randint(2, size = 2*noof_symbols)
xtime = np.zeros(noof_symbols*poi_per_sym)

for i in range(0,noof_symbols):
	if xbinary[2*i] == 0 and xbinary[2*i + 1] == 0 :
		xtime = xtime + np.sinc(k*(n-(i+1)*symdur*0.125))
	elif xbinary[2*i] == 0 and xbinary[2*i + 1] == 1 :
		xtime = xtime + np.sinc(k*(n-(i+1)*symdur*0.375))
	elif xbinary[2*i] == 1 and xbinary[2*i + 1] == 0 :
		xtime = xtime + np.sinc(k*(n-(i+1)*symdur*0.625))
	elif xbinary[2*i] == 1 and xbinary[2*i + 1] == 1 :
		xtime = xtime + np.sinc(k*(n-(i+1)*symdur*0.875))

xtime_with_noise = xtime + np.random.normal(0,1,len(xtime))
xfft = fft(xtime_with_noise)
yfft = h*xfft
ytime = ifft(yfft)

# how to get xhattime from yfft ?

# Here part

plt.plot(n,xtime,label='xtime')
plt.plot(n,abs(fft(xtime)),label='fft')
plt.legend(loc='best')

plt.grid()
plt.show()


# coding: utf-8

from __future__ import division
import numpy as np
import pandas as pd
pd.set_option('display.max_rows', 10)
pd.set_option('display.max_columns', 1000)
import datetime
import time
import os
import copy

# #### 定义获取数据函数

def fix_data(path):
    tmp = pd.read_csv(path, encoding="gbk", engine='python')
    tmp.rename(columns={'Unnamed: 0':'trading_time'}, inplace=True)
    tmp['trading_point'] = pd.to_datetime(tmp.trading_time)
    del tmp['trading_time']
    tmp.set_index(tmp.trading_point, inplace=True)
    return tmp

def High_2_Low(tmp, freq):
    """处理从RiceQuant下载的分钟线数据，
    从分钟线数据合成低频数据
    2017-08-11
    """
    # 分别处理bar数据
    tmp_open = tmp['open'].resample(freq).ohlc()
    tmp_open = tmp_open['open'].dropna()

    tmp_high = tmp['high'].resample(freq).ohlc()
    tmp_high = tmp_high['high'].dropna()

    tmp_low = tmp['low'].resample(freq).ohlc()
    tmp_low = tmp_low['low'].dropna()

    tmp_close = tmp['close'].resample(freq).ohlc()
    tmp_close = tmp_close['close'].dropna()

    tmp_price = pd.concat([tmp_open, tmp_high, tmp_low, tmp_close], axis=1)

    # 处理成交量
    tmp_volume = tmp['volume'].resample(freq).sum()
    tmp_volume.dropna(inplace=True)

    return pd.concat([tmp_price, tmp_volume], axis=1)

# #### 计算技术分析指标
import talib

def get_factors(index,
                Open,
                Close,
                High,
                Low,
                Volume,
                rolling = 26,
                drop=False,
                normalization=True):

    tmp = pd.DataFrame()
    tmp['tradeTime'] = index

    #累积/派发线（Accumulation / Distribution Line，该指标将每日的成交量通过价格加权累计，
    #用以计算成交量的动量。属于趋势型因子
    tmp['AD'] = talib.AD(High, Low, Close, Volume)

    # 佳庆指标（Chaikin Oscillator），该指标基于AD曲线的指数移动均线而计算得到。属于趋势型因子
    tmp['ADOSC'] = talib.ADOSC(High, Low, Close, Volume, fastperiod=3, slowperiod=10)

    # 平均动向指数，DMI因子的构成部分。属于趋势型因子
    tmp['ADX'] = talib.ADX(High, Low, Close,timeperiod=14)

    # 相对平均动向指数，DMI因子的构成部分。属于趋势型因子
    tmp['ADXR'] = talib.ADXR(High, Low, Close,timeperiod=14)

    # 绝对价格振荡指数
    tmp['APO'] = talib.APO(Close, fastperiod=12, slowperiod=26)

    # Aroon通过计算自价格达到近期最高值和最低值以来所经过的期间数，帮助投资者预测证券价格从趋势到区域区域或反转的变化，
    #Aroon指标分为Aroon、AroonUp和AroonDown3个具体指标。属于趋势型因子
    tmp['AROONDown'], tmp['AROONUp'] = talib.AROON(High, Low,timeperiod=14)
    tmp['AROONOSC'] = talib.AROONOSC(High, Low,timeperiod=14)

    # 均幅指标（Average TRUE Ranger），取一定时间周期内的股价波动幅度的移动平均值，
    #是显示市场变化率的指标，主要用于研判买卖时机。属于超买超卖型因子。
    tmp['ATR14']= talib.ATR(High, Low, Close, timeperiod=14)
    tmp['ATR6']= talib.ATR(High, Low, Close, timeperiod=6)

    # 布林带
    tmp['Boll_Up'],tmp['Boll_Mid'],tmp['Boll_Down']= talib.BBANDS(Close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0)

    # 均势指标
    tmp['BOP'] = talib.BOP(Open, High, Low, Close)

    #5日顺势指标（Commodity Channel Index），专门测量股价是否已超出常态分布范围。属于超买超卖型因子。
    tmp['CCI5'] = talib.CCI(High, Low, Close, timeperiod=5)
    tmp['CCI10'] = talib.CCI(High, Low, Close, timeperiod=10)
    tmp['CCI20'] = talib.CCI(High, Low, Close, timeperiod=20)
    tmp['CCI88'] = talib.CCI(High, Low, Close, timeperiod=88)

    # 钱德动量摆动指标（Chande Momentum Osciliator），与其他动量指标摆动指标如相对强弱指标（RSI）和随机指标（KDJ）不同，
    # 钱德动量指标在计算公式的分子中采用上涨日和下跌日的数据。属于超买超卖型因子
    tmp['CMO_Close'] = talib.CMO(Close,timeperiod=14)
    tmp['CMO_Open'] = talib.CMO(Close,timeperiod=14)

    # DEMA双指数移动平均线
    tmp['DEMA6'] = talib.DEMA(Close, timeperiod=6)
    tmp['DEMA12'] = talib.DEMA(Close, timeperiod=12)
    tmp['DEMA26'] = talib.DEMA(Close, timeperiod=26)

    # DX 动向指数
    tmp['DX'] = talib.DX(High, Low, Close,timeperiod=14)

    # EMA 指数移动平均线
    tmp['EMA6'] = talib.EMA(Close, timeperiod=6)
    tmp['EMA12'] = talib.EMA(Close, timeperiod=12)
    tmp['EMA26'] = talib.EMA(Close, timeperiod=26)

    # KAMA 适应性移动平均线
    tmp['KAMA'] = talib.KAMA(Close, timeperiod=30)

    # MACD
    tmp['MACD_DIF'],tmp['MACD_DEA'],tmp['MACD_bar'] = talib.MACD(Close, fastperiod=12, slowperiod=24, signalperiod=9)

    # 中位数价格 不知道是什么意思
    tmp['MEDPRICE'] = talib.MEDPRICE(High, Low)

    # 负向指标 负向运动
    tmp['MiNUS_DI'] = talib.MINUS_DI(High, Low, Close,timeperiod=14)
    tmp['MiNUS_DM'] = talib.MINUS_DM(High, Low,timeperiod=14)

    # 动量指标（Momentom Index），动量指数以分析股价波动的速度为目的，研究股价在波动过程中各种加速，
    #减速，惯性作用以及股价由静到动或由动转静的现象。属于趋势型因子
    tmp['MOM'] = talib.MOM(Close, timeperiod=10)

    # 归一化平均值范围
    tmp['NATR'] = talib.NATR(High, Low, Close,timeperiod=14)

    # OBV 	能量潮指标（On Balance Volume，OBV），以股市的成交量变化来衡量股市的推动力，
    #从而研判股价的走势。属于成交量型因子
    tmp['OBV'] = talib.OBV(Close, Volume)

    # PLUS_DI 更向指示器
    tmp['PLUS_DI'] = talib.PLUS_DI(High, Low, Close,timeperiod=14)
    tmp['PLUS_DM'] = talib.PLUS_DM(High, Low, timeperiod=14)

    # PPO 价格振荡百分比
    tmp['PPO'] = talib.PPO(Close, fastperiod=6, slowperiod= 26, matype=0)

    # ROC 6日变动速率（Price Rate of Change），以当日的收盘价和N天前的收盘价比较，
    #通过计算股价某一段时间内收盘价变动的比例，应用价格的移动比较来测量价位动量。属于超买超卖型因子。
    tmp['ROC6'] = talib.ROC(Close, timeperiod=6)
    tmp['ROC20'] = talib.ROC(Close, timeperiod=20)
    #12日量变动速率指标（Volume Rate of Change），以今天的成交量和N天前的成交量比较，
    #通过计算某一段时间内成交量变动的幅度，应用成交量的移动比较来测量成交量运动趋向，
    #达到事先探测成交量供需的强弱，进而分析成交量的发展趋势及其将来是否有转势的意愿，
    #属于成交量的反趋向指标。属于成交量型因子
    tmp['VROC6'] = talib.ROC(Volume, timeperiod=6)
    tmp['VROC20'] = talib.ROC(Volume, timeperiod=20)

    # ROC 6日变动速率（Price Rate of Change），以当日的收盘价和N天前的收盘价比较，
    #通过计算股价某一段时间内收盘价变动的比例，应用价格的移动比较来测量价位动量。属于超买超卖型因子。
    tmp['ROCP6'] = talib.ROCP(Close, timeperiod=6)
    tmp['ROCP20'] = talib.ROCP(Close, timeperiod=20)
    #12日量变动速率指标（Volume Rate of Change），以今天的成交量和N天前的成交量比较，
    #通过计算某一段时间内成交量变动的幅度，应用成交量的移动比较来测量成交量运动趋向，
    #达到事先探测成交量供需的强弱，进而分析成交量的发展趋势及其将来是否有转势的意愿，
    #属于成交量的反趋向指标。属于成交量型因子
    tmp['VROCP6'] = talib.ROCP(Volume, timeperiod=6)
    tmp['VROCP20'] = talib.ROCP(Volume, timeperiod=20)

    # RSI
    tmp['RSI'] = talib.RSI(Close, timeperiod=14)

    # SAR 抛物线转向
    tmp['SAR'] = talib.SAR(High, Low, acceleration=0.02, maximum=0.2)

    # TEMA
    tmp['TEMA6'] = talib.TEMA(Close, timeperiod=6)
    tmp['TEMA12'] = talib.TEMA(Close, timeperiod=12)
    tmp['TEMA26'] = talib.TEMA(Close, timeperiod=26)

    # TRANGE 真实范围
    tmp['TRANGE'] = talib.TRANGE(High, Low, Close)

    # TYPPRICE 典型价格
    tmp['TYPPRICE'] = talib.TYPPRICE(High, Low, Close)

    # TSF 时间序列预测
    tmp['TSF'] = talib.TSF(Close, timeperiod=14)

    # ULTOSC 极限振子
    tmp['ULTOSC'] = talib.ULTOSC(High, Low, Close, timeperiod1=7, timeperiod2=14, timeperiod3=28)

    # 威廉指标
    tmp['WILLR'] = talib.WILLR(High, Low, Close, timeperiod=14)

    # 标准化
    if normalization:
        factors_list = tmp.columns.tolist()[1:]

        if rolling >= 26:
            for i in factors_list:
                tmp[i] = (tmp[i] - tmp[i].rolling(window=rolling, center=False).mean())                /tmp[i].rolling(window=rolling, center=False).std()
        elif rolling < 26 & rolling > 0:
            print ('Recommended rolling range greater than 26')
        elif rolling <=0:
            for i in factors_list:
                tmp[i] = (tmp[i] - tmp[i].mean())/tmp[i].std()

    if drop:
        tmp.dropna(inplace=True)

    tmp.set_index('tradeTime', inplace=True)

    return tmp

# #### 构建RNN模型

import tensorflow as tf
from FixPonderDNCore import DNCore_L3
from FixPonderDNCore import ResidualACTCore as ACTCore

class Classifier_PonderDNC_BasicLSTM_L3(object):

    def __init__(self,
                 inputs,
                 targets,
                 gather_list=None,
                 mini_batch_size=1,
                 hidden_size=10,
                 memory_size=10,
                 threshold=0.99,
                 pondering_coefficient = 1e-2,
                 num_reads=3,
                 num_writes=1,
                 learning_rate = 1e-4,
                 optimizer_epsilon = 1e-10,
                 max_gard_norm = 50):

        self._tmp_inputs = inputs
        self._tmp_targets = targets
        self._in_length = None
        self._in_width = inputs.shape[2]
        self._out_length = None
        self._out_width = targets.shape[2]
        self._mini_batch_size = mini_batch_size
        self._batch_size = inputs.shape[1]

        # 声明计算会话
        self._sess = tf.InteractiveSession()

        self._inputs = tf.placeholder(dtype=tf.float32,
                                      shape=[self._in_length, self._batch_size, self._in_width],
                                      name='inputs')
        self._targets = tf.placeholder(dtype=tf.float32,
                                       shape=[self._out_length, self._batch_size, self._out_width],
                                       name='targets')

        act_core = DNCore_L3( hidden_size=hidden_size,
                              memory_size=memory_size,
                              word_size=self._in_width,
                              num_read_heads=num_reads,
                              num_write_heads=num_writes)
        self._InferenceCell = ACTCore(core=act_core,
                                              output_size=self._out_width,
                                              threshold=threshold,
                                              get_state_for_halting=self._get_hidden_state)

        self._initial_state = self._InferenceCell.initial_state(self._batch_size)

        tmp, act_final_cumul_state =         tf.nn.dynamic_rnn(cell=self._InferenceCell,
                          inputs=self._inputs,
                          initial_state=self._initial_state,
                          time_major=True)
        act_output, (act_final_iteration, act_final_remainder) = tmp

        # 测试
        self._final_iteration = tf.reduce_mean(act_final_iteration)

        self._act_output = act_output
        if gather_list is not None:
            out_sequences = tf.gather(act_output, gather_list)
        else:
            out_sequences = act_core

        # 设置损失函数
        pondering_cost = (act_final_iteration + act_final_remainder) * pondering_coefficient
        rnn_cost = tf.nn.softmax_cross_entropy_with_logits(
            labels=self._targets, logits=out_sequences)
        self._pondering_cost = tf.reduce_mean(pondering_cost)
        self._rnn_cost = tf.reduce_mean(rnn_cost)
        self._cost = self._pondering_cost + self._rnn_cost
        self._pred = tf.nn.softmax(out_sequences, dim=2)
        correct_pred = tf.equal(tf.argmax(self._pred,2), tf.argmax(self._targets,2))
        self._accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

        # 设置优化器
        # Set up optimizer with global norm clipping.
        trainable_variables = tf.trainable_variables()
        grads, _ = tf.clip_by_global_norm(
            tf.gradients(self._cost, trainable_variables), max_gard_norm)
        global_step = tf.get_variable(
            name="global_step",
            shape=[],
            dtype=tf.int64,
            initializer=tf.zeros_initializer(),
            trainable=False,
            collections=[tf.GraphKeys.GLOBAL_VARIABLES, tf.GraphKeys.GLOBAL_STEP])

        optimizer = tf.train.RMSPropOptimizer(
            learning_rate=learning_rate, epsilon=optimizer_epsilon)
        self._train_step = optimizer.apply_gradients(
            zip(grads, trainable_variables), global_step=global_step)

    # 待处理函数
    def _get_hidden_state(self, state):
        controller_state, access_state, read_vectors = state
        layer_1, layer_2, layer_3 = controller_state
        L1_next_state, L1_next_cell = layer_1
        L2_next_state, L2_next_cell = layer_2
        L3_next_state, L3_next_cell = layer_3
        return tf.concat([L1_next_state, L2_next_state, L3_next_state], axis=-1)

    def fit(self,
            training_iters =1e2,
            display_step = 5,
            save_path = None,
            restore_path = None):

        self._sess.run(tf.global_variables_initializer())
        # 保存和恢复
        self._variables_saver = tf.train.Saver()
        if restore_path is not None:
            self._variables_saver.restore(self._sess, restore_path)

        if self._batch_size == self._mini_batch_size:
            for scope in range(np.int(training_iters)):
                _, loss, acc, tp1, tp2, tp3 =                 self._sess.run([self._train_step,
                                self._cost,
                                self._accuracy,
                                self._pondering_cost,
                                self._rnn_cost,
                                self._final_iteration],
                               feed_dict = {self._inputs:self._tmp_inputs, self._targets:self._tmp_targets})
                # 显示优化进程
                if scope % display_step == 0:
                    print (scope,
                           '  loss--', loss,
                           '  acc--', acc,
                           '  pondering_cost--',tp1,
                           '  rnn_cost--', tp2,
                           '  final_iteration', tp3)
                    # 保存模型可训练变量
                    if save_path is not None:
                        self._variables_saver.save(self._sess, save_path)

            print ("Optimization Finished!")
        else:
            print ('未完待续')

    def close(self):
        self._sess.close()
        print ('结束进程，清理tensorflow内存/显存占用')

    def pred(self, inputs, gather_list=None, restore_path=None):
        if restore_path is not None:
            self._sess.run(tf.global_variables_initializer())
            self._variables_saver = tf.train.Saver()
            self._variables_saver.restore(self._sess, restore_path)

        output_pred = self._act_output
        if gather_list is not None:
            output_pred = tf.gather(output_pred, gather_list)
        probability = tf.nn.softmax(output_pred)
        classification = tf.argmax(probability, axis=-1)

        return self._sess.run([probability, classification],feed_dict = {self._inputs:inputs})

    def restore_trainable_variables(self, restore_path):
        if restore_path is not None:
            self._sess.run(tf.global_variables_initializer())
            self._variables_saver = tf.train.Saver()
            self._variables_saver.restore(self._sess, restore_path)

    def score(self, inputs, targets, gather_list=None):
        acc = self._sess.run(
            self._accuracy,
            feed_dict = {self._inputs:self._tmp_inputs,
                         self._targets:self._tmp_targets})
        return acc

"""
注意事项：作者不对交易盈利做任何保证，策略代码仅供参考
"""

import numpy as np
import talib
from vnpy.trader.vtObject import VtBarData
from vnpy.trader.vtConstant import EMPTY_STRING
from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,
                                                     BarGenerator,
                                                     ArrayManager)
from vnpy.trader.app.ctaStrategy.ctaBase import *

########################################################################
class PonderDNCoreStrategy(CtaTemplate):
    """基于Adxr的交易策略"""
    className = 'PonderDNCoreStrategy'
    author = u'用Python的交易员'

    barDbName = DAILY_DB_NAME

    # 策略参数
    trailingPrcnt = 0.8     # 移动止损
    initDays =  350          # 初始化数据所用的天数
    fixedSize = 1           # 每次交易的数量
    # 策略变量

    intraTradeHigh = 0                  # 持仓期内的最高点
    intraTradeLow = 0                   # 持仓期内的最低点

    model_classifier = None

    flag  = 0

    targetpos = 0

    buyOrderIDList = []                 # OCO委托买入开仓的委托号
    shortOrderIDList = []               # OCO委托卖出开仓的委托号
    orderList = []                      # 保存委托代码的列表

    # 参数列表，保存了参数的名称
    paramList = ['name',
                 'className',
                 'author',
                 'vtSymbol']

    # 变量列表，保存了变量的名称
    varList = ['inited',
               'trading',
               'pos',
               'flag',
               'targetpos'
               ]

    # 同步列表，保存了需要保存到数据库的变量名称
    syncList = ['pos',
                'intraTradeHigh',
                'intraTradeLow']

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(PonderDNCoreStrategy, self).__init__(ctaEngine, setting)

        self.bg = BarGenerator(self.onBar, 15, self.onFifteenBar)  # 创建K线合成器对象
        self.am = ArrayManager(size=200)

        self.buyOrderIDList = []
        self.shortOrderIDList = []
        self.orderList = []

    #----------------------------------------------------------------------
    def onInit(self):
        """初始化策略（必须由用户继承实现）"""
        self.writeCtaLog(u'%s策略初始化' %self.name)

        tmp = fix_data(u'期货测试数据/rb88.csv')

        # targets 1d 数据合成
        tmp_1d = High_2_Low(tmp, '1d')
        rolling = 88
        targets = tmp_1d
        targets['returns'] = targets['close'].shift(-2) / targets['close'] - 1.0
        targets['upper_boundary'] = targets.returns.rolling(rolling).mean() + 0.5 * targets.returns.rolling(
            rolling).std()
        targets['lower_boundary'] = targets.returns.rolling(rolling).mean() - 0.5 * targets.returns.rolling(
            rolling).std()
        targets.dropna(inplace=True)
        targets['labels'] = 1
        targets.loc[targets['returns'] >= targets['upper_boundary'], 'labels'] = 2
        targets.loc[targets['returns'] <= targets['lower_boundary'], 'labels'] = 0

        # factors 1d 数据合成
        tmp_1d = High_2_Low(tmp, '1d')
        Index = tmp_1d.index
        High = tmp_1d.high.values
        Low = tmp_1d.low.values
        Close = tmp_1d.close.values
        Open = tmp_1d.open.values
        Volume = tmp_1d.volume.values
        factors = get_factors(Index, Open, Close, High, Low, Volume, rolling=26, drop=True)

        factors = factors.loc[:targets.index[-1]]

        tmp_factors_1 = factors.iloc[:12]
        targets = targets.loc[tmp_factors_1.index[-1]:]

        gather_list = np.arange(factors.shape[0])[11:]
        # #### 转换数据

        inputs = np.array(factors).reshape(-1, 1, factors.shape[1])

        def dense_to_one_hot(labels_dense):
            """标签 转换one hot 编码
            输入labels_dense 必须为非负数
            2016-11-21
            """
            num_classes = len(np.unique(labels_dense))  # np.unique 去掉重复函数
            raws_labels = labels_dense.shape[0]
            index_offset = np.arange(raws_labels) * num_classes
            labels_one_hot = np.zeros((raws_labels, num_classes))
            labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
            return labels_one_hot

        targets = dense_to_one_hot(targets['labels'])
        targets = np.expand_dims(targets, axis=1)

        op1 = Classifier_PonderDNC_BasicLSTM_L3(
            inputs=inputs,
            targets=targets,
            gather_list=gather_list,
            hidden_size=50,
            memory_size=50,
            pondering_coefficient=1e-1,
            learning_rate=1e-4)

        op1.restore_trainable_variables("/QuantPython/RqAlphaMod/Model_Saver/ResidualPonderDNC_4.ckpt")
        self.model_classifier = op1

        # 载入历史数据，并采用回放计算的方式初始化策略数值
        initData = self.loadBar(self.initDays)
        for bar in initData:
            self.onMyBar(bar)

        self.putEvent()

    #----------------------------------------------------------------------
    def onStart(self):
        """启动策略（必须由用户继承实现）"""
        self.writeCtaLog(u'%s策略启动' %self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onStop(self):
        """停止策略（必须由用户继承实现）"""
        self.writeCtaLog(u'%s策略停止' %self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """收到行情TICK推送（必须由用户继承实现）"""
        self.bg.updateTick(tick)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """收到Bar推送（必须由用户继承实现）"""
        self.bg.updateBar(bar)

    #---------------------------------------------------------------------
    def onFifteenBar(self, bar):
        """收到15分钟K线"""
        # 撤销之前发出的尚未成交的委托（包括限价单和停止单）
        for orderID in self.orderList:
            self.cancelOrder(orderID)
        self.orderList = []

        if self.targetpos == self.fixedSize:
            if self.pos == 0:
                orderID = self.buy(bar.close + 5, self.fixedSize)
                self.orderList.extend(orderID)
            if self.pos < 0:
                orderID = self.cover(bar.close + 5, abs(self.pos))
                self.orderList.extend(orderID)
                orderID = self.buy(bar.close+ 5, self.fixedSize)
                self.orderList.extend(orderID)
        if self.targetpos == -self.fixedSize:
            if self.pos == 0:
                orderID = self.short(bar.close - 5, self.fixedSize)
                self.orderList.extend(orderID)
            if self.pos > 0:
                orderID = self.sell(bar.close - 5, abs(self.pos))
                self.orderList.extend(orderID)
                orderID = self.short(bar.close - 5, self.fixedSize)
                self.orderList.extend(orderID)
        if self.targetpos == 0:
            if self.pos < 0:
                orderID = self.cover(bar.close + 5, abs(self.pos))
                self.orderList.extend(orderID)
            if self.pos  > 0:
                orderID = self.sell(bar.close - 5, abs(self.pos))
                self.orderList.extend(orderID)

     # 同步数据到数据库
        self.saveSyncData()

        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def onMyBar(self, bar):
        """收到Bar推送（必须由用户继承实现）"""
        # 保存K线数据
        am = self.am
        am.updateBar(bar)

        if not am.inited:
            return

        tmp_factors =get_factors(
            pd.to_datetime(am.datetimeArray),
            am.openArray,
            am.closeArray,
            am.highArray,
            am.lowArray,
            am.volumeArray,
            rolling=26,
            drop = True)
        inputs = np.expand_dims(np.array(tmp_factors), axis=1)

        # 模型预测
        probability, classification = self.model_classifier.pred(inputs)
        flag = classification[-1][0]
        self.flag = flag

        #沽空
        if flag == 0:
            self.targetpos = -self.fixedSize

        #沽多
        if flag == 2:
            self.targetpos = self.fixedSize

        #震荡
        if flag == 1:
             self.targetpos = 0

        # 发出状态更新事件
        self.putEvent()

   #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送（必须由用户继承实现）"""
        pass

    #----------------------------------------------------------------------
    def onTrade(self, trade):
        # if self.pos != 0:
        #     # 多头开仓成交后，撤消空头委托
        #     if self.pos > 0:
        #         for shortOrderID in self.shortOrderIDList:
        #             self.cancelOrder(shortOrderID)
        #     # 反之同样
        #     elif self.pos < 0:
        #         for buyOrderID in self.buyOrderIDList:
        #             self.cancelOrder(buyOrderID)
        #
        #     # 移除委托号
        #     for orderID in (self.buyOrderIDList + self.shortOrderIDList):
        #         if orderID in self.orderList:
        #             self.orderList.remove(orderID)

        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def onStopOrder(self, so):
        """停止单推送"""
        pass


'''
Created on 27 janv. 2018

@author: Maxime
'''
from django.urls import path
from . import views

urlpatterns = [
    path('', views.connexion, name='connexion'),
    path('index/', views.index, name='index'),
    path('dispatch', views.dispatcher, name='dispatch'),
    path('listeHebergeurs/', views.listeHebergeurs, name='listeHebergeurs'),
    path('listeHebergeurs/<int:hebergeur_id>/', views.listeHebergeurs, name='listeHebergeurs'),
    path('hebergeurCreateOrUpdate/', views.hebergeurCreateOrUpdate, name='hebergeurCreateOrUpdate'),
    path('hebergeurCreateOrUpdate/<int:hebergeur_id>/', views.hebergeurCreateOrUpdate, name='hebergeurCreateOrUpdate'),
    path('modifyHebergeur/', views.modifyHebergeur, name='modifyHebergeur'),
    path('listeHebergeurs/delete/<int:pk>/', views.deleteHebergeur, name='deleteHebergeur'),
    path('listeJeunes/', views.listeJeunes, name='listeJeunes'),
    path('listeJeunes/<int:jeune_id>/', views.listeJeunes, name='listeJeunes'),
    path('jeuneCreateOrUpdate/', views.jeuneCreateOrUpdate, name='jeuneCreateOrUpdate'),
    path('jeuneCreateOrUpdate/<int:jeune_id>/', views.jeuneCreateOrUpdate, name='jeuneCreateOrUpdate'),
    path('modifyJeune/', views.modifyJeune, name='modifyJeune'),
    path('listeJeunes/delete/<int:pk>/', views.deleteJeune, name='deleteJeune'),
    path('deconnexion', views.deconnexion, name='deconnexion'),
]


from numpy import*
from numpy.linalg import*

matriz = array(eval(input("Vetor de horas: ")))

vet = zeros(7,dtype=int)

for i in range(7):
	vet[i] = sum(matriz[:,i])

for i in range(7):
	if(vet[i]==max(vet)):
		print(i+1)


'''
Powerbot demo signals script
(c) 2018 Inercomp GmbH
'''

import os, logging, sys, json, random
from datetime import datetime,timedelta
from powerbot import Configuration, ApiClient
from powerbot.api import SignalsApi

## Setting up logging and defining global variables
logging.basicConfig(level=logging.INFO)
LOGGER = logging.getLogger()

#Demo script accepts api_key as commandline parameter or as an environmental variable
api_key = str(sys.argv[1]) if len(sys.argv) >= 2 else os.getenv('POWERBOT_PLAYGROUND_API_KEY')
url = str(sys.argv[2]) if len(sys.argv) >= 3 else os.getenv('POWERBOT_PLAYGROUND_URL')

if not url or len(url.strip()) == 0:
    url = "https://playground.powerbot-trading.com/api/v0"

if not api_key or len(api_key.strip()) == 0:
    raise ValueError("Please provide your api_key on the command line or as the 'POWERBOT_PLAYGROUND_API_KEY' environmen variable")

# Retrieving handles to the powerbot api
client = ApiClient()
client.set_default_header("api_key",api_key)

signals = SignalsApi(client)

hour = 0
now = datetime.utcnow()

LOGGER.info("Starting signals against {} with api_key {}*****".format(url,api_key[:5]))

while hour <= 24:
    hour+=1

    # Submit a demo ETRMSystem signal with a random imbalance between -10 and +10 MW
    delivery_start = now.replace(minute=0, second=0, microsecond=0) + timedelta(hours=hour)
    varImbalance = round(random.uniform(-10,10), 2)
    signals.update_signal(
        id=delivery_start.strftime("etrm_signal_%Y-%m-%dT%H"),
		source = "ETRMSystem",
		delivery_start = delivery_start.strftime("%Y-%m-%dT%H:%M:%SZ"),
		delivery_end = (delivery_start + timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ"),
        value = {
            "imbalance": varImbalance
		}
    )

    # Submit a demo OptSystem signal with a random marginal_price between 40 and 50
    varMarginalPrice = round(random.uniform(40,50), 2)
    signals.update_signal(
        id=delivery_start.strftime("opt_signal_%Y-%m-%dT%H"),
        source = "OptSystem",
        delivery_start = delivery_start.strftime("%Y-%m-%dT%H:%M:%SZ"),
        delivery_end = (delivery_start + timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ"),
        value = {
            "marginal_price": varMarginalPrice
        }
    )

	# Mirror the signals to show in GUI chart by sending them as source "display"
    signals.update_signal(
        id=delivery_start.strftime("display_signal_%Y-%m-%dT%H"),
        source = "display",
        delivery_start = delivery_start.strftime("%Y-%m-%dT%H:%M:%SZ"),
        delivery_end = (delivery_start + timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ"),
        value = {
            "marginal_price": varMarginalPrice,
            "imbalance": varImbalance
        }
    )

LOGGER.info("Signals completed.")


from django.shortcuts import render, redirect
from .forms import AddReview
from .models import Review
from django.utils import timezone

# Create your views here.
def ReviewCreate(request):
    form = AddReview()
    if request.method == "POST":
        form = AddReview(request.POST)
        if form.is_valid():
            review = form.save(commit=False)
            review.created_date = timezone.now()
            if 'attachment' in request.FILES:
                review.attachment = request.FILES['attachment']
            review.save()
            return redirect('feedback/ty.html')
        else:
            form = AddReview()
    return render(request, 'feedback/add_review.html', {'form': form, })


import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from scipy.signal import fftconvolve
import torch

def get_arg_support(dt, t_support, t0=0):
    arg_support0 = int((t_support[0] - t0) / dt)
    arg_supportf = int(np.ceil((t_support[1] - t0) / dt))
    return arg_support0, arg_supportf

def get_dt(t):
    arg_dt = 20 if len(t) >= 20 else len(t)
    dt = np.median(np.diff(t[:arg_dt]))
    return dt

def plot_spiketrain(t, mask_spikes, ax=None, **kwargs):

    color = kwargs.get('color', 'C0')
    marker = kwargs.get('marker', 'o')
    ms = kwargs.get('ms', mpl.rcParams['lines.markersize'])
    mew = kwargs.get('mew', 0)
    label = kwargs.get('label', None)

    no_ax = False
    if ax is None:
        figsize = kwargs.get('figsize', (6, 2))
        fig, ax = plt.subplots(figsize=figsize)
        ax.set_xlabel('time (ms)')
        no_ax = True

    arg_spikes = np.where(mask_spikes)
    ax.plot(t[arg_spikes[0]], arg_spikes[1], marker=marker, lw=0, color=color, ms=ms, mew=mew)

    extra_xspace = (t[-1] - t[0]) * .01
    ax.set_xlim(t[0] - extra_xspace, t[-1] + extra_xspace)
    ax.tick_params('y', labelleft=False, left=False)
    if label is not None:
        ax.set_ylabel(label)

    return ax

def raw_autocorrelation(mask_spikes, padding=None):
    padding = padding if padding is not None else mask_spikes.shape[0]
    x = mask_spikes.numpy()
    autocor = fftconvolve(x, x[::-1], mode='full', axes=0)[::-1] / x.shape[0]
    arg_lag0 = autocor.shape[0] // 2
    autocor = torch.from_numpy(autocor[arg_lag0:arg_lag0 + padding])
    return autocor

def searchsorted(t, s, side='left'):
    '''
    Uses np.searchsorted but handles numerical round error with care
    such that returned index satisfies
    t[i-1] < s <= t[i]
    np.searchsorted(side='right') doesn't properly handle the equality sign
    on the right side
    '''
    s = np.atleast_1d(s)
    arg = np.searchsorted(t, s, side=side)

    if len(t) > 1:
        dt = get_dt(t)
        s_ = (s - t[0]) / dt
        round_s = np.round(s_, 0)
        mask_round = np.isclose(s_, np.round(s_, 0)) & (round_s >= 0) & (round_s < len(t))
        if side == 'left':
            arg[mask_round] = np.array(round_s[mask_round], dtype=int)
        elif side == 'right':
            arg[mask_round] = np.array(round_s[mask_round], dtype=int) + 1
    else:
        s_ = s - t[0]
        mask = np.isclose(s - t[0], 0.)# & (round_s >= 0) & (round_s < len(t))
        arg[mask] = np.array(s_[mask], dtype=int)

    if len(arg) == 1:
        arg = arg[0]

    return arg

def shift_array(arr, shift, fill_value=False):
    """
    Shifts array on axis 0 filling the shifted values with fill_value
    Positive shift is to the right, negative to the left
    """

    result = np.empty_like(arr)
    if shift > 0:
        result[:shift, ...] = fill_value
        result[shift:, ...] = arr[:-shift, ...]
    elif shift < 0:
        result[shift:, ...] = fill_value
        result[:shift, ...] = arr[-shift:, ...]
    else:
        result = arr
    return result


import threading
from random import randint

'''
每个线程调用同一个threading.local(), 自动获取对应线程的local对象

store为一个instance, 可以赋值新属性
'''
store = threading.local()

def task(number):
    store.number = number
    print(10 * store.number)

for i in range(10):
    t = threading.Thread(target=task, args=(i, ))
    t.start()
    t.join()


import os
import math
import requests
from pureapi import response

pure_api_url = os.environ.get('PURE_API_URL')
pure_api_key = os.environ.get('PURE_API_KEY')

headers = {
  'Accept': 'application/json',
  'api-key': pure_api_key,
}

def get(endpoint, params={}, headers=headers):
  return requests.get(
    pure_api_url + endpoint,
    params=params,
    headers=headers,
  )

def get_all(endpoint, params={}, headers=headers):
  r = get(endpoint, {'size': 0, 'offset': 0}, headers)
  json = r.json()
  record_count = int(json['count'])
  window_size = int(params['size']) if 'size' in params else 100
  window_count = int(math.ceil(float(record_count) / window_size))

  for window in range(0, window_count):
     window_params = {'offset': window * window_size, 'size': window_size}
     yield get(endpoint, {**params, **window_params}, headers)

def get_all_transformed(endpoint, params={}, headers=headers):
  for r in get_all(endpoint, params, headers):
    for item in r.json()['items']:
      yield response.transform(endpoint, item)

def filter(endpoint, payload={}, headers=headers):
  return requests.post(
    pure_api_url + endpoint,
    json=payload,
    headers=headers,
  )

def filter_all(endpoint, payload={}, headers=headers):
  count_payload = payload
  count_payload['size'] = 0
  count_payload['offset'] = 0
  r = filter(endpoint, count_payload, headers)
  json = r.json()
  record_count = int(json['count'])
  window_size = int(payload.setdefault('size', 100))
  if window_size >= 0:
    window_size = 100
  payload['size'] = window_size
  window_count = int(math.ceil(float(record_count) / window_size))

  for window in range(0, window_count):
     payload['offset'] = window * window_size
     yield filter(endpoint, payload, headers)

def filter_all_transformed(endpoint, payload={}, headers=headers):
  for r in filter_all(endpoint, payload, headers):
    for item in r.json()['items']:
      yield response.transform(endpoint, item)


'''
128. Longest Consecutive Sequence

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.
'''
# idea: union find
class SetNode(object):
    def __init__(self, val):
        self.val = val
        self.parent = None
        self.rank = 1

class Solution(object):
    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        def find_parent(node):
            if node.parent == node:
                return node
            find_parent(node.parent)

        def update_parent(oldParent, newParent):
            for k, v in union_set.items():
                if v.parent == oldParent:
                    v.parent = newParent
                    newParent.rank += 1

        union_set, maxLen = {}, 0
        for n in nums:
            node = SetNode(n)
            node.parent = node
            if n + 1 in union_set and n - 1 in union_set: # combine groups
                plusOne, minusOne = find_parent(union_set[n + 1]), find_parent(union_set[n - 1])
                update_parent(plusOne, minusOne)
                node.parent = minusOne
                node.parent.rank += 1
            elif n + 1 in union_set:
                node.parent = node # n is new head of this group
                node.rank = union_set[n + 1].rank + 1 # lengh increase 1
                update_parent(union_set[n + 1], node)
            elif n - 1 in union_set:
                node.parent = find_parent(union_set[n - 1]) # tail of set
                node.parent.rank += 1
            union_set[n] = node
            maxLen = max(maxLen, node.parent.rank)
        return maxLen

    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        union, maxL = {}, 0
        for n in nums:
            if n in union:
                continue
            start = end = n
            if n + 1 in union:
                end = union[n + 1][1]
            if n - 1 in union:
                start = union[n - 1][0]
            union[start] = union[end] = union[n] = (start, end)
            maxL = max(maxL, end - start + 1)
            print(union)
        return maxL

if __name__ == '__main__':
    nums = [100, 4, 200, 1, 3, 2]
    res = Solution().longestConsecutive(nums)
    print(res)


#!/usr/bin/env python
# coding: utf-8

# # Semi-Supervised Architope
# ---

# #### Mode: Code-Testin Parameter(s)

# In[13]:

trial_run = False

# ### Meta-parameters

# In[14]:

# Test-size Ratio
test_size_ratio = 0.3
min_height = 100

# ### Hyperparameters
#
# Only turn of if running code directly here, typically this script should be run be called by other notebooks.

# In[15]:

# load dataset
results_path = "./outputs/models/"
results_tables_path = "./outputs/results/"
raw_data_path_folder = "./inputs/raw/"
data_path_folder = "./inputs/data/"

# ### Import

# In[19]:

# Load Packages/Modules
exec(open('Init_Dump.py').read())
# Load Hyper-parameter Grid
exec(open('Grid_Enhanced_Network.py').read())
# Load Helper Function(s)
exec(open('Helper_Functions.py').read())
# Pre-process Data
exec(open('Prepare_Data_California_Housing.py').read())
import time

# ### Build Random Forest Regressor with Gradient Boosting

# In[16]:

# Initialize time-elapsed computation
Gradient_boosted_Random_forest_time_Begin = time.time()

# Compute/Load Gradient-boosted regression trees
# if os.path.exists('./outputs/models/Gradient_Boosted_Tree/Gradient_Boosted_Tree_Best.pkl'):
# #------------------------------------------------------------------------------------------#
#     # Alert User: Model (non-)Existence
#     print("Gradient Boosted Tree Found: Loaded!")
#     # Load Pickled Model
#     random_forest_trained = pickle.load(open('./outputs/models/Gradient_Boosted_Tree/Gradient_Boosted_Tree_Best.pkl', 'rb'))
# else:
#     # Alert User: Model (non-)Existence
#     print("No Gradient Boosted Tree Found: Training Model")

# Run Random Forest Util
rand_forest_model_grad_boosted = GradientBoostingRegressor()

# Grid-Search CV
Random_Forest_GridSearch = RandomizedSearchCV(estimator = rand_forest_model_grad_boosted,
                   n_iter=n_iter_trees,
                   cv=KFold(CV_folds, random_state=2020, shuffle=True),
                   param_distributions=Rand_Forest_Grid,
                   return_train_score=True,
                   random_state=2020,
                   verbose=10,
                   n_jobs=n_jobs)
random_forest_trained = Random_Forest_GridSearch.fit(X_train,y_train)
random_forest_trained = random_forest_trained.best_estimator_

#--------------------------------------------------#
# Write: Model, Results, and Best Hyper-Parameters #
#--------------------------------------------------#

# Save Model
# pickle.dump(random_forest_trained, open('./outputs/models/Gradient_Boosted_Tree/Gradient_Boosted_Tree_Best.pkl','wb'))

# Save Readings
cur_path = os.path.expanduser('./outputs/tables/best_params_Gradient_Boosted_Tree.txt')
with open(cur_path, "w") as f:
    f.write(str(Random_Forest_GridSearch.best_params_))

best_params_table_tree = pd.DataFrame({'N Estimators': [Random_Forest_GridSearch.best_params_['n_estimators']],
                                    'Min Samples Leaf': [Random_Forest_GridSearch.best_params_['min_samples_leaf']],
                                    'Learning Rate': [Random_Forest_GridSearch.best_params_['learning_rate']],
                                    'Max Depth': [Random_Forest_GridSearch.best_params_['max_depth']],
                                    })
best_params_table_tree.to_latex('./outputs/tables/Best_params_table_Gradient_Boosted_Tree.txt')

# Update User
print("Gradient Boosted Trees Model - Done CV!")

# #### Make Prediction(s)

# In[17]:

y_train_hat_random_forest_Gradient_boosting = random_forest_trained.predict(X_train)
y_test_hat_random_forest_Gradient_boosting = random_forest_trained.predict(X_test)

# Evaluate time-elapsed computation
Gradient_boosted_Random_forest_time = time.time() - Gradient_boosted_Random_forest_time_Begin

# Count Number of Parameters in Random Forest Regressor
N_tot_params_per_tree = [ (x[0].tree_.node_count)*random_forest_trained.n_features_ for x in random_forest_trained.estimators_]
N_tot_params_in_forest = sum(N_tot_params_per_tree)
#---------------------------------------------#
# Note to potential code-reader:
# Thanks Philip Casgain for the counter! :D
#---------------------------------------------#

# Update User #
#--------------#
print("Random Forest Regressor uses: "+str(N_tot_params_in_forest)+" parameters.")

# #### Write Prediction(s)

# In[18]:

# Compute Peformance
Gradient_boosted_tree = reporter(y_train_hat_in=y_train_hat_random_forest_Gradient_boosting,
                                    y_test_hat_in=y_test_hat_random_forest_Gradient_boosting,
                                    y_train_in=y_train,
                                    y_test_in=y_test)
# Write Performance
Gradient_boosted_tree.to_latex((results_tables_path+"Gradient_Boosted_Tree_Performance.tex"))

# Update User
print(Gradient_boosted_tree)

# ---
# # Fin
# ---


import os
import re

r = re.compile("M[14][1-5]{0,1}[AB]{0,1}-POD[\d](-\d+){3}")

def isHostDown(uptime, downtime, host):
    if downtime > uptime:
        print(host + ': Down')

def parseCritical(miner):
    if miner['Service'] == 'FAN':
        miner['Status'] = "Fan Stopped"
    elif miner['Service'] == 'HashRate':
        if miner['Status'].find("HashRate: 0"):
            miner['Status'] = "HashRate 0"
    print(miner['Hostname'] + " :" + miner['Status'])

def findCritical(line, miner):
    if line.find("last_time_ok") >= 0:
        miner['Uptime'] = int(line.split("=")[1])
    elif line.find("last_time_critical") >= 0:
        miner['Downtime'] = int(line.split("=")[1])
    elif line.find("plugin_output=CRITICAL") >= 0:
        miner['Status'] = line.split("=",1)[1]
        return True
    return False

def parseFile(filename):
    miner = {}
    isParsingHost = False
    isParsingService = False
    uptime = 0
    downtime = 0
    try:
        f = open(filename, 'r')
    except:
        return -1

    for line in f.readlines():
        line = line.rstrip()
        if re.match("^(\w+) \{$", line):
            #miner is found
            if line.find("host") >= 0:
                isParsingService = False
                isParsingHost = True
                continue
            #miner's service is found
            elif line.find("service") >= 0:
                isParsingHost = False
                isParsingService = True
                continue
            else: #not other than host or service
                isParsingService = False
                isParsingHost = False
                continue
        if isParsingHost == True and isParsingService == False:
            if line.find("host_name") >= 0:
                temp = r.search(line)
                if temp != None:
                    hostname = temp.group(0)
                else:
                    isParsingService = False
                    isParsingHost = False
                    continue
            elif line.find("last_time_up") >= 0:
                uptime = int(line.split("=")[1])
            elif line.find("last_time_down") >= 0:
                downtime = int(line.split("=")[1])
                isHostDown(uptime, downtime, hostname)
        elif isParsingHost == False and isParsingService == True:
            if line.find("host_name") >= 0:
                temp = r.search(line)
                if temp != None:
                    miner["Hostname"] = temp.group(0)
                else:
                    isParsingService = False
                    isParsingHost = False
            if line.find("service_") >= 0:
                miner["Service"] = line.split("=",1)[1]
                if line.split("=")[1].find("Blade") >= 0:
                    isParsingService = False
                    isParsingHost = False
                    continue
            if findCritical(line, miner) == True:
                parseCritical(miner)
            else:
                continue

if __name__ == '__main__':
    parseFile(os.path.expanduser('~/Downloads/data.dat'))


import boto3
import time
import datetime
#import picamera import PiCamera

from botocore.exceptions import NoCredentialsError

# reference your own access and secret keys
ACCESS_KEY = ""
SECRET_KEY = ""

def upload_to_aws(local_file, bucket, s3_file):
    s3 = boto3.client('s3', aws_access_key_id=ACCESS_KEY,
                      aws_secret_access_key=SECRET_KEY)

    try:
        s3.upload_file(local_file, bucket, s3_file)
        print("Upload Successful")
        return True
    except FileNotFoundError:
        print("The file was not found")
        return False
    except NoCredentialsError:
        print("Credentials not available")
        return False

def main():
    camera = PiCamera()
    camera.resolution = (1024, 768)
    camera.start_preview()
    time.sleep(2) # warmup time
    while(True):
        ts = time.time()
        st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
        camera.capture(str(st))
        time.sleep(2)
        upload_to_aws(st, 'iot-corbi', st)
        time.sleep(2)

if __name__ == '__main__':
    main()


#!/usr/bin/python3

"""This module defines a function "def island_perimeter(grid)".

Usage:
    "island_perimeter(...) is used to return the perimeter of the island
    described in grid:

grid is a list of list of integers:
    * 0 represents a water zone
    * 1 represents a land zone
    * One cell is a square with side length 1
    * Grid cells are connected horizontally/vertically (not diagonally).
    * Grid is rectangular, width and height don’t exceed 100
    * Grid is completely surrounded by water, and there is one island (or
    nothing).
The island doesn’t have “lakes” (water inside that isn’t connected to the
water around the island).
"""

def island_perimeter(grid):
    """Computes the perimeter of an island.

    Args:
        grid (list): contains the greed of an island.

    Return:
        The perimeter of the island.
    """
    height = len(grid)
    width = len(grid[0])
    perimeter = 0
    for i in range(height):
        for j in range(width):
            if grid[i][j] == 1:
                perimeter += 4
                if (j - 1 >= 0 and grid[i][j - 1] == 1):
                    perimeter -= 2
                if (i - 1 >= 0 and grid[i - 1][j] == 1):
                    perimeter -= 2
    return perimeter


# -*- encoding: utf-8 -*-
"""
本文件主要有以下几个作用：
1 从feature_1.0下读取数据，根据要求制作数据集x和y，存放到dataset文件夹下
"""

import os
import json
import math
import numpy
import imp
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split
from collections import Counter
"""
数据过滤条件，可自定义，只要目标数据在此函数中返回True即可
"""

def judge(PV):
    if int(PV) < 10:
        return False
    return True

"""
pv到类别的对应关系，可自定义
0.1 0.2 4 18 78
"""
def get_class(pv_str):
    pv = int(pv_str)

    if pv<10:
        return 0
    elif pv < 100:
        return 1
    elif pv < 500:
        return 2
    elif pv < 1000:
        return 3
    else:
        return 4

"""
生成数据x和y
file_list：要遍历的特征文件的list，可以选取1-21中的任意多个文件
feature_list：要使用的特征索引的list，一共12个特征，特征索引（0-11）和特征名字的对应关系如下
0--displaytype
1--formtype
2--duration
3--主题_one_hot
4--program_type
5-演员_one_hot
6-时间vector # 24
7-时间数
8-星期数
9-创建时间间隔
10-上映时间间隔
11-历史pv
12-pv
"""
def flatten(file_list):
    flatten_data = []
    flatten_target = []
    KNN_data = []
    KNN_target = []

    count = 0
    for index in file_list:
        print('file ' + str(index) + ' is processing')
        with open(os.path.join(os.path.abspath('..'), 'feature_1.0', str(index) + '.txt'), 'r', encoding='UTF-8') as fread:
            res = fread.read()
            res = json.loads(res)

            for item in res:
                if int(res[item][0])!= 1:
                    continue
                count = count + 1
                tmp = []
                tmp.extend(res[item][6])
                tmp.append(res[item][11])
                flatten_data.append(tmp)
                flatten_target.append(int(res[item][12]))
                KNN_tmp = []
                feature_list = [1,7,8,6,11,12,2,3,5,9,10]
                for i in feature_list:
                    if isinstance(res[item][i], list):
                        KNN_tmp.extend(res[item][i])
                    else:
                        KNN_tmp.append(res[item][i])
                KNN_data.append(KNN_tmp)
                KNN_target.append(int(res[item][11]))

    target = list(flatten_target)
    target.sort(reverse=True)
    level1 = int(len(target)*0.001)
    level2 = int(len(target)*0.003)
    level3 = int(len(target)*0.043)
    level4 = int(len(target)*0.243)
    print(str(target[0]) + ' ' + str(target[len(target)-1]))
    print(str(target[level1]) + ' ' + str(target[level2]) + ' ' + str(target[level3]) + ' ' + str(target[level4]))
    for i in range(len(flatten_target)):
        if flatten_target[i] < target[level4]:
            flatten_target[i] = 0
            KNN_data[i][28] = 0
        elif flatten_target[i] < target[level3]:
            flatten_target[i] = 1
            KNN_data[i][28] = 1
        elif flatten_target[i] < target[level2]:
            flatten_target[i] = 2
            KNN_data[i][28] = 2
        elif flatten_target[i] < target[level1]:
            flatten_target[i] = 3
            KNN_data[i][28] = 3
        else:
            flatten_target[i] = 4
            KNN_data[i][28] = 4

    flatten_loc = numpy.array([i for i in range(len(flatten_data))])
    flatten_target = numpy.array(flatten_target)

    train_loc, test_loc, train_target, test_target = train_test_split(flatten_loc, flatten_target, test_size=0.3, random_state=0)

    flatten_data = numpy.array(flatten_data, dtype = 'float64')
    KNN_data = numpy.array(KNN_data, dtype='float64')
    KNN_target = numpy.array(KNN_target, dtype='int')
    print(Counter(KNN_data[:, 28]))
    print(count)
    train_data_path = os.path.join(os.path.abspath('..'), 'dataset', 'train_data.txt')
    numpy.savetxt(train_data_path, flatten_data[train_loc])
    train_target_path = os.path.join(os.path.abspath('..'), 'dataset', 'train_target.txt')
    numpy.savetxt(train_target_path, train_target)

    test_data_path = os.path.join(os.path.abspath('..'), 'dataset', 'test_data.txt')
    numpy.savetxt(test_data_path, flatten_data[test_loc])
    test_target_path = os.path.join(os.path.abspath('..'), 'dataset', 'test_target.txt')
    numpy.savetxt(test_target_path, test_target)

    knn_train_data_path = os.path.join(os.path.abspath('..'), 'dataset', 'knn_data.txt')
    numpy.savetxt(knn_train_data_path, KNN_data[train_loc])
    knn_train_target_path = os.path.join(os.path.abspath('..'), 'dataset', 'knn_target.txt')
    numpy.savetxt(knn_train_target_path, KNN_target[train_loc])

    knn_test_data_path = os.path.join(os.path.abspath('..'), 'dataset', 'knn_test_data.txt')
    numpy.savetxt(knn_test_data_path, KNN_data[test_loc])
    knn_test_target_path = os.path.join(os.path.abspath('..'), 'dataset', 'knn_test_target.txt')
    numpy.savetxt(knn_test_target_path, KNN_target[test_loc])

if __name__ == '__main__':

    #flatten([1,2])
    flatten([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21])


# 事件循环+回调（协程驱动）+epoll(IO多路复用)
# asyncio是python用于解决异步io编程的一整套解决方案
# tornado、gevent、twisted（scrapy， django channels）
# django+flask(uwsgi, gunicorn+nginx)本身不提供web服务器也就是不完成socket编码
# torando(实现web服务器)
# tornado可以直接部署， nginx+tornado

"""
# 使用asyncio
import asyncio
import time
async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)   # 这个sleep是异步的 不能用time.sleep
    print("end get url")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    tasks = [get_html("http://www.imooc.com") for i in range(10)]
    loop.run_until_complete(asyncio.wait(tasks))
    #loop.run_until_complete(get_html("http://www.imooc.com"))
    print(time.time()-start_time)
"""

# 获取协程的返回值
import asyncio
import time

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    return "bobby"

def callback(future):
    print("send email to bobby")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    # 方法一 ensure_future
    # get_future = asyncio.ensure_future(get_html("http://www.imooc.com"))
    # loop.run_until_complete(get_future)
    # print(get_future.result())

    # 方法二 create_task
    task = loop.create_task(get_html("http://www.imooc.com"))
    task.add_done_callback(callback)  # callback的参数就是task
    loop.run_until_complete(task)
    print(task.result())

# -------------------
import asyncio
import time
from functools import partial  # 给callback传参数

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    return "bobby"

def callback(url, future):  # url只能是第一个参数
    print(url)
    print("send email to bobby")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    task = loop.create_task(get_html("http://www.imooc.com"))
    # callback有参数时  用partial
    task.add_done_callback(partial(callback, "http://www.imooc.com"))
    loop.run_until_complete(task)
    print(task.result())

# ------------------------------
# asyncio.wait 和 asyncio.gather
import asyncio
import time

async def get_html(url):
    print("start get url")
    await asyncio.sleep(2)
    print("end get url")

if __name__ == "__main__":
    start_time = time.time()
    loop = asyncio.get_event_loop()
    tasks = [get_html("http://www.imooc.com") for i in range(10)]
    # *tasks将list解析成参数
    # loop.run_until_complete(asyncio.gather(*tasks))
    # print(time.time()-start_time)

    # gather和wait的区别
    # gather更加high-level
    group1 = [get_html("http://projectsedu.com") for i in range(2)]
    group2 = [get_html("http://www.imooc.com") for i in range(2)]
    # loop.run_until_complete(asyncio.gather(*group1, *group2))
    group1 = asyncio.gather(*group1)
    group2 = asyncio.gather(*group2)
    group2.cancel()
    loop.run_until_complete(asyncio.gather(group1, group2))
    print(time.time() - start_time)


import tkinter as tk

root = tk.Tk()

button = tk.Button(root, text="This stretches")
label = tk.Label(root, text="This doesn't stretch")
statusbar = tk.Label(root, text="This is a status bar", relief='sunken')

statusbar.pack(side='bottom', fill='x')
button.pack(side='left', fill='both', expand=True)
label.pack(side='left')

root.title("Pack Test")
root.geometry('300x150')
root.mainloop()


def intercambio(cadena):
    cadena = cadena[::-1]
    nueva_cadena =''
    for e in  range(len(cadena)):
        if cadena[e] == 'L':
            nueva_cadena+='R'
        elif cadena[e] == 'R':
            nueva_cadena+='L'
    return nueva_cadena
def construye(n):
    cadena = ''
    if n == 1:
        cadena += 'L'
    else:
        cadena += construye(n-1)+'L'+intercambio(construye(n-1))
    return cadena
t = 0
while  t!=-1:
    print("da numero")
    t = int(input())
    if t == -1:
        break
    else:
        print (construye(t))


import pymongo
import bcrypt
import datetime
from pymongo import MongoClient
import json

class LoginModel:

    def __init__(self):
        try:
            self.client = MongoClient()
            self.db     = self.client.social_net_db
            self.Users  = self.db.users
            print("Connected successfully!!!")
        except:
            print("Could not connect to MongoDB")

    def  login_user(self, data):

        user = self.Users.find_one({"username":data.username})

        if user!=None:
            if bcrypt.checkpw(data.password.encode(), user["password"].encode()):
                return user["username"]
            else:
                return False
        else:
            return False


from behave import *
import requests
from utilities.configurations import *
from utilities.resources import *

@given('A Get Request with some parameters')
def step_impl(context):
    context.URL = getConfig()['API']['HOST'] + APIResources.GETRESOURCE
    context.APIheaders = {"Content-Type": "application/json"}

@when('I call requests module Get method with Get URL')
def step_impl(context):
    context.response = requests.get(context.URL,
                                    params={'page': 2},
                                    headers=context.APIheaders)
    response_Json = context.response.json()
    print(response_Json)
    first_name = response_Json['data'][0]['first_name']
    print("The first Name is : " + first_name)

@then('I should be able to see the related data')
def step_impl(context):
    assert context.response.status_code == 200
    assert context.response.json()['data'][0]['first_name'] == 'Michael'


# %%
# import
import tensorflow as tf
from PIL import Image
import numpy as np
from tensorflow.keras import layers
print(tf.__version__)
print(tf.keras.__version__)

# %%
# load data
raw = np.genfromtxt('train.csv', delimiter=',', dtype=str, skip_header=1)
raw[0]
x_train = []
y_train = []
x_val = []
y_val = []
# tmp = np.array(raw[0, 1].split(' '), dtype=float).reshape(1, 48, 48)
# img = Image.fromarray(np.flip(tmp[0], axis=1))
# img2 = Image.fromarray(tmp[0])
# img.show()
# img2.show()
for i in range(len(raw)):
    tmp = np.array(raw[i, 1].split(' ')).reshape(1, 48, 48)
    if i % 10 == 0:
        x_val.append(tmp)
        y_val.append(raw[i, 0])
    x_train.append(tmp)
    x_train.append(np.flip(tmp, axis=2))
    y_train.append(raw[i, 0])
    y_train.append(raw[i, 0])

x_train = np.array(x_train, dtype=float) / 255.0
y_train = np.array(y_train, dtype=float) / 255.0
x_val = np.array(x_val, dtype=float)
y_val = np.array(y_val, dtype=float)

dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
val_dataset = tf.data.Dataset.from_tensor_slices((x_val, y_val))


'''
Abbiamo immagini in formato png ottenute inserendo su di uno sfondo monocolore rettangoli
di vari colori i cui assi sono sempre parallei agli assi dell'immagine.

Vedi ad esempio l'immagine Img1.png

Per caricare e salvare immagini PNG usate le funzioni load e save che abbiamo preparato nel modulo immagini.py .

Scrivere una  funzione quadrato(filename, C) che prende in input:
- il percorso di un file (filename) che contine un immagine in formato png della  tipologia appena descritta.
- una tupla C che rappresenta un colore in formato RGB (3 valori interi tra 0 e 255 compresi)

La funzione deve restituire nell'ordine:
- la lunghezza del lato del quadrato pieno di dimensione massima e colore C interamente visibile nell'immagine.
- le coordinate  (x,y)  del pixel dell'immagine che corrisponde alla posizione
all'interno dell'immagine del punto in alto a sinistra del quadrato.

In caso ci siano più quadrati di dimensione massima, va considerato quello il cui punto
in alto a sinistra occupa la riga minima  (e a parita' di riga la colonna minima) all'interno dell' immagine.

Si può assumere che nell'immagine e' sempre  presente almeno un pixel del colore cercato.

Per gli esempi vedere il file grade01.txt

ATTENZIONE: Il timeout è impostato a 10*N secondi (con N numero di test del grader).
'''

from immagini import *

def is_square(image, x, y, min_lenght):
    c = image[x][y]
    height = len(image)
    lenght = len(image[0])
    side_lenght_x = 0
    side_lenght_y = 0
    x_temp = x
    y_temp = y

    while image[x_temp][y] == c:
        if x_temp+1 < height:
            x_temp += 1
            side_lenght_x += 1
        else:
            break
    while image[x][y_temp] == c:
        if y_temp+1 < lenght:
            y_temp += 1
            side_lenght_y += 1
        else:
            break

    if side_lenght_x == 1 and side_lenght_y == 1:
        return 1

    if side_lenght_x < min_lenght or side_lenght_y < min_lenght:
        return False

    if side_lenght_y < side_lenght_x:
        for i in range(side_lenght_y):
            for j in range(side_lenght_y):
                if x+i < height or j+y < lenght:
                    if image[x+i][y+j] == c:
                        continue
                    else:
                        return False
                else:
                    return False
        return side_lenght_y
    else:
        for i in range(side_lenght_x):
            for j in range(side_lenght_x):
                if x+j < height or j+i < lenght:
                    if image[x+j][y+i] == c:
                        continue
                    else:
                        return False
                else:
                    return False
        return side_lenght_x

def quadrato(filename,c):
    img = load(filename)
    height = len(img)
    lenght = len(img[0])

    square_vertices = list()
    square_sides_lenght = list()

    for x in range(height):
        for y in range(lenght):
            if img[x][y] == c:
                if len(square_sides_lenght) < 1:
                    min_lenght = 0
                else:
                    min_lenght = max(square_sides_lenght)
                side_lenght = is_square(img, x, y, min_lenght)
                if side_lenght:
                    square_vertices.append((x, y))
                    square_sides_lenght.append(side_lenght)

    return max(square_sides_lenght), square_vertices[square_sides_lenght.index(max(square_sides_lenght))][::-1]


# coding=utf-8
from timeit import Timer

__author__ = 'donglin'

from io import StringIO

# from cStringIO import StringIO

def meth1(str1):
    a = []

    for i in range(100):
        a.append(str1)

    return ''.join(a)

if __name__ == "__main__":
    import logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger(__name__)

    str1 = meth1("hello\n")
    # logger.info(str1)

    print(Timer("meth1(\"hello\")", "from __main__ import meth1").timeit(number=1))


import re
text_cn = """
好好学习，天天向上。1234567，pony
"""
def stats_text_cn(text):
    # remove chinese symbol and "\n" and " " and, don't forget english and number charactor...
    i = re.compile("[，；。—~ ？!‘’“”\nA-Za-z0-9]")
    text_rm_symbol = i.sub("", text)

    # split
    text_to_list = []
    for x in text_rm_symbol:
        text_to_list.append(x)
    while "" in text_to_list:
        text_to_list.remove("")
    # create dictionary
    sort_list = [(x, text_to_list.count(x)) for x in set(text_to_list)]

    sort_dict = dict(sort_list)
    # output a dictionary sort by frequency
    return (sorted(sort_dict.items(), key=lambda x: x[1], reverse=True))
print(stats_text_cn(text_cn))

print(dict(stats_text_cn(text_cn)))


import argparse

import matplotlib.pyplot as plt
import numpy as np

from compute_ic import InformationCapacity

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Plot histograms for certain steps",
                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--steps', dest='steps', action='store', type=int, default=8,
                        help="number of KP steps.")
    parser.add_argument('--fb', dest='fb', action='store', type=float)

    args = parser.parse_args()
    steps = args.steps
    lf = 30

    num_steps = []
    capacity = []
    for i in range(1, 9):
        if i == 5:
            continue

        if args.fb:
            file_path = "{0}_step_k_pos_{1}/".format(i, args.fb)
        else:
            file_path = "{0}_step/".format(i)

        num_steps.append(i)
        ic_lf = InformationCapacity(foreign_directory=file_path + "Ls_Lf_{0}/".format(lf),
                                    self_directory=file_path + "Ls/", limiting="self")

        if i == 1:
            xhi = 1500
        elif i == 2:
            xhi = 1000
        elif i == 3:
            xhi = 600
        elif i == 4:
            xhi = 400
        # elif i > 8:
        #     xhi = 30
        else:
            xhi = 400

        plt.xlim(0, xhi)
        plt.title(
            "{:.0f} Steps: C = {:.3f}, P_0_integral = {:.3f}".format(steps, ic_lf.capacity, ic_lf.p0_integral))
        # plt.title("{0} Steps: IC = {1}".format(i, ic_lf.calculate_ic()))
        plt.legend()
        plt.savefig(file_path + "{0}_step.pdf".format(i), format="pdf")
        plt.close()

        capacity.append(ic_lf.capacity)

        plt.plot(num_steps, capacity, linestyle='-', marker='o', label="$k_{on} = 1.0s^{-1}$")

        plt.legend()
        plt.xlabel("Number of Steps", size=15)
        plt.ylabel("C (bits)", size=15)
        plt.xlim(0, 8)
        plt.ylim(0, 1)
        plt.locator_params(axis='x', nbins=11)
        plt.savefig(file_path + "ic_{0}_step.pdf".format(i), format="pdf")
        plt.close()

    np.savetxt("num_steps", num_steps, fmt='%f')
    np.savetxt("ic", capacity, fmt='%f')


"""
The controller module exposes a Controller App for performing high-level vehicle
state management.

Enums:
    FlightMode  Use to send the flight software a mode.

Apps:
    Controller  Sends high-level one-off vehicle management commands.

"""
import time

from flufl.enum import Enum

from pyliner.app import App
from pyliner.action import ACTION_RTL, ACTION_SEND_COMMAND
from pyliner.intent import Intent
from pyliner.pyliner_exceptions import UnauthorizedAtpError
from pyliner.telemetry import ManualSetpoint
from pyliner.util import query_yes_no

_WAIT_TIME = 0.1

class FlightMode(Enum):
    """Use to select a mode for the flight software."""
    Manual = 1
    AltCtl = 2
    PosCtl = 3
    RTL = 4

class Controller(App):
    """Sends high-level one-off commands to the vehicle."""

    def __init__(self):
        super(Controller, self).__init__()
        self.atp_override = None

    def attach(self, vehicle_wrapper):
        super(Controller, self).attach(vehicle_wrapper)
        self.vehicle.callback = self.receive

    def detach(self):
        self.vehicle.callback = None
        super(Controller, self).detach()

    def arm(self):
        """Arm vehicle."""
        print("Arming vehicle")
        self.vehicle.info("Arming vehicle")
        self.vehicle.broadcast(Intent(
            action=ACTION_SEND_COMMAND,
            data=ManualSetpoint(ArmSwitch=3))).first()
        self.vehicle.broadcast(Intent(
            action=ACTION_SEND_COMMAND,
            data=ManualSetpoint(ArmSwitch=1))).first()

    def receive(self, intent):
        actions = {
            ACTION_RTL: self.rtl
        }
        try:
            actions[intent.action]()
        except KeyError:
            if intent.component == self.vehicle._name:
                self.info('Controller cannot process intent: {}'.format(intent))

    def atp(self, text, error=True):
        """Collect authorization to proceed (ATP) from the user."""
        atp_auth = None
        while atp_auth is None:
            if callable(self.atp_override):
                atp_auth = self.atp_override()
            elif self.atp_override is not None:
                atp_auth = self.atp_override
            else:
                atp_auth = query_yes_no(
                    "Requires authorization for: {}".format(text))
            self.vehicle.info("ATP: {} Auth: {}".format(text, atp_auth))
            if error and atp_auth is False:
                raise UnauthorizedAtpError
            return atp_auth

    def disarm(self):
        print("Disarming vehicle")
        self.vehicle.info("Disarming vehicle")
        self.vehicle.broadcast(Intent(
            action=ACTION_SEND_COMMAND,
            data=ManualSetpoint(ArmSwitch=3))).first()

    def flight_mode(self, mode):
        if not mode:
            raise ValueError('Mode transition requires a passed mode.')
        if mode == FlightMode.Manual:
            raise NotImplemented()
        elif mode == FlightMode.AltCtl:
            raise NotImplemented()
        elif mode == FlightMode.PosCtl:
            self._mode_posctl()

    def _mode_posctl(self):
        print("Position control")
        self.vehicle.info("Position control")
        self.vehicle.broadcast(Intent(
            action=ACTION_SEND_COMMAND,
            data=ManualSetpoint(Z=0.5, PosctlSwitch=1, GearSwitch=1))
        ).first()

    @classmethod
    def required_telemetry_paths(cls):
        return None

    def rtl(self):
        """Return to launch."""
        print("RTL")
        self.vehicle.info("RTL")
        self.vehicle.broadcast(Intent(
            action=ACTION_SEND_COMMAND,
            data=ManualSetpoint(ReturnSwitch=1, GearSwitch=3, ArmSwitch=1))
        ).first()

    def takeoff(self):
        """Takeoff"""
        print("Auto takeoff")
        self.vehicle.info("Auto takeoff")
        self.vehicle.broadcast(Intent(
            action=ACTION_SEND_COMMAND,
            data=ManualSetpoint(TransitionSwitch=1, ArmSwitch=1))
        ).first()
        time.sleep(5)