"""ChessWarrior runner"""

import argparse
import os
import logging

from chesswarrior.config import Config
from chesswarrior.data import DataReader
from chesswarrior.train import Trainer
from chesswarrior.play import Player

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console = logging.StreamHandler()
console.setFormatter(fmt)
handler = logging.FileHandler('log.txt')
handler.setFormatter(fmt)
logger.addHandler(handler)
logger.addHandler(console)

config = Config()
parser = argparse.ArgumentParser()
parser.add_argument('-mode', type=str, help="which mode", choices=config.CMD)
parser.add_argument('--no-cuda', action='store_false', help="Running without cuda")
parser.add_argument('-epoch', type=int, help="training epoches",default=config.training.epoches)
parser.add_argument('-lr', type=float, help="learning rate",default=config.training.learning_rate)
parser.add_argument('-batch_size', type=int, help="batch size",default=config.training.batch_size)
parser.add_argument('-l2_reg', type=float, help="l2_regulation",default=config.model.l2_regularizer)
parser.add_argument('-ch', type=int, help="choise for white or black",default=0)

args = parser.parse_args()

config.cuda_avaliable = args.no_cuda
if not config.cuda_avaliable:

    logger.info('CPU is running')
    os.environ["CUDA_VISIBLE_DEVICES"] = ""
else:
    logger.info('GPU is running')

config.training.epoches = args.epoch
config.training.learning_rate = args.lr
config.training.batch_size = args.batch_size
config.training.l2_reg = args.l2_reg

if args.mode == 'data':
    logger.info('Initializing DataReader')
    datareader = DataReader(config)
    datareader.start()
elif args.mode == 'train':
    logger.info('Initializing Trainer')
    trainer = Trainer(config)
    trainer.start()
elif args.mode == 'play':
    logger.info('Initializing Player')
    player = Player(config)
    player.start(args.ch)
else:
    raise RuntimeError("Mode %s is undefined." % args.mode)


import pandas as pd
# from dashboard.backend import dataset_interactions

import dash_html_components as html
from dash.dependencies import Input, Output, State
from sherlock.sherlockinterface import Sherlock
# from dashboard.utils import components_layout_helper
# from dashboard.pages import report_layout
import io
import available_settings
import base64
from dashboard.utils import callbackshelpers

variables_storage = {}

def input_content_callbacks(app):
    @app.callback(
        Output("output-data-upload", "children"),
        [Input("upload-data", "contents")],
        [State("upload-data", "filename")]
    )
    def upload_data_file(uploaded_file_contents, uploaded_filename):
        """Uploaded data file"""
        if uploaded_file_contents is not None:
            df = callbackshelpers.parse_spreadsheet_contents(uploaded_file_contents, uploaded_filename)
            if df is not None:
                variables_storage['data'] = df
                variables_storage['sherlock'] = Sherlock()
                variables_storage['sherlock'].load_data(df)

                return [''.join(['File ', uploaded_filename, ' was uploaded'])]
        return ['File was not uploaded']

    @app.callback(
        [Output("load-data-spinner", "children"),
         Output('loaded-data-description', 'children'),
         Output('loaded-variables-description', 'children')],
        [Input("load-data-button", "n_clicks")]
    )
    def build_sherlock(n):
        """Uploaded data file"""
        if n:
            df = variables_storage['data']
            sh_ai = Sherlock()
            variables_storage['sherlock'] = sh_ai
            sh_ai.load_data(df)
            report = sh_ai.visualize_variables_descriptions(None)
            data_report = callbackshelpers.data_description_visual(report['data'])
            variables_report = callbackshelpers.variables_description_visual(report['variables'])

            return ['Built Sherlock...'], data_report, variables_report

        return ['File was not uploaded'], None, None

def variables_inspection_callbacks(app):
    @app.callback(
        [Output("variables-distributions-results-container", "children"),
         Output("variables-distribution-spinner", "children")],
        [Input('variables-distribution-button', 'n_clicks')],
        [State('n-var-per-page', 'value')]
    )
    def run_variables_visualization(n, variables_per_page):
        # available_companies_list = glob.glob("/data/*.csv")
        if n:
            print('graphs to show')
            settings = {'num_var_per_graph': int(variables_per_page)}

            sh_ai = variables_storage['sherlock']
            figs = sh_ai.visualize_variables_distributions(settings)

            imgs = []
            for fig in figs:
                out_url = callbackshelpers.fig_to_uri(fig, bbox_inches='tight')
                imgs.append(html.Img(src=out_url))

            return imgs, 'Done'

        return [], None

    @app.callback(
        [Output("variables-network-results-container", "children"),
         Output("variables-network-spinner", "children")],
        [Input('variables-network-button', 'n_clicks')],
        [State('network-threshold-input', 'value'), State('network-pval-input', 'value')
            , State('correlated-threshold-text', 'value'), State('nodes-sizes-text', 'value')]
    )
    def run_variables_network_visualization(n, network_threshold, p_val, correlated_threshold, nodes_sizes):
        # available_companies_list = glob.glob("/data/*.csv")
        if n:
            sh_ai = variables_storage['sherlock']
            settings = {'network_connections_threshold_variables_relations': float(network_threshold),
                        'p_value_correlations': float(p_val), 'correlated_threshold': float(correlated_threshold),
                        'node_size': int(nodes_sizes), 'show_report': False, 'fig_size': (12, 10),
                        'max_nodes_to_draw_graph': 90}

            fig = sh_ai.visualize_variables_network(settings)
            img = None

            if fig is not None:
                out_url = callbackshelpers.fig_to_uri(fig)
                img = html.Img(src=out_url)

            return img, 'Done'
            # new_tags = input_tags.split(';')

        return [], None

    @app.callback(
        [Output("variables-response-results-container", "children"),
         Output("variables-response-spinner", "children")],
        [Input('variables-response-button', 'n_clicks')],
        [State('use-correction', 'value'), State('p-var-res-relation', 'value')]
    )
    def run_variables_response_visualization(n, use_correction, p_value):
        # available_companies_list = glob.glob("/data/*.csv")
        if n:
            sh_ai = variables_storage['sherlock']
            settings = {'p_variables_response_relation': float(p_value), 'use_correction': use_correction == 'True'}

            figs = sh_ai.visualize_variables_response_relationship(settings)

            imgs = []
            for fig in figs:
                out_url = callbackshelpers.fig_to_uri(fig, bbox_inches='tight')
                imgs.append(html.Img(src=out_url))

            return imgs, 'Done'
            # new_tags = input_tags.split(';')

        return [], None

    @app.callback(
        [Output("all-data-model-container", "children"),
         Output("all-data-model-spinner", "children")],
        [Input('all-data-model-button', 'n_clicks')],
    )
    def run_model_potential(n):
        # available_companies_list = glob.glob("/data/*.csv")
        if n:
            sh_ai = variables_storage['sherlock']
            settings = None
            fig = sh_ai.visualize_all_data_model(settings)

            out_url = callbackshelpers.fig_to_uri(fig, bbox_inches='tight')
            img = html.Img(src=out_url)

            return img, 'Done'
            # new_tags = input_tags.split(';')

        return [], None

def insights_callbacks(app):
    @app.callback(
        [Output("comparison-against-shuffle-container", "children"),
         Output("compare-against-shuffle-spinner", "children")],
        [Input('compare-against-shuffle-button', 'n_clicks')],
        [State('number-runs', 'value'), State('bagging-perc', 'value'),
         State('select-model', 'value'), State('select-scaler', 'value'), State('select-random', 'value'),
         State('train-perc', 'value')]
    )
    def compare_against_shuffle(n, n_runs, bagging_perc, model, scaler, random_selector, train_perc):
        if n:
            scaler_object = available_settings.available_models_preprocessing[scaler]
            model_object = available_settings.available_models[model]
            settings = {'scaler': scaler_object, 'train_perc': train_perc, 'runs': n_runs,
                        'selection_type': random_selector, 'model': model_object,
                        'bootstrap_aggregate_percentage': bagging_perc, 'fig_size': (12, 10)}

            sh_ai = variables_storage['sherlock']
            fig = sh_ai.visualize_compare_against_shuffle(settings)
            out_url = callbackshelpers.fig_to_uri(fig, bbox_inches='tight')
            img = html.Img(src=out_url)

            return img, [f'Done']

            # new_tags = input_tags.split(';')

        return None, [f'Not compared']

    @app.callback(
        [Output("insights-container", "children"),
         Output("insights-spinner", "children")],
        [Input('insights-button', 'n_clicks')],
        [State('number-runs-insights', 'value'), State('bagging-perc-insights', 'value'),
         State('select-model-insights', 'value'), State('select-scaler-insights', 'value'),
         State('select-random-insights', 'value'), State('train-perc-insights', 'value')]
    )
    def insight(n, n_runs, bagging_perc, model, scaler, random_selector, train_perc):
        if n:
            scaler_object = available_settings.available_models_preprocessing[scaler]
            model_object = available_settings.available_models[model]
            settings = {'scaler': scaler_object, 'train_perc': train_perc, 'runs': n_runs,
                        'selection_type': random_selector, 'model': model_object,
                        'bootstrap_aggregate_percentage': bagging_perc, 'fig_size': (12, 10)}

            sh_ai = variables_storage['sherlock']
            figs = sh_ai.visualize_insights(settings)
            imgs = []
            for fig in figs:
                out_url = callbackshelpers.fig_to_uri(fig, bbox_inches='tight')
                imgs.append(html.Img(src=out_url))

            # out_url = fig_to_uri(fig, bbox_inches='tight')
            # img = html.Img(src=out_url)

            return imgs, [f'Done']

            # new_tags = input_tags.split(';')

        return None, [f'Not compared']


import logging

logging.basicConfig(format="%(asctime)s - %(name)s - %(message)s", level=logging.INFO)
logger = logging.getLogger(__name__)

from telegram import Update
from telegram.ext import (
    Application,
    CommandHandler,
    ContextTypes,
)

TOKEN = "TOKEN"

async def quadratic(update: Update, context: ContextTypes) -> None:
    # Проверить сообщение ли это
    if not update.message:
        return
    # Это нужно пототму что в update.message.text лежит команда и аргументы типа
    # {text: "/quadratic 1 2 3"}
    text = update.message.text.replace("/quadratic", "").split()
    a, b, c = text
    d = int(b) ** 2 - 4 * int(a) * int(c)

    if d < 0:
        await update.message.reply_text("Дискриминант меньше нуля, корней нет")
    elif d == 0:
        x = -int(b) / (2 * int(a))
        await update.message.reply_text(
            f"Дискриминант равен нулю, корень один\n\nD = {d}\nx = {x}"
        )
    else:
        x1 = (-int(b) + d**0.5) / (2 * int(a))
        x2 = (-int(b) - d**0.5) / (2 * int(a))
        await update.message.reply_text(
            f"Дискриминант больше нуля, корней два\n\nD = {d}\nx1 = {x1}\nx2 = {x2}"
        )

def main() -> None:
    application = Application.builder().token(TOKEN).build()

    application.add_handler(CommandHandler("quadratic", quadratic))
    application.run_polling()

if __name__ == "__main__":
    main()


from __future__ import absolute_import
from __future__ import print_function

import re
import sys
from itertools import islice

import requests

from rtmbot.core import Plugin

class CveParser(Plugin):

    def process_message(self, data):
        message = data['text']
        if re.search(r'\bignore\b', message):
            return False
        match_iter = re.finditer(r'CVE-\d{4}-\d{4,7}', message)
        for match in islice(match_iter, 4):
            cve = match.group(0)
            r = requests.get("https://cve.circl.lu/api/cve/{}".format(cve))
            if r.status_code == 200:
                try:
                    summary = r.json()['summary']
                    url = "https://cve.mitre.org/cgi-bin/cvename.cgi?name={}".format(cve)
                    self.slack_client.api_call('chat.postMessage', channel=data['channel'], as_user=True, attachments=[
                        {"fallback": "{}: {} ({})".format(cve, summary, url), "color": "danger", "title": "{}: {}".format(cve, summary), "title_link": url}
                    ])
                except:
                    pass


from pydantic import BaseModel, Field
from beartype import beartype
from kubernetes.client.rest import ApiException

class InputSchema(BaseModel):
    k8s_cli_string: str = Field(
        title='Kubectl Command',
        description='kubectl command '
                    'eg "kubectl get pods --all-namespaces"'
    )
    deployment: str = Field(
        title='Deployment Name',
        description='Deployment Name'
    )
    namespace: str = Field(
        title='Namespace',
        description='Namespace'
    )

@beartype
def k8s_kubectl_rollout_deployment_printer(data: str):
    if data is None:
        print("Error while executing command")
        return

    print (data)

@beartype
def k8s_kubectl_rollout_deployment(
    handle,
    k8s_cli_string: str,
    deployment: str,
    namespace: str
    ) -> str:
    k8s_cli_string = k8s_cli_string.format(deployment=deployment, namespace=namespace)
    result = handle.run_native_cmd(k8s_cli_string)

    if result is None:
        print(
            f"Error while executing command ({k8s_cli_string}) (empty response)")
        return ""

    if result.stderr:
        raise ApiException(
            f"Error occurred while executing command {k8s_cli_string} {result.stderr}")

    return result.stdout

## Duplicate code?


# Program potrzebuje następujących bibliotek:
# pygame, numpy, matplotlib, keras

# import gry Pong
from PongGame import PongGame  # import The Pong Game
from PongGenome import PongGenome
#
import random
import matplotlib.pyplot as plt
import operator

MAX_EVALUATE_FRAMES = 500
MAXEPOCHS = 31

def GetFuzzyValues(BallX, BallY, PlayerY, BDirection):
    """ Metoda zwraca "z-fuzz-owane ;D" przybliżone wartości dla:
    - dystans
    - wysokość
    - kierunek wznoszenia (~Kąt toru lotu)

    Nie są one idealne - wymagają dopracowania
    ToDo - Poprawić otrzymywane wartości """

    DString = 'Null'  # Dystans
    HString = 'Same'  # Wysokość
    DirString = 'Null'  # Kierunek wznoszenia

    """
        Wyliczanie dystansu piłki:
        Far  - Daleko
        Med  ~ W połowie
        Near - Bardzo blisko
    """
    if (BallX >= 175):
        DString = 'Far'
    if ((BallX < 175) and (BallX >= 50)):
        DString = 'Med'
    if (BallX < 50):
        DString = 'Near'

    """
           Wyliczanie wysokości piłki:
           Aboce - Ponad
           Same  - Ten sam poziom
           Below - Poniżej
    """
    DeltaY = (PlayerY + 30) - (BallY + 5)

    if (DeltaY >= 15):
        HString = 'Below'
    if (DeltaY < -15):
        HString = 'Above'

    """
        Wyliczanie wznoszenia/opadania piłki:
    """
    if (BDirection < 0):
        DirString = 'Left'
    else:
        DirString = 'Right'

    return DString, HString, DirString

def CopyGenome(OriginalGenome):
    NewGenome = PongGenome()
    NewGenome.DistanceValues = OriginalGenome.DistanceValues
    NewGenome.HeightValues = OriginalGenome.HeightValues
    NewGenome.BallDirection = OriginalGenome.BallDirection
    NewGenome.LengthGenome = OriginalGenome.LengthGenome
    NewGenome.score = -1
    NewGenome.PongGN = list(OriginalGenome.PongGN)
    return NewGenome

"""
   Główna metoda Fuzzy Logic
"""
def EvaluateGenome(TheGenome):
    FrameTime = 0

    #  Tworzenie instancji gry Pong
    TheGame = PongGame()
    #  Inicjalizacja gry
    TheGame.InitialDisplay()

    #  Inicjalizacja kolejnych akcji:
    #  0:pozostań
    #  1:w górę
    #  2:w dół
    AppliedAction = 'S'
    PMissed = False
    GameQuit = False

    #  Główna pętla całej gry
    while ((FrameTime < MAX_EVALUATE_FRAMES) and (not PMissed) and (not GameQuit)):

        # Aktualny stan gry
        [PlayerYPos, BallXPos, BallYPos, BallXDirection, BallYDirection] = TheGame.ReturnCurrentState()
        DValue, HValue, DirValue = GetFuzzyValues(BallXPos, BallYPos, PlayerYPos, BallXDirection)

        AppliedAction = 'S'

        #  Przesuń w górę, swoją "paletką", jeśli piłka jest wyżej, niż "paletka" przeciwnika
        if (PlayerYPos + 30 > BallYPos + 5):
            BestAction = 'U'
        #  Przesuń w dół, swoją "paletką", jeśli piłka jest niżej, niż "paletka" przeciwnika
        if (PlayerYPos + 30 < BallYPos + 5):
            BestAction = 'D'

        #  Użyj FuzzyLogic, aby wybrać odpowiednią akcję
        AppliedAction = TheGenome.RtnAction(HValue, DValue, DirValue)

        #  Zastosuj najbardziej odpowiednią akcję w grze
        FrameCount, PMissed, GameQuit = TheGame.PlayNextMove(AppliedAction)

        #  Przejdź do kolejnej klatki
        FrameTime = FrameTime + 1

    TheGenome.SetScore(FrameTime)

    return GameQuit

def TrainPopulation():
    print()
    print("Creating Player Population set")

    EpochCount = 0
    HighestScore = 0
    TrainQuit = False

    GameHistory = []

    # Tworzenie najlepszego w historii genomy do zachowania
    BestEverScore = 0
    BestEverGenome = PongGenome()

    # Tworzenie początkowej populacji 14 genomów
    PlayerPopulation = []
    for ix in range(14):
        PlayerPopulation.append(PongGenome())

    print("Wyświetl początkową populację: ")
    for AGenome in PlayerPopulation:
        AGenome.DisplayFlat()

    print("*** Teraz uruchom oceny epoki  *** ")
    # Teraz trenuj całą populację przez MAXEPOCHS
    while ((EpochCount < MAXEPOCHS) and (not TrainQuit)):

        # Do oceny każdego z genomów w populacji
        for AGenome in PlayerPopulation:
            TrainQuit = EvaluateGenome(AGenome)
            if (TrainQuit):
                break

        # Dzielenie populacji na jalepsze wyniki
        PlayerPopulation.sort(key=operator.attrgetter('score'), reverse=True)

        HighestScore = PlayerPopulation[0].score
        # Sprawdź najlepszy w historii genom
        if (HighestScore > BestEverScore):
            BestEverScore = HighestScore
            BestEverGenome = CopyGenome(PlayerPopulation[0])
            BestEverGenome.SetScore(BestEverScore)

        if EpochCount % 5 == 0:
            # Wyświetlanie najlepszego genomu
            print()
            print("Nalepszy obecnie genom: ")
            BestEverGenome.DisplayGenome()
            for AGenome in PlayerPopulation:
                AGenome.DisplayFlat()
            print()

        PlayerPopulation[0] = CopyGenome(BestEverGenome)
        PlayerPopulation[0].SetScore(HighestScore)

        PlayerPopulation[2] = CopyGenome(PlayerPopulation[0])
        PlayerPopulation[2].Mutate()
        PlayerPopulation[3] = CopyGenome(PlayerPopulation[0])
        PlayerPopulation[3].Mutate()
        PlayerPopulation[4] = CopyGenome(PlayerPopulation[0])
        PlayerPopulation[4].Mutate()

        PlayerPopulation[5] = CopyGenome(PlayerPopulation[1])
        PlayerPopulation[5].Mutate()
        PlayerPopulation[6] = CopyGenome(PlayerPopulation[1])
        PlayerPopulation[6].Mutate()
        PlayerPopulation[7] = CopyGenome(PlayerPopulation[1])
        PlayerPopulation[7].Mutate()

        PlayerPopulation[8] = PongGenome()
        PlayerPopulation[8].InheritFromParents(PlayerPopulation[0], PlayerPopulation[1])
        PlayerPopulation[9] = PongGenome()
        PlayerPopulation[9].InheritFromParents(PlayerPopulation[0], PlayerPopulation[1])
        PlayerPopulation[10] = PongGenome()
        PlayerPopulation[10].InheritFromParents(PlayerPopulation[0], PlayerPopulation[1])
        PlayerPopulation[11] = PongGenome()
        PlayerPopulation[11].InheritFromParents(PlayerPopulation[0], PlayerPopulation[1])

        PlayerPopulation[12] = PongGenome()
        PlayerPopulation[13] = PongGenome()

        EpochCount = EpochCount + 1

        print("Epoka: ", EpochCount, "  Najlepszy wynik: ", HighestScore)
        GameHistory.append((EpochCount, HighestScore))

    print("*** Koniec epok testowych*** ")

    #  Narysuj Wynik vs Epoki
    x_val = [x[0] for x in GameHistory]
    y_val = [x[1] for x in GameHistory]

    plt.plot(x_val, y_val)
    plt.xlabel("Epoka ")
    plt.ylabel("Najlepszy wynik")
    plt.show()

    print()
    print("Najlepszy genom: ")
    PlayerPopulation[0].DisplayFlat()
    print()
    PlayerPopulation[0].DisplayGenome()

    print(" *** Rozgrywka najlepszego genomu *** ")
    TrainQuit = EvaluateGenome(PlayerPopulation[0])

    print("******** Koniec ********* ")
    print()

def main():
    # Główna metoda
    TrainPopulation()

if __name__ == "__main__":
    main()


from torchvision import transforms
import random
import os
import numpy as np
import torch
import Utils.config_stomach as CONFIG
import itertools
from matplotlib import pyplot as plt
import scipy
from sklearn.metrics import roc_curve, roc_auc_score
import math

def seed_torch(seed=0):
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.backends.cudnn.deterministic = True

class Random90Rotation():
    def __init__(self, degrees=[0, 90, 180, 270]):
        self.degrees = degrees

    def __call__(self, im):
        degree = random.sample(self.degrees, k=1)[0]
        return im.rotate(degree)

transform_train = transforms.Compose([
    transforms.Resize(256),
    transforms.RandomCrop(224),
    Random90Rotation(),
    transforms.RandomVerticalFlip(),
    transforms.RandomHorizontalFlip(),
    transforms.RandomApply([transforms.ColorJitter(brightness=0.8)], p=0.8),
    transforms.RandomApply([transforms.ColorJitter(contrast=0.8)], p=0.8),
    transforms.RandomApply([transforms.ColorJitter(saturation=0.8, hue=0.2)], p=0.8),

    transforms.ToTensor(),
    transforms.Normalize(
        mean=CONFIG.Vahadane_stomach_10x_Mean, std=CONFIG.Vahadane_stomach_10x_Std
    ),
])

transform_valid = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=CONFIG.Vahadane_stomach_10x_Mean, std=CONFIG.Vahadane_stomach_10x_Std
    ),
])

transform_test = transforms.Compose([
    transforms.Resize(224),
    transforms.ToTensor(),
    transforms.Normalize(
        mean=CONFIG.Vahadane_stomach_10x_Mean, std=CONFIG.Vahadane_stomach_10x_Std
    ),
])

def plot_confusion_matrix(cm, classes,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    # https://blog.csdn.net/qq_32425195/article/details/101537049
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    fig = plt.figure(figsize=(12, 6))
    plt.title(title)
    for plot_index in range(2):
        if plot_index == 1:
            cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

        plt.subplot(1, 2, plot_index + 1)
        plt.imshow(cm, interpolation='nearest', cmap=cmap)
        plt.colorbar()
        tick_marks = np.arange(len(classes))
        plt.xticks(tick_marks, classes, rotation=15);
        plt.yticks(tick_marks, classes)

        thresh = cm.max() / 2.
        for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
            plt.text(j, i,
                     cm[i, j] if plot_index == 0 else "{:.2f}%".format(cm[i, j] * 100),
                     horizontalalignment="center", color="white" if cm[i, j] > thresh else "black")

        plt.ylabel('True label');
        plt.xlabel('Predicted label')
        plt.tight_layout()
    return fig

def print_conf_matrix(confusion_matrix, classes):
    first_line = [' ']
    first_line.extend(classes)
    first_line = map(lambda s: s.ljust(20), first_line)

    print(''.join(first_line))
    all_acc = 0
    i = 0
    for row, _class in zip(confusion_matrix, classes):
        row_pretty = [_class]
        row_pretty.extend(
            ['{:>5.2f}%({:>5.0f}/{:<5.0f})'.format(number * 100 / sum(row), number, sum(row)) for number in row])
        row_pretty = map(lambda s: s.ljust(20), row_pretty)
        all_acc += (row[i] / sum(row))
        i += 1
        print(''.join(row_pretty))
    return all_acc / len(classes)

def make_weights_for_balanced_classes(label_list, nclasses):
    count = [0] * nclasses
    for item in label_list:
        count[item] += 1
    weight_per_class = [0.] * nclasses
    N = float(sum(count))
    print(N)

    for i in range(nclasses):
        print(i)
        weight_per_class[i] = N / float(count[i])
    print(count)
    print(weight_per_class)
    weight = [0] * len(label_list)
    for idx, val in enumerate(label_list):
        weight[idx] = weight_per_class[val]
    return weight, weight_per_class

def eer_threshold(all_labels, all_values):
    fpr, tpr, threshold = roc_curve(all_labels, all_values, pos_label=1)
    min_val = 999
    min_i = 0
    for i in range(len(fpr)):
        val = abs(fpr[i] + tpr[i] - 1)
        if val < min_val:
            min_val = val
            min_i = i
    print(threshold[min_i], fpr[min_i], tpr[min_i])
    return threshold[min_i]

def bootstrap_auc(all_labels, all_values, n_bootstraps=1000):
    rng_seed = 1  # control reproducibility
    bootstrapped_scores = []

    rng = np.random.RandomState(rng_seed)
    for i in range(n_bootstraps):
        # bootstrap by sampling with replacement on the prediction indices
        indices = rng.randint(0, len(all_values), len(all_values))
        if len(np.unique(all_labels[indices])) < 2:
            # We need at least one positive and one negative sample for ROC AUC
            # to be defined: reject the sample
            continue
        score = roc_auc_score(all_labels[indices], all_values[indices])
        bootstrapped_scores.append(score)
#         print("Bootstrap #{} ROC area: {:0.3f}".format(i + 1, score))
    return bootstrapped_scores

def clopper_pearson(x, n, alpha=0.05):
    """Estimate the confidence interval for a sampled Bernoulli random
    variable.
    `x` is the number of successes and `n` is the number trials (x <=
    n). `alpha` is the confidence level (i.e., the true probability is
    inside the confidence interval with probability 1-alpha). The
    function returns a `(low, high)` pair of numbers indicating the
    interval on the probability.
    """
    b = scipy.stats.beta.ppf
    lo = b(alpha / 2, x, n - x + 1)
    hi = b(1 - alpha / 2, x + 1, n - x)
    return 0.0 if math.isnan(lo) else lo, 1.0 if math.isnan(hi) else hi

def print_result(all_labels, all_values, all_predicts):
    all_auc = bootstrap_auc(all_labels, all_values)
    auc_95_ci = scipy.stats.norm.interval(0.95, np.mean(all_auc), np.std(all_auc))
    print("AUC 95% CI:")
    print("(%.4f, %.4f)" % auc_95_ci)
    TP = ((all_predicts == 1) & (all_labels == 1)).sum()
    TN = ((all_predicts == 0) & (all_labels == 0)).sum()
    FN = ((all_predicts == 0) & (all_labels == 1)).sum()
    FP = ((all_predicts == 1) & (all_labels == 0)).sum()
    sensi_95 = []
    lo, hi = clopper_pearson(TP, TP + FN)
    sensi_95.append(lo)
    sensi_95.append(hi)
    print('Sensitivity 95% confidence interval: ({:.2f}, {:.2f})'.format(lo, hi))
    speci_95 = []
    lo, hi = clopper_pearson(TN, FP + TN)
    speci_95.append(lo)
    speci_95.append(hi)
    print('Specificity 95% confidence interval: ({:.2f}, {:.2f})'.format(lo, hi))
    return auc_95_ci, sensi_95, speci_95


# -*- coding: utf-8 -*-
"""stochastic_evolutionary.py: Module containing functionalities to optimize
a given Latin Hypercube Design using an implementation of the Enhanced
Stochastic Evolutionary Algorithm proposed by Jin, Chen, and Sudjianto (1).
Details can be found in (1) for the enhanced version and (2) for the original
version.

**References**

 (1) R. Jin, W. Chen, and A. Sudjianto, "An Efficient Algorithm for Constructing
     Optimal Design of Computer Experiments," Proceedings of DETC'03, ASME 2003
     Design Engineering Technical Conferences and Computers and Information in
     Engineering Conference, Chicago, Illinois, Sept. 2-6, 2003.
 (2) Y.G. Saab and V.B. Rao, "Combinatorial Optimization by Stochastic
     Evolution," IEEE Transactions on Computer-Aided Design, vol. 10(4), 1981.
"""
import types
import math
import numpy as np
from . import objective_functions

__author__ = "Damar Wicaksono"

def pick_obj_function(obj_function: str) -> types.FunctionType:
    """Function to select by name the objective function to optimize

    :param obj_function: the name of the objective function
    :return: the objective function (FunctionType data type)
    """
    if obj_function == "w2_discrepancy":
        return objective_functions.w2_discrepancy_fast
    else:
        raise TypeError("Unsupported objective function")

def init_threshold(dm: np.ndarray,
                   obj_func: types.FunctionType,
                   multiplier: float = 0.005) -> float:
    """Calculate the initial threshold as recommended in the article

    The initial threshold is obtained by multiplying the objective function of
    the initial design by a very small multiplier to get a small threshold.

    :param dm: the initial design matrix
    :param obj_func: the objective function (FunctionType data type)
    :param multiplier: the multiplier to have a very small value of threshold
        based on the initial design's objective function (default = 0.005)
    :return: the initial threshold
    """
    return multiplier*obj_func(dm)

def calc_num_candidate(n: int) -> int:
    """Calculate the number of candidates from perturbing the current design

    Recommended in the article is the maximum number of pair combination from a
    given column divided by a factor of 5.

    It is also recommended that the number of candidates to be evaluated does
    not exceed 50

    :param n: the number of elements to be permuted
    :return: the number of candidates from perturbing the current design
        column-wise
    """
    pairs = math.factorial(n) / math.factorial(n-2) / math.factorial(2)
    fac = 5 # The factor recommended in the article

    return min(int(pairs/fac), 50)

def calc_max_inner(n: int, k: int) -> int:
    """Calculate the maximum number of inner iterations

    :math:`\frac{2 \times n_e \times k}{J}`
    It is recommended that the number of inner iterations does not exceed 100

    :param n: the number of samples in the design
    :param k: the number of design dimension
    :return: the maximum number of inner iterations/loop
    """
    pairs = math.factorial(n) / math.factorial(n-2) / math.factorial(2)

    return min(int(2*pairs*k/calc_num_candidate(n)), 100)

def perturb(dm: np.ndarray,
            num_dimension: int,
            num_exchanges: int,
            obj_func: types.FunctionType) -> np.ndarray:
    """Create new configuration of a design matrix according to ESE algorithm

    According to the algorithm, a distinct `num_candidate` designs have to be
    generated from the current design by carrying out a column-wise perturbation
    on a given column `num_dimension`. The best design according to the select
    `obj_function` will be selected as the "perturbed" design

    :param dm: the current design matrix
    :param num_dimension: the column of design matrix to be perturbed
    :param num_exchanges: the number of distinct candidates to be generated
    :param obj_func: the select objective function
    :return: the perturbed state of the current design
    """
    import itertools

    # Create pairs of all possible combination
    num_samples = dm.shape[0]
    pairs = list(itertools.combinations([_ for _ in range(num_samples)], 2))
    # Create random choices for the pair of perturbation, w/o replacement
    rand_choices = np.random.choice(len(pairs), num_exchanges, replace=False)
    # Initialize the search
    obj_func_current = np.inf
    dm_current = dm.copy()
    for i in rand_choices:
        dm_try = dm.copy() # Always perturb from the design passed in argument
        # Do column-wise operation in a given column 'num_dimension'
        dm_try[pairs[i][0], num_dimension] = dm[pairs[i][1], num_dimension]
        dm_try[pairs[i][1], num_dimension] = dm[pairs[i][0], num_dimension]
        obj_func_try = obj_func(dm_try)
        if obj_func_try < obj_func_current:
            # Select the best trial from all the perturbation trials
            obj_func_current = obj_func_try
            dm_current = dm_try.copy()

    return dm_current

def adjust_threshold(threshold: float,
                     flag_imp: bool,
                     flag_explore: bool,
                     n_accepted: int,
                     n_improved: int,
                     num_exchanges: int,
                     improving_params: list,
                     exploring_params: list) -> tuple:
    """Calculate the new threshold based on the results of previous iteration

    :param threshold: the current threshold
    :param flag_imp: the flag indicating whether new best solution was found
    :param flag_explore: the flag indicating whether in exploration mode
    :param n_accepted: the number of accepted solution in the previous iteration
    :param n_improved: the number of new best solution found in previous iter.
    :param num_exchanges: the number of candidates considered from curr. design
    :param improving_params: The 2 parameters used in improving process phase
        (1) the cut-off value to decrease the threshold
        (2) the multiplier to decrease or increase the threshold
    :param exploring_params: The 4 parameters used in exploring process phase
        (1) the cut-off value of acceptance to start increasing the threshold
        (2) the cut-off value of acceptance to start decreasing the threshold
        (3) the cooling multiplier for the threshold
        (4) the warming multiplier for the threshold
    :return: tuple of the update flag_explore (whether still in explore mode)
        and the adjusted threshold
    """
    # Improve vs. Explore Phase and Threshold Update
    if flag_imp:    # Improve
        # New best solution found, carry out improvement process
        if (float(n_accepted/num_exchanges) > improving_params[0]) & \
                (n_accepted > n_improved):
            # Lots acceptance but not all of them is improvement,
            # reduce threshold, make it harder to accept a trial
            threshold *= improving_params[1]
        else:
            # Few acceptance or all trials are improvement, increase threshold
            # make it easier to accept a trial
            threshold /= improving_params[1]

    else:           # Explore, No new best solution found during last iteration
        # Exploring process, warming up vs. cooling down
        if n_accepted < exploring_params[0] * num_exchanges:
            # Reach below limit, increase threshold ("warming up")
            flag_explore = True
        elif n_accepted > exploring_params[1] * num_exchanges:
            # Reach above limit, decrease threshold ("cooling down")
            flag_explore = False

        if flag_explore:
            # Ramp up exploration and below upper limit, increase threshold
            threshold /= exploring_params[3]
        elif not flag_explore:
            # Slow down exploration and above lower limit, decrease threshold
            threshold *= exploring_params[2]

    return flag_explore, threshold

def optimize(dm_init: np.ndarray,
             obj_func_name: str,
             threshold_init: float,
             num_exchanges: int,
             max_inner: int,
             max_outer: int,
             improving_params: list,
             exploring_params: list):
    """Optimize a given design using Enhanced Evolutionary Algorithm

    :param dm_init: the initial design matrix
    :param obj_func_name: the objective function used in the optimization
    :param threshold_init: the initial threshold, if equal or less than zero,
        then calculate from the recommended value
    :param num_exchanges: the number of candidates obtained by perturbing current design,
        0 or less means calculate from the recommended value
    :param max_inner: the maximum number of inner iterations, 0 or less means calculate
        from the recommended value
    :param max_outer: the maximum number of outer iterations, served as the
        stopping criterion for the optimization algorithm
    :param improving_params: The 2 parameters used in improving process phase
        (1) the cut-off value to decrease the threshold
        (2) the multiplier to decrease or increase the threshold
    :param exploring_params: The 4 parameters used in exploring process phase
        (1) the cut-off value of acceptance to start increasing the threshold
        (2) the cut-off value of acceptance to start decreasing the threshold
        (3) the cooling multiplier for the threshold
        (4) the warming multiplier for the threshold
    :return: a collection of obj_function evolution and best design
    """
    import collections

    # Initialize output structure
    OptSolution = collections.namedtuple("OptSolution",
                                         "dm_init dm_best best_evol try_evol")

    # Initialization of Outer Iteration
    n = dm_init.shape[0]     # number of samples
    k = dm_init.shape[1]     # number of dimension
    obj_function = pick_obj_function(obj_func_name)  # Choose objective function
    if threshold_init <= 0.0:
        threshold = init_threshold(dm_init, obj_function)   # Initial threshold
    else:
        threshold = threshold_init
    if num_exchanges <= 0:                  # number of exchanges
        num_exchanges = calc_num_candidate(n)
    if max_inner <= 0:                      # maximum number of inner iterations
        max_inner = calc_max_inner(n, k)

    dm = dm_init.copy()                     # the current design
    obj_func_best = obj_function(dm)        # the best value of obj.func. so far
    obj_func_best_old = obj_function(dm)    # the old value of obj.func.
    flag_explore = False                    # improved flag

    best_evol = []                      # Keep track the best solution
    try_evol = []                       # Keep track the accepted trial solution

    # Begin Outer Iteration
    for outer in range(max_outer):
        # Initialization of Inner Iteration
        n_accepted = 0              # number of accepted trial
        n_improved = 0              # number of improved trial

        # Begin Inner Iteration
        for inner in range(max_inner):
            obj_func = obj_function(dm)
            # Perturb current design
            dm_try = perturb(dm, inner % k, num_exchanges, obj_function)
            obj_func_try = obj_function(dm_try)
            # Check whether solution is acceptable
            if (obj_func_try - obj_func) <= threshold * np.random.rand():
                # Accept solution
                dm = dm_try.copy()
                n_accepted += 1
                try_evol.append(obj_func_try)
                if obj_func_try < obj_func_best:
                    # Best solution found
                    dm_best = dm.copy()
                    obj_func_best = obj_func_try
                    best_evol.append(obj_func_best)
                    n_improved += 1

        # Accept/Reject as Best Solution for convergence checking
        if ((obj_func_best_old - obj_func_best)/obj_func_best) > 1e-6:
            # Improvement found
            obj_func_best_old = obj_func_best
            flag_explore = False  # Reset the explore flag after new best found
            flag_imp = True
        else:
            # Improvement not found
            flag_imp = False

        # Improve vs. Explore Phase and Threshold Update
        flag_explore, threshold = adjust_threshold(threshold, flag_imp,
                                                   flag_explore, n_accepted,
                                                   n_improved,
                                                   num_exchanges,
                                                   improving_params,
                                                   exploring_params)

    output = OptSolution(dm_init = dm_init, dm_best = dm_best,
                         best_evol = best_evol, try_evol = try_evol)

    return output


from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import TUser,Waste,TransportVehicle,ProcesssingPlant,Landfill

class UserRegisterForm(UserCreationForm):
    class Meta:
        fields = ["username", "email", "password1", "password2",'area','landmark','city','state','zipcode']
        model = TUser

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["username"].label = "Full name"
        self.fields["email"].label = "Email address"

class UserUpdateForm(forms.ModelForm):

    class Meta:
        model = TUser
        fields = ['username', 'email','area','landmark','city','state','zipcode']

class WasteGenerationForm(forms.ModelForm):
    class Meta:
        model = Waste
        fields = ['type_waste', 'created_date','quantity','tv']

    def __init__(self,*args, **kwargs):
        super(WasteGenerationForm,self).__init__(*args, **kwargs)
        self.fields["type_waste"].label = "Type of Waste"
        self.fields["created_date"].label = "Date of Collection"
        self.fields["quantity"].label = "Quantity(in kgs)"
        self.fields["tv"].label = "Transport Vehicle"
class TvGenerationForm(forms.ModelForm):
    class Meta:
        model = TransportVehicle
        fields = ['plate_number', 'capacity','permit','pp','pincode']

    def __init__(self,*args, **kwargs):
        super(TvGenerationForm,self).__init__(*args, **kwargs)
        self.fields["plate_number"].label = "Plate Number/Vehile Number"
        self.fields["capacity"].label = "Total Capacity"
        self.fields["permit"].label = "Permit"
        self.fields["pp"].label = "Processing Plant"
        self.fields["pincode"].label = "Pincode"
class PpGenerationForm(forms.ModelForm):
    class Meta:
        model = ProcesssingPlant
        fields = ['ppname', 'total_waste','landfill_waste','area','landmark','city','state','zipcode']

    def __init__(self,*args, **kwargs):
        super(PpGenerationForm,self).__init__(*args, **kwargs)
        self.fields["ppname"].label = "Processing Plant Name"
        self.fields["total_waste"].label = "Total Waste till date"
        self.fields["landfill_waste"].label = "Landfill waste till date"
        self.fields["area"].label = "Area"
        self.fields["landmark"].label = "Landmark"
        self.fields["city"].label = "City"
        self.fields["state"].label = "State"
        self.fields["zipcode"].label = "Pincode"

class LfGenerationForm(forms.ModelForm):
    class Meta:
        model = Landfill
        fields = ['lfname', 'maximum_capacity','capacity_filled','pp','area','landmark','city','state','zipcode']

    def __init__(self,*args, **kwargs):
        super(LfGenerationForm,self).__init__(*args, **kwargs)
        self.fields["lfname"].label = "Landfill Name"
        self.fields["maximum_capacity"].label = "Maximum Capacity Of Landfill"
        self.fields["capacity_filled"].label = "Capacity Filled"
        self.fields["pp"].label = "Processing Plant"
        self.fields["area"].label = "Area"
        self.fields["landmark"].label = "Landmark"
        self.fields["city"].label = "City"
        self.fields["state"].label = "State"
        self.fields["zipcode"].label = "Pincode"

class TvUpdateForm(forms.ModelForm):
    class Meta:
        model = TransportVehicle
        fields = ['plate_number', 'capacity','permit','pp','pincode']
class PpUpdateForm(forms.ModelForm):
    class Meta:
        model = ProcesssingPlant
        fields = ['ppname', 'total_waste','landfill_waste','area','landmark','city','state','zipcode']
class LfUpdateForm(forms.ModelForm):
    class Meta:
        model = Landfill
        fields = ['lfname', 'maximum_capacity','capacity_filled','pp','area','landmark','city','state','zipcode']


import numpy as np
import matplotlib.pyplot as plt

vanilla_model = "200d_1x128LSTM_2x128out_50drop.txt"
pos_model = "200d_50pos_1x128LSTM_2x128out_50drop_2.txt"

def main():
    data_vanilla = load_data(vanilla_model)
    data_pos = load_data(pos_model)

    print(data_vanilla.shape)
    print(data_pos.shape)
    show_plot(data_vanilla, data_pos)

def load_data(path):
    # Return [None, 4]
    # 0:Train loss
    # 1:Train acc
    # 2:Valid loss
    # 3:Valid acc
    file = open(path)

    data = []
    for line in file:
        data.append(str_to_num(line))

    return np.array(data)

def str_to_num(str):
    # Gets a string containing numbers separated by space and returns a
    # list of floats.
    return [float(num_str) for num_str in str.split()]

def show_plot(data_v, data_p):
    # Accuracy plot
    plt.subplot(2,1,1)
    plt.plot(data_v[:,-1], label="Vanilla")
    plt.plot(data_p[:,-1], label="POS model")
    plt.ylabel("Validation accuracy")
    plt.legend(loc="lower right")

    plt.subplot(2,1,2)
    plt.plot(data_v[:,2], label="Vanilla")
    plt.plot(data_p[:,2], label="POS model")
    plt.ylabel("Average validation cross entropy")
    plt.xlabel("Iterations")
    plt.legend(loc="upper right")
    plt.show()
    return None

main()


from django.db import models

ZONA_MAX_LENGTH = 50

# Create your models here.
class Map(models.Model):
    Zona = models.CharField(max_length = ZONA_MAX_LENGTH)
    Latitud = models.FloatField()
    Longitud = models.FloatField()

    class Meta:
        verbose_name_plural = 'Mapa'

    def __str__(self):
        return self.title


import torch
import torch.nn as nn
import os
from itertools import zip_longest
import numpy as np

class Learner():
    def __init__(self, net, results_dir='./tmp/results/'):
        self.net = net  # Neural network model
        self.loss = []  # List to store different loss functions

        # Initialize the appropriate loss function for each output
        for i in range(self.net.num_outputs):
            if self.net.regression[i]:
                self.loss.append(nn.MSELoss())
            else:
                self.loss.append(nn.BCEWithLogitsLoss())
        # Use Adam optimizer for training
        self.optimizer = torch.optim.Adam(self.net.parameters(), lr=0.01)

        self.T = 0
        self.observed_tasks = set()  # Set to store observed tasks
        self.results_dir = results_dir  # Directory to store results
        self.init_trainloaders = None  # Store initial training data loaders

    def train(self, *args, **kwargs):
        # Placeholder for the main training loop
        raise NotImplementedError('Training loop is algorithm specific')

    def init_train(self, trainloader, task_id, num_epochs, save_freq=1, testloaders=None):
        # This function initializes training for a given task
        if self.init_trainloaders is None:
            self.init_trainloaders = {}
        self.init_trainloaders[task_id] = trainloader

        eval_bool = testloaders is not None  # Boolean indicating if there are test loaders

        if len(self.init_trainloaders) == self.net.num_init_tasks:
            for i in range(num_epochs):
                # Iterates over batches from different tasks in parallel
                for XY_all in zip_longest(*self.init_trainloaders.values()):
                    for task, XY in zip(self.init_trainloaders.keys(), XY_all):
                        if XY is not None:
                            X, Y = XY
                            X = X.to(self.net.device, non_blocking=True)
                            Y = Y.to(self.net.device, non_blocking=True)
                            self.gradient_step(X, Y, task)
                # Evaluate and save data periodically
                if i % save_freq == 0 or i == num_epochs - 1:
                    if eval_bool:
                        self.evaluate(testloaders)
                    self.save_data(i + 1, task_id, save_eval=eval_bool)
            for task, loader in self.init_trainloaders.items():
                self.update_multitask_cost(loader, task)

    def evaluate(self, testloaders):
        # This function evaluates the model using test data
        was_training = self.net.training
        prev_reduction = []

        # Store current loss reduction method and set to sum for evaluation
        for i in range(self.net.num_outputs):
            prev_reduction.append(self.loss[i].reduction)
            self.loss[i].reduction = 'sum'

        self.net.eval()  # Set the model to evaluation mode

        with torch.no_grad():  # No gradient computation during evaluation
            self.test_loss = {}
            self.test_acc = {}
            for task, loader in testloaders.items():
                # Variables to store cumulative loss and accuracy
                l = [0.] * self.net.num_outputs
                acc = [0.] * self.net.regression.count(False)
                n = len(loader.dataset)  # Number of samples
                cnt_not_regression = 0
                for X, Y in loader:
                    X = X.to(self.net.device, non_blocking=True)
                    Y = Y.to(self.net.device, non_blocking=True)
                    Y_hat = self.net(X, task).unsqueeze(1)  # Model predictions

                    # Calculate and accumulate loss and accuracy for each output
                    for i in range(self.net.num_outputs):
                        l[i] += self.loss[i](Y_hat[:, :, i], Y[:, :, i])
                        if not self.net.regression[i]:
                            acc[cnt_not_regression] += ((Y_hat[:, :, i] > 0.5) == (Y[:, :, i] == 1)).sum().item()
                            cnt_not_regression += 1

                # Store computed test loss and accuracy for each task
                cnt_not_regression = 0
                for i in range(self.net.num_outputs):
                    if self.net.regression[i]:
                        self.test_loss.setdefault(task, []).append(np.sqrt(l[i] / n))
                    else:
                        self.test_loss.setdefault(task, []).append(l[i] / n)
                        self.test_acc.setdefault(task, []).append(acc[cnt_not_regression] / n)
                        cnt_not_regression += 1

        # Restore the previous loss reduction method
        for i in range(self.net.num_outputs):
            self.loss[i].reduction = prev_reduction[i]
        if was_training:
            self.net.train()  # Return model to training mode

    def gradient_step(self, X, Y, task_id):
        # This function performs a single optimization step using the provided batch
        Y_hat = self.net(X, task_id=task_id).unsqueeze(1)
        total_loss = 0.

        # Calculate total loss across all outputs
        for i in range(self.net.num_outputs):
            total_loss += self.loss[i](Y_hat[:, :, i], Y[:, :, i])
        mean_loss = total_loss / self.net.num_outputs

        # Backpropagate the error and update model parameters
        self.optimizer.zero_grad()
        mean_loss.backward()
        self.optimizer.step()

    def save_data(self, epoch, task_id, save_eval=False):
        # This function saves model checkpoints and evaluation logs
        task_results_dir = os.path.join(self.results_dir, 'task_{}'.format(task_id))
        os.makedirs(task_results_dir, exist_ok=True)

        # Save model checkpoints periodically
        if epoch == 0 or epoch % 10 == 0:
            path = os.path.join(task_results_dir, 'checkpoint.pt'.format(epoch))
            torch.save({
                'epoch': epoch,
                'model_state_dict': self.net.state_dict(),
                'optimizer_state_dict': self.optimizer.state_dict(),
                'observed_tasks': self.observed_tasks,
                }, path)

        # Log evaluation results if required
        if save_eval:
            log_open_mode = 'a' if epoch > 0 else 'w'
            with open(os.path.join(task_results_dir, 'log.txt'), log_open_mode) as f:
                line = 'epochs: {}, training task: {}\n'.format(epoch, task_id)
                f.write(line)
                print(line, end='')
                for task in self.test_loss:
                    line = '\ttask: {}'.format(task)
                    for i, loss in enumerate(self.test_loss[task]):
                        if type(loss) == tuple:
                            line += '\tloss{}: ({:.4f}, {:.4f})'.format(i+1, loss[0], loss[1])
                        else:
                            line += '\tloss{}: {:.4f}'.format(i+1, loss)
                    line += '\n'
                    f.write(line)
                    print(line, end='')

    def update_multitask_cost(self, loader, task_id):
        # Placeholder for updating multitask cost
        raise NotImplementedError('Update update_multitask is algorithm specific')

class CompositionalLearner(Learner):
    """Define a compositional learning approach."""

    def train(self, trainloader, task_id, component_update_freq=100, num_epochs=100, save_freq=1, testloaders=None):

        # Check if the current task_id has been observed before
        if task_id not in self.observed_tasks:
            self.observed_tasks.add(task_id)
            self.T += 1

        # Check if testloaders are provided and evaluate the network.
        eval_bool = testloaders is not None
        if eval_bool:
            self.evaluate(testloaders)
        self.save_data(0, task_id, save_eval=eval_bool)

         # If number of observed tasks is within the limit of initial tasks, use the initial training method.
        if self.T <= self.net.num_init_tasks:
            self.net.freeze_structure()
            self.init_train(trainloader, task_id, num_epochs, save_freq, testloaders)
        else:
            # Else, freeze modules and adapt structure.
            self.net.freeze_modules()
            self.net.freeze_structure()     # freeze structure for all tasks
            self.net.freeze_structure(freeze=False, task_id=task_id)    # except current one
            for i in range(num_epochs):
                if (i + 1) % component_update_freq == 0:
                    self.update_modules(trainloader, task_id)   # replace one structure epoch with one module epoch
                else:
                    for X, Y in trainloader:
                        X = X.to(self.net.device, non_blocking=True)
                        Y = Y.to(self.net.device, non_blocking=True)
                        self.update_structure(X, Y, task_id)
                if i % save_freq == 0 or i == num_epochs - 1:
                    if eval_bool:
                        self.evaluate(testloaders)
                    self.save_data(i + 1, task_id, save_eval=eval_bool)
            self.update_multitask_cost(trainloader, task_id)

    # Update the network structure using gradients.
    def update_structure(self, X, Y, task_id):
        self.gradient_step(X, Y, task_id)    # assume shared parameters are frozen and just take a gradient step on the structure

    def update_modules(self, *args, **kwargs):
        raise NotImplementedError('Update modules is algorithm specific')

class JointLearner(Learner):
    pass

class NoComponentsLearner(Learner):
    pass

class CompositionalDynamicLearner(CompositionalLearner):
    """This class extends the functionality of CompositionalLearner by allowing dynamic changes to the network components."""

    def train(self, trainloader, task_id, valloader, component_update_freq=100, num_epochs=100, save_freq=1, testloaders=None):

        # Initial training steps are similar to CompositionalLearner.
        if task_id not in self.observed_tasks:
            self.observed_tasks.add(task_id)
            self.T += 1
        eval_bool = testloaders is not None
        if eval_bool:
            self.evaluate(testloaders)
        self.save_data(0, task_id, save_eval=eval_bool)
        if self.T <= self.net.num_init_tasks:
            self.net.freeze_structure()
            self.init_train(trainloader, task_id, num_epochs, save_freq, testloaders)
        else:
            # Add dynamic handling of network components.
            self.net.freeze_modules()
            self.net.freeze_structure()     # freeze structure for all tasks
            self.net.add_tmp_module(task_id)   # freeze original modules and structure
            self.optimizer.add_param_group({'params': self.net.components[-1].parameters()})
            if hasattr(self, 'preconditioner'):
                self.preconditioner.add_module(self.net.components[-1])

            self.net.freeze_structure(freeze=False, task_id=task_id)    # unfreeze (new) structure for current task

            for i in range(num_epochs):
                if (i + 1) % component_update_freq == 0:
                    self.update_modules(trainloader, task_id)
                else:
                    for X, Y in trainloader:
                        X = X.to(self.net.device, non_blocking=True)
                        Y = Y.to(self.net.device, non_blocking=True)
                        self.update_structure(X, Y, task_id)
                        self.net.hide_tmp_module()
                        self.update_structure(X, Y, task_id)
                        self.net.recover_hidden_module()
                if i % save_freq == 0 or i == num_epochs - 1:
                    if eval_bool:
                        self.evaluate(testloaders)
                    self.save_data(i + 1, task_id, save_eval=eval_bool)

            # Decide whether to keep the temporary module or not
            self.conditionally_add_module(valloader, task_id)
            self.save_data(num_epochs + 1, task_id, save_eval=False, final_save=True)
            self.update_multitask_cost(trainloader, task_id)

    # Method to evaluate whether to keep a temporary module or not
    def conditionally_add_module(self, valloader, task_id):
        test_loss = self.test_loss
        test_acc = self.test_acc
        self.evaluate({task_id: valloader})
        W_losses, WO_losses = [], []
        for output in self.test_loss[task_id]:
            W_losses.append(output[0])
            WO_losses.append(output[1])
        update_loss = np.mean(W_losses)
        no_update_loss = np.mean(WO_losses)
        print('W/update: {}, WO/update: {}'.format(update_loss, no_update_loss))
        if (no_update_loss - update_loss) / update_loss > .05:
            print('Keeping new module. Total: {}\n'.format(self.net.num_components))
        else:
            self.net.remove_tmp_module()
            print('Not keeping new module. Total: {}\n'.format(self.net.num_components))

        self.test_loss = test_loss
        self.test_acc = test_acc

    # Evaluate network performance on multiple tasks
    def evaluate(self, testloaders, eval_no_update=True):
        was_training = self.net.training
        prev_reduction = []
        for i in range(self.net.num_outputs):
            prev_reduction.append(self.loss[i].reduction)
            self.loss[i].reduction = 'sum'     # make sure the loss is summed over instances
        self.net.eval()
        with torch.no_grad():
            self.test_loss = {}
            self.test_acc = {}
            for task, loader in testloaders.items():
                l = [0.] * self.net.num_outputs
                acc = [0.] * self.net.regression.count(False)
                n = len(loader.dataset)
                cnt_not_regression = 0
                for X, Y in loader:
                    X = X.to(self.net.device, non_blocking=True)
                    Y = Y.to(self.net.device, non_blocking=True)
                    Y_hat = self.net(X, task).unsqueeze(1)
                    for i in range(self.net.num_outputs):
                        l[i] += self.loss[i](Y_hat[:, :, i], Y[:, :, i])
                        if not self.net.regression[i]:
                            acc[cnt_not_regression] += ((Y_hat[:, :, i] > 0.5) == (Y[:, :, i] == 1)).sum().item()
                            cnt_not_regression += 1
                cnt_not_regression = 0
                if eval_no_update and task == self.T - 1 and self.T > self.net.num_init_tasks:
                    self.net.hide_tmp_module()
                    l1 = [0.] * self.net.num_outputs
                    acc1 = [0.] * self.net.regression.count(False)
                    for X, Y in loader:
                        X = X.to(self.net.device, non_blocking=True)
                        Y = Y.to(self.net.device, non_blocking=True)
                        Y_hat = self.net(X, task).unsqueeze(1)
                        for i in range(self.net.num_outputs):
                            l1[i] += self.loss[i](Y_hat[:, :, i], Y[:, :, i])
                            if not self.net.regression[i]:
                                acc1[cnt_not_regression] += ((Y_hat[:, :, i] > 0.5) == (Y[:, :, i] == 1)).sum().item()
                                cnt_not_regression += 1
                    cnt_not_regression = 0
                    for i in range(self.net.num_outputs):
                        if self.net.regression[i]:
                            if task not in self.test_loss.keys():
                                self.test_loss[task] = [(np.sqrt(l[i] / n), np.sqrt(l1[i] / n))]
                            else:
                                self.test_loss[task].append((np.sqrt(l[i] / n), np.sqrt(l1[i] / n)))
                        else:
                            if task not in self.test_loss.keys():
                                self.test_loss[task] = [(l[i] / n, l1[i] / n)]
                            else:
                                self.test_loss[task].append((l[i] / n, l1[i] / n))
                            if task not in self.test_acc.keys():
                                self.test_acc[task] = [(acc[cnt_not_regression] / n, acc1[cnt_not_regression] / n)]
                            else:
                                self.test_acc[task] = [(acc[cnt_not_regression] / n, acc1[cnt_not_regression] / n)]
                            cnt_not_regression += 1
                    self.net.recover_hidden_module()
                else:
                    for i in range(self.net.num_outputs):
                        if self.net.regression[i]:
                            if task not in self.test_loss.keys():
                                self.test_loss[task] = [np.sqrt(l[i] / n)]
                            else:
                                self.test_loss[task].append(np.sqrt(l[i] / n))
                        else:
                            if task not in self.test_loss.keys():
                                self.test_loss[task] = [l[i] / n]
                            else:
                                self.test_loss[task].append(l[i] / n)
                            if task not in self.test_acc.keys():
                                self.test_acc[task] = [acc[cnt_not_regression] / n]
                            else:
                                self.test_acc[task] = [acc[cnt_not_regression] / n]
                            cnt_not_regression += 1

        for i in range(self.net.num_outputs):
            self.loss[i].reduction = prev_reduction[i]
        if was_training:
            self.net.train()

    # Save training data
    def save_data(self, epoch, task_id, save_eval=False, final_save=False):
        super().save_data(epoch, task_id, save_eval)
        if final_save:
            task_results_dir = os.path.join(self.results_dir, 'task_{}'.format(task_id))
            with open(os.path.join(task_results_dir, 'num_components.txt'), 'w') as f:
                line = 'final components: {}'.format(self.net.num_components)
                f.write(line)


import logging
from group import ZabbixGroups
from object import ZabbixObject

# Connect to logger object
log = logging.getLogger(__name__)

class ZabbixAutoreg(ZabbixObject):

    """
    Implements working with zabbix autoregister action objects.

    Arguments:
    zapi  (ZabbixAPI)   ZabbixAPI connector to send request.
    obj   (dict)        Dictionary discribed zabbix application template.
    """

    def __init__(self, zapi, obj):
        self.zapi = zapi
        self.obj = obj
        self.obj_type = 'action'
        ZabbixObject(self.zapi, self.obj)

    def _create_request(self):
        """
        Create request for changes.

        Return  (str)   Request for changes.
        """

        result = {}
        result['name'] = 'Auto registration {role}'.format(
            role=self.obj['name'])

        # if contains metadata tag then use it
        if isinstance(
                self.obj['autoreg'],
                dict) and self.obj['autoreg'].get('metadata'):
            metadata = self.obj['autoreg']['metadata']
        else:
            metadata = self.obj['name']

        result['conditions'] = [
            # actionid: host metadata - 24, like - 2
            {'conditiontype': 24, 'operator': 2, 'value': metadata}
        ]

        result['operations'] = [
            {
                # actionid: link template - 6
                'operationtype': 6, 'esc_step_to': 1, 'esc_step_from': 1, 'esc_period': 0,
                'optemplate': [self.zapi.get_id('template', self.obj['name'], with_id=True)],
            },
            # Add host
            {'esc_step_from': 1,
             'esc_period': 0,
             'operationtype': 2,
             'esc_step_to': 1},
            # Disable host
            {'esc_step_from': 1,
             'esc_period': 0,
             'operationtype': 9,
             'esc_step_to': 1},
        ]

        # if contains add_to_group
        if isinstance(
                self.obj['autoreg'],
                dict) and self.obj['autoreg'].get('add_to_group'):
            result['operations'].append(
                {
                    # actionid: add to hostgroup - 4
                    'operationtype': 4, 'esc_step_to': 1, 'esc_step_from': 1, 'esc_period': 0,
                    'opgroup': ZabbixGroups(
                        self.zapi,
                        self.obj.get('autoreg')['add_to_group']).apply()
                },
            )
        return result

    def apply(self):
        """
        Push action object to zabbix server.
        """

        result = None
        req = self._create_request()

        log.info("Auto-registration: '%s'", req['name'])

        # Get 'action' object id
        log.debug('ZabbixAutoreg._create_request: %s', req)
        obj_id = self.zapi.get_id('action', req['name'])

        if obj_id:
            result = self.zapi.action.update(
                actionid=obj_id,
                eventsource=2,
                status=0,
                esc_period=0,
                evaltype=0,
                conditions=req['conditions'],
                operations=req['operations'])
        else:
            result = self.zapi.action.create(
                name=req['name'],
                eventsource=2,
                status=0,
                esc_period=0,
                evaltype=0,
                conditions=req['conditions'],
                operations=req['operations'])
        return result


import os
import gym
import numpy as np
import torch
import matplotlib.pyplot as plt
import argparse
from copy import  deepcopy
import torch.multiprocessing as mp
from torch.utils.tensorboard import SummaryWriter
from OppModeling.atari_wrappers import make_ftg_ram, make_ftg_ram_nonstation
from OppModeling.SAC import MLPActorCritic

def test_proc(global_ac, env, args, device):
    scores, wins, m_score, win_rate = [], [], 0, 0
    o, ep_ret, ep_len = env.reset(), 0, 0
    discard = False
    local_t = 0
    local_e = 0
    while local_e < args.test_episode:
        with torch.no_grad():
            a = global_ac.get_action(o, greedy=True, device=device)
        # Step the env
        o2, r, d, info = env.step(a)
        if info.get('no_data_receive', False):
            discard = True
        ep_ret += r
        ep_len += 1
        d = False if (ep_len == args.max_ep_len) or discard else d
        o = o2
        local_t += 1
        # End of trajectory handling
        if d or (ep_len == args.max_ep_len) or discard:
            # logger.store(EpRet=ep_ret, EpLen=ep_len)
            local_e += 1
            if info.get('win', False):
                wins.append(1)
            else:
                wins.append(0)
            scores.append(ep_ret)
            o, ep_ret, ep_len = env.reset(), 0, 0
            discard = False
    m_score = np.mean(scores)
    win_rate = np.mean(wins)
    return m_score, win_rate, local_t

def test_summary(p2, steps, m_score, win_rate, writer, args, e):
    print("\n" + "=" * 20 + "TEST SUMMARY" + "=" * 20)
    summary = "opponent:\t{}\n# test episode:\t{}\n# total steps:\t{}\nmean score:\t{:.1f}\nwin_rate:\t{}".format(
        p2, args.test_episode, steps, m_score, win_rate)
    print(summary)
    print("=" * 20 + "TEST SUMMARY" + "=" * 20 + "\n")
    writer.add_scalar("Test/mean_score", m_score.item(), e)
    writer.add_scalar("Test/win_rate", win_rate.item(), e)
    writer.add_scalar("Test/total_step", steps, e)

def test_func(global_ac, rank, e, p2, args, device, tensorboard_dir, ):
    torch.manual_seed(args.seed + rank)
    np.random.seed(args.seed + rank)
    print("set up Test process env")
    temp_dir = os.path.join(tensorboard_dir, "test_{}".format(p2))
    if not os.path.exists(temp_dir):
        os.makedirs(temp_dir)
    writer = SummaryWriter(log_dir=temp_dir)

    # Main loop: collect experience in env and update/log each epoch
    if args.exp_name == "test":
        env = gym.make("CartPole-v0")
    elif p2 == "Non-station":
        env = make_ftg_ram_nonstation(args.env, p2_list=args.list, total_episode=args.test_episode,stable=args.stable)
    else:
        env = make_ftg_ram(args.env, p2=p2)
    print("TESTING process {} start to test, opp: {}".format(rank, p2))
    m_score, win_rate, steps = test_proc(global_ac, env, args, device)
    test_summary(p2, steps, m_score, win_rate, writer, args, e)
    env.close()
    del env
    print("TESTING process {} finished, opp: {}".format(rank, p2))

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    # running setting
    parser.add_argument('--cuda', default=False, action='store_true')
    parser.add_argument('--seed', '-s', type=int, default=0)
    parser.add_argument('--n_process', type=int, default=1)
    # basic env setting
    parser.add_argument('--env', type=str, default="FightingiceDataFrameskip-v0")
    parser.add_argument('--p2', type=str, default="Toothless")
    # non station agent settings
    parser.add_argument('--non_station', default=False, action='store_true')
    parser.add_argument('--stable', default=False, action='store_true')
    parser.add_argument('--station_rounds', type=int, default=1000)
    parser.add_argument('--list', nargs='+')
    # training setting
    parser.add_argument('--hid', type=int, default=256)
    parser.add_argument('--l', type=int, default=2, help="layers")
    parser.add_argument('--test_episode', type=int, default=10)
    parser.add_argument('--max_ep_len', type=int, default=1000)
    # CPC setting
    parser.add_argument('--cpc', default=False, action="store_true")
    parser.add_argument('--z_dim', type=int, default=64)
    parser.add_argument('--c_dim', type=int, default=32)
    parser.add_argument('--timestep', type=int, default=10)
    # Saving settings
    parser.add_argument('--exp_name', type=str, default='test')
    parser.add_argument('--save-dir', type=str, default="./experiments")
    parser.add_argument('--traj_dir', type=str, default="./experiments")
    parser.add_argument('--model_para', type=str, default="test_sac.torch")
    parser.add_argument('--cpc_para', type=str, default="test_cpc.torch")
    parser.add_argument('--numpy_para', type=str, default="test.numpy")
    parser.add_argument('--train_indicator', type=str, default="test.data")
    args = parser.parse_args()

    mp.set_start_method("forkserver")
    os.environ['OMP_NUM_THREADS'] = '1'
    os.environ['MKL_NUM_THREADS'] = '1'
    experiment_dir = os.path.join(args.save_dir, args.exp_name)
    tensorboard_dir = os.path.join(experiment_dir, "evaluation")
    if not os.path.exists(tensorboard_dir):
        os.makedirs(tensorboard_dir)
    file_list = os.listdir(experiment_dir)
    print()
    model_para = [i for i in file_list if "model_torch" in i]
    model_para = ["model_torch_{}".format(i*100) for i in range(len(model_para)) if "model_torch_{}".format(i*100) in model_para ]
    obs_dim = 143
    act_dim = 56
    ac_kwargs = dict(hidden_sizes=[args.hid] * args.l)
    p2_list = ["Non-station"] + args.list
    global_ac = MLPActorCritic(obs_dim, act_dim, **ac_kwargs)

    scores, win_rates,rounds = [[], [], [], [],], [[], [], [], []], [[], [], [], []]
    for e in range(2):
        global_ac.load_state_dict(torch.load(os.path.join(experiment_dir, model_para[e])))
        global_ac.share_memory()
        for index, p2 in enumerate(p2_list):
            if args.exp_name == "test":
                env = gym.make("CartPole-v0")
            elif p2 == "Non-station":
                env = make_ftg_ram_nonstation(args.env, p2_list=args.list, total_episode=args.test_episode,
                                              stable=args.stable)
            else:
                env = make_ftg_ram(args.env, p2=p2)
            m_score, win_rate, steps = test_proc(global_ac, env, args, torch.device("cpu"))
            scores[index].append(m_score)
            win_rates[index].append(win_rate)
            rounds[index].append(e*100)
            env.close()
            del env
        print("First Round finished")
        torch.save((scores, win_rates, rounds,), os.path.join(tensorboard_dir, "test_data_{}".format(e*100)))

    for index in range(len(scores)):
        plt.plot(rounds[index], scores[index], label=p2_list[index])
    plt.legend(title='Opponent')
    plt.savefig(os.path.join(tensorboard_dir, "evaluation_plot"))


import sdl2
import sdlboy_console_component
import sdlboy_time
import hw_video as vid
import ctypes
import math

class Color:
    def __init__(self, r, g, b, a=255):
        self.r = r
        self.g = g
        self.b = b
        self.a = a
        self.c_argb = (ctypes.c_uint)((a<<24)|(r<<16)|(g<<8)|b)

class Tileview(sdlboy_console_component.ConsoleComponent):
    pixels = None
    tiles_texture = None
    tiles_texture_rect = None
    tiles_color_map = None
    tiles_num_rows = 0
    tiles_num_cols = 0
    tiles_scale = 0
    tiles_spacing = 0
    last_render_time = 0
    def on_init(self):
        self.tiles_color_map = [None]*4
        self.tiles_color_map[3] = Color(0x00, 0x00, 0x00)
        self.tiles_color_map[2] = Color(0x55, 0x55, 0x55)
        self.tiles_color_map[1] = Color(0xAA, 0xAA, 0xAA)
        self.tiles_color_map[0] = Color(0xFF, 0xFF, 0xFF)
    def on_visible(self):
        if(self.tiles_texture == None):
            self.tiles_texture_rect = sdl2.SDL_Rect(0,0,0,0)
            self.tiles_texture_dst_rect = sdl2.SDL_Rect(0,0,0,0)
    def on_update(self):
        if(sdlboy_time.since_start - self.last_render_time > 0.25):
            self.set_render_required()
    def on_render(self):
        self.last_render_time = sdlboy_time.since_start
        pixels = self.pixels
        color_map = self.tiles_color_map
        pattern_ptr = 0
        pixel_index = 0
        col_counter = 0
        for i in range(0, 512):
            # draw tile row by row
            for j in range(0, 8):
                byte_1 = vid.videoram[pattern_ptr]
                byte_2 = vid.videoram[pattern_ptr+1]
                pixels[pixel_index+0] = color_map[((byte_2>>6)&0x2)|((byte_1>>7)&0x1)].c_argba
                pixels[pixel_index+1] = color_map[((byte_2>>5)&0x2)|((byte_1>>6)&0x1)].c_argba
                pixels[pixel_index+2] = color_map[((byte_2>>4)&0x2)|((byte_1>>5)&0x1)].c_argba
                pixels[pixel_index+3] = color_map[((byte_2>>3)&0x2)|((byte_1>>4)&0x1)].c_argba
                pixels[pixel_index+4] = color_map[((byte_2>>2)&0x2)|((byte_1>>3)&0x1)].c_argba
                pixels[pixel_index+5] = color_map[((byte_2>>1)&0x2)|((byte_1>>2)&0x1)].c_argba
                pixels[pixel_index+6] = color_map[((byte_2>>0)&0x2)|((byte_1>>1)&0x1)].c_argba
                pixels[pixel_index+7] = color_map[((byte_2<<1)&0x2)|((byte_1>>0)&0x1)].c_argba
                # point to next pair of bytes
                pattern_ptr += 2
                # point to next row
                pixel_index += self.tiles_texture_rect.w
            col_counter += 1
            if(col_counter == self.tiles_num_cols):
                col_counter = 0
                pixel_index += self.tiles_texture_rect.w*(self.tiles_spacing-1)
                pixel_index += 8
            else:
                pixel_index -= self.tiles_texture_rect.w*8
                pixel_index += (8+self.tiles_spacing)
        sdl2.SDL_UpdateTexture(
            self.tiles_texture,
            self.tiles_texture_rect,
            pixels,
            self.tiles_texture_rect.w*4
        )
        sdl2.SDL_RenderCopy(
            self.renderer,
            self.tiles_texture,
            self.tiles_texture_rect,
            self.tiles_texture_dst_rect
        )
    def on_resize(self):
        pass
    def set_tiles_dimensions(self, num_rows, num_cols, scale, spacing):
        if(num_rows == self.tiles_num_rows
           and num_cols == self.tiles_num_cols
           and scale == self.tiles_scale
           and spacing == self.tiles_spacing
        ):
            return
        self.tiles_num_rows = num_rows
        self.tiles_num_cols = num_cols
        self.tiles_scale = scale
        self.tiles_spacing = spacing
        pixels_inital = [0]*(0x8000)
        self.pixels = ((ctypes.c_uint)*(256*256))(*pixels_inital)
        self.tiles_texture_rect.w = self.tiles_num_cols*(8+self.tiles_spacing)-self.tiles_spacing
        self.tiles_texture_rect.h = self.tiles_num_rows*(8+self.tiles_spacing)-self.tiles_spacing
        self.tiles_texture_dst_rect.w = self.tiles_texture_rect.w*self.tiles_scale
        self.tiles_texture_dst_rect.h = self.tiles_texture_rect.h*self.tiles_scale
        if(self.tiles_texture):
            sdl2.SDL_DestroyTexture(self.tiles_texture)
        self.tiles_texture = sdl2.SDL_CreateTexture(
            self.renderer,
            sdl2.SDL_PIXELFORMAT_ARGB8888,
            sdl2.SDL_TEXTUREACCESS_TARGET,
            self.tiles_texture_rect.w,
            self.tiles_texture_rect.h
        )
        self.preferred_h = self.tiles_texture_dst_rect.h
    def on_present_width(self, w):
        spacing = 1
        scale = 2
        tile_width = (8+spacing)*scale
        try:
            cols = math.floor(w/tile_width)
            cols = cols - (cols%8) # make cols multiple of 8 (round down)
            rows = math.ceil(512/cols)
        except Exception as e:
            cols = 64
            rows = 8
            print(e)
        self.set_tiles_dimensions(rows, cols, scale, spacing)


# -*- coding: utf-8 -*-
"""
Created on Sun Feb 18 10:28:32 2018

@author: User
"""
# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import random
from deap import creator, tools, base, gp
import operator

def preprocessData():
    #Importing the dataset
    dataset = pd.read_csv('train.csv')
    X = dataset[['Pclass','Age', 'Sex','SibSp','Parch','Fare']].values
    Y = dataset.iloc[:, 1].values

    #Dealing with encoding the labels
    from sklearn.preprocessing import LabelEncoder#, OneHotEncoder
    labelencoder_X = LabelEncoder()
    X[:,2] = labelencoder_X.fit_transform(X[:,2])

    #Dealing with missing datas
    from sklearn.preprocessing import Imputer
    imputer = Imputer()
    imputer=Imputer(missing_values='NaN',
                    strategy='mean', axis=0)
    imputer=imputer.fit(X[:,1:2])
    X[:,1:2]=imputer.transform(X[:,1:2])
    return X, Y

#Number of attribute param
IND_SIZE = 6

#Creating the individuals
#lists of floats with a minimizing objectives fitness
creator.create("FitnessMin", base.Fitness, weights = (1.0,))
creator.create("Individual", gp.PrimitiveTree, fitness = creator.FitnessMin)

#initialize a primitive set and add all the primitives our trees can use
pset = gp.PrimitiveSet("MAIN", 6, "IN")
pset.addPrimitive(np.add, arity=2)
pset.addPrimitive(np.subtract, arity=2)
pset.addPrimitive(np.multiply, arity=2)
pset.addPrimitive(np.negative, arity=1)
#Addional primitives? ========================================================
pset.addPrimitive(np.absolute, arity=1)
pset.addPrimitive(np.log, arity=1)
pset.renameArguments(ARG0='x')
pset.renameArguments(ARG1='y')
pset.addTerminal(0)
pset.addTerminal(1)

toolbox = base.Toolbox()
#Returns a primitive tree based on a primitive set and a minimum and maximum tree depth
#Maybe change the size of the tree?
toolbox.register("expr", gp.genHalfAndHalf, pset=pset, min_=1, max_=5)

toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.expr)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("compile", gp.compile, pset=pset)

inputs, outputs = preprocessData()

def evaluateInd(individual, pset):
    func = gp.compile(expr=individual, pset=pset)
    #sqerrors = (func(X) - Y)**2
    #print(inputs, outputs)
    #print(individual)
    #print([func(*in_>0) for in_ in inputs])
    #print([out for out in outputs])
    #result = np.array([func(*in_>0) for in_ in inputs]) & np.array([out for out in outputs])
    #return np.sum(result)
    return sum((func(*in_)>0) == out for in_, out in zip(inputs, outputs)),
    '''
    for i in range(len(X)):
        #sqerrors += ((func([1,2]) - Y[i]))**2
        print("=========", func(X[i]))
        sqerrors += ((func(X[i]) - Y[i]))**2
    return (np.sqrt(sqerrors) / len(X),)
    '''
    #return (np.sqrt(sqerrors) / len(X),)

toolbox.register("evaluate", evaluateInd, pset = pset)

'''
CHANGE THE THINGS HERE!!!!!!
==============================================================================
'''
#Change the params here for mating, mutating, and selecting
#toolbox.register("mate", tools.cxBlend, alpha = 0.5)
toolbox.register("mate", gp.cxOnePoint)
#there is a variety of mutation operators in the deap.tools module
toolbox.register("expr_mut", gp.genFull, min_=0, max_=2)
#https://github.com/DEAP/deap/blob/master/deap/gp.py <-- more mutator methods
toolbox.register("mutate", gp.mutUniform, expr=toolbox.expr_mut, pset=pset)
toolbox.register("select", tools.selTournament, tournsize=3)

#Optional, limits tree size
toolbox.decorate("mate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))
toolbox.decorate("mutate", gp.staticLimit(key=operator.attrgetter("height"), max_value=17))
'''
==============================================================================
'''

def main():
    gen = range(50)
    avg_list = []
    max_list = []
    min_list = []

    pop = toolbox.population(n=10)

    # Evaluate the entire population
    fitnesses = list(map(toolbox.evaluate, pop))
    for ind, fit in zip(pop, fitnesses):
        ind.fitness.values = fit

    # Begin the evolution
    for g in gen:
        print("-- Generation %i --" % g)

        # Select the next generation individuals
        offspring = toolbox.select(pop, len(pop))
        # Clone the selected individuals
        offspring = list(map(toolbox.clone, offspring))

        # Apply crossover and mutation on the offspring
        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random.random() < 0.5:
                toolbox.mate(child1, child2)
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:
            if random.random() < 0.2:
                toolbox.mutate(mutant)
                del mutant.fitness.values

        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            print(ind)
            ind.fitness.values = fit

        # Replace population
        pop[:] = offspring

        # Gather all the fitnesses in one list and print the stats
        fits = [ind.fitness.values[0] for ind in pop]

        length = len(pop)
        mean = sum(fits) / length
        sum2 = sum(x*x for x in fits)
        std = abs(sum2 / length - mean**2)**0.5
        g_max = max(fits)
        g_min = min(fits)

        avg_list.append(mean)
        max_list.append(g_max)
        min_list.append(g_min)

        print("  Min %s" % g_min)
        print("  Max %s" % g_max)
        print("  Avg %s" % mean)
        print("  Std %s" % std)

    print("-- End of (successful) evolution --")

    best_ind = tools.selBest(pop, 1)[0]
    print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

    plt.plot(gen, avg_list, label="average")
    plt.plot(gen, min_list, label="minimum")
    plt.plot(gen, max_list, label="maximum")
    plt.xlabel("Generation")
    plt.ylabel("Fitness")
    plt.legend(loc="upper right")
    plt.show()

main()


import logging
import sqlite3
from uuid import uuid4

log = logging.getLogger(__name__)

def create_connection():
    conn = sqlite3.connect("db/tournament_tool.db", check_same_thread=False)
    return conn

conn = create_connection()

class Tournament:
    def __init__(self):
        pass

    def check_active_tournament(self):
        cursor = conn.cursor()

        cursor.execute(
            "SELECT tournament_id FROM tournaments WHERE tournament_status = 'ONGOING'")

        tournament = cursor.fetchone()

        if not tournament:
            print("NO ACTIVE TOURNAMENT")
            return None

        return tournament[0]

    def init_players(self, tour_id):
        cursor = conn.cursor()

        with open("players.txt") as f:
            for conf in f.readlines():

                name = conf.split(" ")[0].replace("\n", "")
                cursor.execute(
                    """
                        INSERT INTO players (player_name, tournament_id) VALUES (?, ?)
                    """, (name, tour_id))
                conn.commit()

    def init_options(self, tournament_id):
        cursor = conn.cursor()

        cursor.execute("""
                INSERT INTO tournament_options (
                    tournament_id,
                    map,
                    time_limit
                ) VALUES (
                    ?,
                    1,
                    120
                )
                """, (tournament_id, ))
        conn.commit()

    def init_matches(self, tour_id):
        cursor = conn.cursor()

        cursor.execute(
            "SELECT player_id FROM players WHERE tournament_id = ?", (tour_id, ))

        players = cursor.fetchall()
        match_count = int(len(players) / 2)

        print(f"PLAYER COUNT: {len(players)}")
        print(f"MATCH COUNT: {match_count}")

        ct_side = [p[0] for p in players[:match_count]]
        t_side = [p[0] for p in players[match_count:]]

        for pair in range(match_count):

            match_name = f"{ct_side[pair]} VS {t_side[pair]}"
            match_id = str(uuid4())
            cursor.execute("""
                INSERT INTO matches (
                    match_id,
                    match_name,
                    map_id,
                    tournament_id
                ) VALUES (
                    ?,
                    ?,
                    1,
                    ?
                )
            """, (match_id, match_name, tour_id))
            conn.commit()

            params = [
                (match_id, ct_side[pair], "CT"),
                (match_id, t_side[pair], "T")
            ]

            cursor.executemany("""
                INSERT INTO players_in_matches (
                    match_id,
                    player_id,
                    side
                ) VALUES
                    (?, ?, ?)
            """, params)
            conn.commit()

    def activate_tournament(self, tour_id):
        cursor = conn.cursor()

        cursor.execute(
            "UPDATE tournaments SET tournament_status = 'ONGOING' WHERE tournament_id = ?", (tour_id, ))
        conn.commit()

    def init(self):
        cursor = conn.cursor()

        tour_id = str(uuid4())

        cursor.execute(
            "INSERT INTO tournaments (tournament_id, tournament_name) VALUES (?, 'DEMO TOURNAMENT')", (tour_id, ))
        conn.commit()

        self.init_options(tour_id)
        self.init_players(tour_id)
        self.init_matches(tour_id)
        self.activate_tournament(tour_id)

if __name__ == "__main__":
    tournament = Tournament()

    tournament.init()


from magicbus.compat import ntob
import os
thismodule = os.path.abspath(__file__)
import sys

import pytest

from magicbus import bus
from magicbus.plugins import opsys
from magicbus.test import Process, WebAdapter, WebService
from magicbus.test import WebHandler

from magicbus.plugins import loggers
loggers.StdoutLogger(bus).subscribe()

pidfile = opsys.PIDFile(bus, os.path.join(thismodule + '.pid'))

class Handler(WebHandler):

    bus = bus

    def do_GET(self):
        if self.path == '/':
            self.respond('Hello World')
        elif self.path == '/pid':
            self.respond(str(os.getpid()))
        elif self.path == '/exit':
            self.respond('ok')
            self.bus.transition('EXITED')
        else:
            self.respond(status=404)
service = WebService(handler_class=Handler)

@pytest.mark.xfail(
    sys.version_info[0] > 2, reason="""
    Hangs under Python 3 because it loops too fast causing a race
    condition in `magicbus.plugins.opsys.PIDFile.join()`.

    Refs:
    * https://github.com/cherrypy/magicbus/issues/7
    * https://github.com/cherrypy/magicbus/pull/8
    """,
    run=False,
)
@pytest.mark.skipif(os.name != 'posix', reason='not on POSIX')
def test_daemonize():
    # Spawn the process and wait, when this returns, the original process
    # is finished.  If it daemonized properly, we should still be able
    # to access pages.
    p = Process([sys.executable, thismodule, 'daemonize'])
    p.start()
    pidfile.wait()
    try:
        # Just get the pid of the daemonization process.
        resp = service.do_GET('/pid')
        assert resp.status == 200
        page_pid = int(resp.read())
        with open(pidfile.pidfile, 'rb') as pid_file:
            actual_pid = pid_file.read()
        assert ntob(str(page_pid)) == actual_pid
    finally:
        # Shut down the spawned process
        service.do_GET('/exit')
    pidfile.join()

    # Wait until here to test the exit code because we want to ensure
    # that we wait for the daemon to finish running before we fail.
    p.process.wait()
    assert p.process.returncode == 0, (
        'Daemonized parent process returned exit code {rc!s}.'.
        format(rc=p.process.returncode)
    )

if __name__ == '__main__':
    mode = sys.argv[1]
    if mode == 'daemonize':
        opsys.Daemonizer(bus).subscribe()
    pidfile.subscribe()
    WebAdapter(bus, service).subscribe()
    bus.transition('RUN')
    bus.block()


# coding=utf-8
import re, sys
reload(sys)
sys.setdefaultencoding("utf-8")

import scrapy

class StackOverflowSpider(scrapy.Spider):
    name = 'priceza'
    start_urls = ['http://www.priceza.com.my/search', 'http://www.priceza.com.sg/search', 'http://www.priceza.com.ph/search', 'http://www.priceza.com.vn/search', 'http://www.priceza.com/search', 'http://www.priceza.co.id/search']

    def parse(self, response):
        for item in response.css('div.products div.item.group'):

            prices = item.css('small a::text').extract()[0]
            prices = re.sub("[^0-9]", "", prices)

            try:
                prices = int(prices)

                if prices > 1:
                    yield {
                        'name': item.css('h3::text').extract()[0],
                        'prices': prices,
                        'url' : response.urljoin(item.css('a::attr(href)').extract()[0])
                    }
            except:
                pass

        next_page = response.css('div.paging a.next::attr(href)')
        if len(next_page) > 0:
            full_url = response.urljoin(next_page[0].extract())
            yield scrapy.Request(full_url, callback=self.parse)