# -*- coding: utf-8 -*-
"""
Created on Tue Feb 26 10:21:15 2019
This is the modl with Keras framework
@author: ago
"""

from __future__ import print_function
from matplotlib import pyplot as plt

import numpy as np
import pandas as pd
import seaborn as sns

from scipy import stats
from IPython.display import display, HTML

from sklearn import metrics
from sklearn.metrics import classification_report
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Reshape
from keras.layers import Conv2D, MaxPooling2D
from keras.utils import np_utils
from keras.layers import LSTM

# Set some standard parameters upfront
pd.options.display.float_format = '{:.1f}'.format
sns.set() # Default seaborn look and feel
plt.style.use('ggplot')
print('keras version ', keras.__version__)
# Same labels will be reused throughout the program
LABELS = ['Frequency','V RMS','I ph.angle','V ph.angle','I RMS']
# The number of steps within one time segment
TIME_PERIODS = 80
# The steps to take from one segment to the next; if this value is equal to
# TIME_PERIODS, then there is no overlap between the segments
STEP_DISTANCE = 40

def read_data(file_path):

    columns = ['Time','value a','value b','label']
    df = pd.read_csv(file_path,
                     header=None,
                     names=columns)

    # will show up as NAN
    df.dropna(axis=0, how='any', inplace=True)

    return df

def convert_to_float(x):

    try:
        return np.float(x)
    except:
        return np.nan

def show_basic_dataframe_info(dataframe):

    # Shape and how many rows and columns
    print('Number of columns in the dataframe: %i' % (dataframe.shape[1]))
    print('Number of rows in the dataframe: %i\n' % (dataframe.shape[0]))

# Load data set containing all the data from csv
df = verticalStack

# Describe the data
show_basic_dataframe_info(df)
df.head(20)
# Define column name of the label vector
LABEL = 'label'
# Transform the labels from String to Integer via LabelEncoder
le = preprocessing.LabelEncoder()
# Add a new column to the existing DataFrame with the encoded values
df[LABEL] = le.fit_transform(df['label'].values.ravel())

RANDOM_SEED =50

N_TIME_STEPS = 200
N_FEATURES = 2
classes= 4
step = 1
segments = []
labels = []
for i in range(1, len(df) - N_TIME_STEPS, step):
    x1 = df['value a'].values[i: i + N_TIME_STEPS]
    x2 = df['value b'].values[i: i + N_TIME_STEPS]

    label = stats.mode(df['label'][i: i + N_TIME_STEPS])[0][0]
    segments.append([x1,x2])
    labels.append(label)

reshaped_segments = np.asarray(segments, dtype= np.float32).reshape(-1, N_TIME_STEPS, N_FEATURES)
labels = np.asarray(pd.get_dummies(labels), dtype = np.float32)

X_train, X_test, y_train, y_test = train_test_split(reshaped_segments, labels, test_size=0.2, random_state=RANDOM_SEED)

print('x_train shape: ', X_train.shape)
print( X_train.shape[0], 'training samples')
print('y_train shape: ', y_train.shape)

model = Sequential()
model.add(LSTM(200, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Dropout(0.3))
#    model.add(LSTM(70))
#    model.add(Dropout(0.3))
model.add(Dense(classes))
callbacks_list = [
    keras.callbacks.ModelCheckpoint(
        filepath='best_model.{epoch:02d}-{val_loss:.2f}.h5',
        monitor='val_loss', save_best_only=True),
    keras.callbacks.EarlyStopping(monitor='acc', patience=1)
]

model.compile(loss='categorical_crossentropy',
                optimizer='adam', metrics=['accuracy'])
print(model.summary())

# Hyper-parameters
BATCH_SIZE = 1024
EPOCHS =10

# Enable validation to use ModelCheckpoint and EarlyStopping callbacks.
history = model.fit(X_train,
                      y_train,
                      batch_size=BATCH_SIZE,
                      epochs=EPOCHS,
                      callbacks=callbacks_list,
                      validation_split=0.2,
                      verbose=1)

plt.figure(figsize=(6, 4))
plt.plot(history.history['acc'], 'r', label='Accuracy of training data')
plt.plot(history.history['val_acc'], 'b', label='Accuracy of validation data')
plt.plot(history.history['loss'], 'r--', label='Loss of training data')
plt.plot(history.history['val_loss'], 'b--', label='Loss of validation data')
plt.title('Model Accuracy and Loss')
plt.ylabel('Accuracy and Loss')
plt.xlabel('Training Epoch')
plt.ylim(0)
plt.legend()
plt.show()

def show_confusion_matrix(validations, predictions):

    matrix = metrics.confusion_matrix(validations, predictions)
    plt.figure(figsize=(6, 4))
    sns.heatmap(matrix,
                cmap='coolwarm',
                linecolor='white',
                linewidths=1,
                xticklabels=LABELS,
                yticklabels=LABELS,
                annot=True,
                fmt='d')
    plt.title('Confusion Matrix')
    plt.ylabel('True Label')
    plt.xlabel('Predicted Label')
    plt.show()

y_pred_test = model.predict(X_test)
# Take the class with the highest probability from the test predictions
max_y_pred_test = np.argmax(y_pred_test, axis=1)
max_y_test = np.argmax(y_test, axis=1)

show_confusion_matrix(max_y_test, max_y_pred_test)

print(classification_report(max_y_test, max_y_pred_test))


import itertools
import matplotlib.pyplot as plt
import numpy as np

def get_mtot(event_jets):
    all_px = sum([j.px ** 2 for j in event_jets])
    all_py = sum([j.py ** 2 for j in event_jets])
    all_pz = sum([j.pz ** 2 for j in event_jets])
    all_e = sum([j.e for j in event_jets])

    if all_e ** 2 - all_px - all_py - all_pz >= 0:
        return (all_e ** 2 - all_px - all_py - all_pz) ** 0.5
    else:
        raise Exception('Bad MTot: all_e=%d, all_px=%d, all_py=%d, all_pz=%d'.format(all_e, all_px, all_py, all_pz))

def get_mjj(event_jets):
    """
    The 2 first jets are the leading jets

    :param event_jets:
    :return: The mjj for the 2 leading jets
    """
    e = event_jets[0].e + event_jets[1].e
    px = event_jets[0].px + event_jets[1].px
    py = event_jets[0].py + event_jets[1].py
    pz = event_jets[0].pz + event_jets[1].pz
    return (e ** 2 - px ** 2 - py ** 2 - pz ** 2) ** 0.5

def get_mjj_all_pairs(event_jets):
    mjj_all_pairs = []
    for pair in itertools.product(event_jets, repeat=2):
        (jo, jt) = pair
        e = jo.e + jt.e
        px = jo.px + jt.px
        py = jo.py + jt.py
        pz = jo.pz + jt.pz
        if (e ** 2 - px ** 2 - py ** 2 - pz ** 2) >= 0:
            mjj_all_pairs += [(e ** 2 - px ** 2 - py ** 2 - pz ** 2) ** 0.5]
        else:
            raise Exception('Bad Mjj: e=%d, px=%d, py=%d, pz=%d'.format(e, px, py, pz))
    return mjj_all_pairs

def get_lead_pt(event_jets):
    return event_jets[0].pt

def get_nj(event_jets):
    return len(event_jets)

def get_mht(event_jets, pt_cutoff=30, eta_cutoff=5):
    all_px = np.array([jet.px for jet in event_jets if (jet.pt > pt_cutoff and jet.eta < eta_cutoff)])
    all_py = np.array([jet.py for jet in event_jets if (jet.pt > pt_cutoff and jet.eta < eta_cutoff)])
    return sum(np.square(all_px) + np.square(all_py)) ** 0.5

def get_ht(event_jets, pt_cutoff=30, eta_cutoff=2.5):
    all_px = np.array([jet.px for jet in event_jets if (jet.pt > pt_cutoff and jet.eta < eta_cutoff)])
    all_py = np.array([jet.py for jet in event_jets if (jet.pt > pt_cutoff and jet.eta < eta_cutoff)])
    return sum(np.square(all_px) + np.square(all_py)) ** 0.5

def get_meff(event_jets):
    all_px = np.array([jet.px for jet in event_jets])
    all_py = np.array([jet.py for jet in event_jets])
    return sum(jet.pt for jet in event_jets) + (sum(np.square(all_px) + np.square(all_py)))**0.5

def plot_histogram(data, x_label, y_label, color='b'):
    plt.figure()
    plt.hist(data, bins=50, facecolor=color, alpha=0.2)
    plt.xlabel(x_label)
    plt.ylabel(y_label)
    plt.show()

def plot_scatter(x, y, x_label, y_label):
    plt.figure()
    plt.scatter(x, y)
    plt.xlabel(x_label)
    plt.ylabel(y_label)
    plt.show()

def get_m1(event_jets):
    jet1 = event_jets[0]
    return (jet1.e ** 2 - jet1.px ** 2 - jet1.py ** 2 - jet1.pz ** 2) ** 0.5

def get_m2(event_jets):
    jet2 = event_jets[1]
    return (jet2.e ** 2 - jet2.px ** 2 - jet2.py ** 2 - jet2.pz ** 2) ** 0.5

def get_m1_sub_m2(event_jets):
    return abs(get_m1(event_jets) - get_m2(event_jets))


from __future__ import unicode_literals
try:
    from urllib2 import Request
except ImportError:
    from urllib.request import Request
from mock import MagicMock, patch
from requests_kerberos import HTTPKerberosAuth

from grafana_dashboards.client.connection import (KerberosConnection,
                                                  BearerAuthConnection,
                                                  BasicAuthConnection,
                                                  SSLAuthConnection)

__author__ = 'Jakub Plichta <jakub.plichta@gmail.com>'

class Capture(object):
    """
    Class for use in method call verification that captures call argument that can be tested later on.
    """

    def __eq__(self, other):
        """
        Captures argument and always returns true to make verification successful.
        :return: True
        """
        self.value = other
        return True

def test_connection():
    connection = BasicAuthConnection('username', 'password', 'https://host')
    connection._opener = MagicMock()
    # noinspection PyProtectedMember
    connection._opener.open().read.return_value = '{"hello":"world"}'

    assert connection.make_request('/uri', {'it\'s': 'alive'}) == {'hello': 'world'}

    request = Request('https://host/uri',
                      '{"it\'s": "alive"}',
                      headers={
                          'Content-type': 'application/json',
                          'Accept': 'application/json',
                          'Authorization': b'Basic dXNlcm5hbWU6cGFzc3dvcmQ='
                      })
    capture = Capture()
    # noinspection PyProtectedMember
    connection._opener.open.assert_called_with(capture)
    assert request.get_full_url() == capture.value.get_full_url()
    assert request.header_items() == capture.value.header_items()
    assert request.get_method() == capture.value.get_method()
    assert request.data.encode('utf-8') == capture.value.data

def test_connection_with_token():
    connection = BearerAuthConnection('token', 'https://host')
    connection._opener = MagicMock()
    # noinspection PyProtectedMember
    connection._opener.open().read.return_value = '{"hello":"world"}'

    assert connection.make_request('/uri', {'it\'s': 'alive'}) == {'hello': 'world'}

    request = Request('https://host/uri',
                      '{"it\'s": "alive"}',
                      headers={
                          'Content-type': 'application/json',
                          'Accept': 'application/json',
                          'Authorization': 'Bearer token'
                      })
    capture = Capture()
    # noinspection PyProtectedMember
    connection._opener.open.assert_called_with(capture)
    assert request.get_full_url() == capture.value.get_full_url()
    assert request.header_items() == capture.value.header_items()
    assert request.get_method() == capture.value.get_method()
    assert request.data.encode('utf-8') == capture.value.data

@patch('requests.post')
def test_connection_with_kerberos(post):
    connection = KerberosConnection('https://host')

    post().json.return_value = {'hello': 'world'}

    assert connection.make_request('/uri', {'it\'s': 'alive'}) == {'hello': 'world'}

    capture = Capture()
    post.assert_called_with('https://host/uri', auth=capture, json={"it's": 'alive'}, verify=False)
    assert isinstance(capture.value, HTTPKerberosAuth)

@patch('requests.post')
def test_connection_with_sslauth(post):
    connection = SSLAuthConnection('https://host', ('/fake/cert'))

    post().json.return_value = {'hello': 'world'}

    assert connection.make_request('/uri', {'it\'s': 'alive'}) == {'hello': 'world'}

    post.assert_called_with('https://host/uri', json={"it's": 'alive'}, cert='/fake/cert')


# Recursive
def maxSum(n, arr):
    # Write your code here.
    def recurse(idx):
        if idx == 0:
            return arr[idx]

        if idx < 0:
            return 0

        pick = arr[idx] + recurse(idx-2)
        not_pick = recurse(idx-1)

        return max(pick, not_pick)

    return recurse(n-1)

# Memoisation
def maxSum2(n, arr):
    # Write your code here.
    def memoise(idx, dp):
        if idx == 0:
            return arr[idx]

        if idx < 0:
            return 0

        if dp[idx] != -1:
            return dp[idx]

        pick = arr[idx] + memoise(idx-2, dp)
        not_pick = memoise(idx-1, dp)
        dp[idx] = max(pick, not_pick)
        return max(dp)

    dp = [-1] * (n)
    return memoise(n-1, dp)

# Tabulation
def maxSum3(n, arr):
    def tabule(idx, dp):
        dp[0] = arr[0]
        neg = 0
        for i in range(1, n):
            if i >1:
                pick = arr[i] + dp[i-2]
            else:
                pick = arr[i]
            not_pick = dp[i-1]
            dp[i] = max(pick, not_pick)
        return max(dp)
    dp = [-1]*(n)
    return tabule(n-1, dp)

# Space Optimisation
def maxSum4(n, arr):
    prev2, prev = 0, arr[0]
    for i in range(1, n):
        take = arr[i]
        if i > 1:
            take += prev2
        not_take = prev
        curr = max(take, not_take)
        prev2 = prev
        prev = curr

    return prev

print(maxSum(4, [2, 1, 1, 2]))
print(maxSum2(4, [2, 1, 1, 2]))


import argparse
import torch
from model import Pretrain_SegmentationNet, DPRAN
import os
from data.dataloader import create_dataloader
from train import net_Pretrain, DPRAN_Train
import segmentation_models_pytorch as smp

def main():
    parser = argparse.ArgumentParser(description='DPRAN')
    parser.add_argument('--num_classes', default=1, type=int, help='Number of output classes [2]')
    parser.add_argument('--num_channels', default=1, type=int, help='Dimension of the input CEUS frames')
    parser.add_argument('--lr_pre', default=0.0002, type=float, help='Initial learning rate [0.0002]')
    parser.add_argument('--lr', default=0.0002, type=float, help='Initial learning rate [0.0002]')
    parser.add_argument('--num_epochs', default=50, type=int, help='Number of total training epochs [40]')
    parser.add_argument('--num_epochs_pre', default=50, type=int, help='Number of total training epochs [40]')
    parser.add_argument('--dataset', default='data', type=str, help='Dataset folder name')
    args = parser.parse_args()

    save_path = os.path.join('checkpoint')
    os.makedirs(save_path, exist_ok=True)

    layers = [32, 32, 64, 128]
    # data load and split
    train_loader, val_loader, test_loader = create_dataloader(dataset=args.dataset, batch_size=1, is_pretraining=True)

    # stage 1
    net = Pretrain_SegmentationNet(n_channels=args.num_channels, n_classes=args.num_classes, layers=layers)
    net.cuda()
    criterion = smp.losses.DiceLoss('binary', classes=None, log_loss=False, from_logits=True, smooth=0.0,
                                    ignore_index=None, eps=1e-07)
    # Optimizer
    optimizer = torch.optim.Adam(net.parameters(), lr=args.lr_pre)
    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9862, last_epoch=-1)
    # Parameters
    epoch_start = 0
    epoch_end = args.num_epochs_pre
    print("Start net Pre-Training...")
    net = net_Pretrain(net, criterion, optimizer, scheduler, epoch_start, epoch_end, train_loader, val_loader,
                       save_path)
    # stage 2
    print("Start DPRAN Training...")
    model = DPRAN(n_channels=args.num_channels, n_classes=args.num_classes, layers=layers)
    model.encoder_ceus.load_state_dict(net.encoder.state_dict())
    model.cuda()

    # Optimizer and loss
    optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)

    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9862, last_epoch=-1)
    epoch_end = args.num_epochs
    train_loader.dataset.is_pretraining = False
    val_loader.dataset.is_pretraining = False
    test_loader.dataset.is_pretraining = False
    test_result, trained_model = DPRAN_Train(model, net, criterion, optimizer, scheduler,
                                             epoch_start, epoch_end, train_loader, val_loader,
                                             test_loader)
    torch.save({'test_rec': test_result, 'DpRAN': trained_model, 'Pretrain_SegmentationNet': net.state_dict()},
               os.path.join(save_path, 'DpRAN' + '.pt'))

if __name__ == "__main__":
    os.environ['CUDA_VISIBLE_DEVICES'] = '0'
    SEED = 0
    torch.manual_seed(SEED)
    if torch.cuda.is_available():
        torch.cuda.manual_seed(SEED)
    main()


'''PROGRAM ANALISIS VARIANSI (Rata-Rata n Populasi -- Kalo Variansi sama dari uji
Levene test)'''

import scipy.stats as st
print(" H0 : miu sampe n sama semua")
print(" H1 : Ada miu yang tidak sama\n")

alfa = input("Tingkat Signifikansi : ")

jumlah_populasi = int(input("Jumlah Populasi : "))
data_populasi = [[17.5,16.9,15.8,18.6],[16.4,19.2,17.7,15.4],
                 [20.3,15.7,17.8,18.9],[14.6,16.7,20.8,18.9],
                 [17.5,19.2,16.5,20.5],[18.3,16.2,17.5,20.1]]
#data_populasi = [[1.06,0.79,0.82,0.89,1.05,0.95,0.65,1.15,1.12],
#                 [1.58,1.45,0.57,1.16,1.12,0.91,0.83,0.43],
#                 [0.29,0.06,0.44,0.55,0.61,0.43,0.51,0.10,0.53,
#                  0.34,0.06,0.09,0.17,0.17,0.60]]
#data_populasi = [[42.5,39.3,39.6,39.9,42.9,43.6],
#                 [39.8,40.1,40.5,42.3,42.5,43.1],
#                 [40.2,40.5,41.3,43.4,44.9,45.1],
#                 [41.3,42.2,43.5,44.2,45.9,42.3]]

#data_populasi = []

ukuran_sampel = input("Ukuran sampel sama (Ya/Tidak) : ")

#for i in range(1,jumlah_populasi+1):
#    populasi_i = []
#    jumlah_data_i = int(input("Jumlah data populasi ke {0} : ".format(i)))
#    for j in range(1,jumlah_data_i+1):
#        data_j = float(input("Data ke {0} : ".format(j)))
#        populasi_i.append(data_j)
#    print("\n")
#    data_populasi.append(populasi_i)

#JKT, JKK, JKG untuk menentukan f
#=============================================
x_kuadrat = 0
jumlah_nilai_T = []
k = jumlah_populasi
nilai_T_masing_kuadrat = []
N = 0

if ukuran_sampel == "Ya" :
    n = len(data_populasi[0])
    for i in range (0,jumlah_populasi):
        for j in range (0,len(data_populasi[i])):
            x_kuadrat += (data_populasi[i][j])**2
#            print(x_kuadrat)
        jumlah_nilai_i = sum (data_populasi[i])
        jumlah_nilai_T.append(jumlah_nilai_i)
        nilai_T_masing_kuadrat.append((jumlah_nilai_i)**2)

    print("Jumlah nilai Ti. =",jumlah_nilai_T)

    jumlah_nilai_T_kuadrat = (sum(jumlah_nilai_T))**2
    JKT = x_kuadrat-((jumlah_nilai_T_kuadrat)/(n*k))
    print("JKT = :",round(JKT,4))

    JKK = (sum(nilai_T_masing_kuadrat)/n) - ((jumlah_nilai_T_kuadrat)/(n*k))
    print("JKK = :",round(JKK,4))

    print("JKT - JKK = :",round(JKT-JKK,4))

    s1_2 = JKK/(k-1)
    s2_2 = (JKT-JKK)/(k*(n-1))
    print("\nRata-rata jumlah Kuadrat")
    print("s1^2 = {0}       s^2 = {1}".format(round(s1_2,4),round(s2_2,4)))

    F = s1_2 / s2_2
    print("F hitung =",round(F,4))

    distribusi_f = st.f(k-1,k*(n-1))
    x = distribusi_f.ppf(1-float(alfa))
    print("F dengan alfa =",str(alfa),",dfn =",str(k-1),",dan dfd =",str(k*(n-1)),"adalah"
          ,str(round(x,4)))

    print("\n")
    print(" {0}               {1}              {2}             {3}           {4}"
          .format("Sumber Variansi","Derajat Bebas",
                  "Jumlah Kuadrat", "RJK", "Statistik F"))
    print("{0}                   {1}                       {2}                   {3}           {4}"
          .format("AntarMesin(Kolom)",k-1,round(JKK,4),
                  round(s1_2,4),round(F,4)))
    print("      {0}                        {1}                       {2}                   {3}"
          .format("Galat",k*(n-1),round(JKT-JKK,4),
                  round(s2_2,4)))
    print("      {0}                        {1}                       {2}"
          .format("Total",k*(n-1)+k-1,round(JKT,4)))

elif ukuran_sampel == "Tidak" :
    for i in range (0,jumlah_populasi):
        for j in range (0,len(data_populasi[i])):
            x_kuadrat += (data_populasi[i][j])**2
#            print(x_kuadrat)
        jumlah_nilai_i = sum (data_populasi[i])
        jumlah_nilai_T.append(jumlah_nilai_i)
        nilai_T_masing_kuadrat.append(((jumlah_nilai_i)**2)/len(data_populasi[i]))

        N_jumlah = len(data_populasi[i])
        N += N_jumlah

    print("Jumlah nilai Ti. =",jumlah_nilai_T)

    jumlah_nilai_T_kuadrat = (sum(jumlah_nilai_T))**2
    JKT = x_kuadrat-((jumlah_nilai_T_kuadrat)/(N))
    print("JKT = :",round(JKT,4))

    JKK = sum(nilai_T_masing_kuadrat) - ((jumlah_nilai_T_kuadrat)/(N))
    print("JKK = :",round(JKK,4))

    print("JKT - JKK = :",round(JKT-JKK,4))

    s1_2 = JKK/(k-1)
    s2_2 = (JKT-JKK)/(N-k)
    print("\nRata-rata jumlah Kuadrat")
    print("s1^2 = {0}       s^2 = {1}".format(round(s1_2,4),round(s2_2,4)))

    F = s1_2 / s2_2
    print("F hitung =",round(F,4))

    distribusi_f = st.f(k-1,N-k)
    x = distribusi_f.ppf(1-float(alfa))
    print("F dengan alfa =",str(alfa),",dfn =",str(k-1),",dan dfd =",str(N-k),"adalah"
          ,str(round(x,4)))

    print("\n")
    print(" {0}               {1}              {2}             {3}           {4}"
          .format("Sumber Variansi","Derajat Bebas",
                  "Jumlah Kuadrat", "RJK", "Statistik F"))
    print("{0}                   {1}                       {2}                   {3}           {4}"
          .format("AntarMesin(Kolom)",k-1,round(JKK,4),
                  round(s1_2,4),round(F,4)))
    print("      {0}                        {1}                       {2}                   {3}"
          .format("Galat",N-k,round(JKT-JKK,4),
                  round(s2_2,4)))
    print("      {0}                        {1}                       {2}"
          .format("Total",N-1,round(JKT,4)))

#print(st.f.sf(2,2,12)) #p_value langsung ini bisa
print("\n")
if F > float(round(x,4)) :
    print("Karena F hitung > F tabel, H0 ditolak")
else :
    print("Karena F hitung < F tabel, H0 tidak dapat ditolak")

'''RUMUS CEPAT'''
#print(st.f_oneway(data_populasi[0],data_populasi[1],data_populasi[2]))

Statistic Method/Analisis Variansi Satu Arah.py


# from time import sleep
import os
# from reply1024 import postreply1024
# import time
from datetime import datetime, timedelta

tday = datetime.now()+timedelta(hours = 8)
print(tday.hour)
tday.strftime("%Y-%m-%d %H:%M:%S")
print(tday)
if os.path.isdir("tmp")==0:
    os.mkdir("tmp")

with open("./tmp/test.txt","r+") as f:
    # f.write(f"{tday} 成功添加一行内容\n")
    con=f.read()
    a=60
    f.seek(0)
    f.truncate()
    f.write(f"{int(con)+a}")
# print(f"文件关闭了吗：{f.closed}")
with open("./tmp/test.txt") as f:
    con=f.read()

# print(f"文件关闭了吗：{f.closed}")
print("读取内容：",con)


# Importamos Pillow
from PIL import Image
import glob

# Importamos Pandas
import pandas as pd
import csv

# TIME
import time
import datetime
from time import gmtime, strftime

# Importamos Pytesseract
import pytesseract

import os

path = "./output/media"

for root,dirs,files in os.walk(path):
    for infile in [f for f in files if f.lower().endswith('.jpg')]:
        file, ext = os.path.splitext(infile)
        full_path = os.path.join(root,infile)

        a = root[15:]
        b = full_path[full_path.rfind("/")+1:]

        print ("-------------------------------------------------------")

        try:
            img = Image.open(full_path)
            texto = pytesseract.image_to_string(img)

            if len(texto) is 0:
               c = 'none'
            else:
              txt =  texto.replace("\n"," ")
              c = txt

            row = [a,b,c]

        except:
            print ("Lo siento, no es una imagen legible")
            c = 'No legible'
            row = [a,b,c]

        with open('./output/media/data_ocr.csv', 'a') as csvFile:
            writer = csv.writer(csvFile)
            print (row)
            writer.writerow(row)
        csvFile.close()

df = pd.read_csv("./output/media/data_ocr.csv", sep=',')
print (df)


users={}
name = input("What is your Name : ")
age = input("What is your age : ")
fav_movies=input("Enter your fav movies seprated by , ").split(',')
fav_songs=input("Enter your fav songs seprated by , ").split(',')

users['name']=name
users['age']=age
users['fav_movies']=fav_movies
users['fav_songs']=fav_songs

print(users)

#To print in different lines

for key, value in users.items():
    print(f'{key} : {value}')


# -*- coding: utf-8 -*-
"""
Created on Mon Jun 22 11:31:56 2020

@author: admin
"""

from __future__ import print_function
import os, sys, time, argparse
from sensapex import SensapexDevice, UMP, UMPError

parser = argparse.ArgumentParser(
    description="Test for sensapex devices; prints position and status updates continuously.")
parser.add_argument('--group', type=int, default=0, help="Device group number")
args = parser.parse_args()

ump = UMP.get_ump(group=args.group)
devids = ump.list_devices()
devs = {i:SensapexDevice(i) for i in devids}

print("SDK version:", ump.sdk_version())
print("Found device IDs:", devids)

def print_pos(timeout=None):
    line = ""
    for i in devids:
        dev = devs[i]
        try:
            pos = str(dev.get_pos(timeout=timeout))
        except Exception as err:
            pos = str(err.args[0])
        pos = pos + " " * (30 - len(pos))
        line += "%d:  %s" % (i, pos)
    print(line)

t = time.time()
while True:
    t1 = time.time()
    dt = t1 - t
    t = t1
    line = "%3f" % dt
    for id in sorted(list(devs.keys())):
        line += "   %d: %s busy: %s" % (id, devs[id].get_pos(timeout=0), devs[id].is_busy())
    line += "                           \r"
    print(line, end=" ")
    sys.stdout.flush()
    time.sleep(0.01)


# -*- coding: utf-8 -*-
"""
Created on Fri Apr 14 15:00:34 2017

@author: rsotoc
"""

import numpy as np
import pandas as pd
import time

import re
import nltk
from nltk.corpus import stopwords
from nltk.util import ngrams
from sklearn.model_selection import train_test_split

from bs4 import BeautifulSoup
from sklearn.naive_bayes import MultinomialNB

def document_features_ngrams(document, global_features):
    features = [0] * len(global_features)
    nd = len(document)
    for elem in document:
        if elem in global_features:
            tf = document.freq(elem) / nd
            index, idf = global_features[elem]
            if ( idf > 0 ):
                features[index] = tf * idf
    return features

# ------------------------------------------------------------------
movies_reviews = pd.read_csv("Movies Reviews/labeledTrainData.tsv", sep='\t')

# Limpiar los documentos. Conservar sólo plabras (alfabéticas) y pasar a minúsculas
movies_reviews.review = list(map(lambda row: re.sub("[^a-zA-Z]", " ",
                                BeautifulSoup(row, "lxml").get_text().lower()),
                                 movies_reviews.review))

# Agregar una columna con la conversión de mensajes a listas de palabras
# Sin eliminar las palabras vacías
movies_reviews["words"] = list(map(lambda row: row.split(), movies_reviews.review))
corpus_len = len(movies_reviews.words)

# Agregar una columna con la conversión de mensajes a listas de palabras
# Se eliminan las palabras vacías
stop_words = set(stopwords.words("english"))
most_common_words = nltk.FreqDist(w for wl in movies_reviews.words for w in wl)
#my_stop_words = [ w for (w,f) in most_common_words.most_common(15)]

movies_reviews["words"] = list(map(lambda row: [w for w in row.split() if not w in stop_words],
                                   movies_reviews.review))

movies_reviews["bigrams"] = list(map(lambda row: list(ngrams(row,2)),
                                   movies_reviews.words))

# Generar un arreglo con los valores de clasificación
Sentiments = np.array([int(x) for x in movies_reviews.sentiment])

#movies_reviews["trigrams"] = list(map(lambda row: list(ngrams(row,3)),
#                                   movies_reviews.words))

#words_frq = nltk.FreqDist(w.lower() for wl in movies_reviews.words for w in wl
#                         ).most_common(4000)
bigrams_frq = nltk.FreqDist(w for wl in movies_reviews.bigrams for w in wl
                            ).most_common(4000)

print("empezando")
start_time = time.time()
bag_idf = {}
for i, (elem, f) in zip (range(len(bigrams_frq)), bigrams_frq):
    nt = 0
    for row in movies_reviews.bigrams:
        if elem in row:
            nt += 1
    bag_idf[elem] = (i, np.log(corpus_len / nt))

featuresets_bigrams = [
    document_features_ngrams(nltk.FreqDist(w for w in d),
                             bag_idf) for d in movies_reviews["bigrams"]]

#trigrams_frq = nltk.FreqDist(w for wl in movies_reviews.trigrams for w in wl
#                            ).most_common(4000)

#featuresets_words = [
#    document_features_ngrams(d, words_frq) for d in movies_reviews["words"]]
#
#bag_dict = {}
#for i, (elem, f) in zip (range(len(bigrams_frq)), bigrams_frq):
#    bag_dict[elem] = (i, float(f)/word_bag_len)
#featuresets_bigrams = [
#    document_features_ngrams(nltk.FreqDist(d), bigrams_frq)
#    for d in movies_reviews["bigrams"]]
#featuresets_trigrams = [
#    document_features_ngrams(nltk.FreqDist(d), trigrams_frq)
#    for d in movies_reviews["trigrams"]]
elapsed_time = time.time() - start_time

#for i in range(100):
#    print(sum(x > 0 for x in featuresets_bigrams[i]))

bigrams_train, bigrams_test, biy_train, biy_test = train_test_split(
    featuresets_bigrams, Sentiments, test_size=0.1)

# Entrenamiento de un clasificador Multinomial Bayes ingenuo
clfM = MultinomialNB()
clfM.fit(bigrams_train, biy_train)
print(elapsed_time)

# Pruebas del clasificador
predictions_train = clfM.predict(bigrams_train)
fails_train = sum(biy_train  != predictions_train)
print("Puntos mal clasificados en el conjunto de entrenamiento: {} de {} ({}%)\n"
      .format(fails_train, len(bigrams_train), 100*fails_train/len(bigrams_train)))
predictions_test = clfM.predict(bigrams_test)
fails_test = sum(biy_test  != predictions_test)
print("Puntos mal clasificados en el conjunto de prueba: {} de {} ({}%)\n"
      .format(fails_test, len(bigrams_test), 100*fails_test/len(bigrams_test)))


from typing import Dict, List, Union
import csv
import os
from unittest import result

def load_csv(
    file_path: str,
    delimiter: str = ',',
    has_header: bool = True,
    try_casting: bool = True

) -> List[Dict]:
    '''
    This function laods a csv file from the given path. It accepts both csv with headers and without them.

    Args:
        file_path: (str) the path to the given csv file.
        delimiter: (str) the string delimiter between columns of the csv.
        has_headers: (bool) flag to indicate if the file has headers. [Default True]

    Output:
    Returns a List of dictionaries representing each row. The keys of each dictionary ar the
    column name.

    Throws:
    - FileNotFoundError

    '''
    if not os.path.exists(file_path):
        print(f'The path {file_path} does not exists!')
        raise FileNotFoundError

    results = []

    with open(file_path, 'r') as f:
        csv_reader = csv.reader(f, delimiter=delimiter)

        if has_header:
            headers = next(csv_reader)

        for row in csv_reader:
            if try_casting:
                mapped_row = list(map(lambda item: cast_to_num(item), row))
            else:
                mapped_row = row

            new_row = { key : item for key, item in zip(headers, mapped_row)}
            results.append(new_row)

    return results

def cast_to_num(value: str) -> Union[str, int, float]:

    int_val = None
    float_val = None

    try:
        int_val = int(value)
    except ValueError:
        try:
            float_val = float(value)
        except ValueError:
            pass

    if int_val is not None:
        return int_val

    if float_val is not None:
        return float_val

    return value


__author__ = 'jacopobacchi'
import RPi.GPIO as GPIO
import time
import shlex
import subprocess

# Define Buttons
PREV = 4
NEXT = 17
PLAY = 27
REPEAT = 22
GPIO.setmode(GPIO.BCM)
GPIO.setup(PREV, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(REPEAT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
prev_input = 0
next_input = 0
play_input = 0
repeat_input = 0
play = 1
while True:
  #take a reading
  input1 = GPIO.input(PREV)
  #if the last reading was low and this one high, print
  if ((not prev_input) and input):
    print("Button PREV pressed")
    cmd = "mpc prev"
    args = shlex.split(cmd)
    output = subprocess.Popen(args)
  #update previous input
  prev_input = input1
  time.sleep(0.05)
  #take a reading
  input2 = GPIO.input(NEXT)
  #if the last reading was low and this one high, print
  if ((not next_input) and input):
    print("Button NEXT pressed")
    cmd = "mpc next"
    args = shlex.split(cmd)
    output = subprocess.Popen(args)
  #update previous input
  next_input = input2
  time.sleep(0.05)
  #take a reading
  input3 = GPIO.input(PLAY)
  #if the last reading was low and this one high, print
  if ((not play_input) and input):
    print("Button PLAY pressed")
    print(play)
    if (play == 1 ):
        cmd = "mpc play"
        args = shlex.split(cmd)
        output = subprocess.Popen(args)
        play = 0
    else:
        cmd = "mpc pause"
        args = shlex.split(cmd)
        output = subprocess.Popen(args)
        play = 1
  #update previous input
  play_input = input3
  time.sleep(0.05)
  #take a reading
  input4 = GPIO.input(REPEAT)
  if ((not repeat_input) and input):
    print("Button REPEAT pressed")
    cmd = "mpc repeat"
    args = shlex.split(cmd)
    output = subprocess.Popen(args)
  #update previous input
  repeat_input = input4
  #slight pause to debounce
  time.sleep(0.05)


# find the minimum length of the subarray whose values sum
# to a value greater than or equal to a target. assume all
# array entries are positive
import numpy as np

vec = np.array([2,3,1,2,4,3])
target = 7

L=0
R=0
min_length = np.inf
cur_length = np.inf
cur_sum = 0
for R,n in enumerate(vec):
    cur_sum += n
    while cur_sum>=target:
        cur_length = R-L+1
        cur_sum -= vec[L]
        L += 1
    if (cur_length<min_length):
        min_length=cur_length

if (min_length==np.inf):
    print(0)
else:
    print(min_length)


''' . Isomorphic Strings
All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character,
but a character may map to itself.
'''
# def reduce(s):
#     result = []
#     lookup = {}
#     for i, c in enumerate(s):
#         if c in lookup:
#             result[lookup[c]].append(i)
#         else:
#             result.append([i])
#             lookup[c] = len(result)-1
#     return result

# class Solution(object):
#     def isIsomorphic(self, s, t):
#         return reduce(s) == reduce(t)

def isIsomorphic(self, s: str, t: str, second: bool = False) -> bool:

        morph = {} # character map

        # just checking if morphs are all identical
        for i, first in enumerate(s):
            if first in morph:
                if t[i] != morph[first]:
                    return False
            else:
                morph[first] = t[i]

        # check the other way round if it's not the second check
        return (True if second else self.isIsomorphic(t, s, True))


"""empty message

Revision ID: 08084a992d8b
Revises:
Create Date: 2018-03-23 09:28:07.017990

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '08084a992d8b'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('username', sa.String(), nullable=False),
    sa.Column('email', sa.String(), nullable=False),
    sa.Column('password', sa.String(), nullable=False),
    sa.Column('hash_key', sa.String(), nullable=False),
    sa.Column('activate', sa.String(), nullable=False),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('email'),
    sa.UniqueConstraint('hash_key'),
    sa.UniqueConstraint('username')
    )
    op.create_table('businesses',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(), nullable=True),
    sa.Column('logo', sa.String(), nullable=True),
    sa.Column('location', sa.String(), nullable=True),
    sa.Column('category', sa.String(), nullable=True),
    sa.Column('bio', sa.String(), nullable=True),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_businesses_category'), 'businesses', ['category'], unique=False)
    op.create_index(op.f('ix_businesses_location'), 'businesses', ['location'], unique=False)
    op.create_index(op.f('ix_businesses_name'), 'businesses', ['name'], unique=False)
    op.create_table('reviews',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('title', sa.String(), nullable=True),
    sa.Column('desc', sa.String(), nullable=True),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.Column('updated_at', sa.DateTime(), nullable=True),
    sa.Column('business_id', sa.Integer(), nullable=False),
    sa.ForeignKeyConstraint(['business_id'], ['businesses.id'], ),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('reviews')
    op.drop_index(op.f('ix_businesses_name'), table_name='businesses')
    op.drop_index(op.f('ix_businesses_location'), table_name='businesses')
    op.drop_index(op.f('ix_businesses_category'), table_name='businesses')
    op.drop_table('businesses')
    op.drop_table('users')
    # ### end Alembic commands ###


from django.urls import path
from . import views

urlpatterns = [
    path('', views.loginView, name='login'),
    path('register/', views.registerView, name='register'),
    path('logout/', views.logoutView, name='logout'),
    path('akun/', views.update_akunView, name='update_akun'),
    path('register/berhasil', views.berhasilView.as_view(aksi='register_berhasil'), name='register_berhasil'),
    path('akun/berhasil', views.berhasilView.as_view(aksi='update_akun_berhasil'), name='update_akun_berhasil'),
]


import sys
sys.stdin = open('input.txt')

T = int(input())
for t in range(T):
    N, M, L = map(int, input().split())
    tree = [0] * (N+1)
    for i in range(M):
        node, val = map(int, input().split())
        tree[node] = val
    for i in range(N, 0, -1):
        if tree[i] == 0 and 2*i + 1 < N+1:
            tree[i] = tree[2*i] + tree[2 * i + 1]
        elif tree[i] == 0:
            tree[i] = tree[2*i]
    print(f'#{t+1}', tree[L])


from pyherc.ports import set_action_factory
from pyherc.data import Model
from pyherc.test.builders import ActionFactoryBuilder
from pyherc.test.cutesy import (Arrows, Bow, Club, Dagger, LeatherArmour,
                                PlateMail, Rune, ScaleMail, Sword, Warhammer,
                                LightBoots, HeavyBoots, IronBoots, SpeedBoots,
                                FlyingBoots)

def default_context(fn):
    """
    Decorator to set up context

    .. versionadded:: 0.8
    """
    def context_setup(*args, **kwargs):
        """
        Set up context
        """
        context = args[0]

        if not hasattr(context, 'model'):
            context.model = Model()

        if not hasattr(context, 'items'):
            context.items = []

        if not hasattr(context, 'characters'):
            context.characters = []

        if not hasattr(context, 'places'):
            context.places = []

        return fn(*args, **kwargs)

    return context_setup

def with_action_factory(fn):
    """
    Decorator to inject action factory

    .. versionadded:: 0.8
    """
    def action_factorize(*args, **kwargs):
        """
        Inject action factory
        """
        context = args[0]

        if not hasattr(context, 'action_factory'):
            context.action_factory = (ActionFactoryBuilder()
                                      .with_drink_factory()
                                      .with_inventory_factory()
                                      .build())

            set_action_factory(context.action_factory)

        return fn(*args, **kwargs)

    return action_factorize

def armour_list(fn):
    """
    Decorator to set up armour list

    .. versionadded:: 0.8
    """
    def armour_setup(*args, **kwargs):
        """
        Set up armour list
        """
        context = args[0]

        if not hasattr(context, 'armour_list'):
            context.armour_list = {}
            context.armour_list['leather armour'] = LeatherArmour
            context.armour_list['scale mail'] = ScaleMail
            context.armour_list['plate mail'] = PlateMail

        return fn(*args, **kwargs)

    return armour_setup

def boots_list(fn):
    """
    Decorator to set up boots list
    """
    def boots_setup(*args, **kwargs):
        """
        Setup boots list
        """
        context = args[0]

        if not hasattr(context, 'boots_list'):
            context.boots_list = {}
            context.boots_list['light boots'] = LightBoots
            context.boots_list['heavy boots'] = HeavyBoots
            context.boots_list['iron boots'] = IronBoots
            context.boots_list['speed boots'] = SpeedBoots
            context.boots_list['flying boots'] = FlyingBoots

        return fn(*args, **kwargs)

    return boots_setup

def weapon_list(fn):
    """
    Decorator to set up weapon list

    .. versionadded:: 0.8
    """
    def weapon_setup(*args, **kwargs):
        """
        Setup weapon list
        """
        context = args[0]

        if not hasattr(context, 'weapon_list'):
            context.weapon_list = {}
            context.weapon_list['warhammer'] = Warhammer
            context.weapon_list['sword'] = Sword
            context.weapon_list['dagger'] = Dagger
            context.weapon_list['club'] = Club
            context.weapon_list['bow'] = Bow
            context.weapon_list['arrows'] = Arrows

        return fn(*args, **kwargs)

    return weapon_setup

def misc_item_list(fn):
    """
    Decorator to set up misc items list

    .. versionadded:: 0.10
    """
    def misc_item_setup(*args, **kwargs):
        """
        Setup misc items list
        """
        context = args[0]

        if not hasattr(context, 'misc_item_list'):
            context.misc_item_list = {}
            context.misc_item_list['rune'] = Rune

        return fn(*args, **kwargs)

    return misc_item_setup

def get_character(context, character_name):
    """
    Get character from context

    :param context: context
    :param character_name: name of character
    :type character_name: string

    .. versionadded:: 0.8
    """
    characters = [x for x in context.characters
                  if x.name == character_name]
    return characters[0]

def get_location(context, location_name):
    """
    Get location from context

    :param context: context
    :param location_name: name of location
    :type location_name: string

    .. versionadded:: 0.8
    """
    locations = [x for x in context.places
                 if ((hasattr(x, 'name') and x.name == location_name)
                     or (hasattr(x, 'keys') and x['name'] == location_name))]
    return locations[0]

def get_item(context, item_name):
    """
    Get item from context

    :param context: context
    :param item_name: name of item
    :type item_name: string

    .. versionadded:: 0.8
    """
    items = [x for x in context.items
             if x.name == item_name]
    return items[0]

def get_entity(context, entity_name):
    """
    Get entity from context

    :param context: context
    :param entity_name: name of entity
    :type entity_name: string

    .. versionadded:: 0.8
    """
    entities = []
    entities.extend(context.characters)
    entities.extend(context.items)

    entity = [x for x in entities
              if x.name == entity_name]

    if entity:
        return entity[0]
    else:
        return get_location(context, entity_name)


#Dependencies
import os
import csv

csvpath = os.path.join('..', 'Resources', 'election_data.csv')

# Open the file using "write" mode. Specify the variable to hold the contents
with open(csvpath, newline='') as csvfile:

    #set variable
    vote_count= []
    candidatelist = []
    unique_candidate= []
    vote_percent= []
    count=0

 # Initialize csv.writer
    csvreader = csv.reader(csvfile, delimiter=',')
    csv_header = next(csvreader)

    print(csvreader)

    for row in csvreader:
        vote_count.append(row[1])
        candidatelist.append(row[2])

        count= count + 1

    for x in set(candidatelist):
        unique_candidate.append(x)

        y= candidatelist.count(x)
        vote_count.append(y)

        a= (y/count) *100
        vote_percent.append(a)

print("Election Results")
print("-------------------")
print(f"Total Votes: {len(vote_count)}")
for i in range(len(unique_candidate)):
          print(unique_candidate[i])
          print(str(vote_percent[i]) + "%")

text_file = open("main.txt","w",newline='')

text_file.write(("Finacial Analysis"))
text_file.write("--------------------")
text_file.write(f"Total Votes: {len(vote_count)}")
for i in range(len(unique_candidate)):
    text_file.write(unique_candidate[i])
    text_file.write(str(vote_percent[i]))
text_file.close()


import cv2
import pickle

import numpy as np
import random
import threading
import warnings

from ..utils.image import read_image_bgr

import numpy as np
from PIL import Image
from six import raise_from

import csv
import sys
import os.path

import keras

from ..utils.anchors import (
    anchor_targets_bbox_centers,
    anchor_targets_bbox,
    anchors_for_shape,
    guess_shapes
)
from ..utils.image import (
    TransformParameters,
    adjust_transform_for_image,
    apply_transform,
    preprocess_image,
    resize_image,
)
from ..utils.transform import transform_aabb, random_transform_generator

class Centers_Generator(object):

    def __init__(
            self,
            pairs,
            BCS_path,
            BoxCars_dataset,
            BoxCars_images,
            BCS_sessions=range(4),
            no_centers=False,
            fake_centers=False,
            split_exclusion_function=None,
            batch_size=1,
            group_method='random',  # one of 'none', 'random', 'ratio'
            shuffle_groups=True,
            image_min_side=400,
            image_max_side=600,
            transform_list=None,
            transform_parameters=None,
            compute_anchor_targets=anchor_targets_bbox_centers,
            compute_shapes=guess_shapes,
            preprocess_image=preprocess_image
    ):
        """ Initialize Generator object.

        Args
            transform_generator    : A generator used to randomly transform images and annotations.
            batch_size             : The size of the batches to generate.
            group_method           : Determines how images are grouped together (defaults to 'ratio', one of ('none', 'random', 'ratio')).
            shuffle_groups         : If True, shuffles the groups each epoch.
            image_min_side         : After resizing the minimum side of an image is equal to image_min_side.
            image_max_side         : If after resizing the maximum side is larger than image_max_side, scales down further so that the max side is equal to image_max_side.
            transform_parameters   : The transform parameters used for data augmentation.
            compute_anchor_targets : Function handler for computing the targets of anchors for an image and its annotations.
            compute_shapes         : Function handler for computing the shapes of the pyramid for a given input.
            preprocess_image       : Function handler for preprocessing an image (scaling / normalizing) for passing through a network.
        """

        self.image_names = []
        self.image_data = {}

        self.classes = {'car': 0}

        # Take base_dir from annotations file if not explicitly specified.

        self.labels = {}
        for key, value in self.classes.items():
            self.labels[value] = key

        self.fake_centers = fake_centers
        self.no_centers = no_centers

        self.split_exclusion_function = split_exclusion_function

        self.image_data = {}
        self.transform_indices = []

        for pair in pairs:
            if BoxCars_dataset is not None:
                self.dataset_name = 'BoxCars'
                self.parse_BoxCars(BoxCars_dataset.format(pair), BoxCars_images.format(pair))

            for i in BCS_sessions:
                self.dataset_name = 'BCS'
                ds_path = os.path.join(BCS_path.format(pair), 'dataset_{}.pkl'.format(i))
                im_path = os.path.join(BCS_path.format(pair), 'images_{}'.format(i))
                self.parse_BCS(dataset_path=ds_path, images_path=im_path)

        print("Generator size: {}".format(self.size()))

        # self.transform_generator    = transform_generator
        self.batch_size = int(batch_size)
        self.group_method = group_method
        self.shuffle_groups = shuffle_groups
        self.image_min_side = image_min_side
        self.image_max_side = image_max_side

        if transform_parameters is not None:
            self.transform_list = transform_list
        else:
            self.transform_list = [
                random_transform_generator(
                    min_translation=(-0.4, -0.4),
                    max_translation=(0.4, 0.4),
                    min_scaling=(0.9, 0.9),
                    max_scaling=(2.0, 2.0),
                    flip_x_chance=0.5
                ),
                random_transform_generator(
                    min_translation=(-0.5, -0.5),
                    max_translation=(0.5, 0.5),
                    min_scaling=(0.03, 0.03),
                    max_scaling=(1.0, 1.0),
                    flip_x_chance=0.5
                ),
            ]

        self.transform_parameters = transform_parameters or TransformParameters(fill_mode='constant')
        if self.no_centers:
            self.compute_anchor_targets = anchor_targets_bbox
        else:
            self.compute_anchor_targets = compute_anchor_targets
        self.compute_shapes = compute_shapes
        self.preprocess_image = preprocess_image

        self.group_index = 0
        self.lock = threading.Lock()

        self.group_images()

    def size(self):
        """ Size of the dataset.
        """
        return len(self.image_names)

    def num_classes(self):
        """ Number of classes in the dataset.
        """
        return max(self.classes.values()) + 1

    def name_to_label(self, name):
        """ Map name to label.
        """
        return self.classes[name]

    def label_to_name(self, label):
        """ Map label to name.
        """
        return self.labels[label]

    def image_path(self, image_index):
        """ Returns the image path for image_index.
        """
        return self.image_names[image_index]

    def image_aspect_ratio(self, image_index):
        """ Compute the aspect ratio for an image with image_index.
        """
        # PIL is fast for metadata
        image = Image.open(self.image_path(image_index))
        return float(image.width) / float(image.height)

    def load_image(self, image_index):
        """ Load an image at the image_index.
        """
        return read_image_bgr(self.image_path(image_index))

    def load_annotations(self, image_index):
        """ Load annotations for an image_index.
        """
        path = self.image_names[image_index]
        annots = self.image_data[path]

        if self.no_centers:
            boxes = np.zeros((len(annots), 5))
        else:
            boxes = np.zeros((len(annots), 6))

        for idx, annot in enumerate(annots):
            class_name = annot['class']
            boxes[idx, 0] = float(annot['x1'])
            boxes[idx, 1] = float(annot['y1'])
            boxes[idx, 2] = float(annot['x2'])
            boxes[idx, 3] = float(annot['y2'])
            boxes[idx, 4] = self.name_to_label(class_name)
            if not self.no_centers:
                boxes[idx, 5] = float(annot['c'])

        return boxes

    def load_transform_indices(self, group):
        return [self.transform_indices[index] for index in group]

    def load_annotations_group(self, group):
        """ Load annotations for all images in group.
        """
        return [self.load_annotations(image_index) for image_index in group]

    def filter_annotations(self, image_group, annotations_group, group):
        """ Filter annotations by removing those that are outside of the image bounds or whose width/height < 0.
        """
        # test all annotations
        for index, (image, annotations) in enumerate(zip(image_group, annotations_group)):
            assert (isinstance(annotations,
                               np.ndarray)), '\'load_annotations\' should return a list of numpy arrays, received: {}'.format(
                type(annotations))

            # test x2 < x1 | y2 < y1 | x1 < 0 | y1 < 0 | x2 <= 0 | y2 <= 0 | x2 >= image.shape[1] | y2 >= image.shape[0]
            invalid_indices = np.where(
                (annotations[:, 2] <= annotations[:, 0]) |
                (annotations[:, 3] <= annotations[:, 1]) |
                (annotations[:, 0] < 0) |
                (annotations[:, 1] < 0) |
                (annotations[:, 2] > image.shape[1]) |
                (annotations[:, 3] > image.shape[0])
            )[0]

            # delete invalid indices
            if len(invalid_indices):
                # cv2.imwrite("ID_.png".format(group[index]), image)
                # warnings.warn("Following warning happens in:{}".format(self.dataset_name))
                # warnings.warn('Image with id {} (shape {}) contains the following invalid boxes: {}.'.format(
                #     group[index],
                #     image.shape,
                #     [annotations[invalid_index, :] for invalid_index in invalid_indices]
                # ))
                annotations_group[index] = np.delete(annotations, invalid_indices, axis=0)

        return image_group, annotations_group

    def load_image_group(self, group):
        """ Load images for all images in a group.
        """
        return [self.load_image(image_index) for image_index in group]

    def random_transform_group_entry(self, image, annotations, transform_index):
        """ Randomly transforms image and annotation.
        """
        # randomly transform both image and annotations
        transform_generator = self.transform_list[transform_index]
        if transform_generator:

            transform = adjust_transform_for_image(next(transform_generator), image,
                                                   self.transform_parameters.relative_translation)
            image = apply_transform(transform, image, self.transform_parameters)

            # Transform the bounding boxes in the annotations.
            annotations = annotations.copy()
            for index in range(annotations.shape[0]):
                annotations[index, :4] = transform_aabb(transform, annotations[index, :4])

        return image, annotations

    def resize_image(self, image):
        """ Resize an image using image_min_side and image_max_side.
        """
        return resize_image(image, min_side=self.image_min_side, max_side=self.image_max_side)

    def preprocess_group_entry(self, image, annotations, transform_index):
        """ Preprocess image and its annotations.
        """
        # preprocess the image
        image = self.preprocess_image(image)

        # randomly transform image and annotations
        image, annotations = self.random_transform_group_entry(image, annotations, transform_index)

        # resize image
        image, image_scale = self.resize_image(image)

        # apply resizing to annotations too
        annotations[:, :4] *= image_scale

        return image, annotations

    def preprocess_group(self, image_group, annotations_group, transform_indices):
        """ Preprocess each image and its annotations in its group.
        """
        for index, (image, annotations, transform_index) in enumerate(
                zip(image_group, annotations_group, transform_indices)):
            # preprocess a single group entry
            image, annotations = self.preprocess_group_entry(image, annotations, transform_index)

            # copy processed data back to group
            image_group[index] = image
            annotations_group[index] = annotations

        return image_group, annotations_group

    def group_images(self):
        """ Order the images according to self.order and makes groups of self.batch_size.
        """
        # determine the order of the images
        order = list(range(self.size()))
        if self.group_method == 'random':
            random.shuffle(order)
        elif self.group_method == 'ratio':
            order.sort(key=lambda x: self.image_aspect_ratio(x))

        # divide into groups, one group = one batch
        self.groups = [[order[x % len(order)] for x in range(i, i + self.batch_size)] for i in
                       range(0, len(order), self.batch_size)]

    def compute_inputs(self, image_group):
        """ Compute inputs for the network using an image_group.
        """
        # get the max image shape
        max_shape = tuple(max(image.shape[x] for image in image_group) for x in range(3))

        # construct an image batch object
        image_batch = np.zeros((self.batch_size,) + max_shape, dtype=keras.backend.floatx())

        # copy all images to the upper left part of the image batch object
        for image_index, image in enumerate(image_group):
            image_batch[image_index, :image.shape[0], :image.shape[1], :image.shape[2]] = image

        return image_batch

    def generate_anchors(self, image_shape):
        return anchors_for_shape(image_shape, shapes_callback=self.compute_shapes)

    def compute_targets(self, image_group, annotations_group):
        """ Compute target outputs for the network using images and their annotations.
        """
        # get the max image shape
        max_shape = tuple(max(image.shape[x] for image in image_group) for x in range(3))
        anchors = self.generate_anchors(max_shape)

        if self.no_centers:
            labels_batch, regression_batch, _ = self.compute_anchor_targets(
                anchors,
                image_group,
                annotations_group,
                self.num_classes()
            )
            return [regression_batch, labels_batch]
        else:
            labels_batch, regression_batch, centers_batch, _ = self.compute_anchor_targets(
                anchors,
                image_group,
                annotations_group,
                self.num_classes()
            )

            return [regression_batch, labels_batch, centers_batch]

    def compute_input_output(self, group):
        """ Compute inputs and target outputs for the network.
        """
        # load images and annotations
        image_group = self.load_image_group(group)
        annotations_group = self.load_annotations_group(group)

        # check validity of annotations
        image_group, annotations_group = self.filter_annotations(image_group, annotations_group, group)

        # perform preprocessing steps
        transform_indices = self.load_transform_indices(group)
        image_group, annotations_group = self.preprocess_group(image_group, annotations_group, transform_indices)

        # compute network inputs
        inputs = self.compute_inputs(image_group)

        # compute network targets
        targets = self.compute_targets(image_group, annotations_group)

        return inputs, targets

    def __next__(self):
        return self.next()

    def next(self):
        # advance the group index
        with self.lock:
            if self.group_index == 0 and self.shuffle_groups:
                # shuffle groups at start of epoch
                random.shuffle(self.groups)
            group = self.groups[self.group_index]
            self.group_index = (self.group_index + 1) % len(self.groups)

        return self.compute_input_output(group)

    def parse_BCS(self, dataset_path, images_path):
        with open(dataset_path, "rb") as f:
            ds = pickle.load(f, encoding='latin-1', fix_imports=True)

        for i, entry in enumerate(ds):

            filename = os.path.join(images_path, entry['filename'])
            if self.split_exclusion_function is not None:
                if self.split_exclusion_function(filename):
                    continue

            if filename not in self.image_data:
                self.image_data[filename] = []
                self.image_names.append(filename)
                self.transform_indices.append(0)
            if self.no_centers:
                for label in entry['labels']:
                    dict = {'x1': label['x_min'], 'x2': label['x_max'],
                            'y1': label['y_min'], 'y2': label['y_max'],
                            'class': 'car'}
                    self.image_data[filename].append(dict)
            elif self.fake_centers:
                for label in entry['labels']:
                    dict = {'x1': label['x_min'], 'x2': label['x_max'],
                            'y1': label['y_min'], 'y2': label['y_max'],
                            'c': 0.0, 'class': 'car'}
                    self.image_data[filename].append(dict)
            else:
                for label in entry['labels']:
                    dict = {'x1': label['x_min'], 'x2': label['x_max'],
                            'y1': label['y_min'], 'y2': label['y_max'],
                            'c': label['centery'], 'class': 'car'}
                    self.image_data[filename].append(dict)

    def parse_BoxCars(self, dataset_path, images_path):
        with open(dataset_path, "rb") as f:
            ds = pickle.load(f, encoding='latin-1', fix_imports=True)
        for sample in ds['samples']:
            # to_camera = sample['to_camera']
            for i_id, instance in enumerate(sample['instances']):
                filename = os.path.join(images_path, instance['filename'])
                if filename not in self.image_data:
                    self.image_data[filename] = []
                    self.image_names.append(filename)
                    self.transform_indices.append(1)

                if self.no_centers:
                    dict = {'x1': instance['bb_out']['x_min'], 'x2': instance['bb_out']['x_max'],
                            'y1': instance['bb_out']['y_min'], 'y2': instance['bb_out']['y_max'],
                            'class': 'car'}
                else:
                    if self.fake_centers:
                        centery = 0.0
                    else:
                        centery = (instance['bb_in']['y_min'] - instance['bb_out']['y_min']) / \
                                  (instance['bb_out']['y_max'] - instance['bb_out']['y_min'])

                    dict = {'x1': instance['bb_out']['x_min'], 'x2': instance['bb_out']['x_max'],
                            'y1': instance['bb_out']['y_min'], 'y2': instance['bb_out']['y_max'],
                            'c': centery, 'class': 'car'}
                self.image_data[filename].append(dict)


import functools
import ipaddress
import re
import socket

from pathlib import Path, PurePath
from random import SystemRandom
from types import TracebackType
from typing import Any, AsyncContextManager, Awaitable, Callable, Dict
from typing import Generator, Generic, IO, Mapping, Optional, Sequence
from typing import Tuple, Type, TypeVar, Union, cast, overload
from typing_extensions import Literal, Protocol

from .constants import DEFAULT_LANG
from .constants import DISC_COMPRESSION_ERROR, DISC_CONNECTION_LOST
from .constants import DISC_HOST_KEY_NOT_VERIFIABLE, DISC_ILLEGAL_USER_NAME
from .constants import DISC_KEY_EXCHANGE_FAILED, DISC_MAC_ERROR
from .constants import DISC_NO_MORE_AUTH_METHODS_AVAILABLE
from .constants import DISC_PROTOCOL_ERROR, DISC_PROTOCOL_VERSION_NOT_SUPPORTED
from .constants import DISC_SERVICE_NOT_AVAILABLE

class _Hash(Protocol):
    """Protocol for hashing data"""

    @property
    def digest_size(self) -> int:
        """Return the hash digest size"""

    @property
    def block_size(self) -> int:
        """Return the hash block size"""

    @property
    def name(self) -> str:
        """Return the hash name"""

    def digest(self) -> bytes:
        """Return the digest value as a bytes object"""

    def hexdigest(self) -> str:
        """Return the digest value as a string of hexadecimal digits"""

    def update(self, __data: bytes) -> None:
        """Update this hash object's state with the provided bytes"""

class HashType(Protocol):
    """Protocol for returning the type of a hash function"""

    def __call__(self, __data: bytes = ...) -> _Hash:
        """Create a new hash object"""

class _SupportsWaitClosed(Protocol):
    """A class that supports async wait_closed"""

    async def wait_closed(self) -> None:
        """Wait for transport to close"""

_T = TypeVar('_T')
DefTuple = Union[Tuple[()], _T]
MaybeAwait = Union[_T, Awaitable[_T]]

ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType]
OptExcInfo = Union[ExcInfo, Tuple[None, None, None]]

BytesOrStr = Union[bytes, str]
FilePath = Union[str, PurePath]
HostPort = Tuple[str, int]
IPAddress = Union[ipaddress.IPv4Address, ipaddress.IPv6Address]
IPNetwork = Union[ipaddress.IPv4Network, ipaddress.IPv6Network]
SockAddr = Union[Tuple[str, int], Tuple[str, int, int, int]]

# Define a version of randrange which is based on SystemRandom(), so that
# we get back numbers suitable for cryptographic use.
_random = SystemRandom()
randrange = _random.randrange

_unit_pattern = re.compile(r'([A-Za-z])')
_byte_units = {'': 1, 'k': 1024, 'm': 1024*1024, 'g': 1024*1024*1024}
_time_units = {'': 1, 's': 1, 'm': 60, 'h': 60*60,
               'd': 24*60*60, 'w': 7*24*60*60}

def hide_empty(value: object, prefix: str = ', ') -> str:
    """Return a string with optional prefix if value is non-empty"""

    value = str(value)
    return prefix + value if value else ''

def plural(length: int, label: str, suffix: str = 's') -> str:
    """Return a label with an optional plural suffix"""

    return '%d %s%s' % (length, label, suffix if length != 1 else '')

def all_ints(seq: Sequence[object]) -> bool:
    """Return if a sequence contains all integers"""

    return all(isinstance(i, int) for i in seq)

def get_symbol_names(symbols: Mapping[str, int], prefix: str,
                     strip_leading: int = 0) -> Mapping[int, str]:
    """Return a mapping from values to symbol names for logging"""

    return {value: name[strip_leading:] for name, value in symbols.items()
            if name.startswith(prefix)}

# Punctuation to map when creating handler names
_HANDLER_PUNCTUATION = (('@', '_at_'), ('.', '_dot_'), ('-', '_'))

def map_handler_name(name: str) -> str:
    """Map punctuation so a string can be used as a handler name"""

    for old, new in _HANDLER_PUNCTUATION:
        name = name.replace(old, new)

    return name

def _normalize_scoped_ip(addr: str) -> str:
    """Normalize scoped IP address

       The ipaddress module doesn't handle scoped addresses properly,
       so we normalize scoped IP addresses using socket.getaddrinfo
       before we pass them into ip_address/ip_network.

    """

    try:
        addrinfo = socket.getaddrinfo(addr, None, family=socket.AF_UNSPEC,
                                      type=socket.SOCK_STREAM,
                                      flags=socket.AI_NUMERICHOST)[0]
    except socket.gaierror:
        return addr

    if addrinfo[0] == socket.AF_INET6:
        sa = addrinfo[4]
        addr = sa[0]

        idx = addr.find('%')
        if idx >= 0: # pragma: no cover
            addr = addr[:idx]

        ip = ipaddress.ip_address(addr)

        if ip.is_link_local:
            scope_id = cast(Tuple[str, int, int, int], sa)[3]
            addr = str(ipaddress.ip_address(int(ip) | (scope_id << 96)))

    return addr

def ip_address(addr: str) -> IPAddress:
    """Wrapper for ipaddress.ip_address which supports scoped addresses"""

    return ipaddress.ip_address(_normalize_scoped_ip(addr))

def ip_network(addr: str) -> IPNetwork:
    """Wrapper for ipaddress.ip_network which supports scoped addresses"""

    idx = addr.find('/')
    if idx >= 0:
        addr, mask = addr[:idx], addr[idx:]
    else:
        mask = ''

    return ipaddress.ip_network(_normalize_scoped_ip(addr) + mask)

def open_file(filename: FilePath, mode: str, buffering: int = -1) -> IO[bytes]:
    """Open a file with home directory expansion"""

    return open(Path(filename).expanduser(), mode, buffering=buffering)

@overload
def read_file(filename: FilePath) -> bytes:
    """Read from a binary file with home directory expansion"""

@overload
def read_file(filename: FilePath, mode: Literal['rb']) -> bytes:
    """Read from a binary file with home directory expansion"""

@overload
def read_file(filename: FilePath, mode: Literal['r']) -> str:
    """Read from a text file with home directory expansion"""

def read_file(filename, mode = 'rb'):
    """Read from a file with home directory expansion"""

    with open_file(filename, mode) as f:
        return f.read()

def write_file(filename: FilePath, data: bytes, mode: str = 'wb') -> int:
    """Write or append to a file with home directory expansion"""

    with open_file(filename, mode) as f:
        return f.write(data)

def _parse_units(value: str, suffixes: Mapping[str, int], label: str) -> float:
    """Parse a series of integers followed by unit suffixes"""

    matches = _unit_pattern.split(value)

    if matches[-1]:
        matches.append('')
    else:
        matches.pop()

    try:
        return sum(float(matches[i]) * suffixes[matches[i+1].lower()]
                   for i in range(0, len(matches), 2))
    except KeyError:
        raise ValueError('Invalid ' + label) from None

def parse_byte_count(value: str) -> int:
    """Parse a byte count with optional k, m, or g suffixes"""

    return int(_parse_units(value, _byte_units, 'byte count'))

def parse_time_interval(value: str) -> float:
    """Parse a time interval with optional s, m, h, d, or w suffixes"""

    return _parse_units(value, _time_units, 'time interval')

_ACM = TypeVar('_ACM', bound=AsyncContextManager, covariant=True)

class _ACMWrapper(Generic[_ACM]):
    """Async context manager wrapper"""

    def __init__(self, coro: Awaitable[_ACM]):
        self._coro = coro
        self._coro_result: Optional[_ACM] = None

    def __await__(self) -> Generator[Any, None, _ACM]:
        return self._coro.__await__()

    async def __aenter__(self) -> _ACM:
        self._coro_result = await self._coro

        return await self._coro_result.__aenter__()

    async def __aexit__(self, exc_type: Optional[Type[BaseException]],
                        exc_value: Optional[BaseException],
                        traceback: Optional[TracebackType]) -> Optional[bool]:
        assert self._coro_result is not None

        exit_result = await self._coro_result.__aexit__(
            exc_type, exc_value, traceback)

        self._coro_result = None

        return exit_result

_ACMCoro = Callable[..., Awaitable[_ACM]]
_ACMWrapperFunc = Callable[..., _ACMWrapper[_ACM]]

def async_context_manager(coro: _ACMCoro[_ACM]) -> _ACMWrapperFunc[_ACM]:
    """Decorator for functions returning asynchronous context managers

       This decorator can be used on functions which return objects
       intended to be async context managers. The object returned by
       the function should implement __aenter__ and __aexit__ methods
       to run when the async context is entered and exited.

       This wrapper also allows the use of "await" on the function being
       decorated, to return the context manager without entering it.

    """

    @functools.wraps(coro)
    def context_wrapper(*args, **kwargs) -> _ACMWrapper[_ACM]:
        """Return an async context manager wrapper for this coroutine"""

        return _ACMWrapper(coro(*args, **kwargs))

    return context_wrapper

async def maybe_wait_closed(writer: '_SupportsWaitClosed') -> None:
    """Wait for a StreamWriter to close, if Python version supports it

       Python 3.8 triggers a false error report about garbage collecting
       an open stream if a close is in progress when a StreamWriter is
       garbage collected. This can be avoided by calling wait_closed(),
       but that method is not available in Python releases prior to 3.7.
       This function wraps this call, ignoring the error if the method
       is not available.

    """

    try:
        await writer.wait_closed()
    except AttributeError: # pragma: no cover
        pass

class Options:
    """Container for configuration options"""

    kwargs: Dict[str, object]

    def __init__(self, options: Optional['Options'] = None, **kwargs: object):
        if options:
            if not isinstance(options, type(self)):
                raise TypeError('Invalid %s, got %s' %
                                (type(self).__name__, type(options).__name__))

            self.kwargs = options.kwargs.copy()
        else:
            self.kwargs = {}

        self.kwargs.update(kwargs)
        self.prepare(**self.kwargs)

    def prepare(self, **kwargs: object) -> None:
        """Pre-process configuration options"""

    def update(self, kwargs: Dict[str, object]) -> None:
        """Update options based on keyword parameters passed in"""

        self.kwargs.update(kwargs)
        self.prepare(**self.kwargs)

class _RecordMeta(type):
    """Metaclass for general-purpose record type"""

    def __new__(mcs: Type['_RecordMeta'], name: str, bases: Tuple[type, ...],
                ns: Dict[str, object]) -> '_RecordMeta':
        if name != 'Record':
            fields = cast(Mapping[str, str],
                          ns.get('__annotations__', {})).keys()
            defaults = {k: ns.get(k) for k in fields}

            ns = {k: v for k, v in ns.items() if k not in fields}
            ns['__slots__'] = defaults

        return cast(_RecordMeta, super().__new__(mcs, name, bases, ns))

class Record(metaclass=_RecordMeta):
    """Generic Record class"""

    __slots__: Mapping[str, object] = {}

    def __init__(self, *args: object, **kwargs: object):
        for k, v in self.__slots__.items():
            setattr(self, k, v)

        for k, v in zip(self.__slots__, args):
            setattr(self, k, v)

        for k, v in kwargs.items():
            setattr(self, k, v)

    def __repr__(self) -> str:
        return '%s(%s)' % (type(self).__name__,
                           ', '.join('%s=%r' % (k, getattr(self, k))
                                     for k in self.__slots__))

    def __str__(self) -> str:
        values = ((k, self._format(k, getattr(self, k)))
                  for k in self.__slots__)

        return ', '.join('%s: %s' % (k, v) for k, v in values if v is not None)

    def _format(self, k: str, v: object) -> Optional[str]:
        """Format a field as a string"""

        # pylint: disable=no-self-use,unused-argument

        return str(v)

class Error(Exception):
    """General SSH error"""

    def __init__(self, code: int, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(reason)
        self.code = code
        self.reason = reason
        self.lang = lang

class DisconnectError(Error):
    """SSH disconnect error

       This exception is raised when a serious error occurs which causes
       the SSH connection to be disconnected. Exception codes should be
       taken from :ref:`disconnect reason codes <DisconnectReasons>`.
       See below for exception subclasses tied to specific disconnect
       reasons if you want to customize your handling by reason.

       :param code:
           Disconnect reason, taken from :ref:`disconnect reason
           codes <DisconnectReasons>`
       :param reason:
           A human-readable reason for the disconnect
       :param lang: (optional)
           The language the reason is in
       :type code: `int`
       :type reason: `str`
       :type lang: `str`

    """

class CompressionError(DisconnectError):
    """SSH compression error

       This exception is raised when an error occurs while compressing
       or decompressing data sent on the SSH connection.

       :param reason:
           Details about the compression error
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_COMPRESSION_ERROR, reason, lang)

class ConnectionLost(DisconnectError):
    """SSH connection lost

       This exception is raised when the SSH connection to the remote
       system is unexpectedly lost. It can also occur as a result of
       the remote system failing to respond to keepalive messages or
       as a result of a login timeout, when those features are enabled.

       :param reason:
           Details about the connection failure
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_CONNECTION_LOST, reason, lang)

class HostKeyNotVerifiable(DisconnectError):
    """SSH host key not verifiable

       This exception is raised when the SSH server's host key or
       certificate is not verifiable.

       :param reason:
           Details about the host key verification failure
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_HOST_KEY_NOT_VERIFIABLE, reason, lang)

class IllegalUserName(DisconnectError):
    """SSH illegal user name

       This exception is raised when an error occurs while processing
       the username sent during the SSL handshake.

       :param reason:
           Details about the illegal username
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_ILLEGAL_USER_NAME, reason, lang)

class KeyExchangeFailed(DisconnectError):
    """SSH key exchange failed

       This exception is raised when the SSH key exchange fails.

       :param reason:
           Details about the connection failure
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_KEY_EXCHANGE_FAILED, reason, lang)

class MACError(DisconnectError):
    """SSH MAC error

       This exception is raised when an error occurs while processing
       the message authentication code (MAC) of a message on the SSH
       connection.

       :param reason:
           Details about the MAC error
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_MAC_ERROR, reason, lang)

class PermissionDenied(DisconnectError):
    """SSH permission denied

       This exception is raised when there are no authentication methods
       remaining to complete SSH client authentication.

       :param reason:
           Details about the SSH protocol error detected
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_NO_MORE_AUTH_METHODS_AVAILABLE, reason, lang)

class ProtocolError(DisconnectError):
    """SSH protocol error

       This exception is raised when the SSH connection is disconnected
       due to an SSH protocol error being detected.

       :param reason:
           Details about the SSH protocol error detected
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_PROTOCOL_ERROR, reason, lang)

class ProtocolNotSupported(DisconnectError):
    """SSH protocol not supported

       This exception is raised when the remote system sends an SSH
       protocol version which is not supported.

       :param reason:
           Details about the unsupported SSH protocol version
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_PROTOCOL_ERROR, reason, lang)

class ServiceNotAvailable(DisconnectError):
    """SSH service not available

       This exception is raised when an unexpected service name is
       received during the SSH handshake.

       :param reason:
           Details about the unexpected SSH service
       :param lang: (optional)
           The language the reason is in
       :type reason: `str`
       :type lang: `str`

    """

    def __init__(self, reason: str, lang: str = DEFAULT_LANG):
        super().__init__(DISC_SERVICE_NOT_AVAILABLE, reason, lang)

class ChannelOpenError(Error):
    """SSH channel open error

       This exception is raised by connection handlers to report
       channel open failures.

       :param code:
           Channel open failure reason, taken from :ref:`channel open
           failure reason codes <ChannelOpenFailureReasons>`
       :param reason:
           A human-readable reason for the channel open failure
       :param lang:
           The language the reason is in
       :type code: `int`
       :type reason: `str`
       :type lang: `str`

    """

class ChannelListenError(Exception):
    """SSH channel listen error

       This exception is raised to report failures in setting up
       remote SSH connection listeners.

       :param details:
           Details of the listen failure
       :type details: `str`

    """

class PasswordChangeRequired(Exception):
    """SSH password change required

       This exception is raised during password validation on the
       server to indicate that a password change is required. It
       should be raised when the password provided is valid but
       expired, to trigger the client to provide a new password.

       :param prompt:
           The prompt requesting that the user enter a new password
       :param lang:
           The language that the prompt is in
       :type prompt: `str`
       :type lang: `str`

    """

    def __init__(self, prompt: str, lang: str = DEFAULT_LANG):
        super().__init__('Password change required: %s' % prompt)
        self.prompt = prompt
        self.lang = lang

class BreakReceived(Exception):
    """SSH break request received

       This exception is raised on an SSH server stdin stream when the
       client sends a break on the channel.

       :param msec:
           The duration of the break in milliseconds
       :type msec: `int`

    """

    def __init__(self, msec: int):
        super().__init__('Break for %s msec' % msec)
        self.msec = msec

class SignalReceived(Exception):
    """SSH signal request received

       This exception is raised on an SSH server stdin stream when the
       client sends a signal on the channel.

       :param signal:
           The name of the signal sent by the client
       :type signal: `str`

    """

    def __init__(self, signal: str):
        super().__init__('Signal: %s' % signal)
        self.signal = signal

class SoftEOFReceived(Exception):
    """SSH soft EOF request received

       This exception is raised on an SSH server stdin stream when the
       client sends an EOF from within the line editor on the channel.

    """

    def __init__(self) -> None:
        super().__init__('Soft EOF')

class TerminalSizeChanged(Exception):
    """SSH terminal size change notification received

       This exception is raised on an SSH server stdin stream when the
       client sends a terminal size change on the channel.

       :param width:
           The new terminal width
       :param height:
           The new terminal height
       :param pixwidth:
           The new terminal width in pixels
       :param pixheight:
           The new terminal height in pixels
       :type width: `int`
       :type height: `int`
       :type pixwidth: `int`
       :type pixheight: `int`

    """

    def __init__(self, width: int, height: int, pixwidth: int, pixheight: int):
        super().__init__('Terminal size change: (%s, %s, %s, %s)' %
                         (width, height, pixwidth, pixheight))
        self.width = width
        self.height = height
        self.pixwidth = pixwidth
        self.pixheight = pixheight

_disc_error_map = {
    DISC_PROTOCOL_ERROR: ProtocolError,
    DISC_KEY_EXCHANGE_FAILED: KeyExchangeFailed,
    DISC_MAC_ERROR: MACError,
    DISC_COMPRESSION_ERROR: CompressionError,
    DISC_SERVICE_NOT_AVAILABLE: ServiceNotAvailable,
    DISC_PROTOCOL_VERSION_NOT_SUPPORTED: ProtocolNotSupported,
    DISC_HOST_KEY_NOT_VERIFIABLE: HostKeyNotVerifiable,
    DISC_CONNECTION_LOST: ConnectionLost,
    DISC_NO_MORE_AUTH_METHODS_AVAILABLE: PermissionDenied,
    DISC_ILLEGAL_USER_NAME: IllegalUserName
}

def construct_disc_error(code: int, reason: str, lang: str) -> DisconnectError:
    """Map disconnect error code to appropriate DisconnectError exception"""

    try:
        return _disc_error_map[code](reason, lang)
    except KeyError:
        return DisconnectError(code, '%s (error %d)' % (reason, code), lang)


from .gameunit import GameUnit

class Explosion(GameUnit):

    def __init__(self):
        super().__init__()
        self.health = 1

    def expand_calc(self):
        factor = 1 + 0.01*(self.factor - self.health)
        self.size[0] = int((self.origin_size[0])*factor)
        self.size[1] = int((self.origin_size[1])*factor)
        self.pos[0] = int(self.pos[0] - (self.size[0]*(factor-1)//2))
        self.pos[1] = int(self.pos[1] - (self.size[1]*(factor-1)//2))
        self.health -= 1

class ExplBig(Explosion):

    def __init__(self):
        super().__init__()
        self.size = [self.ww//4, self.ww//4]
        self.origin_size = self.size
        self.health = 10
        self.factor = self.health

class ExplSmall(Explosion):

    def __init__(self):
        super().__init__()
        self.size = [self.ww//10, self.ww//10]
        self.origin_size = self.size
        self.health = 5
        self.factor = self.health


import sys
import os
from Model.Pairwise.Embedding import RelationEmbedding
from typing import List, Dict, Tuple
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(BASE_DIR)

class InputExample(object):
    """A single training/test example for simple sequence classification."""
    relationEmbedding = RelationEmbedding()
    haveRels = {}
    noRels = {}
    def __init__(self, guid, text_a, text_b=None, label=None, entitys = None, rels=[],\
                    answerType: str = '', answerStr: str = ''):
        self.guid = guid
        self.text_a = text_a
        self.text_b = text_b
        self.label = label
        self.freebaseEntity = entitys
        self.freebaseRels = rels
        self.relsId = InputExample.relation2id(self.freebaseRels)
        self.answerType = answerType
        self.answerStr = answerStr

    @staticmethod
    def relation2id(freebaseRels):
        relsId: List[int] = []
        for rel in freebaseRels:
            if(rel in InputExample.relationEmbedding.rel2id):
                relsId.append(InputExample.relationEmbedding.rel2id[rel])
                InputExample.haveRels[rel] = 1
            else:
                relsId.append(InputExample.relationEmbedding.rel2id['UNK'])
                # print(rel)
                InputExample.noRels[rel] = 1
        while(len(relsId) < 2):
            relsId.append(InputExample.relationEmbedding.rel2id['UNK'])
        return relsId[0:2]


from enum import Enum, unique

@unique
class Move(Enum):
    THE_SAME = 0,
    LEFT = 1,
    TOP = 2,
    RIGHT = 3,
    DOWN = 4,
    LEFT_TOP = 5,
    RIGHT_TOP = 6
    LEFT_DOWN = 7,
    RIGHT_DOWN = 8

class P:
    Left = 0.2
    Right = 0.4
    Top = 0.3
    Down = 0.2
    Vertical_Same = 0.5
    Horizontal_Same = 0.4

def classify_move(x_diff, y_diff):
    if x_diff == 0 and y_diff == 0:
        return Move.THE_SAME
    if x_diff == -1 and y_diff == 0:
        return Move.LEFT
    if x_diff == 0 and y_diff == 1:
        return Move.TOP
    if x_diff == 1 and y_diff == 0:
        return Move.RIGHT
    if x_diff == 0 and y_diff == -1:
        return Move.DOWN
    if x_diff == -1 and y_diff == 1:
        return Move.LEFT_TOP
    if x_diff == 1 and y_diff == 1:
        return Move.RIGHT_TOP
    if x_diff == -1 and y_diff == -1:
        return Move.LEFT_DOWN
    if x_diff == 1 and y_diff == -1:
        return Move.RIGHT_DOWN

def calculate_move_probability(move):
    result = {
        Move.THE_SAME:    P.Vertical_Same * P.Horizontal_Same,
        Move.LEFT:        P.Left * P.Vertical_Same,
        Move.TOP:         P.Top * P.Horizontal_Same,
        Move.RIGHT:       P.Right * P.Vertical_Same,
        Move.DOWN:        P.Down * P.Horizontal_Same,
        Move.LEFT_TOP:    P.Left * P.Top,
        Move.RIGHT_TOP:   P.Right * P.Top,
        Move.LEFT_DOWN:   P.Left * P.Down,
        Move.RIGHT_DOWN:  P.Right * P.Down
    }
    return result[move]

def calculate_common_direction_probability(path):
    p = 0
    for move in path:
        p += calculate_move_probability(move)
    return p

def calculate_single_path_probability(path):
    p = 1
    for move in path:
        p *= calculate_move_probability(move)
    return p

# This recursion can calculate probability without copying moves to paths to speed up process
# But this solution is more clear, easily testable and debuggable.
def calculate_paths(paths_success, paths_fail, moves, x0, y0, step):
    if step == 5:
        if x0 == 0 and y0 == 0:
            paths_success.append(moves.copy())
        else:
            paths_fail.append(moves.copy())
    elif step < 5:
        for x in range(-1, 2):
            for y in range(-1, 2):
                move = classify_move(x, y)
                moves.append(move)
                calculate_paths(paths_success, paths_fail, moves, x0 + x, y0 + y, step + 1)
                del moves[-1]

def calculate_multiple_paths_probability(paths):
    p = 0
    for path in paths:
        p += calculate_single_path_probability(path)
    return p

def test1():
    p = calculate_common_direction_probability([Move.THE_SAME,
                                                Move.LEFT,
                                                Move.LEFT_DOWN,
                                                Move.DOWN,
                                                Move.RIGHT_DOWN,
                                                Move.RIGHT,
                                                Move.RIGHT_TOP,
                                                Move.TOP,
                                                Move.LEFT_TOP])
    res = round(p, 0) == 1
    print(res)

def test2():
    p = calculate_single_path_probability([Move.LEFT, Move.RIGHT])
    res = round(p, 2) == 0.02
    print(res)

def test3():
    paths_success = []
    paths_fail = []
    moves = []
    calculate_paths(paths_success, paths_fail, moves, 0, 0, 0)
    p_success = calculate_multiple_paths_probability(paths_success)
    p_fail = calculate_multiple_paths_probability(paths_fail)
    res = round(p_success + p_fail, 0) == 1
    print(res)

def test():
    test1()
    test2()
    test3()

def main():
    paths_success = []
    paths_fail = []
    moves = []
    calculate_paths(paths_success, paths_fail, moves, 0, 0, 0)
    p_success = calculate_multiple_paths_probability(paths_success)
    p_fail = calculate_multiple_paths_probability(paths_fail)
    print(p_success)
    print(p_fail)

#test()
main()