from msilib import sequence
import os
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt
from datetime import date
from random import randint
from numpy.typing import ArrayLike
from pandas import DataFrame
from typing import Tuple
from typing import List
from typing import Union
from tensorflow import Tensor
from tensorflow.python.keras.models import Model
from tensorflow.python.keras.losses import MeanSquaredError
from tensorflow.python.keras.metrics import MeanAbsoluteError
from tensorflow.python.keras.callbacks import EarlyStopping

from sqlalchemy import create_engine
from sqlalchemy import MetaData
"""
Tensorflow Logging:
    0 = all messages printed (default)
    1 = INFO messages are not printed
    2 = INFO and WARNING messages are not printed
    3 = INFO, WARNING, and ERROR messages are not printed
"""
os.environ["TF_CPP_MIN_LOG_LEVEL"] = '1'

config = {
    "input_width": 30,
    "label_width": 5,
    "offset": 5,
    "num_features": None,
    "label_columns": ["close"],
    "train_split": 0.7,
    "val_split": 0.8,
    "batch_size": 32,
    "epochs": 36,
    "patience": 2,
    "loss_func": MeanSquaredError(),
    "optmizer": tf.optimizers.Adam(),
    "metrics": [MeanAbsoluteError()],
    "callbacks": [EarlyStopping()]
}

class Sequence(object):
    """
    Class to hold raw data, normailizd data, and train/val/test split
    for each security
    """

    def __init__(self, sym: str, timeseries: DataFrame) -> None:
        # Flip the dataframe so start index is oldest date
        timeseries = timeseries.iloc[::-1]

        # Record symbol and original dataframe
        self.sym = sym
        self.timeseries_df: DataFrame = timeseries

        # Column headers and Date before stripping them
        self.n_rows, self.n_columns = self.timeseries_df.shape
        self.dates: List[date] = [timestamp.date() for timestamp in timeseries.index.to_list()]

        self.columns: List[str] = timeseries.columns.to_list()
        self.column_indices = {col:i for i, col in enumerate(self.columns)}

        train_val_index = int(self.n_rows*config["train_split"])
        val_test_index = int(self.n_rows*config["val_split"])

        # Slices for easily indexing datasets
        self.train_slice = slice(0, train_val_index)
        self.val_slice = slice(train_val_index, val_test_index)
        self.test_slice = slice(val_test_index, None)

        config["num_features"] = self.n_columns

        # Strip the features into 2D Arrays
        self.timeseries: ArrayLike = timeseries.to_numpy()
        self.train: ArrayLike = None
        self.val: ArrayLike = None
        self.test: ArrayLike = None

        # Save the corresponding dates in lists
        self.train_dates: List[date] = None
        self.val_dates: List[date] = None
        self.test_dates: List[date] = None

        # Split and normalize the data to feed into the model
        self.__split()
        self.__normalize()

    def __split(self) -> None:
        """ Split self.timeseries and self.dates into appopiate train, val, test sets"""
        self.train = self.timeseries[self.train_slice]
        self.train_dates = self.dates[self.train_slice]

        self.val = self.timeseries[self.val_slice]
        self.val_dates = self.dates[self.val_slice]

        self.test = self.timeseries[self.test_slice]
        self.test_dates = self.dates[self.test_slice]

        # Ensure that no datapoints were loss
        assert len(self.train) + len(self.val) + len(self.test) == len(self.timeseries)
        assert len(self.train_dates) + len(self.val_dates) + len(self.test_dates) == len(self.dates)

    def __normalize(self) -> None:
        """Normalize the data using the training metrics"""
        self.mean = self.train.mean(axis=0)
        self.std = self.train.std(axis=0)

        self.train = (self.train - self.mean) / self.std
        self.val = (self.val - self.mean) / self.std
        self.test = (self.test - self.mean) / self.std

        # Ensure each feature has a mean value of 0
        assert any(np.around(self.train.mean(axis=0), decimals=5)) == False

    def invert(self, x: ArrayLike) -> ArrayLike:
        """Reverses the normalization for readiability"""
        return (x * self.std) + self.mean

    def __getitem__(self, i: Union[int, slice]) -> ArrayLike:
        """ Dunder to retrieve a datum """
        return self.timeseries[i]

    def __repr__(self) -> str:
        """ Dunder for represetnation """
        return (f'TimeSeries Data - Train/Val/Test: {self.train.shape}/{self.val.shape}/{self.test.shape}')

    def get_splits(self) -> Tuple[ArrayLike, ArrayLike, ArrayLike]:
        """ Get method for train, val, test arrays """
        return self.train, self.val, self.test

    def plot(self) -> None:
        """ Plot the train/val/test splits normalized for closing price """
        close_index = self.column_indices['close']

        plt.figure(figsize=(12, 8))
        plt.plot(self.train_dates, self.train[:, close_index], c='#ff0000', label='train')
        plt.plot(self.val_dates, self.val[:, close_index], c='#00ff00', label='val')
        plt.plot(self.test_dates, self.test[:, close_index], c='#0000ff', label='test')

        plt.title(self.sym)
        plt.ylabel('Close [Normed]')
        plt.xlabel('Date')
        plt.legend()
        plt.show()

class WindowGenerator(object):
    """
    Class to handle the "windowing" of a given sequence

    LSTM uses previous values to predict the next value(s), so we need to have
    inputs of previous values and labels of current values.

    If given the params of:
        input_width = 3
        label_width = 1
        offset = 1
        series = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    Then we will want our features and labels to look like:
        x = [[1, 2, 3],
             [2, 3, 4],
             [3, 4, 5],
             [4, 5, 6],
             [5, 6, 7],
             [6, 7, 8],
             [7, 8, 9]
            ]

        y = [4, 5, 6, 7, 8, 9, 10]
    """

    def __init__(self, seq: Sequence) -> None:
        """
        inputs_width = the window size of the input(s)
        label_width = the window size of label(s)
        offset = the timesteps betwen input_width and the end of label_width
        """

        # Record the sequence
        self.sequence = seq

        # Record indices for column lookups
        self.label_columns = config["label_columns"]
        self.label_columns_indices = {name:i for i, name in enumerate(self.label_columns)}
        self.column_indices = self.sequence.column_indices

        # Dimensions for windowing will want final shape of the window, inputs, and labels to be (batch, time, features)
        self.inputs_width = config["input_width"]
        self.labels_width = config["label_width"]
        self.offset = config["offset"]
        self.total_window_size = self.inputs_width + self.offset

        # Determine the inputs indices
        self.inputs_slice = slice(0, self.inputs_width)
        self.inputs_indices = np.arange(self.total_window_size)[self.inputs_slice]

        # Determine indices of the labels
        self.labels_slice = slice(self.total_window_size - self.labels_width, None)
        self.labels_indices = np.arange(self.total_window_size)[self.labels_slice]

    def __split_window(self, features: Tensor) -> Tensor:
        """
        Apply "windowing" to a given tensor
        """

        inputs: Tensor = features[:, self.inputs_slice, :]
        labels: Tensor = features[:, self.labels_slice, :]
        labels: Tensor = tf.stack([labels[:, :, self.sequence.column_indices[name]] for name in self.label_columns],
                        axis=-1)

        inputs.set_shape([None, self.inputs_width, None])
        labels.set_shape([None, self.labels_width, None])

        return inputs, labels

    def __make_dataset(self, data: ArrayLike) -> tf.data.Dataset:
        ds: tf.data.Dataset = tf.keras.utils.timeseries_dataset_from_array(
                                            data=data,
                                            targets=None,
                                            sequence_length=self.total_window_size,
                                            sequence_stride=1,
                                            shuffle=True,
                                            batch_size=config["batch_size"],
                                        )

        return ds.map(self.__split_window)

    def plot_window(self, column: str = None, n: int=3) -> None:
        inputs, labels = next(iter(self.get_train_dataset()))
        plt.figure(figsize=(12, 8))

        if not column:
            column = self.label_columns[0]

        input_column_index = self.column_indices[column]
        label_column_index = self.label_columns_indices[column]

        n = min(n, len(inputs))
        for i in range(n):
            plt.subplot(n, 1, i+1)
            plt.ylabel(f'{column} [normed]')
            plt.plot(self.inputs_indices, inputs[i, :, input_column_index],
                     label='Inputs', marker='.', zorder=-10)

            plt.scatter(self.labels_indices, labels[i, :, label_column_index],
                edgecolors='k', label='Labels', c='#2ca02c', s=64)

            if i == 0:
                plt.legend()

        plt.xlabel('Time Step')
        plt.show()

    def plot_predictions(self, inputs: ArrayLike, labels: ArrayLike,
                         predictions: ArrayLike, column: str = None) -> None:

        # Default column to plot if not specified
        if not column:
            column = config["label_columns"][0]

        # Convert 3D to 2D
        inputs, labels, predictions = inputs[0], labels[0], predictions[0]

        # Inverse the normalziation
        inputs = self.sequence.invert(inputs)
        labels = self.sequence.invert(labels)
        predictions = self.sequence.invert(predictions)

        # Grab input column index and label column index
        input_col_index = self.column_indices[column]
        label_col_index = self.label_columns_indices[column]

        # Grab the corresponding dates
        input_dates = self.sequence.train_dates + self.sequence.val_dates
        label_dates = self.sequence.test_dates

        # Shape the dates
        input_dates = input_dates[-1*len(inputs):]
        label_dates = label_dates[:len(labels)]

        # Ensure the correct shapes
        assert len(input_dates) == len(inputs)
        assert len(label_dates) == len(labels)

        # Plot hte results
        plt.figure(figsize=(12, 8))
        plt.plot(input_dates, inputs[:, input_col_index],
                    label='Inputs', marker='.', zorder=-10)
        plt.scatter(label_dates, labels[:, label_col_index], edgecolors='k',
                    label='Labels', c='#2ca02c', s=64)
        plt.scatter(label_dates, predictions[:, label_col_index], edgecolors='k',
                    marker='X', label='Predictions', c='#ff7f0e', s=64)

        plt.title(self.sequence.sym)
        plt.ylabel(f'{column}')
        plt.xlabel('Dates')
        plt.legend()
        plt.show()
        return

    def get_train_dataset(self) -> tf.data.Dataset:
        return self.__make_dataset(self.sequence.train)

    def get_val_dataset(self) -> tf.data.Dataset:
        return self.__make_dataset(self.sequence.val)

    def get_test_dataset(self) -> tf.data.Dataset:
        return self.__make_dataset(self.sequence.test)

    def __repr__(self) -> str:
        return (f'\nTotal window size: {self.total_window_size}\n'
                f'Input indices: {self.inputs_indices}\n'
                f'Label indices: {self.labels_indices}\n'
                f'Label column names: {self.label_columns}\n')

def load_data() -> List[Sequence]:
    """Function to load local stored data"""

    engine = create_engine('sqlite:///../data/test.db')

    metadata = MetaData(engine)
    metadata.reflect(engine)
    syms = list(metadata.tables.keys())
    data = []
    for sym in syms:
        df = pd.read_sql_table(sym, engine.connect(), index_col='date', parse_dates=['date'])
        data.append(Sequence(sym, df))

    assert len(data) == len(syms)
    return data

if __name__ == "__main__":
    data = load_data()
    seq = data[randint(0, len(data) - 1)]
    print(f'Random sequnce selected for ticker={seq.sym} \n')
    print(f'{seq} \n')
    seq.plot()

    window = WindowGenerator(seq)
    print(f'{window} \n')

    train_ds = window.get_test_dataset()
    for inputs, labels in train_ds.take(1):
        print("Dataset Shape: ")
        print(f'\tInputs shape (batch, steps, features): {inputs.shape}')
        print(f'\tLabels shape (batch, steps, features): {labels.shape}\n')

    window.plot_window()


import os

import click
from tqdm import tqdm
import spoteno

@click.command()
@click.argument('source_path', type=click.Path(exists=True))
@click.argument('target_path', type=click.Path())
def run(source_path, target_path):
    if not os.path.isfile(target_path):
        os.makedirs(os.path.dirname(target_path), exist_ok=True)
        print('Create character level data ...')

        with open(source_path, 'r') as f:
            sentences = [l.strip() for l in f.readlines()]

        words = set()

        for s in sentences:
            words.update(s.split(' '))

        split_words = [' '.join(list(w)) for w in words if len(w) > 1]

        with open(target_path, 'w') as f:
            f.write('\n'.join(split_words))
    else:
        print('Already character level done')

if __name__ == '__main__':
    run()


# -*- coding:UTF-8 -*-
import re

def get_score_from_file_GM_new():   #read P1 P2 P3 for calculate  the final score
    scores = []
    scores_num = []
    f_data = open("result.txt", "r")
    try:
        all_the_text = f_data.read()
        every_frame_information = all_the_text.split('query')
        for string in every_frame_information[1:]:
            P1_first_index = string.index('P1: ')   #first time it exist
            if string[P1_first_index+7].isdigit() == True:
                P1_score = float(string[P1_first_index+4:P1_first_index+8])
            else:
                P1_score = float(string[P1_first_index+4:P1_first_index+7])
            if P1_score < 0.2:
                scores_num.append(0)
            else:
                P2_first_index = string.index('P2: ')
                if string[P2_first_index+5].isdigit() == True:
                    P2_score = float(string[P2_first_index+4:P2_first_index+6])
                else:
                    P2_score = float(string[P2_first_index+4:P2_first_index+5])

                P3_first_index = string.index('max_same_angle_count is : ')
                if string[P3_first_index+27].isdigit() == True:       #
                    if string[P3_first_index+28] == '.':
                        P3_score = float(string[P3_first_index+26:P3_first_index+30])  #like: 10.5
                    else:
                        P3_score = int(string[P3_first_index+26:P3_first_index+28])  #like: 10
                elif string[P3_first_index+27] == '.':
                    P3_score = float(string[P3_first_index+26:P3_first_index+29])  #like: 8.5
                else:
                    P3_score = int(string[P3_first_index+26:P3_first_index+27])   #like: 8

                tem_final_score = P1_score + 5*P2_score + 2*P3_score
                scores_num.append(tem_final_score)
    finally:
        f_data.close()
    return scores_num

score_GM = get_score_from_file_GM_new()

def R_P_calculate(frames_num, scores, score_threshold, true_positive, flag = ' '):
    FP_list = [];  TP_list = []
    TP=0 ; FP =0 ; TN=0 ; FN=0
    for i in range(frames_num):
        if scores[i] ==-1:
            continue
        elif  scores[i] >=score_threshold:   #positive
            if true_positive[i] == 1:
                TP = TP+ 1
                TP_list.append(i)
            elif true_positive[i] == 0:
                FP = FP + 1
                FP_list.append(i)
        elif scores[i] < score_threshold:  #negetive
            if true_positive[i] == 1:
                FN = FN+ 1
            elif true_positive[i] == 0:
                TN = TN + 1

    if TP +FN == 0:
        recall_once = 0
    else:
        recall_once = float(TP) / (TP +FN)

    if TP +FP == 0:
        precision_once = 0
    else:
        precision_once =  float(TP) / (TP +FP)

    # print(FP_list)
    return recall_once, precision_once, FP_list, TP_list

#true positive
frames_num = 300
true_positive = [0 for i in range(frames_num)]
for i in range(frames_num):                #scenenet-209-1675frame
    if (i>=0 and i<=74) or (i>=167 and i<=213) or (i>=293 and i<=299) :
        true_positive[i] = 1  #positive
    else:             #negetive
        true_positive[i] = 0

#P-R curve
recall_GM = [] ; precision_GM = []
precision_GM.append(1) ; recall_GM.append(0)
for score_threshold in range(1000, -1, -1):
    score_threshold = float(score_threshold)/10

    recall_GM_once, precision_GM_once, FP_list, TP_list = R_P_calculate(frames_num, score_GM, score_threshold, true_positive, 'ours')
    if recall_GM_once != 0 or precision_GM_once != 0:
        recall_GM.append( recall_GM_once )
        precision_GM.append( precision_GM_once )
        # print(recall_GM_once, precision_GM_once)

def R_P_area_calculate(precision_list, recall_list): #P-R curve area
    area = 0
    for i in range(len(recall_list)-1):
        area += float(precision_list[i] + precision_list[i+1]) * (recall_list[i+1] - recall_list[i]) /2
    print( "The area of the P-R curve is: "+str(area))
    return area

R_P_area_calculate(precision_GM,recall_GM)

import matplotlib.pyplot as plt
plt.plot(recall_GM, precision_GM, 'r', label='area:0.986')
plt.legend()

plt.show()


import pygame, math, sys

def refresh(screen, player, grid):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.MOUSEBUTTONUP:
            pos = pygame.mouse.get_pos()
            column = math.floor(pos[0] / 100)
            return _add_piece(grid, column, player)

    screen.fill((0, 128, 255))
    _draw_grid(screen, grid)
    pygame.display.update()

    return True

def _draw_grid(screen, grid):
    y = 50
    for row in grid:
        x = 50
        for cell in row:
            color = (0, 0, 0)
            if cell == 1:
                color = (255, 128, 0)
            elif cell == 2:
                color = (0, 255, 128)
            pygame.draw.circle(screen, color, (x, y), 40)
            x = x + 100
        y = y + 100

def _add_piece(grid, column, player):
    i = 5
    while i >= 0:
        if grid[i][column] == 0:
            grid[i][column] = player
            return False
        i = i - 1
    return True

def display_result(screen, outcome):
    font = pygame.font.Font("roboto.ttf", 32)
    text = font.render(f"You {outcome}", True, (0, 0, 0), (255, 255, 255))
    text_rect = text.get_rect()
    text_rect.center = (350, 300)
    screen.blit(text, text_rect)
    pygame.display.update()


from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

class CursoAutomacao:
    def __init__(self):
        chrome_options = Options()
        chrome_options.add_argument('--lang=pt-BR')
        self.driver = webdriver.Chrome(executable_path=r'./chromedriver.exe', options=chrome_options)

    def Iniciar(self):
        self.driver.get('http://www.waves.com.br')
        self.driver.maximize_window()
        self.pergunta = input("Qual praia vocês deseja verificar a previsão do mar? Joaquina, Mole, Campeche, Vila,Porto, Rosa Sul, Rosa Norte, Ribanceira ?")
        time.sleep(15)

        botao_wavescheck = self.driver.find_element_by_class_name("sf-with-ul")
        time.sleep(5)
        botao_wavescheck.click()

        botao_estado = self.driver.find_element_by_link_text("Santa Catarina")
        time.sleep(3)
        botao_estado.click()
        time.sleep(3)

        # print(f'{title} R$: {price}')

        botao_escolher_praia = self.driver.find_element_by_link_text(self.pergunta)
        time.sleep(3)
        botao_escolher_praia.click()
        time.sleep(2)
        self.driver.execute_script('window.scrollBy(0,800)')
        time.sleep(10)
        self.driver.execute_script('window.scrollBy(0,1200)')

curso = CursoAutomacao()
curso.Iniciar()


import numpy
import torch
import random

class ToTensor(object):
  """Convert ndarrays in sample to Tensors."""
  def __call__(self, sample):
    clip_len = len(sample)
    trans_clip = []
    for i in range(clip_len):
        trans_clip.append(torch.from_numpy(sample[i]))
    return trans_clip

class SpacialCrop(object):
  def __init__(self, crop_size=112, crop_position=None):
    self.crop_size = crop_size
    if crop_position is None:
      self.randomize = True
    else:
      self.randomize = False
      self.crop_position = crop_position
      self.crop_positions = ['c', 'tl', 'tr', 'bl', 'br']

  def __call__(self, sample):
    clip_len = len(sample)
    t, h, w, c = sample[0].shape
    assert h > self.crop_size, "Frame height is smaller than target crop size"
    assert w > self.crop_size, "Frame width is smaller than target crop size"

    if self.randomize == True:
      x1 = random.randint(0, w - self.crop_size)
      y1 = random.randint(0, h - self.crop_size)
    elif self.crop_position == 'c':
      x1 = (w - self.crop_size) // 2
      y1 = (h - self.crop_size) // 2
    elif self.crop_position == 'tl':
      x1 = 0
      y1 = 0
    elif self.crop_position == 'tr':
      x1 = w - self.crop_size
      y1 = 0
    elif self.crop_position == 'bl':
      x1 = 0
      y1 = h - self.crop_size
    elif self.crop_position == 'br':
      x1 = w - self.crop_size
      y1 = h - self.crop_size

    x2 = x1 + self.crop_size
    y2 = y1 + self.crop_size

    trans_clip = []
    for i in range(clip_len):
        trans_clip.append(self._crop_clip(sample[i], y1, y2, x1, x2))
    return trans_clip

  def _crop_clip(clip, y1, y2, x1, x2):
      return clip[:,y1:y2,x1:x2,:]


from __future__ import unicode_literals
import ezdxf
# FILENAME = r'C:\Users\manfred\Desktop\Now\page_setup_R12.dxf'
FILENAME = 'page_setup_R12.dxf'

def draw_raster(dwg):
    marker = dwg.blocks.new(name='MARKER')
    attribs = {'color': 2}
    marker.add_line((-1, 0), (1, 0), dxfattribs=attribs)
    marker.add_line((0, -1), (0, 1), dxfattribs=attribs)
    marker.add_circle((0, 0), .4, dxfattribs=attribs)

    marker.add_attdef('XPOS', (0.5, -1.0), dxfattribs={'height': 0.25, 'color': 4})
    marker.add_attdef('YPOS', (0.5, -1.5), dxfattribs={'height': 0.25, 'color': 4})
    modelspace = dwg.modelspace()
    for x in range(10):
        for y in range(10):
            xcoord = x * 10
            ycoord = y * 10
            values = {
                'XPOS': "x = %d" % xcoord,
                'YPOS': "y = %d" % ycoord
            }
            modelspace.add_auto_blockref('MARKER', (xcoord, ycoord), values)

def setup_active_viewport(dwg):
    # delete '*Active' viewport configuration
    dwg.viewports.delete_config('*ACTIVE')
    # the available display area in AutoCAD has the virtual lower-left corner (0, 0) and the virtual upper-right corner
    # (1, 1)

    # first viewport, uses the left half of the screen
    viewport = dwg.viewports.new('*ACTIVE')
    viewport.dxf.lower_left = (0, 0)
    viewport.dxf.upper_right = (.5, 1)
    viewport.dxf.target_point = (0, 0, 0)  # target point defines the origin of the DCS, this is the default value
    viewport.dxf.center_point = (40, 30)  # move this location (in DCS) to the center of the viewport
    viewport.dxf.height = 15  # height of viewport in drawing units, this parameter works
    viewport.dxf.aspect_ratio = 1.0  # aspect ratio of viewport (x/y)

    # second viewport, uses the right half of the screen
    viewport = dwg.viewports.new('*ACTIVE')
    viewport.dxf.lower_left = (.5, 0)
    viewport.dxf.upper_right = (1, 1)
    viewport.dxf.target_point = (60, 20, 0)  # target point defines the origin of the DCS
    viewport.dxf.center_point = (0, 0)  # move this location (in DCS, model space = 60, 20) to the center of the viewport
    viewport.dxf.height = 15  # height of viewport in drawing units, this parameter works
    viewport.dxf.aspect_ratio = 2.0  # aspect ratio of viewport (x/y)

def layout_page_setup(dwg):
    # DXF R12 supports just one paper space layout
    layout = dwg.layout()
    layout.page_setup(size=(11, 8.5), margins=(1, 2, 1, 2), units='inch')
    (x1, y1), (x2, y2) = layout.get_paper_limits()
    center_x = (x1+x2)/2
    center_y = (y1+y2)/2
    layout.add_line((x1, center_y), (x2, center_y))  # horizontal center line
    layout.add_line((center_x, y1), (center_x, y2))  # vertical center line
    layout.add_circle((0, 0), radius=.1)  # plot origin

if __name__ == '__main__':
    dwg = ezdxf.new('R12')
    draw_raster(dwg)
    setup_active_viewport(dwg)
    layout_page_setup(dwg)
    dwg.saveas(FILENAME)
    print("drawing '%s' created.\n" % FILENAME)


import Downsampling.downsampling_data_distributions as ddd
from matplotlib import pyplot as plt
import matplotlib.mlab as mlab
import Recurrent_ANN.read_data as rd
import math
import numpy as np

def plot_downsample_norm_dists(data_range= None, fifty=False, decimate=False, resample=False, average=False, every_second=False):
    one_to_three_means, one_to_three_sigmas, labels = ddd.norm_dist_differences([0, 3], data_range=data_range, fifty=fifty, decimate=decimate, resample=resample, average=average, every_second=every_second)
    four_to_six_means, four_to_six_sigmas, labels  = ddd.norm_dist_differences([3, 6], data_range=data_range, fifty=fifty, decimate=decimate, resample=resample, average=average, every_second=every_second)

    x = np.arange(-1, 1, 0.01)

    for i in range(len(one_to_three_sigmas)):
        plt.plot(x, mlab.normpdf(x, one_to_three_means[i], one_to_three_sigmas[i]), label=labels[i]+"BACK?")
        plt.plot(x, mlab.normpdf(x, four_to_six_means[i], four_to_six_sigmas[i]), label=labels[i]+"THIGH?")

    plt.axvline(x=0, linestyle='--', color="Red")
    plt.legend()
    plt.show()

def plot_data_norm_dists(paths_to_data_folders):
    data_points_list = read_datapoints_to_list(paths_to_data_folders)
    print(data_points_list[0].shape)

    normal_mean_THIGH, normal_mean_BACK = get_sensor_mean(data_points_list[0])
    normal_var_THIGH, normal_var_BACK = get_sensor_variance(data_points_list[0])
    normal_sigma_THIGH = math.sqrt(normal_var_THIGH)
    normal_sigma_BACK = math.sqrt(normal_var_BACK)

    in_lab_mean_THIGH, in_lab_mean_BACK = get_sensor_mean(data_points_list[1])
    in_lab_var_THIGH, in_lab_var_BACK  = get_sensor_variance(data_points_list[1])
    in_lab_sigma_THIGH = math.sqrt(in_lab_var_THIGH)
    in_lab_sigma_BACK = math.sqrt(in_lab_var_BACK)

    x = np.arange(-2, 2, 0.01)

    plt.title("In Lab data vs Out of Lab data")
    plt.plot(x, mlab.normpdf(x, normal_mean_THIGH, normal_sigma_THIGH), label="out-of-lab_THIGH")
    plt.plot(x, mlab.normpdf(x, normal_mean_BACK, normal_sigma_BACK), label="out-of-lab_BACK")

    plt.plot(x, mlab.normpdf(x, in_lab_mean_THIGH, in_lab_sigma_THIGH), label="in-Lab_THIGH")
    plt.plot(x, mlab.normpdf(x, in_lab_mean_BACK, in_lab_sigma_BACK), label="in-Lab_BACK")
    plt.legend()
    plt.show()

def get_sensor_mean(datapoints):
    means = []
    for i in range(datapoints.shape[1]):
        means.append(np.mean(datapoints[:, i, :]))
    return means

def get_sensor_variance(datapoints):
    variances = []
    for i in range(datapoints.shape[1]):
        variances.append(np.var(datapoints[:, i, :]))

    return variances

def read_datapoints_to_list(list_of_folders):
    folder_datapoints = []

    for folder in list_of_folders:
        print(folder)
        datapoints, labels = rd.select_csv_files(folder)
        datapoints = rd.generate_examples_and_labels(datapoints, labels, 1, 20, print_stats=True, generate_labels=False)
        datapoints = np.reshape(datapoints, newshape=[datapoints.shape[0], datapoints.shape[2]])
        datapoints = np.reshape(datapoints,
                                newshape=[datapoints.shape[0], datapoints.shape[1] / (datapoints.shape[1] / 2),
                                          datapoints.shape[1] / 2])
        folder_datapoints.append(datapoints)

    return folder_datapoints

plot_data_norm_dists(["/home/guest/Documents/HAR-Pipeline/DATA/trene", "/home/guest/Documents/HAR-Pipeline/DATA/HUNT4-Training-Data-InLab-UpperBackThigh"])


import bottlenose
import logging
import random
import time

from bs4 import BeautifulSoup

from dateutil import parser

from price_monitor import (
    app_settings,
    utils,
)

from urllib.error import HTTPError

logger = logging.getLogger('price_monitor.product_advertising_api')

class ProductAdvertisingAPI(object):
    """
    A wrapper class for the necessary Amazon Product Advertising API calls.
    See the API reference here: http://docs.aws.amazon.com/AWSECommerceService/latest/DG/CHAP_ApiReference.html
    See bottlenose here: https://github.com/lionheart/bottlenose
    """

    def __init__(self):
        self.__amazon = bottlenose.Amazon(
            AWSAccessKeyId=app_settings.PRICE_MONITOR_AWS_ACCESS_KEY_ID,
            AWSSecretAccessKey=app_settings.PRICE_MONITOR_AWS_SECRET_ACCESS_KEY,
            AssociateTag=app_settings.PRICE_MONITOR_AMAZON_PRODUCT_API_ASSOC_TAG,
            Region=app_settings.PRICE_MONITOR_AMAZON_PRODUCT_API_REGION,
            Parser=lambda response_text: BeautifulSoup(response_text, 'lxml'),
            ErrorHandler=ProductAdvertisingAPI.handle_error,
        )

    @staticmethod
    def __get_item_attribute(item, attribute):
        """
        Returns the attribute value from a bs4 parsed item.
        :param item: bs4 item returned from PA API upon item lookup
        :param attribute: the attribute to search for
        :return: the value if found, else None
        :rtype: basestring
        """
        value = item.itemattributes.find_all(attribute, recursive=False)
        return value[0].string if len(value) == 1 else None

    @staticmethod
    def format_datetime(value):
        """
        Formats the given value if it is not None in the given format.
        :param value: the value to format
        :type value: basestring
        :return: formatted datetime
        :rtype: basestring
        """
        if value is not None:
            try:
                return parser.parse(value)
            except ValueError:
                logger.error('Unable to parse %s to a datetime', value)
                return None

    @staticmethod
    def handle_error(error):
        """
        Generic error handler for bottlenose requests.
        @see https://github.com/lionheart/bottlenose#error-handling
        :param error: error information
        :type error: dict
        :return: if to retry the request
        :rtype: bool
        :
        """
        ex = error['exception']

        logger.error('Error upon requesting Amazon URL %s (Code: %s, Cache-URL: %s): %r', error['api_url'], error['cache_url'], ex, ex.code)

        # try reconnect
        if isinstance(ex, HTTPError) and ex.code == 503:
            time.sleep(random.expovariate(0.1))
            return True

        return False

    def lookup_at_amazon(self, item_ids):
        """
        Outsourced this call to better mock in tests.
        :param item_ids: the item ids
        :type item_ids: list
        :return: parsed xml
        :rtype: bs4.BeautifulSoup
        """
        return self.__amazon.ItemLookup(ItemId=','.join(item_ids), ResponseGroup=app_settings.PRICE_MONITOR_PA_RESPONSE_GROUP)

    def item_lookup(self, item_ids):
        """
        Lookup of the item with the given id on Amazon. Returns it values or None if something went wrong.
        :param item_ids: the item ids
        :type item_ids: list
        :return: the values of the item
        :rtype: dict
        """
        logger.info('starting lookup for ASINs %s', ', '.join(item_ids))
        item_response = self.lookup_at_amazon(item_ids)

        if getattr(item_response, 'items') is None:
            logger.error(
                'Request for item lookup (ResponseGroup: %s, ASINs: %s) returned nothing',
                app_settings.PRICE_MONITOR_PA_RESPONSE_GROUP,
                ', '.join(item_ids),
            )
            return dict()

        if item_response.items.request.isvalid.string == 'True':

            # the dict that will contain a key for every ASIN and as value the parsed values
            product_values = dict()

            for item_node in item_response.find_all(['item']):

                # parse the values
                try:
                    isbn = self.__get_item_attribute(item_node, 'isbn')
                    eisbn = self.__get_item_attribute(item_node, 'eisbn')
                    if eisbn is None and isbn is not None:
                        if len(isbn) == 13:
                            eisbn = isbn
                            isbn = None

                    item_values = {
                        'asin': item_node.asin.string,
                        'title': item_node.itemattributes.title.string,
                        'artist': item_node.itemattributes.artist.string if item_node.itemattributes.artist is not None else None,
                        'isbn': isbn,
                        'eisbn': eisbn,
                        'binding': item_node.itemattributes.binding.string,
                        'date_publication': self.format_datetime(self.__get_item_attribute(item_node, 'publicationdate')),
                        'date_release': self.format_datetime(self.__get_item_attribute(item_node, 'releasedate')),
                        'large_image_url': item_node.largeimage.url.string if item_node.largeimage.url is not None else None,
                        'medium_image_url': item_node.mediumimage.url.string if item_node.mediumimage.url is not None else None,
                        'small_image_url': item_node.smallimage.url.string if item_node.smallimage.url is not None else None,
                        'offer_url': utils.get_offer_url(item_node.asin.string),
                        'audience_rating': self.__get_item_attribute(item_node, 'audiencerating'),
                    }

                    # check if there are offers, if so add price
                    if item_node.offers is not None and int(item_node.offers.totaloffers.string) > 0:
                        item_values['price'] = float(int(item_node.offers.offer.offerlisting.price.amount.string) / 100)
                        item_values['currency'] = item_node.offers.offer.offerlisting.price.currencycode.string

                    # insert into main dict
                    product_values[item_values['asin']] = item_values
                except AttributeError:
                    raise
                    logger.error('fetching item values from returned XML for ASIN %s failed', item_node.asin)

            # check if all ASINs are included, if not write error message to log
            failed_asins = []
            for asin in item_ids:
                if asin not in product_values.keys():
                    failed_asins.append(asin)

            if failed_asins:
                logger.error('Lookup for the following ASINs failed: %s', ', '.join(failed_asins))

            # if there is at least a single ASIN in the list, return the list, else None
            return dict() if len(product_values) == 0 else product_values

        else:
            logger.error(
                'Request for item lookup (ResponseGroup: %s, ASINs: %s) was not valid',
                app_settings.PRICE_MONITOR_PA_RESPONSE_GROUP,
                ', '.join(item_ids),
            )
            return dict()


# Chem Kit V2.0 - main.py
# Author: Finn Bear
# Date: December 6, 2016

#########
# Input #
#########

# Gassium [Ga] (A fictional gas)
gassium_particles_initial = 150 # How many gassium particles are in the simulation initially
gassium_rate = 0 # How many gassium particles to add or subtract each tick
gassium_radius = 5 # The radius of a gassium particle

# Brownium [Br] (A fictional particle for brownian motion)
brownium_particles_initial = 300 # How many brownium particles are in the simulation initially
brownium_rate = 0 # How many brownium particles to add or subtract each tick
brownium_radius = 1 # The radius of a brownium particle

############
# Settings #
############

# Physics
max_velocity = 2
gravity = 0

# Rendering
output_directory = "../out/"
length = 20 # Length of the video in seconds
width = 1000 # How many pixels wide is the video
height = 1000 # How many pixels tall is the video
ticks_per_frame = 1 # How many simulation updates per frame of video
frames_per_second = 10 # How many frames of video per second
background_color = "black" # The color of the background
overlay_title_text = "Particle Simulator" # The title text of the overlay
overlay_subtitle_text = "By Finn Bear" # The subtitle text of the overlay

###########
# Imports #
###########
import os
import math
import random
import datetime
import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw

#############
# Variables #
#############

# Physics
tick_counter = 0 # How many simulation updates have been made
particles = [] # Store the particles in the simulation

# Rendering
frame_counter = 0 # How many frames have been created

#############
# Constants #
#############

# Rendering
center_x = width / 2;
center_y = height / 2;
max_frames = length * frames_per_second # Number of frames to render in total
overlay_title_position = (5, 5) # Position of overlay title text
overlay_subtitle_position = (5, 15) # Position of overlay subtitle text
overlay_frames_position = (5, 25) # Position of frame counter

##########
# main() #
##########

def main():
	global ticks_per_frame
	global frams_per_second
	global tick_counter
	global frame_counter

	init()

	try:
		while True:
			t0 = datetime.datetime.now()
			tick()
			tick_counter += 1
			if frame_counter < max_frames:
				if tick_counter % ticks_per_frame == 0:
					draw()
					frame_counter += 1
			else:
				# Compile video
				os.system("yes y | ffmpeg -framerate " + str(frames_per_second) + " -i " + output_directory + "frame%05d.png -c:v libx264 -r 30 -pix_fmt yuv420p " + output_directory + "out.mp4")
				os.system("rm " + output_directory + "*.png")

				# Exit
				exit(0)
			t1 = datetime.datetime.now()

			print("Tick #" + str(tick_counter) + " took " + str(int((t1 - t0).total_seconds() * 1000)) + "ms")

	except KeyboardInterrupt:
		# Compile video
		os.system("yes y | ffmpeg -framerate " + str(frames_per_second) + " -i " + output_directory + "frame%05d.png -c:v libx264 -r 30 -pix_fmt yuv420p " + output_directory + "out.mp4")
		os.system("rm " + output_directory + "*.png")

		# Exit
		exit(0)

############
# Routines #
############

# Physics
def init():
	global center_x
	global center_y
	global particles
	global gassium_particles_initial
	global gassium_radius
	global brownium_particles_initial
	global brownium_radius

	# Clear the output directory to remove old frames
	for file in os.listdir(output_directory):
		path = os.path.join(output_directory, file)
		try:
		    if os.path.isfile(path) and "frame" in path:
		        os.unlink(path)
		except Exception as e:
		    print(e)

	# Create particles
	gassium_particles = []
	brownium_particles = []
	id = 0;
	for i in range(0, gassium_particles_initial):
		gassium_particles.append({'id': id, 'type': 'Ga', 'radius': gassium_radius, 'x': center_x, 'y': center_y, 'vx': 0, 'vy': 0})
		id += 1

	for i in range(0, brownium_particles_initial):
		brownium_particles.append({'id': id, 'type': 'Br', 'radius': brownium_radius, 'x': center_x, 'y': center_y, 'vx': 0, 'vy': 0})
		id += 1;

	# Add the new particles to the list of particles
	particles.extend(gassium_particles)
	particles.extend(brownium_particles)

def tick():
	global particles
	global center_x
	global center_y

	# A list to store the updated particles
	newParticles = []

	# Iterate throught the particles
	for particle1 in particles:
		newParticle = particle1
		for particle2 in particles:
			if particle1 != particle2:
				newParticle = physics(newParticle, particle2)
		newParticles.append(newParticle)

	# Put the new particles back into the list of particles
	particles = newParticles

def physics(particle1, particle2):
	distance = distanceParticles(particle1, particle2)
	angle = vecRadians(particle1["x"], particle1["y"], particle2["x"], particle2["y"])
	multiplier = 1 / (distance + 0.001);

	# Check if the particles intersect
	if distance < particle1["radius"] + particle2["radius"]:
		multiplier = 2 / (distance + 0.001);

	particle1["vx"] -= multiplier * math.cos(angle + (random.random() - 0.5))
	particle1["vy"] -= multiplier * math.sin(angle + (random.random() - 0.5))

	# <Hack>
	#cAngle = vecRadians(particle1["x"], particle1["y"], center_x, center_y)
	#particle1["vx"] += 1 * math.cos(cAngle + (random.random() - 0.5))
	#particle1["vy"] += 1 * math.sin(cAngle + (random.random() - 0.5))
	# </Hack>

	# Apply gravity
	particle1["y"] += gravity

	# Apply velocity
	particle1["x"] += particle1["vx"]
	particle1["y"] += particle1["vy"]

	# Constrain position
	particle1["x"] = clamp(particle1["x"], 0, width)
	particle1["y"] = clamp(particle1["y"], 0, height)

	# Constrain velocity
	particle1["vx"] = clamp(particle1["vx"], 0, max_velocity)
	particle1["vy"] = clamp(particle1["vy"], 0, max_velocity)

	return particle1

# Rendering
def draw():
	global particles
	global frame_counter
	global output_directory

	# Create a blank frame
	frame = Image.new( 'RGB', (width, height), background_color)

	# Load the pixels of the blank frame
	pixels = frame.load()

	# Render
	for particle in particles:
		pt = particle['type']
		px = int(particle['x'])
		py = int(particle['y'])
		pr = particle['radius']

		for x in range(int(px) - pr - 1, int(px) + pr + 1):
			for y in range(int(py) - pr - 1, int(py) + pr + 1):
				if inRect(x, y, 0, 0, frame.size[0] - 1, frame.size[1] - 1) and distance(x, y, particle['x'], particle['y']) <= particle['radius']:
					if (pt == "Ga"):
						pixels[x,y] = (0, 255, 255)
					elif (pt == "Br"):
						pixels[x,y] = (255, 255, 255)

	# Overlays
	overlay = ImageDraw.Draw(frame)
	overlay.text(overlay_title_position, overlay_title_text, (255,255,0))
	overlay.text(overlay_subtitle_position, overlay_subtitle_text, (255,255,0))
	overlay.text(overlay_frames_position, "Frame: #" + str(frame_counter), (255,255,0))

	# Save the frame
	frame.save(output_directory + "frame" + str(str(frame_counter).zfill(5)) + ".png")

#############
# Functions #
#############

# Math
def chance(probability):
	return random.random() < probability

def translate(value, leftMin, leftMax, rightMin, rightMax):
	leftSpan = leftMax - leftMin
	rightSpan = rightMax - rightMin
	valueScaled = float(value - leftMin) / float(leftSpan)

	return rightMin + (valueScaled * rightSpan)

def clamp(value, minimum, maximum):
	return max(minimum, min(maximum, value))

def distance(x1, y1, x2, y2):
	return math.hypot(x2 - x1, y2 - y1)

def distanceParticles(particle1, particle2):
	return math.hypot(particle2["x"] - particle1["x"], particle2["y"] - particle1["y"])

def inRect(x, y, bx1, by1, bx2, by2):
	return (bx1 <= x <= bx2 and by1 <= y <= by2) or (bx1 >= x >= bx2 and by1 >= y >= by2)

def vecRadians(x1, y1, x2, y2):
	angle = math.atan2(y1 - y2, x1 - x2);
	while (angle < 0):
		angle += math.pi;
	return angle

###########
# Program #
###########
main()


try:
	import sys
	if sys.__name__ is None:
		raise ImportError("OMG! we could not import os. We're like in the matrix! ABORT. ABORT.")
except Exception as err:
	raise ImportError(err)

try:
	if 'os' not in sys.modules:
		import os
	else:  # pragma: no branch
		os = sys.modules["""os"""]
except Exception:
	raise ImportError("OS Failed to import.")

try:
	if 'argparse' not in sys.modules:
		import argparse
	else:  # pragma: no branch
		argparse = sys.modules["""argparse"""]
except Exception:
	raise ImportError("argparse Failed to import.")

try:
	if str("pku") in __file__:
		__sys_path__ = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
		if __sys_path__ not in sys.path:
			sys.path.insert(0, __sys_path__)
except Exception as importErr:
	print(str(importErr))
	print(str(importErr.args))
	importErr = None
	del importErr
	raise ImportError("Failed to import " + str(__file__))

try:
	if str("""piaplib""") not in sys.modules:
		raise ImportError("Pocket PKU failed to import.")  # import piaplib as piaplib
	piaplib = sys.modules["""piaplib"""]
except Exception:
	raise ImportError("Pocket PKU failed to import.")

try:
	if str("piaplib.pku.upgrade") not in sys.modules:
		from piaplib.pku import upgrade as upgrade
	else:
		upgrade = sys.modules[str("piaplib.pku.upgrade")]
except Exception:
	try:
		import piaplib.pku.upgrade as upgrade
	except Exception as err:
		raise ImportError(err, "Error Importing piaplib.pku.upgrade")

try:
	if str("piaplib.pku.config") not in sys.modules:
		from piaplib.pku import config as config
	else:
		config = sys.modules[str("piaplib.pku.config")]
except Exception:
	try:
		import piaplib.pku.config as config
	except Exception as err:
		raise ImportError(err, "Error Importing piaplib.pku.config")

try:
	if str("piaplib.pku.utils") not in sys.modules:
		from piaplib.pku import utils as utils
	else:
		utils = sys.modules[str("piaplib.pku.utils")]
	if utils.__name__ is None:
		raise ImportError("Error Importing piaplib.pku.utils")
except Exception:
	try:
		import piaplib.pku.utils as utils
	except Exception as err:
		raise ImportError(err, "Error Importing piaplib.pku.utils")

try:
	if str("piaplib.pku.remediation") not in sys.modules:
		from piaplib.pku import remediation as remediation
	else:
		remediation = sys.modules[str("piaplib.pku.remediation")]
except Exception:
	try:
		import piaplib.pku.remediation as remediation
	except Exception as err:
		raise ImportError(err, "Error Importing remediation")

try:
	if str("piaplib.pku.interfaces") not in sys.modules:
		from piaplib.pku import interfaces as interfaces
	else:
		interfaces = sys.modules[str("piaplib.pku.interfaces")]
except Exception:
	try:
		import piaplib.pku.interfaces as interfaces
	except Exception as err:
		raise ImportError(err, "Error Importing interfaces")

try:
	if str("piaplib.book.logs.logs") not in sys.modules:
		from piaplib.book.logs import logs as logs
	else:
		logs = sys.modules[str("piaplib.book.logs.logs")]
except Exception:
	try:
		import piaplib.book.logs.logs as logs
	except Exception as err:
		raise ImportError(err, "Error Importing piaplib.book.logs.logs")

__prog__ = """piaplib.pku"""
"""The name of this PiAPLib tool is Pocket Knife Unit"""

__description__ = """Pocket Knife Units. PiAP Pocket Controller for main tools."""
"""The description is 'Pocket Knife Unit PiAP Pocket Controller for main tools.'"""

__epilog__ = """Handles PiAP pockets tools"""
"""...Handles PiAP pockets tools"""

PKU_UNITS = {
	u'config': config,
	u'backup': None,
	u'upgrade': upgrade,
	u'help': None,
	u'interfaces': interfaces
}
""" The Pocket Knife Unit actions.
	config -  configuration stuff
	backup -  (FUTURE/RESERVED)
	upgrade -  (see reactive-firewall/PiAP-python-tools#1)
	help -  (FUTURE/RESERVED)
	"""

def generateParser(calling_parser_group):
	"""Parses the CLI arguments."""
	if calling_parser_group is None:
		parser = argparse.ArgumentParser(
			prog=__prog__,
			description=__description__,
			epilog=__epilog__
		)
	else:
		parser = calling_parser_group.add_parser(
			str(__prog__).split(".")[-1], help='the pocket pku service option.'
		)
	parser.add_argument('-V', '--version', action='version', version=str(
		"%(prog)s {}"
	).format(str(piaplib.__version__)))
	subparser = parser.add_subparsers(
		title="Units", dest='pku_unit',
		help='The pocket pku options.', metavar="PKU_UNIT"
	)
	for sub_parser in sorted(PKU_UNITS.keys()):
		if PKU_UNITS[sub_parser] is not None:
			subparser = PKU_UNITS[sub_parser].generateParser(subparser)
	if calling_parser_group is None:
		calling_parser_group = parser
	return calling_parser_group

@remediation.error_handling
def parseArgs(arguments=None):
	"""Parses the CLI arguments."""
	parser = generateParser(None)
	return parser.parse_known_args(arguments)

def usePKUTool(tool, arguments=[None]):
	"""Handler for launching pocket-tools."""
	theExitCode = 1
	if tool is None:
		theExitCode = 0
	elif tool in PKU_UNITS.keys():
		try:
			logs.log(str("pku launching: {}").format(str(tool)), "DEBUG")
			theExitCode = 0
			PKU_UNITS[tool].main(arguments)
		except Exception:
			logs.log(str("An error occurred while handling the PKU tool. "), "WARNING")
			logs.log(str("PKU failure."), "Error")
			theExitCode = 3
	return theExitCode

@remediation.bug_handling
def main(argv=None):
	"""The main event"""
	(args, extra) = parseArgs(argv)
	pku_cmd = args.pku_unit
	return usePKUTool(pku_cmd, argv[1:])

if __name__ in u'__main__':
	exit_code = main(sys.argv[1:])
	exit(exit_code)


import os
from flask import render_template, Blueprint, current_app, request, send_from_directory, flash, redirect, url_for, abort
from flask_login import login_required, current_user

from ..decorators import confirm_required, permission_required
from ..extensions import db
from ..models import Photo, Comment, Tag
from ..utils import rename_image, resize_image, flash_errors
from ..forms.main import CommentForm, DescriptionForm, TagForm

main_bp = Blueprint('main', __name__)

@main_bp.route('/')
def index():
    return render_template('main/index.html')

@main_bp.route('/explore')
def explore():
    return render_template('main/explore.html')

@main_bp.route('/upload', methods=['GET', 'POST'])
@login_required
@confirm_required
@permission_required('UPLOAD')
def upload():
    if request.method == 'POST' and 'file' in request.files:
        f = request.files.get('file')
        filename = rename_image(f.filename)
        f.save(os.path.join(current_app.config['ALBUMY_UPLOAD_PATH'], filename))
        filename_s = resize_image(f, filename, current_app.config['ALBUMY_PHOTO_SIZE']['small'])
        filename_m = resize_image(f, filename, current_app.config['ALBUMY_PHOTO_SIZE']['medium'])
        photo = Photo(
            filename=filename,
            filename_s=filename_s,
            filename_m=filename_m,
            author=current_user._get_current_object()
        )
        db.session.add(photo)
        db.session.commit()
    return render_template('main/upload.html')

@main_bp.route('/avatars/<path:filename>')
def get_avatar(filename):
    return send_from_directory(current_app.config['AVATARS_SAVE_PATH'], filename)

@main_bp.route('/uploads/<path:filename>')
def get_image(filename):
    return send_from_directory(current_app.config['ALBUMY_UPLOAD_PATH'], filename)

@main_bp.route('/photo/<int:photo_id>')
def show_photo(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    page = request.args.get('page', 1, type=int)
    per_page = current_app.config['ALBUMY_COMMENT_PER_PAGE']
    pagination  = Comment.query.with_parent(photo).order_by(Comment.timestamp.desc()).paginate(page, per_page)
    comments = pagination.items

    comment_form = CommentForm()
    description_form = DescriptionForm()
    tag_form = TagForm()

    description_form.description.data = photo.description
    return render_template('main/photo.html', photo=photo, comment_form=comment_form, description_form=description_form,
                           tag_form=tag_form, pagination=pagination, comments=comments)

@main_bp.route('/photo/n/<int:photo_id>')
def photo_next(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    photo_n = Photo.query.with_parent(photo.author).filter(Photo.id < photo_id).order_by(Photo.id.desc()).first()

    if photo_n is None:
        flash('This is already the last one.', 'info')
        return redirect(url_for('.show_photo', photo_id=photo_id))
    return redirect(url_for('.show_photo', photo_id=photo_n.id))

@main_bp.route('/photo/p/<int:photo_id>')
def photo_previous(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    photo_p = Photo.query.with_parent(photo.author).filter(Photo.id < photo_id).order_by(Photo.id.desc()).frist()

    if photo_p is None:
        flash('This is already the first one.', 'info')
        return redirect(url_for('.show_photo', photo_id=photo_id))
    return redirect(url_for('.show_photo', photo_id=photo_p.id))

@main_bp.route('/report/comment/<int:comment_id>', methods=['POST'])
@login_required
@confirm_required
def report_comment(comment_id):
    comment = Comment.query.get_or_404(comment_id)
    comment.flag += 1
    db.session.commit()
    flash('Comment reported.', 'info')
    return redirect(url_for('.show_photo', photo_id=comment.photo_id))

@main_bp.route('/report/photo/<int:photo_id>', methods=['POST'])
@login_required
@confirm_required
def report_photo(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    photo.flag += 1
    db.session.commit()
    flash('Photo reported.', 'info')
    return redirect(url_for('.show_photo', photo_id=photo_id))

@main_bp.route('/photo/<int:photo_id>/description', methods=['POST'])
@login_required
def edit_description(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    if current_user != photo.author:
        abort(403)

    form = DescriptionForm()
    if form.validate_on_submit():
        photo.description = form.description.data
        db.session.commit()
        flash('Description updated.', 'success')

    flash_errors(form)
    return redirect(url_for('.show_photo', photo_id=photo_id))

@main_bp.route('/photo/<int:photo_id>/comment/new', methods=['POST'])
@login_required
@permission_required('COMMENT')
def new_comment(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    page = request.args.get('page', 1, type=int)
    form = CommentForm()
    if form.validate_on_submit():
        body = form.body.data
        author = current_user._get_current_object()
        comment = Comment(body=body, author=author, photo=photo)

        replied_id = request.args.get('reply')
        if replied_id:
            comment.replied = Comment.query.get_or_404(replied_id)
        db.session.add(comment)
        db.session.commit()
        flash('Comment published.', 'success')

    flash_errors(form)
    return redirect(url_for('.show_photo', photo_id=photo_id, page=page))

@main_bp.route('/photo/<int:photo_id>/tag/new', methods=['POST'])
@login_required
def new_tag(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    if current_user != photo.author:
        abort(403)

    form = TagForm()
    if form.validate_on_submit():
        for name in form.tag.data.split():
            tag = Tag.query.filter_by(name=name).first()
            if tag is None:
                tag = Tag(name=tag)
                db.session.add(tag)
            if tag not in photo.tags:
                photo.tags.append(tag)
                db.session.commit()
        flash('Tag added', 'success')
    flash_errors(form)
    return redirect(url_for('.show_photo', photo_id=photo_id))

@main_bp.route('/set-comment/<int:photo_id>', methods=['POST'])
@login_required
def set_comment(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    if current_user != photo.author:
        abort(403)

    if photo.can_comment:
        photo.can_comment = False
        flash('Comment disabled.', 'info')
    else:
        photo.can_comment = True
        flash('Comment enabled.', 'info')
    db.session.commit()
    return redirect(url_for('.show_photo', photo_id=photo_id))

@main_bp.route('/reply/comment/<int:comment_id>')
@login_required
@permission_required('COMMENT')
def reply_comment(comment_id):
    comment = Comment.query.get_or_404(comment_id)
    return redirect(url_for('.show_photo', photo_id=comment.photo_id, reply=comment_id, author=comment.author.name)
                    + '#comment-form')

@main_bp.route('/delete/photo/<int:photo_id>', methods=['POST'])
@login_required
def delete_photo(photo_id):
    photo = Photo.query.get_or_404(photo_id)
    if current_user != photo.author:
        abort(403)

    db.session.delete(photo)
    db.session.commit()
    flash('Photo deleted.', 'info')

    photo_n = Photo.query.with_parent(photo.author).filter(Photo.id > photo.id).first()
    if photo_n is None:
        photo_p = Photo.query.with_parent(photo.author).filter(Photo.id < photo.id).first()
        if photo_p is None:
            return redirect(url_for('user.index', username=photo.author.username))
        return redirect(url_for('.show_photo', photo_id=photo_p.id))
    return redirect(url_for('.show_photo', photo_id=photo_n.id))

@main_bp.route('/delete/comment/<int:comment_id>', methods=['POST'])
@login_required
def delete_comment(comment_id):
    comment = Comment.query.get_or_404(comment_id)
    if current_user != comment.author:
        abort(403)

    db.session.delete(comment)
    db.session.commit()
    flash('Comment deleted.', 'info')
    return redirect(url_for('.show_photo', photo_id=comment.photo_id))  # comment is a python object

@main_bp.route('/tag/<int:tag_id>', defaults={'order': 'by_time'})
@main_bp.route('/tag/<int:tag_id>/<order>')
def show_tag(tag_id, order):
    tag = Tag.query.get_or_404(tag_id)
    page = request.args.get('page', 1, type=int)
    per_page = current_app.config['ALBUMY_PHOTO_PER_PAGE']
    order_rule = 'time'
    pagination = Photo.query.with_parent(tag).order_by(Photo.timestamp.desc()).paginate(page, per_page)
    photos = pagination.items

    if order == 'by_collects':
        photos.sort(key=lambda x: len(x.collectors), reverse=True)
        order_rule = 'collects'
    return render_template('main/tag.html', tag=tag, pagination=pagination, photos=photos, order_rule=order_rule)

@main_bp.route('/delete/tag/<int:photo_id>/<int:tag_id>', methods=['POST'])
@login_required
def delete_tag(photo_id, tag_id):
    tag = Tag.query.get_or_404(tag_id)
    photo = Photo.query.get_or_404(photo_id)
    if current_user != photo.author:
        abort(403)

    photo.tags.remove(tag)
    db.session.commit()

    if not tag.photos:
        db.session.delete(tag)
        db.session.commit()
    flash('Tag deleted.', 'info')
    return redirect(url_for('.show_photo', photo_id=photo_id))


#-*-coding:utf-8-*-
# date:2020-03-28
# Author: X.L.Eric
# function: image B G R show

import cv2 # 加载OpenCV库
import numpy as np
if __name__ == "__main__":
    img_h = 320
    img_w = 480

    img = np.zeros([img_h,img_w,3], dtype = np.float)
    img[:,:,0].fill(1.0)
    cv2.namedWindow('B', 1)
    cv2.imshow('B', img)

    img = np.zeros([img_h,img_w,3], dtype = np.float)
    img[:,:,1].fill(1.0)
    cv2.namedWindow('G', 1)
    cv2.imshow('G', img)

    img = np.zeros([img_h,img_w,3], dtype = np.float)
    img[:,:,2].fill(1.0)
    cv2.namedWindow('R', 1)
    cv2.imshow('R', img)

    cv2.waitKey(0)

    cv2.destroyAllWindows() # 销毁所有显示窗口


from future.utils import iteritems

import difflib

from recipe_engine.post_process import DropExpectation

DEPS = ['cipd', 'json', 'path', 'properties', 'step', 'swarming', 'buildbucket']

EXECUTION_TIMEOUT_SECS = 3600

def RunSteps(api):
  api.swarming.ensure_client()

  # Create a new Swarming task request.
  request = (api.swarming.task_request().
      with_name('recipes-go').
      with_priority(100).
      with_service_account('account@example.iam.gserviceaccount.com').
      with_realm('chromium:ci').
      with_resultdb())

  ensure_file = api.cipd.EnsureFile()
  ensure_file.add_package('infra/git/${platform}', 'version:2.14.1.chromium10')

  # Configure the first slice.
  request = (request.with_slice(0, request[0].
        with_command(['recipes', 'run', '"example"']).
        with_relative_cwd('some/subdir').
        with_dimensions(pool='example.pool', os='Debian').
        with_cipd_ensure_file(ensure_file).
        with_env_vars(SOME_VARNAME='stuff', GOPATH='$HOME/go').
        with_env_prefixes(PATH=["path/to/bin/dir", "path/to/other/bin/dir"]).
        with_expiration_secs(3600).
        with_wait_for_capacity(True).
        with_io_timeout_secs(600).
        with_execution_timeout_secs(EXECUTION_TIMEOUT_SECS).
        with_idempotent(True).
        with_containment_type('AUTO').
        with_named_caches({'cache_name': 'cache/path'}),
      )
  )

  request = request.with_slice(
      0, request[0].with_cas_input_root(
          '24b2420bc49d8b8fdc1d011a163708927532b37dc9f91d7d8d6877e3a86559ca/73')
  )

  # Check a request with no tags and no user can make it to JSON and back.
  # These requests should be considered valid.
  req_no_tag_no_user_jsonish = request.to_jsonish()
  api.swarming.task_request_from_jsonish(req_no_tag_no_user_jsonish)

  # Add user and tags for coverage of those.
  request = request.with_user('defaultuser').with_tags(
      {'key': ['value1', 'value2']})

  # Append a slice that is a variation of the last one as a starting point.
  request = request.add_slice(request[-1].with_grace_period_secs(
      20).with_secret_bytes(b'shh, don\'t tell').with_outputs(
          ['my/output/file']))

  # There should be three task slices at this point.
  assert len(request) == 2

  # Assert from_josnish(x.to_jonish()) == x
  jsonish = request.to_jsonish()
  from_jsonish = api.swarming.task_request_from_jsonish(jsonish)
  back_to_jsonish = from_jsonish.to_jsonish()
  diff = list(difflib.unified_diff(
      api.json.dumps(jsonish, indent=2).splitlines(),
      api.json.dumps(back_to_jsonish, indent=2).splitlines()))
  assert not diff, ''.join(diff)

  # Dimensions, and environment variables and prefixes can be unset.
  slice = request[-1]
  assert slice.dimensions == {'pool': 'example.pool', 'os': 'Debian'}
  assert slice.env_vars == {'SOME_VARNAME': 'stuff', 'GOPATH': '$HOME/go'}
  assert (slice.env_prefixes ==
          {'PATH' : ["path/to/bin/dir", "path/to/other/bin/dir"]})

  slice = (slice.
    with_dimensions(os=None).
    with_env_vars(GOPATH=None).
    with_env_prefixes(PATH=None)
  )

  assert slice.dimensions == {'pool': 'example.pool'}
  assert slice.env_vars == {'SOME_VARNAME': 'stuff'}
  assert slice.env_prefixes == {}

  # Setting environment prefixes is additive.
  slice = slice.with_env_prefixes(PATH=['a']).with_env_prefixes(PATH=['b'])
  assert slice.env_prefixes == {'PATH': ['a', 'b']}

  # Trigger the task request.
  metadata = api.swarming.trigger('trigger 1 task', requests=[request])

  # From the request metadata, one can access the task's name, ID, and
  # associated UI link.
  assert len(metadata) == 1
  metadata[0].name
  metadata[0].id
  metadata[0].task_ui_link
  metadata[0].invocation

  # Retrieve TaskRequest.
  api.swarming.test_api.set_task_for_show_request(request)
  retrieved_task = api.swarming.show_request('show-request', metadata[0])
  diff = list(
      difflib.unified_diff(
          api.json.dumps(jsonish, indent=2).splitlines(),
          api.json.dumps(retrieved_task.to_jsonish(), indent=2).splitlines()))
  assert not diff, '\n'.join(diff)

  # Or retrieve by ID.
  _ = api.swarming.show_request('show-request via task id', metadata[0].id)

  # Collect the result of the task by metadata.
  output_dir = api.path.mkdtemp('swarming')
  results = api.swarming.collect('collect', metadata, output_dir=output_dir,
                                 timeout='5m', verbose=True)
  # Or collect by ID.
  results += api.swarming.collect('collect other pending task', ['0'],
                                  eager=True)

  results[0].name
  results[0].id
  results[0].state
  results[0].success
  results[0].output
  results[0].outputs
  results[0].output_dir
  results[0].duration_secs
  results[0].bot_id
  results[0].raw

  # Raise an error if something went wrong.
  if not results[0].success:
    threw = False
    try:
      results[0].analyze()
    except api.step.StepFailure as e:
      threw = True
      s = str(e)
      if results[0].state == api.swarming.TaskState.BOT_DIED:
        assert s == 'The bot running this task died', repr(s)
      elif results[0].state == api.swarming.TaskState.CLIENT_ERROR:
        assert s == 'The task encountered an error caused by the client'
      elif results[0].state == api.swarming.TaskState.CANCELED:
        assert s == 'The task was canceled before it could run', repr(s)
      elif results[0].state == api.swarming.TaskState.COMPLETED:
        out = '(…)' + 'A' * 996
        assert s in ('Swarming task failed:\n' + out,
                     'Swarming task failed:\nNone'), repr(s)
      elif results[0].state == api.swarming.TaskState.EXPIRED:
        assert s == 'Timed out waiting for a bot to run on', repr(s)
      elif results[0].state == api.swarming.TaskState.KILLED:
        assert s == 'The task was killed mid-execution', repr(s)
      elif results[0].state == api.swarming.TaskState.NO_RESOURCE:
        assert s == 'Found no bots to run this task', repr(s)
      elif results[0].state == api.swarming.TaskState.TIMED_OUT:
        out = '(…)' + '\nDying' * 166
        expected = [
            'Timed out after 3599 seconds.\nOutput:\n' + out,
            'Execution timeout: exceeded 3600 seconds.\nOutput:\nhello world!',
            'I/O timeout: exceeded 600 seconds.\nOutput:\nhello world!',
        ]
        assert s in expected, repr(s)
      elif results[0].state is None:
        assert (
            s == 'Failed to collect:\nBot could not be contacted'), repr(s)
      else:  # pragma: no cover
        raise AssertionError('unexpected state: %r\n%r' % (results[0].state, s))
    except Exception as e:  # pragma: no cover
      raise AssertionError('wrong exception raised: %r' % e)
    if not threw:  # pragma: no cover
      raise AssertionError('exception was not raised')
  else:
    results[0].analyze()

  with api.swarming.on_path():
    api.step('some step with swarming on path', [])

  # verify swarming server correctly reverts
  api.swarming.trigger(
      'trigger on original server', requests=[request], verbose=True)
  api.swarming.collect('collect on original server', ['0'])

def GenTests(api):
  # For coverage
  api.swarming.example_task_request_jsonish()

  yield api.test('basic')

  yield api.test(
      'resultdb',
      api.override_step_data(
          'trigger 1 task', api.swarming.trigger(['recipes-go'],
                                                 resultdb=True)))

  yield api.test(
      'no-resultdb',
      api.override_step_data(
          'trigger 1 task', api.swarming.trigger(['recipes-go'],
                                                 resultdb=False)))

  states = {state.name : api.swarming.TaskState[state.name]
            for state in api.swarming.TaskState if state not in [
              api.swarming.TaskState.INVALID,
              api.swarming.TaskState.PENDING,
              api.swarming.TaskState.RUNNING,
              api.swarming.TaskState.TIMED_OUT,
            ]}
  states['unreachable'] = None

  for name, value in iteritems(states):

    result = api.swarming.task_result(
        id='0', name='recipes-go', state=value, outputs=('out.tar'),
    )
    yield api.test(
        'collect_with_state_%s' % name,
        api.override_step_data('collect', api.swarming.collect([result])),
    )

  timeout_result = api.swarming.task_result(
      id='100', name='recipes-go', duration=EXECUTION_TIMEOUT_SECS - 1,
      state=api.swarming.TaskState.TIMED_OUT,
      output='Dying\n' * 500,
  )
  yield api.test(
      'collect_with_state_TIMED_OUT',
      api.override_step_data('collect', api.swarming.collect([timeout_result])),
  )

  io_timeout_result = api.swarming.task_result(
      id='0', name='recipes-go', duration=EXECUTION_TIMEOUT_SECS - 1,
      state=api.swarming.TaskState.TIMED_OUT,
  )
  yield api.test(
      'collect_with_state_TIMED_OUT_by_io',
      api.override_step_data(
          'collect', api.swarming.collect([io_timeout_result])),
  )

  execution_timeout_result = api.swarming.task_result(
      id='0',
      name='recipes-go',
      duration=EXECUTION_TIMEOUT_SECS + 1,
      state=api.swarming.TaskState.TIMED_OUT,
  )
  yield api.test(
      'collect_with_state_TIMED_OUT_by_execution',
      api.override_step_data(
          'collect', api.swarming.collect([execution_timeout_result])),
  )

  failed_result = api.swarming.task_result(
      id='0', name='recipes-go', state=api.swarming.TaskState.COMPLETED,
      failure=True, outputs=('out.tar'),
      output='AAA'*500,
  )
  yield api.test(
      'collect_with_state_COMPLETED_and_failed',
      api.override_step_data('collect', api.swarming.collect([failed_result])),
  )

  no_output_result = api.swarming.task_result(
      id='0',
      name='recipes-go',
      state=api.swarming.TaskState.COMPLETED,
      failure=True,
      output=None,
  )
  yield api.test(
      'collect_with_no_output',
      api.override_step_data(
          'collect', api.swarming.collect([no_output_result])),
      api.post_process(DropExpectation),
  )

  yield api.test(
      'check_triggered_request',
      api.post_check(
          api.swarming.check_triggered_request,
          'trigger 1 task',
          lambda check, request: check(request[0].dimensions == {
            'os': 'Debian',
            'pool': 'example.pool'
          })),
      api.post_check(
          api.swarming.check_triggered_request,
          'trigger 1 task',
          lambda check, request: check(request[0].env_vars[
            'SOME_VARNAME'] == 'stuff'), lambda check, request: check(request[
              0].wait_for_capacity)),
      api.post_process(DropExpectation),
  )

  yield api.test(
      'show_request_invalid_key',
      api.override_step_data(
          'show-request',
          stdout=api.json.invalid(
              'swarming: failed to get task request. task ID = 0: failed to '
              'call TaskRequest: googleapi: Error 400: 0 is an invalid key.'),
          retcode=1),
      status='INFRA_FAILURE',
  )

  yield api.test('test_new_swarming_experiment',
                 api.buildbucket.ci_build(experiments=['swarming.prpc.cli']))


import bisect
import math
from math import atan2

import pygame

from sprites import X, Y
import random

MAX_TERRAIN = 200
MIN_TERRAIN = 0
LINE_WIDTH = 2

class OutOfMapException(Exception):
    pass

class Terrain:
    def __init__(self, dimension, color):

        # Game details
        self._dimension = dimension

        # Terrain Generation
        self._terrain = []
        self._color = color
        self._terrain_polygon = []

        # Generate terrain
        self.generate_terrain()

    def height_at_point(self, pt):
        return self._terrain[pt]

    def grade_at_point(self, pt, width=4):
        # TODO: Do smart things with small tall peaks, use some physics maybe??

        # dist either side
        dist = int(width/2.0)

        # Get the x value for point left and right of middle point
        less_x = pt - dist if pt - dist >= 0 else 0
        high_x = pt + dist if pt + dist < self._dimension[X] else self._dimension[X] - 1

        # Get the y value for point left and right of middle point
        h_less = self._terrain[less_x]
        h_high = self._terrain[high_x]

        # Calculate and return slope - What a bitch
        slope = - (360 + ((atan2((h_less - h_high), (less_x - high_x)) * 180.0 / math.pi) - 180))
        return slope

    def generate_terrain(self):
        # previous_height = random.randint(self._dimension[Y] - MAX_TERRAIN, self._dimension[Y] - 1)
        # for x in range(0, self._dimension[X]):
        #     self._terrain.append(self._random_height(previous_height))  # Generate and save current height
        #     previous_height = self._terrain[x]  # Save off for previous in next iteration

        points = self._midpoint_displacement(start=[0, self._dimension[Y] - MAX_TERRAIN],
                                             end=[self._dimension[X]+1, self._dimension[Y] - MAX_TERRAIN],
                                             roughness=0.9,
                                             vertical_displacement=self._dimension[Y] - MAX_TERRAIN,
                                             num_of_iterations=13)

        for point in points:
            self._terrain.append(point[1] if point[1] < self._dimension[Y] else self._dimension[Y] - 1)

        # Generate the polygon for this terrain list
        self._terrain_polygon.append([0, self._dimension[Y]])  # Bottom left corner of the screen
        for x, y in enumerate(self._terrain):
            self._terrain_polygon.append([x, y])  # points along the terrain
        self._terrain_polygon.append([self._dimension[X], self._dimension[Y]])  # Bottom Right
        self._terrain_polygon.append([0, self._dimension[Y]])  # Bottom left corner of the screen again to close polygon

    def intersects_terrain(self, location, buffer_x=0, buffer_y=0):
        # TODO Add a buffer to calculation to make it easier
        if location[X] > self._dimension[X]:
            # thing is out of the map
            # print(location)
            raise OutOfMapException("Projectile out of map to the right.")
        elif location[X] < 0:
            # thing is out side of the map
            # print(location)
            # print(self._dimension)
            raise OutOfMapException("Projectile out of map to the left.")

        # print(location)

        # We made it here, the thing is still in the map
        if self._terrain[location[X]] <= location[Y]:
            # print("INTERSECT WITH GROUND: " + str(self._terrain[location[X]]) + " " + str(location[Y]))
            # Terrain is over or equal to height of projectile at this X location, we intersect
            return True
        else:
            # Otherwise we do not intersect
            return False

    def draw(self, surface):
        pygame.draw.polygon(
            surface,
            self._color,
            self._terrain_polygon,
            LINE_WIDTH
        )

    # def _random_height(self, previous_height):
    #     greater = random.randint(0, 100) > 50  # Generate a yes no
    #
    #     if greater:
    #         return random.randint(self._dimension[Y] - MAX_TERRAIN, previous_height)
    #     else:
    #         return random.randint(previous_height, self._dimension[Y] - 1)

    # Iterative midpoint vertical displacement
    def _midpoint_displacement(self, start, end, roughness, vertical_displacement=None,
                               num_of_iterations=16):
        """
        Given a straight line segment specified by a starting point and an endpoint
        in the form of [starting_point_x, starting_point_y] and [endpoint_x, endpoint_y],
        a roughness value > 0, an initial vertical displacement and a number of
        iterations > 0 applies the  midpoint algorithm to the specified segment and
        returns the obtained list of points in the form
        points = [[x_0, y_0],[x_1, y_1],...,[x_n, y_n]]

        From:
        https://bitesofcode.wordpress.com/2016/12/23/landscape-generation-using-midpoint-displacement/

        """
        # Final number of points = (2^iterations)+1
        if vertical_displacement is None:
            # if no initial displacement is specified set displacement to:
            #  (y_start+y_end)/2
            vertical_displacement = (start[1] + end[1]) / 2
        # Data structure that stores the points is a list of lists where
        # each sublist represents a point and holds its x and y coordinates:
        # points=[[x_0, y_0],[x_1, y_1],...,[x_n, y_n]]
        #              |          |              |
        #           point 0    point 1        point n
        # The points list is always kept sorted from smallest to biggest x-value
        points = [start, end]
        iteration = 1
        while iteration <= num_of_iterations:
            # Since the list of points will be dynamically updated with the new computed
            # points after each midpoint displacement it is necessary to create a copy
            # of the state at the beginning of the iteration so we can iterate over
            # the original sequence.
            # Tuple type is used for security reasons since they are immutable in Python.
            points_tup = tuple(points)
            for i in range(len(points_tup) - 1):
                # Calculate x and y midpoint coordinates:
                # [(x_i+x_(i+1))/2, (y_i+y_(i+1))/2]
                midpoint = list(map(lambda x: (points_tup[i][x] + points_tup[i + 1][x]) / 2,
                                    [0, 1]))
                # Displace midpoint y-coordinate
                midpoint[1] += random.choice([-vertical_displacement,
                                              vertical_displacement])
                # Insert the displaced midpoint in the current list of points
                bisect.insort(points, midpoint)
                # bisect allows to insert an element in a list so that its order
                # is preserved.
                # By default the maintained order is from smallest to biggest list first
                # element which is what we want.
            # Reduce displacement range
            vertical_displacement *= 2 ** (-roughness)
            # update number of iterations
            iteration += 1

        return points


# --------------------------------------------------------------------------
# ------------  Metody Systemowe i Decyzyjne w Informatyce  ----------------
# --------------------------------------------------------------------------
#  Zadanie 3: Regresja logistyczna
#  autorzy: A. Gonczarek, J. Kaczmar, S. Zareba
#  2017
# --------------------------------------------------------------------------
# --------------------------------------------------------------------------
# ----------------- TEN PLIK MA POZOSTAC NIEZMODYFIKOWANY ------------------
# --------------------------------------------------------------------------

import numpy as np
from scipy.ndimage.filters import convolve

def hog(image):
    nwin_x = 5
    nwin_y = 5
    B = 7
    (L, C) = np.shape(image)
    H = np.zeros(shape=(nwin_x * nwin_y * B, 1))
    m = np.sqrt(L / 2.0)
    if C is 1:
        raise NotImplementedError
    step_x = np.floor(C / (nwin_x + 1))
    step_y = np.floor(L / (nwin_y + 1))
    cont = 0
    hx = np.array([[1, 0, -1]])
    hy = np.array([[-1], [0], [1]])
    grad_xr = convolve(image, hx, mode='constant', cval=0.0)
    grad_yu = convolve(image, hy, mode='constant', cval=0.0)
    angles = np.arctan2(grad_yu, grad_xr)
    magnit = np.sqrt((grad_yu ** 2 + grad_xr ** 2))
    for n in range(nwin_y):
        for m in range(nwin_x):
            cont += 1
            angles2 = angles[int(n * step_y):int((n + 2) * step_y), int(m * step_x):int((m + 2) * step_x)]
            magnit2 = magnit[int(n * step_y):int((n + 2) * step_y), int(m * step_x):int((m + 2) * step_x)]
            v_angles = angles2.ravel()
            v_magnit = magnit2.ravel()
            K = np.shape(v_angles)[0]
            bin = 0
            H2 = np.zeros(shape=(B, 1))
            for ang_lim in np.arange(start=-np.pi + 2 * np.pi / B, stop=np.pi + 2 * np.pi / B, step=2 * np.pi / B):
                for k in range(K):
                    if v_angles[k] < ang_lim:
                        v_angles[k] = 100
                        H2[bin] += v_magnit[k]
                bin += 1

            H2 = H2 / (np.linalg.norm(H2) + 0.01)
            H[(cont - 1) * B:cont * B] = H2
    return H


import os
import json
import jieba.analyse
import threading
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse, QueryDict
from .models import Post, Comment, Photo, Favor, TextKey
from user.models import User
from django.views.decorators.csrf import csrf_exempt, csrf_protect

gen_response = {
    'success': {
        "code": 200,
        "data": {
            "msg": "success"
        }
    },
    'method_err': {
        "code": 600,
        "data": {
            "msg": "wrong method"
        }
    },
    'param_err': {
        "code": 700,
        "data": {
            "msg": "wrong parameter"
        }
    },
    'post_not_exist': {
        "code": 300,
        "data": {
            "msg": "post not exists"
        }
    },
    'user_not_exist': {
        "code": 300,
        "data": {
            "msg": "user not exists"
        }
    },
    'user_error': {
        "code": 400,
        "data": {
            "msg": "not authorized"
        }
    }
}

def demo(request):
    return HttpResponse('Post Response')

def posts(request):
#动态列表
    print('server receive {} {}'.format(request.method, request.get_full_path()))

    if request.method == 'GET':
    #请求动态列表，GET /posts/?limit&start

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            num = int(request.GET.get('limit', default=10)) #请求动态数量
            start = int(request.GET.get('start', default=0)) #起始动态id
        except:
            return JsonResponse(gen_response['param_err'])

        post_list = Post.objects.order_by('-post_id')[start:start+num] #获取最新动态

        posts = []
        for item in post_list:

            # 加载图片
            multimedia = []
            if item.is_video == False:
                for photo in Photo.objects.filter(post=item):
                    multimedia.append(photo.photo)

            # 判断是否给自己点赞
            user = User.objects.get(id=request.user.id)
            if Favor.objects.filter(post=item).filter(user=user):
                self_favor = 1
            else:
                self_favor = 0

            # 一条摘要动态的数据结构
            publisher_info = {
                'userID': item.publisher.id,
                'username': item.publisher.username,
                'avatar': item.publisher.avatar
            }
            favorcnt = Favor.objects.filter(post=item).count()
            post_info =  {
                'postID': item.post_id,
                'publisher': publisher_info,
                'time': int(item.time.timestamp()*1000),
                'text': item.text,
                'multimediaContent': multimedia,
                'favor': {
                    'self': self_favor,
                    'favorCnt': favorcnt
                }
            }
            posts.append(post_info)

        response = {
            "code": 200,
            "data": {
                "downloadCount": len(posts),
                "posts": posts
            }
        }
        return JsonResponse(response)
    else:
        return JsonResponse(gen_response['method_err'])

@csrf_exempt
def post(request):
#动态获取、添加、删除
    if request.method == 'GET':
    #请求动态，GET /post/?postID&comments
        print('server receive GET', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.GET.get('postID')) #动态id
            comments_num = int(request.GET.get('comments', default=10)) #评论数量
        except:
            return JsonResponse(gen_response['param_err'])

        # 获取动态数据
        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        # 获取评论区列表
        total_cnt = Comment.objects.filter(post=post).count()
        comments = Comment.objects.filter(post=post)[:comments_num]
        comment_list = []
        for comment in comments:

            user = {
                'userID': comment.user.id,
                'username': comment.user.username,
                'avatar': comment.user.avatar
            }
            comment_list.append({
                'commentID': comment.id,
                'user': user,
                'time': int(comment.time.timestamp()*1000),
                'text': comment.text
            })
        if len(comment_list):
            _start = comment_list[0]['commentID']
        else:
            _start = -1
        comment_list_info = {
            'postID': post.post_id,
            'totalCount': total_cnt,
            'downloadCount': len(comment_list),
            'start': _start,
            'comments': comment_list
        }

        publisher_info = {
            'userID': post.publisher.id,
            'username': post.publisher.username,
            'avatar': post.publisher.avatar
        }

        # 加载多媒体内容
        multimedia = []
        if post.is_video == False:
            photos = Photo.objects.filter(post=post)
            for photo_info in photos:
                multimedia.append(photo_info.photo)
        elif post.is_video == True:
            multimedia.append(post.video)

        # 判断是否给自己点赞
        user = User.objects.get(id=request.user.id)
        if Favor.objects.filter(post=post).filter(user=user):
            self_favor = 1
        else:
            self_favor = 0

        favorcnt = Favor.objects.filter(post=post).count()
        post_info =  {
            'postID': post.post_id,
            'publisher': publisher_info,
            'time': int(post.time.timestamp()*1000),
            'text': post.text,
            'isVideo': post.is_video,
            'multimediaContent': multimedia,
            'commentList': comment_list_info,
            'favor': {
                'self': self_favor,
                'favorCnt': favorcnt
            }
        }
        response = {
            "code": 200,
            "data": {
                "downloadCount": 1,
                "post": post_info
            }
        }
        return JsonResponse(response)

    if request.method == 'POST':
        # 发布动态, POST /post/

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        text = request.POST.get('text')
        isVideo = request.POST.get('isVideo')
        #print('isVideo', repr(isVideo))
        multimediaContent = request.POST.getlist('multimediaContent')

        if isVideo == '1':
            isVideo = True
        elif isVideo == '0':
            isVideo = False
        else:
            return JsonResponse(gen_response['param_err'])

        # 分析参数
        if text is None and len(multimediaContent) == 0:
            return JsonResponse(gen_response['param_err'])
        if isVideo and len(multimediaContent) == 0:
            return JsonResponse(gen_response['param_err'])

        publisher = User.objects.get(id=request.user.id)

        # 创建数据库动态数据
        post = Post()
        post.publisher = publisher
        post.text = text if not text is None else ""
        post.is_video = isVideo
        if post.is_video:
            post.video = multimediaContent[0]
        post.save()

        # 存储图片
        if isVideo == False:
            for photo_path in multimediaContent:
                photo = Photo()
                photo.photo = photo_path
                photo.post = post
                photo.save()

        # 创建关键词数据
        if not text is None:
            keywords = jieba.analyse.extract_tags(text, topK=10)
            for key in keywords:
                TextKey(key=key, post=post).save()

        response = {
            "code": 200,
            "data": {
                "postID": post.post_id,
                "time": int(post.time.timestamp()*1000)
            }
        }
        return JsonResponse(response)

    if request.method == 'DELETE':
    # 删除动态, DELETE /post/?postID=123
        print('server receive DELETE', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        DELETE = json.loads(request.body)
        try:
            post_id = int(DELETE.get('postID'))
        except:
            return JsonResponse(gen_response['param_err'])

        # 不存在id
        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            post.delete()
        except:
            response = {
                "code": 300,
                "data": {
                    "msg": "delete fail"
                }
            }
            return JsonResponse(response)

        response = {
            "code": 200,
            "data": {
                "msg": "delete post successfully"
            }
        }
        return JsonResponse(response)

    response = gen_response['method_err']
    return JsonResponse(response)

def search(request):
# 搜索动态
    if request.method == 'GET':
    # 搜索动态, GET /posts/search/?userID=123&keyword=大威
        print('server receive GET', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            user_id = int(request.GET.get('userID', default=-1))
            keyword = request.GET.get('keyword', default=None)
            if user_id < 0 and keyword==None:
                return JsonResponse(gen_response['param_err'])
        except:
            return JsonResponse(gen_response['param_err'])

        if user_id >= 0:
            # 从User数据库获取user
            try:
                publisher = User.objects.get(id=user_id)
            except:
                return JsonResponse(gen_response['user_not_exist'])

            post_list = Post.objects.filter(publisher=publisher)

        else:
            # 获取包含该关键词的post
            keyword_list = TextKey.objects.filter(key=keyword)
            post_list = []
            for key in keyword_list:
                post_list.append(key.post)

        user = User.objects.get(id=request.user.id)
        posts = []
        for item in post_list:

            # 加载图片
            multimedia = []
            if item.is_video == False:
                for photo in Photo.objects.filter(post=item):
                    multimedia.append(photo.photo)

            # 判断是否给自己点赞
            if Favor.objects.filter(post=item).filter(user=user):
                self_favor = 1
            else:
                self_favor = 0

            # 一条摘要动态的数据结构
            publisher_info = {
                'userID': item.publisher.id,
                'username': item.publisher.username,
                'avatar': item.publisher.avatar
            }
            favorcnt = Favor.objects.filter(post=item).count()
            post_info =  {
                'postID': item.post_id,
                'publisher': publisher_info,
                'time': int(item.time.timestamp()*1000),
                'text': item.text,
                'multimediaContent': multimedia,
                'favor': {
                    'self': self_favor,
                    'favorCnt': favorcnt
                }
            }
            posts.append(post_info)

        response = {
            "code": 200,
            "data": {
                "downloadCount": len(posts),
                "posts": posts
            }
        }
        return JsonResponse(response)

    response = gen_response['method_err']
    return JsonResponse(response)

@csrf_exempt
def comments(request):
    if request.method == 'GET':
    # 获取评论列表, GET /post/comments/?postID=123&limit=10&start=10
        print('server receive GET', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.GET.get('postID')) # 评论的动态id
            num = int(request.GET.get('limit', default=10)) # 获取多少个评论
            start = int(request.GET.get('start', default=0)) # 上一次获取的结束评论号
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        # 获取评论区列表
        total_cnt = Comment.objects.filter(post=post).count()

        comments = Comment.objects.filter(post=post).order_by('-id')[start:start+num]

        comment_list = []
        for comment in comments:

            user = {
                'userID': comment.user.id,
                'username': comment.user.username,
                'avatar': comment.user.avatar
            }
            comment_list.append({
                'commentID': comment.id,
                'user': user,
                'time': int(comment.time.timestamp()*1000),
                'text': comment.text
            })
        if len(comment_list):
            _start = comment_list[0]['commentID']
        else:
            _start = -1
        comment_list_info = {
            'postID': post.post_id,
            'totalCount': total_cnt,
            'downloadCount': len(comment_list),
            'start': _start,
            'comments': comment_list
        }

        response = {
            "code": 200,
            "data": {
                "commentList": comment_list_info
            }
        }
        return JsonResponse(response)
    response = gen_response['method_err']
    return JsonResponse(response)

@csrf_exempt
def favor(request):
    if request.method == 'POST':
    # 点赞, POST /post/favor/?postID=123
        print('server receive POST', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.POST.get('postID'))
            user_id = request.user.id
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            user = User.objects.get(id=user_id)
        except:
            return JsonResponse(gen_response['user_not_exist'])

        fail = {
            "code": 300,
            "data": {
                "msg": "favored already"
            }
        }

        if Favor.objects.filter(post=post).filter(user=user):
            return JsonResponse(fail)
        try:
            Favor(post=post, user=user).save()
        except:
            pass

        return JsonResponse(gen_response['success'])
    elif request.method == 'DELETE':
    # 取消点赞, DELETE /post/favor/?postID=123&userID=123
        print('server receive DELETE', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        DELETE = json.loads(request.body)
        try:
            post_id = int(DELETE.get('postID'))
            user_id = int(DELETE.get('userID'))
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            user = User.objects.get(id=user_id)
        except:
            return JsonResponse(gen_response['user_not_exist'])

        fail = {
            "code": 300,
            "data": {
                "msg": "never favored"
            }
        }
        try:
            favor = Favor.objects.filter(post=post).filter(user=user)[0]
            favor.delete()
        except:
            return JsonResponse(fail)

        return JsonResponse(gen_response['success'])

    return JsonResponse(gen_response['method_err'])

@csrf_exempt
def comment(request):
    if request.method == 'POST':
    # 评论, POST /post/comment/?postID=123&text=“test”
        print('server receive POST', request.get_full_path())

        # 检查登陆状态
        if not request.user.is_authenticated:
            return JsonResponse(gen_response["user_error"])

        try:
            post_id = int(request.POST.get('postID'))
            user_id = request.user.id
            text = request.POST.get('text', default='')
        except:
            return(JsonResponse(gen_response['param_err']))

        try:
            post = Post.objects.get(post_id=post_id)
        except:
            return JsonResponse(gen_response['post_not_exist'])

        try:
            user = User.objects.get(id=user_id)
        except:
            return JsonResponse(gen_response['user_not_exist'])

        comment = Comment()
        comment.post = post
        comment.user = user
        comment.text = text

        try:
            comment.save()
        except:
            response = {
                "code": 300,
                "data": {
                    "msg": "comment fail"
                }
            }
            return JsonResponse(response)

        return JsonResponse(gen_response['success'])
    response = gen_response['method_err']
    return JsonResponse(response)