# Scenario handler
import numpy as np
class scenarioHandler(object):
    def __init__(self, df, estNS=False, l=0.7308):
        self.data = df
        self.periods = np.arange(df['Period'].min(),df['Period'].max()+1,1)
        try:
            self.scenario = np.arange(df['Scenario'].min(),df['Scenario'].max()+1,1)
        except:
            pass
        self.stocks = df.columns[2:12]
        self.bonds = df.columns[12:17]
        self.bondDuration = []
        for b in self.bonds:
            try:
                self.bondDuration.append(int(b[-2:]))
            except:
                pass

        if estNS:
            NSParameters = np.array([])
            M = []
            for t in self.bondDuration:
                M.append([1,(1-np.exp(-l*t))/(l*t+0.0000001),((1-np.exp(-l*t))/(l*t+0.0000001)) - np.exp(-l*t)])
            M = np.array(M)
            for p in range(len(self.periods)):
                R = []
                for t in range(len(self.bondDuration)):
                    R.append(df[self.bonds[t]].iloc[p])
                R = np.array(R)
                NSParameters = np.append(NSParameters,np.matmul(np.matmul(np.linalg.inv(np.matmul(M.T,M)),M.T),R))
            self.NSParameters = NSParameters.reshape(-1, 3)

            # Bond values
            for t in range(len(self.bondDuration)):
                zcbValue = []
                for p in range(len(self.periods)):
                    zcbValue.append(100/pow(1+df[self.bonds[t]].iloc[p],self.bondDuration[t]))
                df[self.bonds[t]] = zcbValue
                df['b1'] = self.NSParameters[:,0]
                df['b2'] = self.NSParameters[:,1]
                df['b3'] = self.NSParameters[:,2]

        else:
            self.NSParameters = self.data[df.columns[17:20]].to_numpy()

        self.stockLogReturns = np.log(df[self.stocks]).diff().dropna()
        self.bondLogReturns = np.log(df[self.bonds]).diff().dropna()

    def split(self):
        self.scenarioArray = []
        for i in self.scenario:
            self.scenarioArray.append(scenarioHandler(self.data[(self.data['Scenario'] == i)]))
        return


from Utilities import dto_respond

def edit_response(
    question_i=None,
    answer_i=None,
    category_i=None,
    quote_i=None,
    freeText_i=None,
    numberQuestion_i=None,
    boolean_i=None,
    meanProbability_i=None,
    value_i=None,
    denomination_i=None,
) -> dict:
    """
    This function edit the response
    Args:
        inputs
    Returns:
        dict: This is a dictionary with text and mean probability.
    """

    respond = dto_respond.Respond(
        question="",
        answer="",
        category=0,
        quote="",
        freeText=False,
        numberQuestion=0,
        boolean=False,
        meanProbability=0,
        value=None,
        denomination=None,
    ).__dict__

    if question_i is not None:
        respond["question"] = question_i
    if answer_i is not None:
        respond["answer"] = answer_i
    if category_i is not None:
        respond["category"] = category_i
    if quote_i is not None:
        respond["quote"] = quote_i
    if freeText_i is not None:
        respond["freeText"] = freeText_i
    if numberQuestion_i is not None:
        respond["numberQuestion"] = numberQuestion_i
    if boolean_i is not None:
        respond["boolean"] = boolean_i
    if meanProbability_i is not None:
        respond["meanProbability"] = meanProbability_i
    if value_i is not None:
        respond["value"] = value_i
    if denomination_i is not None:
        respond["denomination"] = denomination_i

    return respond


import os

import yaml
from troposphere import Base64, Join, Ref, Template, GetAtt, Output, Export, Tags, Split, Select, ImportValue
from troposphere import (
    ec2, elasticloadbalancingv2, autoscaling, iam, ecs, s3, cloudwatch, sns, kms, certificatemanager, route53, cloudfront)

from util import create_or_update_stack

# Load stack config
stack_config_file = os.path.join(
    os.path.dirname(os.path.realpath(__file__)),
    'stack_config.yml')
CONFIG = yaml.load(open(stack_config_file), Loader=yaml.Loader)['config']

###
# Initialize template
###
t = Template()
t.add_version('2010-09-09')

###
# Shared Tags
###
shared_tags_args = {
    'StackName': CONFIG['STACK_NAME'],
    'StackType': 'fusebox',
}

###
# VPC
###

FuseboxVPC = t.add_resource(ec2.VPC(
    'FuseboxVPC',
    CidrBlock=CONFIG['FUSEBOX_VPC_CIDR_BLOCK'],
    EnableDnsSupport='true',
    EnableDnsHostnames='true',
    Tags=Tags(Name=f'{CONFIG["STACK_NAME"]}-app-vpc', **shared_tags_args),
))

# Internet Gateway
FuseboxIGW = t.add_resource(ec2.InternetGateway(
    'FuseboxIGW',
    Tags=Tags(Name=f'{CONFIG["STACK_NAME"]}-fusebox-igw', **shared_tags_args),
))
FuseboxIGWAttachment = t.add_resource(ec2.VPCGatewayAttachment(
    'FuseboxIGWAttachment',
    VpcId=Ref(FuseboxVPC),
    InternetGatewayId=Ref(FuseboxIGW),
))

# Route Table
FuseboxRouteTable = t.add_resource(ec2.RouteTable(
    'FuseboxRouteTable',
    VpcId=Ref(FuseboxVPC),
    Tags=Tags(Name=f'{CONFIG["STACK_NAME"]}-fusebox-rtb', **shared_tags_args),
))
t.add_resource(ec2.Route(
    'FuseboxRouteToIGW',
    RouteTableId=Ref(FuseboxRouteTable),
    GatewayId=Ref(FuseboxIGW),
    DestinationCidrBlock='0.0.0.0/0',
    DependsOn=[FuseboxIGWAttachment],
))

# Subnets
FuseboxVPCSubnet = t.add_resource(ec2.Subnet(
    'FuseboxVPCSubnet',
    VpcId=Ref(FuseboxVPC),
    CidrBlock=CONFIG['FUSEBOX_VPC_CIDR_BLOCK'],
    AvailabilityZone=CONFIG['VPC_SUBNET_AZ'],
    MapPublicIpOnLaunch='true',
    Tags=Tags(Name=f'{CONFIG["STACK_NAME"]}-app-subnet-1a', **shared_tags_args),
))
t.add_resource(ec2.SubnetRouteTableAssociation(
    'FuseboxVPCSubnetAssociation',
    SubnetId=Ref(FuseboxVPCSubnet),
    RouteTableId=Ref(FuseboxRouteTable),
))

# ACL Omitted

###
# EC2 Instance
###

FuseboxRole = t.add_resource(iam.Role(
    'FuseboxRole',
    Path='/',
    ManagedPolicyArns=[
        'arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM'
    ],
    AssumeRolePolicyDocument={
        'Version': '2012-10-17',
        'Statement': [
            {
                'Action': 'sts:AssumeRole',
                'Principal': {'Service': 'ec2.amazonaws.com'},
                'Effect': 'Allow',
            }
        ]
    }
))
FuseboxInstanceProfile = t.add_resource(iam.InstanceProfile(
    'FuseboxInstanceProfile',
    Path='/',
    Roles=[Ref(FuseboxRole)],
))

# SG
FuseboxSecurityGroup = t.add_resource(ec2.SecurityGroup(
    'FuseboxSecurityGroup',
    GroupDescription='Fusebox security group',
    VpcId=Ref(FuseboxVPC),
    Tags=Tags(shared_tags_args),
))
t.add_resource(ec2.SecurityGroupIngress(
    'FuseboxSecurityGroupIngressSSHPorts',
    GroupId=Ref(FuseboxSecurityGroup),
    CidrIp=CONFIG['FUSEBOX_INBOUND_IP'],
    IpProtocol='tcp',
    FromPort=22,
    ToPort=22,
))

FuseboxEC2Instance = t.add_resource(ec2.Instance(
    'FuseboxInstance',
    AvailabilityZone=CONFIG['VPC_SUBNET_AZ'],
    SubnetId=Ref(FuseboxVPCSubnet),
    BlockDeviceMappings=[
        ec2.BlockDeviceMapping(
            DeviceName='/dev/sda1',
            Ebs=ec2.EBSBlockDevice(
                DeleteOnTermination=False,
                Encrypted=True,
                VolumeSize=10,
                VolumeType='gp2'
            )
        ),
    ],
    CreditSpecification=ec2.CreditSpecification(CPUCredits='standard'),
    DisableApiTermination=True,
    EbsOptimized=False,
    IamInstanceProfile=Ref(FuseboxInstanceProfile),
    ImageId=CONFIG['FUSEBOX_AMI'],
    InstanceInitiatedShutdownBehavior='stop',
    InstanceType='t3.nano',  # nano: 2vCPU, 0.5gb, $0.0052/hr = $3.74/mo
    KeyName=CONFIG['FUSEBOX_SSH_KEY_NAME'],
    # LaunchTemplate=,
    Monitoring=False,
    SecurityGroupIds=[GetAtt(FuseboxSecurityGroup, 'GroupId')],
    SourceDestCheck=True,
    Tenancy='default',
    Tags=Tags(
        Name=f'{CONFIG["STACK_NAME"]}-Fusebox',
        InstanceResponsibility='Fusebox',
        **shared_tags_args)
))

FuseboxEIP = t.add_resource(ec2.EIP(
    'FuseboxEIP',
    InstanceId=Ref(FuseboxEC2Instance),
    Domain='vpc',
    DependsOn=[FuseboxVPC],
))

###
# Route 53
###
t.add_resource(route53.RecordSetGroup(
    'FuseboxRecordSetGroup',
    HostedZoneId=CONFIG['HOSTED_ZONE_ID'],
    RecordSets=[route53.RecordSet(
        'HostedZoneAliasToFusebox',
        Name=f'{CONFIG["DOMAIN_NAME"]}.',
        Type='A',
        ResourceRecords=[Ref(FuseboxEIP)],
        TTL=300)]
))

###
# S3 Bucket
###
StorageBucketName = CONFIG["STORAGE_BUCKET_NAME"]
StorageBucket = t.add_resource(s3.Bucket(
    'StorageBucket',
    BucketName=StorageBucketName,
    DeletionPolicy='Retain',
    AccessControl="Private",
    VersioningConfiguration=s3.VersioningConfiguration(
        Status='Enabled'
    ),
    Tags=Tags(**shared_tags_args),
))
t.add_resource(s3.BucketPolicy(
    'StorageBucketPolicy',
    Bucket=Ref(StorageBucket),
    PolicyDocument={
        "Statement": [
            {
                "Action": "s3:*",
                "Effect": "Allow",
                "Resource": [
                    Join("", ["arn:aws:s3:::", Ref(StorageBucket), "/*"]),
                    Join("", ["arn:aws:s3:::", Ref(StorageBucket)]),
                ],
                "Principal": {
                    "AWS": GetAtt(FuseboxRole, 'Arn')
                },
            }
        ]
    },
))

###
# Outputs
###
t.add_output(Output(
    'FuseboxUrl',
    Description='Fusebox url',
    Value=CONFIG["DOMAIN_NAME"]
))

if __name__ == '__main__':

    stack_policy = '''{ "Statement" : [
        {
            "Effect" : "Allow",
            "Principal" : "*",
            "Action" : "Update:*",
            "Resource" : "*"
        }
    ]}'''

    create_or_update_stack(
        stack_name=CONFIG['STACK_NAME'],
        template=t,
        stack_policy=stack_policy,
        aws_region_name=CONFIG['AWS_REGION_NAME'],
        notification_arn=CONFIG.get('CLOUDFORMATION_NOTIFICATION_ARN'),
        cf_template_bucket=CONFIG['CF_TEMPLATE_BUCKET'])


#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt

num_events = np.zeros(256)
num_hits_col = np.zeros(256)
num_hits_sens = np.zeros(256)

filename = '../data/2022-01-30/hitpix2-1-crosstalk/log.txt'

with open(filename) as f:
    for line in f:
        line = line.strip()
        if line.startswith('otherpixel') or line.startswith('running') or line.startswith('dac_cfg'):
            continue
        i_frame, testpixel, testpixel_abs, otherpixels, otherpixels_col = map(int, line.split())
        if testpixel == 1:
            num_events[testpixel_abs] += 1
            num_hits_col[testpixel_abs] += otherpixels_col
            num_hits_sens[testpixel_abs] += otherpixels
        elif testpixel != 0:
            print(testpixel, otherpixels, otherpixels_col)

# num_events_per_bit = np.zeros(8)
# for i_bit in range(8):
#     for i, v in enumerate(num_events):
#         if ((i >> i_bit) & 0x01) == 0x01:
#             num_events_per_bit[i_bit] += v

# plt.bar(np.arange(8), num_events_per_bit / np.sum(num_events), width=1)

plt.bar(np.arange(256), num_events, width=1)
plt.semilogy()
plt.axhline(0.5)
plt.ylabel('fraction X of events with crosstalk had bit N set')
plt.xlabel('bit [n] set in PuT counter beforehand')
plt.show()


import torch
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import argparse
import pandas as pd
import time
import os

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

def read_encode(file_name,vocab,words,corpus,threshold):

    wID = len(vocab)

    if threshold > -1:
        with open(file_name,'rt') as f:
            for line in f:
                line = line.replace('\n','')
                tokens = line.split(' ')
                for t in tokens:
                    try:
                        elem = words[t]
                    except:
                        elem = [wID,0]
                        vocab.append(t)
                        wID = wID + 1
                    elem[1] = elem[1] + 1
                    words[t] = elem

        temp = words
        words = {}
        vocab = []
        wID = 0
        words['<unk>'] = [wID,100]
        vocab.append('<unk>')
        for t in temp:
            if temp[t][1] >= threshold:
                vocab.append(t)
                wID = wID + 1
                words[t] = [wID,temp[t][1]]

    with open(file_name,'rt') as f:
        for line in f:
            line = line.replace('\n','')
            tokens = line.split(' ')
            for t in tokens:
                try:
                    wID = words[t][0]
                except:
                    wID = words['<unk>'][0]
                corpus.append(wID)

    return [vocab,words,corpus]

#### FFNN ####
class FFNN(nn.Module):
    def __init__(self, vocab, words,d_model, d_hidden, dropout ,batch_size, context_size, path):
        super(FFNN,self).__init__()

        self.PATH = path # model path to where the model will be saved
        self.vocab = vocab
        self.words = words
        self.batch_size = batch_size
        self.vocab_size = len(self.vocab)
        self.d_model = d_model
        self.d_hidden = d_hidden
        self.dropout = nn.Dropout(p=dropout)
        self.context_size = context_size

        # model architecture
        self.embeds = nn.Embedding(self.vocab_size,self.d_model)
        self.layer1 = nn.Linear(self.d_model*self.context_size,self.d_model)
        self.relu1 = nn.ReLU()
        self.layer2 = nn.Linear(self.d_model, self.vocab_size)
        self.init_weights()

    def forward(self, src):
        x = self.dropout(self.embeds(src).flatten(start_dim=1))
        x = self.layer1(x)
        x = self.relu1(x)
        x = self.layer2(x)
        return x

    def init_weights(self):
        self.forward(torch.randint(low=0, high=1, size=(1, self.context_size)))

    def train_model(self, loader, optimizer, loss_ce, base_perplexity, mode="train"):
        perplexities= np.zeros((len(loader)))
        for itr, X in enumerate(loader):
            context = X[:,0:3]
            target = X[:,3]

            # Clearing the accumulated gradients
            optimizer.zero_grad()

            # get log probabilities over next words
            logits = self.forward(context)

            # compute loss function
            loss = loss_ce(logits,target)

            # track perplexity
            p  = torch.exp(loss)
            perplexities[itr] = p

            if mode == "train":
                if p < base_perplexity:
                    base_perplexity = p
                    torch.save(self.state_dict(), self.PATH)

                # backward pass and update gradient
                loss.backward()
                optimizer.step()

            if itr % 1000 == 0:
                print("--- Mode: {} | Iteration number: {} | Loss: {} | Perplexity: {} ---".format(mode, itr+1, loss, base_perplexity))
        return perplexities

def generate_blind_prob_dist(data, params, model, threshold):
    bios = []
    bio = []
    for i in range(len(data)):
        bio.append(data[i])
        if data[i] == 121: # <end_bio>
            bios.append(bio)
            bio = []

    labels = []
    for index, bio in enumerate(bios):
        x,y = split_data(bio, params.window+1)
        test_set = np.concatenate([x,y],axis=1)
        test_loader = torch.utils.data.DataLoader(test_set, batch_size=params.batch_size,shuffle=False)
        bio_prob = test_model_probs(test_loader, model)
        label = '[REAL]' if bio_prob > threshold else '[FAKE]'
        labels.append(label)
    return labels

def generate_prob_dist(data, params, model):
    bios = []
    bio = []
    for i in range(len(data)):
        bio.append(data[i])
        if data[i] == 122 or data[i] == 635: # [FAKE] or [REAL]
            bios.append(bio)
            bio = []

    real_labels = [] # probability distribution over bios
    probs = []
    for index, bio in enumerate(bios):
        x,y = split_data(bio, params.window+1)
        test_set = np.concatenate([x,y],axis=1)
        test_loader = torch.utils.data.DataLoader(test_set, batch_size=params.batch_size,shuffle=False)
        bio_prob = test_model_probs(test_loader, model)
        label = '[REAL]' if bio[-1] == 635 else '[FAKE]'
        real_labels.append(label)
        probs.append(bio_prob)
    return real_labels, probs

def test_model_probs(test_loader,model):
    probs = []

    for X in test_loader:
        context = X[:,0:3]
        target = X[:,3]

        with torch.no_grad():

            logits = model(context)

            pred_words = torch.softmax(logits,dim=1) # applying softmax per row
            # get the probability of the target word
            target_word_prob = -1 * torch.log(pred_words[torch.arange(pred_words.shape[0]), target])
            # add prob to list
            probs.extend(target_word_prob)
    return torch.mean(torch.stack(probs)).item()  # torch.stack, stacks each row on top of each other, .mean calculates the mean, .item() gets the value

def train_fnn(model, train, test, params, loss_function, optimizer, epochs):
    model.train()
    epoch_perplexities_train = []
    epoch_perplexities_test = []
    base_perplexity = float('inf')

    # train data loader
    x_train,y_train = split_data(train, params.window+1)
    train_set = np.concatenate([x_train,y_train],axis=1)
    train_loader = torch.utils.data.DataLoader(train_set, batch_size=params.batch_size,shuffle=True,drop_last=True)

    # test data loader
    x_test,y_test = split_data(test, params.window+1)
    test_set = np.concatenate([x_test,y_test],axis=1)
    test_loader = torch.utils.data.DataLoader(test_set, batch_size=params.batch_size,shuffle=False)
    # train the network
    for e in range(epochs):
        epoch_perplexity_train = model.train_model(train_loader, optimizer, loss_function, base_perplexity)
        epoch_perplexity_test = model.train_model(test_loader, optimizer, loss_function, base_perplexity, mode="test")

        epoch_perplexities_train.append(epoch_perplexity_train)
        epoch_perplexities_test.append(epoch_perplexity_test)

        torch.save(epoch_perplexities_train, "save/FFNN_epoch_perplexities_train.pt")
        torch.save(epoch_perplexities_test, "save/FFNN_epoch_perplexities_test.pt")

##### LSTM #####
class LSTM(nn.Module):
    def __init__(self, vocab, words,d_model, dropout, d_hidden, seq_len, batch_size, n_layers, savename):
        super().__init__()

        self.PATH = savename + '.pt'
        self.vocab = vocab
        self.words = words
        self.vocab_size = len(self.vocab)
        self.n_layers = n_layers
        self.seq_len = seq_len
        self.batch_size = batch_size
        self.d_hidden = d_hidden
        self.d_model = d_model
        self.dropout = nn.Dropout(p=dropout)

        self.embeds = nn.Embedding(self.vocab_size,self.d_model)
        self.lstm = nn.LSTM(input_size=self.d_model, hidden_size=self.d_hidden, num_layers=self.n_layers, batch_first=True)
        self.hidden2word = nn.Linear(self.d_hidden, self.vocab_size)

        self.embeds.weight = self.hidden2word.weight
        self.init_weights()

    def forward(self,src,h,c):
        embeds = self.dropout(self.embeds(src))
        preds, h = self.lstm(embeds, (h.detach(), c.detach()))
        preds = self.hidden2word(preds)

        return [preds,h]

    def init_weights(self):
        init_val = 0.2
        self.embeds.weight.data.uniform_(-init_val, init_val)
        self.hidden2word.weight.data.uniform_(-init_val, init_val)
        for i in range(self.n_layers): self.lstm_init(i, init_val)
        print("=====Done with init ====")

    def lstm_init(self, i, init_val):
        self.lstm.all_weights[i][1] = torch.FloatTensor(self.d_hidden, self.d_hidden).uniform_(-init_val, init_val)
        self.lstm.all_weights[i][0] = torch.FloatTensor(self.d_model, self.d_hidden).uniform_(-init_val, init_val)

    def train_model(self, loader, optimizer, loss_ce, base_perplexity, params, mode="train"):
        perplexities= np.zeros((len(loader)))
        h = torch.zeros(self.n_layers, self.batch_size, self.d_hidden).requires_grad_()
        c = torch.zeros(self.n_layers, self.batch_size, self.d_hidden).requires_grad_()

        for itr, X in enumerate(loader):
            context = X[:,:params.seq_len-1]
            target = X[:,params.seq_len-1]

            # Clearing the accumulated gradients
            optimizer.zero_grad()

            # get log probabilities over next words
            logits, (h,c) = self.forward(context, h, c)

            # target = nn.functional.one_hot(target, num_classes=model.vocab_size)
            loss = loss_ce(logits[:,-1,:],target)

            # track perplexity
            p  = torch.exp(loss)
            perplexities[itr] = p

            if mode == "train":
                # backward pass and update gradient
                loss.backward()
                optimizer.step()

                if p < base_perplexity:
                    torch.save(self.state_dict(), self.PATH)
                    base_perplexity = p

            if itr % params.printevery == 0:
                print("--- Iteration number: {} | Loss: {} | Perplexity: {} ---".format(itr+1, loss, p))

        return perplexities

def train_lstm(model, train, test, params, loss_function, optimizer, epochs):
    epoch_perplexities_train_lstm = []
    epoch_perplexities_test_lstm = []
    base_perplexity = float('inf')

    train = torch.tensor(train).unfold(dimension=0, size=params.seq_len, step=params.seq_len-1)
    test = torch.tensor(test).unfold(dimension=0, size=params.seq_len, step=params.seq_len-1)

    train_loader = torch.utils.data.DataLoader(train, batch_size=params.batch_size,shuffle=False, drop_last=True)
    test_loader = torch.utils.data.DataLoader(test, batch_size=params.batch_size,shuffle=False, drop_last=True)
    for e in range(epochs):
        print("Epoch: ",e)

        # train
        model.train()
        epoch_perplexity_train = model.train_model(train_loader, optimizer, loss_function, base_perplexity, params)
        epoch_perplexities_train_lstm.append(epoch_perplexity_train)

        # test
        model.eval()
        epoch_perplexity_test = model.train_model(test_loader, optimizer, loss_function, base_perplexity, params, mode="test")
        epoch_perplexities_test_lstm.append(epoch_perplexity_test)

        torch.save(epoch_perplexities_train_lstm, "save/LSTM_epoch_perplexities_train.pt")
        torch.save(epoch_perplexities_test_lstm, "save/LSTM_epoch_perplexities_test.pt")

def test_lstm(model, data, params, vocab, words):
    real_wid = words['[REAL]'][0]
    fake_wid = words['[FAKE]'][0]

    data = np.array(data)
    vocab_np = np.array(vocab)
    true_label_inds = [i for i in range(len(data)) if data[i] == real_wid or data[i] == fake_wid]

    true_labels = vocab_np[data[true_label_inds]]

    padded_bios = np.pad(data, (0, params.seq_len-1), 'constant')

    processed_data = torch.tensor(padded_bios).unfold(dimension=0, size=params.seq_len-1, step=params.seq_len-1)
    # test_loader = torch.utils.data.DataLoader(data, batch_size=params.batch_size,shuffle=False, drop_last=False)

    h = torch.zeros(model.n_layers, model.d_hidden).requires_grad_()
    c = torch.zeros(model.n_layers, model.d_hidden).requires_grad_()

    output = []
    for itr, X in enumerate(processed_data):
        with torch.no_grad():
            logits, (h,c) = model(X, h, c)
            pred_words_probs = torch.softmax(logits,dim=1) # applying softmax per row
            output.extend(pred_words_probs)

    pred_labels = []

    for i in range(len(true_label_inds)):
        preds = output[true_label_inds[i]]
        real_pred = preds[real_wid]
        fake_pred = preds[fake_wid]
        pred = '[REAL]' if real_pred > fake_pred else '[FAKE]'
        # print(pred, real_pred, fake_pred)
        pred_labels.append(pred)

    # print_logit_preds(output, vocab)
    return true_labels, pred_labels

def blind_test_lstm(model, data, params, vocab, words):
    end_bio_wid = words['end_bio'][0]
    real_wid = words['[REAL]'][0]
    fake_wid = words['[FAKE]'][0]

    data = np.array(data)
    true_label_inds = [i+2 for i in range(len(data)) if data[i] == end_bio_wid]

    padded_bios = np.pad(data, (0, params.seq_len-1), 'constant')
    processed_data = torch.tensor(padded_bios).unfold(dimension=0, size=params.seq_len-1, step=params.seq_len-1)

    h = torch.zeros(model.n_layers, model.d_hidden).requires_grad_()
    c = torch.zeros(model.n_layers, model.d_hidden).requires_grad_()

    output = []
    for itr, X in enumerate(processed_data):
        with torch.no_grad():
            logits, (h,c) = model(X, h, c)
            pred_words_probs = torch.softmax(logits,dim=1) # applying softmax per row
            output.extend(pred_words_probs)

    pred_labels = []
    for i in range(len(true_label_inds)):
        preds = output[true_label_inds[i]]
        real_pred = preds[real_wid]
        fake_pred = preds[fake_wid]
        pred = '[REAL]' if real_pred > fake_pred else '[FAKE]'
        # print(pred, real_pred, fake_pred)
        # print(sorted(preds,reverse=True)[:10])
        pred_labels.append(pred)

    # print_logit_preds(output, vocab)

    return pred_labels

#### UTILS ####
#-----------------------#

def split_data(X, window):
  x = []
  y = []
  seq= None
  for i in range(0, len(X)-window):
    seq = X[i:i+window]
    x.append(seq[:-1])
    y.append([seq[-1]])
  return np.array(x),np.array(y)

# Plot a histogram of the data labelled by the class
def plot_probs(df, threshold):
    dfreal = df[df['label'] == '[REAL]']['prob'].values
    dffake = df[df['label'] == '[FAKE]']['prob'].values

    if len(dfreal) > len(dffake):
        dfreal = dfreal[:len(dffake)]
    else:
        dffake = dffake[:len(dfreal)]
    X = [dffake, dfreal]

    sns.displot(X, kind='kde', height=5, aspect=1.5, fill=True, legend=False)
    plt.axvline(threshold, color='red', label='Threshold')
    plt.legend(labels=['[REAL]', '[FAKE]', 'Threshold'])
    plt.xlabel('-ve log probability')
    plt.ylabel('Kernel Density Estimate')
    plt.title('Probability Distribution of Bios')
    plt.savefig('save/prob_dist_plot.png')
    plt.show()

def print_logit_preds(output, vocab):
    for i in range(len(output)):
        preds = output[i]
        ind = torch.argmax(preds)
        pred = vocab[ind]
        prob = preds[ind]
        sort_inds = np.argsort(preds)[-5:]
        pred_words = []
        for i in range(len(sort_inds)-1, -1, -1):
            pred_words.append(vocab[sort_inds[i]])
        # print(preds)
        print(ind, pred, prob)
        print("top 5 preds: ", pred_words)

def plot_epoch_perplexities(trainLoadFile, testLoadFile, saveFile):
    epoch_perplexities_train = torch.load(trainLoadFile)
    epoch_perplexities_test = torch.load(testLoadFile)

    with torch.no_grad():
        epoch_perplexities_train = np.mean(np.array(epoch_perplexities_train), axis=1)
        epoch_perplexities_test = np.mean(np.array(epoch_perplexities_test), axis=1)

    plt.plot(epoch_perplexities_train, label='train')
    plt.plot(epoch_perplexities_test, label='test')
    plt.legend(loc='upper right')
    plt.xlabel('Epoch')
    plt.ylabel('Perplexity')
    plt.title('Average Perplexity per Epoch')
    plt.savefig(saveFile)
    plt.show()

def accuracy_score(true_labels, pred_labels):
    correct = 0
    for i in range(len(pred_labels)):
        if pred_labels[i] == true_labels[i]:
            correct += 1
    return correct/len(pred_labels)

def plot_confusion_matrix(true_labels, pred_labels, saveFile=None):
        cm = confusion_matrix(true_labels, pred_labels)
        disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=['[FAKE]', '[REAL]'])
        disp.plot()
        if saveFile is None:
            plt.show()
        else:
            plt.savefig(saveFile)
#-----------------------#

def main():
    # use params to decide what model to use, what mode to run in, etc. check main for clarity
    parser = argparse.ArgumentParser()
    parser.add_argument('-d_model', type=int, default=100) #FFNN: 100, LSTM: 64
    parser.add_argument('-d_hidden', type=int, default=200) #FFNN: 200, LSTM: 64
    parser.add_argument('-n_layers', type=int, default=2) #LSTM: 2
    parser.add_argument('-batch_size', type=int, default=200) #FFNN: 200, LSTM: 20
    parser.add_argument('-seq_len', type=int, default=30) #LSTM: 30
    parser.add_argument('-window', type=int, default=3) #FFNN: 3
    parser.add_argument('-epochs', type=int, default=20)
    parser.add_argument('-lr', type=float, default=0.0001)
    parser.add_argument('-dropout', type=int, default=0.35)
    parser.add_argument('-model', type=str,default='ffnn') #FFNN: 'ffnn', LSTM: 'lstm'
    parser.add_argument('-mode', type=str,default='eval')

    parser.add_argument('-savename', type=str,default='save/ffnn') #FFNN: 'ffnn', LSTM: 'lstm'
    parser.add_argument('-loadname', type=str,default='models/ffnn') #FFNN: 'ffnn', LSTM: 'lstm'
    parser.add_argument('-trainname', type=str,default='data/mix.train.tok')
    parser.add_argument('-validname', type=str,default='data/mix.valid.tok')
    parser.add_argument('-testname', type=str,default='data/mix.test.tok')
    parser.add_argument('-blindtestname', type=str,default='data/blind.test.tok')

    parser.add_argument('-fnn_threshold', type=float,default=4.5806)
    parser.add_argument('-printevery', type=int, default=1000)

    params = parser.parse_args()
    torch.manual_seed(0)

    [vocab,words,train] = read_encode(params.trainname,[],{},[],3)
    print('vocab: %d train: %d' % (len(vocab),len(train)))
    [vocab,words,test] = read_encode(params.testname,vocab,words,[],-1)
    print('vocab: %d test: %d' % (len(vocab),len(test)))
    [vocab,words,valid] = read_encode(params.validname,vocab,words,[],-1)
    print('vocab: %d valid: %d' % (len(vocab),len(test)))
    params.vocab_size = len(vocab)

    [vocab,words,blind_test] = read_encode(params.blindtestname,vocab,words,[],-1)
    print('vocab: %d blind_test: %d' % (len(vocab),len(test)))

    if params.model == 'ffnn':
        fn = FFNN(vocab, words, params.d_model, params.d_hidden, params.dropout, params.batch_size, params.window, params.savename)
        loss_function = nn.CrossEntropyLoss()
        optimizer = optim.Adam(fn.parameters(), lr=params.lr)
        default_threshold = params.fnn_threshold

        if params.mode == 'train':
            # trains & gets epoch perplexities for training set and test set
            train_fnn(fn, train, test, params, loss_function, optimizer, epochs=params.epochs)

            # Plot epoch perplexities for training set and test set
            trainLoadFile = "save/epoch_perplexities_train.pt"
            testLoadFile = "save/epoch_perplexities_test.pt"
            saveFile = "save/FFNN_epoch_perplexities.png"
            plot_epoch_perplexities(trainLoadFile, testLoadFile, saveFile)

        elif params.mode == 'eval':
            # Generate predictions for test set
            fn.load_state_dict(torch.load(params.loadname + ".pt"))
            fn.eval()
            labels, probs = generate_prob_dist(test, params, fn)
            pred_labels = ['[REAL]' if x > default_threshold else '[FAKE]' for x in probs]

            # Calculate prediction accuracy
            accuracy = accuracy_score(labels, pred_labels)
            print("Accuracy: ", accuracy)

            # Plot confusion matrix
            plot_confusion_matrix(labels, pred_labels)

        elif params.mode == 'plot': # Get threshold from validation set
            fn.load_state_dict(torch.load(params.loadname + ".pt"))
            fn.eval()
            labels, probs = generate_prob_dist(valid, params, fn)
            plot_probs(pd.DataFrame({'label' : labels, 'prob' : probs}), default_threshold)

        elif params.mode == 'test':
            fn.load_state_dict(torch.load(params.loadname + ".pt"))
            fn.eval()
            labels = generate_blind_prob_dist(blind_test, params, fn, params.fnn_threshold)
            pd.DataFrame(labels).to_csv("save/ffnn_blind_test_labels.csv", index=False, header=False)

    elif params.model == 'lstm':
        params.d_model = 64
        params.d_hidden = 64
        params.batch_size = 20
        params.savename = 'save/lstm'
        params.loadname = 'models/lstm'

        lstm = LSTM(vocab, words, params.d_model, params.dropout, params.d_hidden, params.seq_len, params.batch_size, params.n_layers, params.savename)
        loss_function = nn.CrossEntropyLoss()
        optimizer = optim.Adam(lstm.parameters(), lr=params.lr)

        if params.mode == 'train':
            train_lstm(lstm, train, valid, params, loss_function, optimizer, epochs=params.epochs)

            # Plot epoch perplexities for training set and valid set
            plot_epoch_perplexities("save/LSTM_epoch_perplexities_train.pt", "save/LSTM_epoch_perplexities_test.pt", "save/LSTM_epoch_perplexities.png")

        elif params.mode == 'eval':
            lstm.load_state_dict(torch.load(params.loadname + ".pt"))
            lstm.eval()
            true_labels, pred_labels = test_lstm(lstm, test, params, vocab, words)
            # Calculate prediction accuracy
            accuracy = accuracy_score(true_labels, pred_labels)
            print("Accuracy: ", accuracy)

            # Plot confusion matrix
            plot_confusion_matrix(true_labels, pred_labels)

        elif params.mode == 'test':
            lstm.load_state_dict(torch.load(params.loadname + ".pt"))
            lstm.eval()
            pred_labels = blind_test_lstm(lstm, blind_test, params, vocab, words)
            pd.DataFrame(pred_labels).to_csv("save/LSTM_blind_test_labels.csv", index=False, header=False)

if __name__ == "__main__":
    main()


from datetime import datetime, timedelta
import random

class API:
    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs

    @property
    def device_info(self):
        return {"name": "Time machine device"}

    @staticmethod
    def calculate_value(point, aprox):
        rstate = random.getstate()
        random.seed(point)
        ret = aprox * random.randint(75, 100) / 100
        random.setstate(rstate)

        return ret

    def get_historical_data(self, start=None, end=None, step=None):
        return list(self._get_historical_data(start, end, step))

    def _get_historical_data(self, start=None, end=None, step=None):
        """
        Returns a random distribution of values for a series of intervals
        between start and end (size determined by step)
        Those values are random but fixed for each interval.
        Ex.
        _get_historical_data(0, 5, 1) ->
            [(0, 1, 0.4),
             (1, 2, 0.2),
             (2, 3, 0.7),
             (3, 4, 0.1),
             (4, 5, 0.8)]
        _get_historical_data(2, 7, 1) ->
            [(2, 3, 0.7),
             (3, 4, 0.1),
             (4, 5, 0.8),
             (5, 6, 0.3),
             (6, 7, 0.4)]
        """

        start = start or datetime.now()
        end = end or datetime.now()
        step = step or timedelta(minutes=10)

        start = min([start, end])
        end = max([start, end])

        reduction = 1635721200  # 2021-11-01 00:00:00
        start_value = int(start.timestamp()) - reduction
        end_value = int(end.timestamp()) - reduction
        n_blocks = int((end - start) / step)

        available = end_value - start_value

        curr = start_value
        available_per_block = available / n_blocks
        for x in range(n_blocks):
            p1 = start + (step * x)
            p2 = start + (step * (x + 1))

            value_for_block = self.calculate_value(
                p1.timestamp(), available_per_block
            )
            value_for_block = min([available, value_for_block])

            available = available - value_for_block
            curr = curr + value_for_block

            yield p1, p2, value_for_block


from user import User
from post import Post

app_user_one = User("xx@xx.com", "f-name l-name", "pwd", "DevOps Engineer")
app_user_one.get_user_info()

app_user_two = User("yy@yy.com", "name name", "spwd", "Developer")
app_user_two.get_user_info()

new_post = Post("on a secret mission today", app_user_two.name)
new_post.get_post_info()


with open('Lanternfish.txt', 'r') as f:
    data = f.readline().strip().split(',')
    data = list(map(int, data))
    # the map() function applies the int() function to every value in the list

print(data)

# keeps track of how many fish are in each stage of life
buckets = [0 for _ in range(10)]

for fish_life in data:
    buckets[fish_life] += 1

total_days = 256
for day in range(total_days):
    for idx, count in enumerate(buckets):
        # Enumerate simultaneously gives you indexes and values from a list, Super useful!
        if idx == 0:
            # we use 7 because the enumerate will decrease it to 6 in the current iter.
            buckets[7] += count
            buckets[9] += count
            buckets[idx] = 0
        else:
            buckets[idx - 1] += count
            buckets[idx] = 0

print(sum(buckets))


from spack.package import *

class PerlStrictures(PerlPackage):
    """Turn on strict and make most warnings fatal"""

    homepage = "https://metacpan.org/pod/strictures"
    url = "https://cpan.metacpan.org/authors/id/H/HA/HAARG/strictures-2.000006.tar.gz"

    maintainers("EbiArnie")

    license("Artistic-1.0-Perl OR GPL-1.0-or-later")

    version("2.000006", sha256="09d57974a6d1b2380c802870fed471108f51170da81458e2751859f2714f8d57")

    depends_on("perl@5.6.0:", type=("build", "link", "run", "test"))

    def test_use(self):
        """Test 'use module'"""
        options = ["-we", 'use strict; use strictures; print("OK\n")']

        perl = self.spec["perl"].command
        out = perl(*options, output=str.split, error=str.split)
        assert "OK" in out


import numpy as np
import pandas as pd

def linear_regression_noreg(X, y):
  """
  Compute the weight parameter given X and y.
  Inputs:
  - X: A numpy array of shape (num_samples, D) containing feature.
  - y: A numpy array of shape (num_samples, ) containing label
  Returns:
  - w: a numpy array of shape (D, )
  """
  X_transpose = np.transpose(X)
  XXtranspose_inv = np.linalg.inv(np.dot(X_transpose,X))
  w = np.dot(np.dot(XXtranspose_inv,X_transpose),y)
  return w

def regularized_linear_regression(X, y, lambd):
  """
    Compute the weight parameter given X, y and lambda.
    Inputs:
    - X: A numpy array of shape (num_samples, D) containing feature.
    - y: A numpy array of shape (num_samples, ) containing label
    - lambd: a float number containing regularization strength
    Returns:
    - w: a numpy array of shape (D, )
    """
  [N, D] = X.shape
  regularizer = lambd*np.identity(D)
  X_transpose = np.transpose(X)
  XXtranspose_inv = np.linalg.inv(np.dot(X_transpose,X) + regularizer)
  w = np.dot(np.dot(XXtranspose_inv,X_transpose),y)
  return w

def tune_lambda(Xtrain, ytrain, Xval, yval, lambds):
  """
    Find the best lambda value.
    Inputs:
    - Xtrain: A numpy array of shape (num_training_samples, D) containing training feature.
    - ytrain: A numpy array of shape (num_training_samples, ) containing training label
    - Xval: A numpy array of shape (num_val_samples, D) containing validation feature.
    - yval: A numpy array of shape (num_val_samples, ) containing validation label
    - lambds: a list of lambdas
    Returns:
    - bestlambda: the best lambda you find in lambds
    """
  lambda_performance = {}
  for l in lambds:
    w = regularized_linear_regression(Xtrain, ytrain, l)
    err = test_error(w, Xval, yval)
    lambda_performance[l] = err
  bestlambda = min(lambda_performance, key=lambda_performance.get)
  return bestlambda

def test_error(w, X, y):
  """
    Compute the mean squre error on test set given X, y, and model parameter w.
    Inputs:
    - X: A numpy array of shape (num_samples, D) containing test feature.
    - y: A numpy array of shape (num_samples, ) containing test label
    - w: a numpy array of shape (D, )
    Returns:
    - err: the mean square error
    """
  [N, D] = X.shape
  w_tranpose = np.transpose(w)
  predictions = np.dot(X, w_tranpose)
  error_square = np.square(y-predictions)
  sum_error_square = np.sum(error_square)
  err = (sum_error_square/N)
  return err

def data_processing():
  white = pd.read_csv('winequality-white.csv', low_memory=False, sep=';').values

  [N, d] = white.shape

  np.random.seed(3)
  # prepare data
  ridx = np.random.permutation(N)
  ntr = int(np.round(N * 0.8))
  nval = int(np.round(N * 0.1))
  ntest = N - ntr - nval

  # spliting training, validation, and test

  Xtrain = np.hstack([np.ones([ntr, 1]), white[ridx[0:ntr], 0:-1]])

  ytrain = white[ridx[0:ntr], -1]

  Xval = np.hstack([np.ones([nval, 1]), white[ridx[ntr:ntr + nval], 0:-1]])
  yval = white[ridx[ntr:ntr + nval], -1]

  Xtest = np.hstack([np.ones([ntest, 1]), white[ridx[ntr + nval:], 0:-1]])
  ytest = white[ridx[ntr + nval:], -1]
  return Xtrain, ytrain, Xval, yval, Xtest, ytest

def main():
  np.set_printoptions(precision=3)
  Xtrain, ytrain, Xval, yval, Xtest, ytest = data_processing()
  w = linear_regression_noreg(Xtrain, ytrain)
  print("dimensionality of the model parameter is ", len(w), ".", sep="")
  print("model parameter is ", np.array_str(w))

  lambd = 5.0
  wl = regularized_linear_regression(Xtrain, ytrain, lambd)
  print("\n")
  print("dimensionality of the model parameter is ", len(wl), sep="")
  print("lambda = ", lambd, ", model parameter is ", np.array_str(wl), sep="")

  lambds = [0, 10 ** -4, 10 ** -3, 10 ** -2, 10 ** -1, 1, 10, 10 ** 2]
  bestlambd = tune_lambda(Xtrain, ytrain, Xval, yval, lambds)
  print("\n")
  print("tuning lambda, the best lambda =  ", bestlambd, sep="")

  wbest = regularized_linear_regression(Xtrain, ytrain, bestlambd)
  mse = test_error(wbest, Xtest, ytest)
  print("\n")
  print("Mean Square Error(MSE) on test is %.3f" % mse)

if __name__ == "__main__":
    main()


import json
import copy
import os
import random
import string
from os import listdir
from os.path import isfile,join
import subprocess
import shutil
import time
import sys
import uuid
from pathlib import Path

if __name__ == "__main__":
    """
    This module is used to convert the given pdf slides into the h5p package

Example:
    To run the file, please use the following command:

        $ python generateh5p.py <inputfilename> --dpi 300 --resolution 1920

The last two parameters (dpi) and resolution are non mandatory values

Defaults:
    The value DPI defaults to 600 and the resolutiion defaults to 1920

Todo:
    * Add Support for Adding interactive quizzes

"""

    ##Get  Home Path
    import os
    home_dir_path = os.getcwd()

    if(len(sys.argv) <= 1):
        print("Please enter the Input Argument as the name of PDF file")
        exit(0)
    elif(len(sys.argv) <=2):
        inputFileName = sys.argv[1]
        DPI = 600
        pixel = 1920
        webOutputdir = "."
    else:
        inputFileName = sys.argv[1]
        for i in range(2,len(sys.argv)):
            if(sys.argv[i] == "--dpi"):
                DPI = int(sys.argv[i+1])
            elif(sys.argv[i] == "--resolution"):
                pixel = int(sys.argv[i+1])
            elif(sys.argv[i] == "--webOutput"):
                webOutputdir = sys.argv[i+1]
    ## GLOBAL VARIABLES

    Title = Path(inputFileName).stem
    OPFileName = Path(inputFileName).stem

    home_dir_path = os.getcwd()
    contentPath = os.path.join(home_dir_path,"content")
    imagePath = os.path.join(contentPath,"images")

    with open (f"{home_dir_path}/contentBase/content.json","r") as f:
        jsonData = json.load(f)
    JsonDataCopy = copy.deepcopy(jsonData)

    ## get Copy of one Slide
    SlideDataBase = copy.deepcopy(jsonData['presentation']['slides'][0])

    ## remove content directory
    dirpath = contentPath
    if os.path.exists(dirpath) and os.path.isdir(dirpath):
        shutil.rmtree('content')

    ## make a new content directory

    p1 = subprocess.call(f"mkdir -p {contentPath}".split(" "))

    p1 = subprocess.call(f"mkdir -p {imagePath}".split(" "))

    ## Extract all the image files to Folder images
    # Copy the PDF to the content folder
    p1 = subprocess.call(f'cp {webOutputdir}/{inputFileName} {imagePath}'.split(" "))

    ## Extract all the pdf as images
    p1 = subprocess.call(f'pdftoppm -png -r {DPI} -scale-to {pixel} {inputFileName} image-{Title}'.split(" "), cwd=imagePath)

    ## Delete pdf file
    p1 = subprocess.call(f'rm {imagePath}/{inputFileName}'.split(" "))

    ## Extract Image Files
    imageFiles = [f for f in listdir(f"{imagePath}") if isfile(join(imagePath,f))]

    # print(imageFiles)

    imageFilesRenamed = []
    ## rename the images with hashes at end
    for index,img in enumerate(imageFiles):
        k = str(uuid.uuid4())[:8]
        filename, file_extension = os.path.splitext(img)
        # print(f"mv {imagePath}/{filename}{file_extension}  {imagePath}/{filename}-{k}{file_extension}")
        # print(img)
        p1 = shutil.move(f'{imagePath}/{filename}{file_extension}', f'{imagePath}/{filename}-{k}{file_extension}')

        img = f"{filename}-{k}{file_extension}"
        imageFilesRenamed.append(img)

    ## remove base slide data from main json data
    ## the copy is available in SliSlideDataBase
    del jsonData['presentation']['slides'][0]

    ## create a new folder and copy contents over there
    p1 = subprocess.call(f'cp -r {home_dir_path}/BaseTemplate/ {OPFileName}'.split(" "))

    ## Sort them Alphabeticallty
    imageFilesRenamed.sort()

    print("Converting the PDF File into h5p..!")

    ## Create a Slide for each image
    for image in imageFilesRenamed:
        currSlide = copy.deepcopy(SlideDataBase)
        currSlide['elements'][0]['action']['params']['file']['path'] = f"images/{image}"
        currSlide['elements'][0]['action']['subContentId'] = str(uuid.uuid4())

        jsonData['presentation']['slides'].append(currSlide)

    ## Write the current json to content folder
    with open(f"{contentPath}/content.json" , 'w') as f:
        json.dump(jsonData,f)

    ## copy to the OOP folder
    p1 = subprocess.call(f'cp -r {contentPath}/ {OPFileName}/'.split(" "))

    ## make zip file
    shutil.make_archive(OPFileName, 'zip', OPFileName)

    ## rename to h5p
    p1 = subprocess.call(f'mv {OPFileName}.zip {OPFileName}.h5p'.split(" "))

    ## remove folder
    p1 = subprocess.call(f'rm -r {OPFileName}/'.split(" "))

    ## Copy file to webconfig folder for downloading
    p1 = subprocess.call(f'mv {OPFileName}.h5p {webOutputdir}/'.split(' '))

    os.chdir(home_dir_path)

    print(f"[ Message: ] {OPFileName}.h5p Successfully generated")


import os
import sys
import glob

sys.path.append('/opt/eva/lib')
from eva.client.apiclient import APIClientLocal

for fname in glob.glob('/opt/eva-phi/phi/**/*.py', recursive=True):

    # os.system('/opt/eva-phi/convert_v4.py {} i'.format(fname))
    os.system('yapf -i --style google {}'.format(fname))

    mod = os.path.basename(fname).split('.')[0]

    content = open(fname).read()

    api = APIClientLocal('uc')

    code, result = api.call('put_phi_mod', {
        'm': mod,
        'c': content,
        'force': True
    })
    if code != 0:
        print(result)
        exit(1)

    code, result = api.call('modinfo_phi', {'m': mod})
    if code != 0:
        print(result)
        exit(1)

    if result.get('mod') != mod:
        print('no mod in result')
        exit(1)

    if not result.get('lpi_default'):
        print('no default LPI is set')
        exit(1)

    if result.get('description') == 'Generic PHI, don\'t use':
        print('serialize error')
        exit(1)

    code, result = api.call('unlink_phi_mod', {'m': mod})
    if code != 0:
        print(result)
        exit(1)


import gym
import time
import gym_os2r_real
from gym_ignition.utils import logger

# Set verbosity
# logger.set_level(gym.logger.ERROR)
# logger.set_level(gym.logger.WARN)
logger.set_level(gym.logger.DEBUG)

# Available tasks
env_id = "Real-monopod-simple-v1"

env = gym.make(env_id)
for epoch in range(2):

    # Reset the environment
    observation = env.reset()

    # Initialize returned values
    done = False
    count = 0
    while not done:
        # action = env.action_space.sample()
        action = [0, -1]
        observation, reward, done, _ = env.step(action)
        count += 1
        if (count % env.agent_rate == 0):
            print("Second.", count/env.agent_rate)

env.close()
time.sleep(5)


import torch
import torch.nn as nn
from torch.autograd import Variable
from deep_math.constants import VOCAB_SZ, MAX_ANSWER_SZ, MAX_QUESTION_SZ

class SimpleLSTM(nn.Module):

    def __init__(self):
        super(SimpleLSTM, self).__init__()
        self.num_hidden = 2048
        self.vocab_sz = VOCAB_SZ
        self.max_answer_sz = MAX_ANSWER_SZ
        self.max_question_sz = MAX_QUESTION_SZ

        self.lstm = nn.LSTM(VOCAB_SZ, self.num_hidden, 1)
        self.tgt_word_prj = nn.Linear(self.num_hidden, VOCAB_SZ, bias=False)

    def forward(self, x):

        batch_size = len(x)

        x = torch.transpose(x, 0, 1)
        x = nn.functional.one_hot(x, self.vocab_sz)

        x = x.float()  # (max_q_sz, batch_sz, vocab_sz)

        # type_as(x) is required for setting the device (cuda or cpu)
        # https://forums.pytorchlightning.ai/t/training-fails-but-found-at-least-two-devices-cuda-0-and-cpu/694

        hidden_state = Variable(
            torch.zeros(1, batch_size, self.num_hidden,
                        dtype=torch.float)).type_as(x)
        cell_state = Variable(
            torch.zeros(1, batch_size, self.num_hidden,
                        dtype=torch.float)).type_as(x)
        output_seq = torch.empty(
            (self.max_answer_sz - 1, batch_size, self.vocab_sz)).type_as(x)
        thinking_input = torch.zeros(1,
                                     batch_size,
                                     self.vocab_sz,
                                     dtype=torch.float).type_as(x)

        # Input question phase
        self.lstm.flatten_parameters()
        for t in range(self.max_question_sz):
            outputs, (hidden_state,
                      cell_state) = self.lstm(x[t].unsqueeze(0),
                                              (hidden_state, cell_state))
        # Extra 15 Computational Steps
        for t in range(15):
            _, (hidden_state,
                cell_state) = self.lstm(thinking_input,
                                        (hidden_state, cell_state))

        # Answer generation phase, need to input correct answer as hidden/cell state, find what to put in input
        for t in range(self.max_answer_sz - 1):
            output_seq[t] = self.tgt_word_prj(outputs)
            char = output_seq[t].clone().unsqueeze(0)
            outputs, (hidden_state,
                      cell_state) = self.lstm(char, (hidden_state, cell_state))

        batch_ans_size = output_seq.size(2)  # batch_size x answer_length
        return output_seq.reshape(-1, batch_ans_size)


"""
This file contains methods that are needed in all apps.

Author: André Holl
Organization: Spatial data infrastructure Rheinland-Pfalz, Germany
Contact: andre.holl@vermkv.rlp.de
Created on: 02.05.19
"""

import requests
from pymemcache.client import base
from phpserialize import *
from django.http import HttpRequest
from Geoportal.settings import DEFAULT_GUI, HTTP_OR_SSL, INTERNAL_SSL, PROJECT_DIR, SESSION_NAME
from Geoportal.utils.mbConfReader import get_mapbender_config_value
from useroperations.models import MbUser

### IMPORTANT NOTE ####
# LATER VERSIONS OF php-memcached will use "memc.sess.key.XYZ" as session storage string,
# If users dont see their login status anymore in the frontend after php upgrade,
# this will probably be the reason why, has to be changed in line 28 AND 42.
def get_mapbender_session_by_memcache(session_id):
    client = base.Client(('localhost', 11211))

    try:
        session_data = client.get('memc.sess.key.' + session_id)
    except ConnectionRefusedError:
        print("Connection Refused!Memcached not running?")

    try:
        session_data = loads(session_data)
    except ValueError:
        session_data = None
    return session_data

def delete_mapbender_session_by_memcache(session_id):
    client = base.Client(('localhost', 11211))
    client.delete('memc.sess.key.' + session_id)

def get_session_data(request):
    """ Parses the PHP session file

    To link between Django and old times PHP components, we need to fetch
    data from the PHP session file on the filesystem.
    This function parses the file and returns the information.

    Args:
        request (HttpRequest): The incoming request
    Returns:
         dict: Contains the session data for python
    """

    user = b'Noone'
    userid = None
    gui = DEFAULT_GUI
    guis = None
    loggedin = False
    session_data = None

    if request.COOKIES.get(SESSION_NAME) is not None:
        session_data = get_mapbender_session_by_memcache(request.COOKIES.get(SESSION_NAME))
        if session_data != None:
            if b'mb_user_id' in session_data:
                guest_id = get_mapbender_config_value(PROJECT_DIR, 'ANONYMOUS_USER')
                user = session_data[b'mb_user_name']
                userid = session_data[b'mb_user_id']

                if session_data[b'mb_user_id'] == guest_id.encode('utf-8'):
                    gui = str(session_data[b'mb_user_gui'], 'utf-8')
                    loggedin = False
                else:
                    response = requests.post(HTTP_OR_SSL + '127.0.0.1/local/guiapi.php', verify=INTERNAL_SSL, data=session_data[b'mb_user_guis'])

                    if session_data[b'mb_user_guis']:

                        guistring = response.text
                        guistring = guistring.replace('"', '')
                        guistring = guistring.replace('[', '')
                        guistring = guistring.replace(']', '')
                        guistring = guistring.replace('\\u00e4', 'ä')
                        guis = guistring.split(",")
                        loggedin = True
                    else:
                        guis = DEFAULT_GUI
                        loggedin = False

    data = {
        'session_data': session_data,
        'gui': gui,
        'guis': guis,
        'loggedin': loggedin,
    }

    return data

def get_mb_user_session_data(request: HttpRequest):
    """ Parse PHP session, focusing on mb_user data

    Args:
        request (HttpRequest):
    Returns:
        dict: Contains only user relevant data
    """
    session_data = get_session_data(request)
    ret_dict = {}
    guest_gui = [DEFAULT_GUI]
    guest_id = get_mapbender_config_value(PROJECT_DIR, 'ANONYMOUS_USER')
    guest_name = MbUser.objects.get(mb_user_id=guest_id)
    # USER
    if session_data['loggedin']:
        ret_dict["user"] = str(session_data['session_data'].get(b'mb_user_name', b""), "utf-8")
        ret_dict["userid"] = int(session_data['session_data'].get(b'mb_user_id', b""))
        ret_dict["gui"] = session_data['gui']
        ret_dict["guis"] = session_data['guis']
        ret_dict["loggedin"] = session_data['loggedin']
        ret_dict["dsgvo"] = str(session_data['session_data'].get(b'dsgvo', b""), "utf-8")
        ret_dict["preferred_gui"] = str(session_data['session_data'].get(b'preferred_gui', b"") or DEFAULT_GUI.encode("utf-8"), "utf-8")
    # GUEST
    else:
        ret_dict["username"] = guest_name.mb_user_name
        ret_dict["userid"] = guest_id
        ret_dict["gui"] = guest_gui
        ret_dict["guis"] = guest_gui
        ret_dict["loggedin"] = False

    return ret_dict


num= []
a=int(input("Enter size of array :"))

for i in range(a):
    b=int(input())
    num.append(b)

sumE=0
sumO=0
for i in range(a):
    if(num[i]%2==0):
        sumE+=1
    else:
        sumO+=1
print("Count of Even Numbers = ", sumE)
print("count of Odd  Numbers = ", sumO)

python/pythonProject1/count even odd num.py


import os
import boto3
from boto3.dynamodb.conditions import Key
import json
from decimal import Decimal

filepath = '../json/aggregate_happydata_countries_formatted.json'

with open(filepath, 'r') as file:
    json_data = file.read()

data_dict = json.loads(json_data, parse_float=Decimal)

DB = boto3.resource('dynamodb').Table('worldhappiness-appdata')

print(data_dict)

record = {
    'pKey': 'aggregate' ,
    'rKey': 'happydata_countries',
    'countries': data_dict
}

DB.put_item(Item = record)


import warnings
from typing import Any, Dict, List, Optional, Tuple

from torch import nn
from torch.utils import model_zoo
from torchvision.models import alexnet

from pystiche.misc import build_deprecation_message

from ..multi_layer_encoder import MultiLayerEncoder
from ..preprocessing import get_preprocessor

MODEL_URLS = {"torch": "https://download.pytorch.org/models/alexnet-owt-4df8aa71.pth"}

__all__ = ["alexnet_multi_layer_encoder"]

class MultiLayerAlexNetEncoder(MultiLayerEncoder):
    def __init__(
        self, weights: str, internal_preprocessing: bool, allow_inplace: bool
    ) -> None:
        self.weights = weights
        self.internal_preprocessing = internal_preprocessing
        self.allow_inplace = allow_inplace

        super().__init__(self._collect_modules())

    def _collect_modules(self) -> List[Tuple[str, nn.Module]]:
        base_model = alexnet()
        url = MODEL_URLS[self.weights]
        state_dict = model_zoo.load_url(url)
        base_model.load_state_dict(state_dict)
        model = base_model.features

        modules = []
        if self.internal_preprocessing:
            modules.append(("preprocessing", get_preprocessor(self.weights)))
        block = 1
        for module in model.children():
            if isinstance(module, nn.Conv2d):
                name = f"conv{block}"
            elif isinstance(module, nn.ReLU):
                if not self.allow_inplace:
                    module = nn.ReLU(inplace=False)
                name = f"relu{block}"
                if block in (3, 4):
                    # in the third and forth block the ReLU layer marks the end of the
                    # block
                    block += 1
            else:  # isinstance(module, nn.MaxPool2d):
                name = f"pool{block}"
                # each pooling layer marks the end of the current block
                block += 1

            modules.append((name, module))

        return modules

    def _properties(self) -> Dict[str, Any]:
        dct = super()._properties()
        dct["weights"] = self.weights
        if not self.internal_preprocessing:
            dct["internal_preprocessing"] = self.internal_preprocessing
        if self.allow_inplace:
            dct["allow_inplace"] = self.allow_inplace
        return dct

class AlexNetEncoder(MultiLayerAlexNetEncoder):
    def __init__(self, *args: Any, **kwargs: Any) -> None:
        msg = build_deprecation_message(
            "The class AlexNetEncoder",
            "0.4.0",
            info="It was replaced by MultiLayerAlexNetEncoder.",
        )
        warnings.warn(msg)
        super().__init__(*args, **kwargs)

def alexnet_multi_layer_encoder(
    weights: str = "torch",
    preprocessing: Optional[bool] = None,
    internal_preprocessing: bool = True,
    allow_inplace: bool = False,
) -> MultiLayerAlexNetEncoder:
    if preprocessing is not None:
        msg = build_deprecation_message(
            "The parameter preprocessing",
            "0.4.0",
            info="It was replaced by internal_preprocessing.",
        )
        warnings.warn(msg)
        internal_preprocessing = preprocessing
    return MultiLayerAlexNetEncoder(weights, internal_preprocessing, allow_inplace)

def alexnet_encoder(*args: Any, **kwargs: Any) -> MultiLayerAlexNetEncoder:
    msg = build_deprecation_message(
        "The function alexnet_encoder",
        "0.4.0",
        info="It was replaced by alexnet_multi_layer_encoder.",
    )
    warnings.warn(msg)
    return alexnet_multi_layer_encoder(*args, **kwargs)


import sys

n = int(sys.stdin.readline().rstrip())
white = 0
blue = 0
board = [list(map(int, sys.stdin.readline().rstrip().split())) for _ in range(n)]

def is_same(row, col, size):
    color = board[row][col]
    for i in range(row, row + size):
        for j in range(col, col + size):
            if board[i][j] != color:
                return False
    return True

def quanrant(row, col, size):
    global white, blue
    if is_same(row, col, size):
        if board[row][col] == 0:
            white += 1
        else:
            blue += 1
    else:
        newSize = size // 2

        quanrant(row, col, newSize)
        quanrant(row, col + newSize, newSize)
        quanrant(row + newSize, col, newSize)
        quanrant(row + newSize, col + newSize, newSize)

quanrant(0, 0, n)

print(white)
print(blue)

백준/Silver/2630. 색종이 만들기/색종이 만들기.py


"""
.. module:: bargraph

*********
Bargraph Click
*********

This module contains the :class:`Bargraph` is a 10 segment shift register
that can vary led intensity with PWM.

"""

import spi
import pwm

class Bargraph(spi.Spi):
    """
.. class:: Bargraph

    Creates an intance of a new Bargraph.

    :param cs: Chip select used for latching
    :param rst: Reset pin used to reset display
    :param pwm: PWM Pin for display intensity
    :param drvname: SPI Bus used `( SPI0, SPI1 )`

    :Example:

.. code-block:: python

    bargraph = bargraph_click.Bargraph( SPI0, D22, D21, D6.PWM )
    bargraph.set_number( 5 )
    bargraph.set_inensity( 95 )

    """
    # initialize object
    def __init__(self, cs, rst, pwm, drvname=SPI0):
        #Global variables for class needed
        spi.Spi.__init__(self,cs, drvname)
        self.rst = rst
        self.pwm = pwm
        self.cs = cs

        #Set modes of included pins
        pinMode(self.rst, OUTPUT)
        #Reset system to default values
        self._reset()
        self.set_number( 0 )
        self.set_intensity( 50.0 )

    #Latch the shift registers
    def _latch( self ):
        self.select()
        sleep(3, MILLIS)
        self.unselect()

    #Reset the display
    def _reset( self ):
        digitalWrite(self.rst, LOW)
        sleep(3, MILLIS)
        digitalWrite(self.rst, HIGH)

    def set_number( self, number ):
        """
.. method:: set_number( number )

        Writes number from 0 to 10 on display.

        """
        if number > 10:
            return

        temp = 0x0000
        temp = ( 1 << number ) - 1
        value = bytearray(2)
        value[0] = ( temp & 0xff00 ) >> 8
        value[1] = ( temp & 0x00ff )

        self._reset()
        self.lock()

        try:
            self.write( value )
        except PeripheralError as e:
            print(e)
        finally:
            self.unlock()

        self._latch()

    def set_intensity( self, percent ):
        """
.. method:: set_inensity( percent)

        Set the intensity of the led display from 0 to 100 percent.
        """
        new_period = ( percent / 100.0 ) * 10
        try:
            pwm.write( self.pwm, 10, int(new_period) )
        except Exception as e:
            return e


import re
from typing import List, Union, Optional, TypedDict, cast

from gsuid_core.utils.api.minigg.models import CharacterTalents
from gsuid_core.utils.api.ambr.request import (
    get_ambr_char_data,
    get_ambr_weapon_data,
)

from .map.grow_curve import GROW_CURVE_LIST, WEAPON_GROW_CURVE

PROP_MAP = {
    'FIGHT_PROP_BASE_HP': '基础生命值',
    'FIGHT_PROP_HP': '总生命值',
    'FIGHT_PROP_HP_PERCENT': '生命值',
    'FIGHT_PROP_BASE_ATTACK': '基础攻击力',
    'FIGHT_PROP_ATTACK': '总攻击力',
    'FIGHT_PROP_ATTACK_PERCENT': '攻击力',
    'FIGHT_PROP_BASE_DEFENSE': '基础防御力',
    'FIGHT_PROP_DEFENSE': '总防御力',
    'FIGHT_PROP_DEFENSE_PERCENT': '防御力',
    'FIGHT_PROP_CRITICAL': '暴击率',
    'FIGHT_PROP_ANTI_CRITICAL': '暴击抵抗',
    'FIGHT_PROP_CRITICAL_HURT': '暴击伤害',
    'FIGHT_PROP_CHARGE_EFFICIENCY': '元素充能效率',
    'FIGHT_PROP_HEAL_ADD': '治疗加成',
    'FIGHT_PROP_HEALED_ADD': '受治疗加成',
    'FIGHT_PROP_ELEMENT_MASTERY': '元素精通',
    'FIGHT_PROP_PHYSICAL_ADD_HURT': '物理伤害加成',
    'FIGHT_PROP_FIRE_ADD_HURT': '火元素伤害加成',
    'FIGHT_PROP_ELEC_ADD_HURT': '雷元素伤害加成',
    'FIGHT_PROP_WATER_ADD_HURT': '水元素伤害加成',
    'FIGHT_PROP_GRASS_ADD_HURT': '草元素伤害加成',
    'FIGHT_PROP_WIND_ADD_HURT': '风元素伤害加成',
    'FIGHT_PROP_ROCK_ADD_HURT': '岩元素伤害加成',
    'FIGHT_PROP_ICE_ADD_HURT': '冰元素伤害加成',
    'FIGHT_PROP_FIRE_SUB_HURT': '火元素抗性',
    'FIGHT_PROP_ELEC_SUB_HURT': '雷元素抗性',
    'FIGHT_PROP_WATER_SUB_HURT': '水元素抗性',
    'FIGHT_PROP_GRASS_SUB_HURT': '草元素抗性',
    'FIGHT_PROP_WIND_SUB_HURT': '风元素抗性',
    'FIGHT_PROP_ROCK_SUB_HURT': '岩元素抗性',
    'FIGHT_PROP_ICE_SUB_HURT': '冰元素抗性',
}

ELEMENT_MAP = {
    'Wind': '风',
    'Ice': '冰',
    'Grass': '草',
    'Water': '水',
    'Electric': '雷',
    'Rock': '岩',
    'Fire': '火',
}

TYPE_TO_INT = {
    'GROW_CURVE_HP_S4': 0,
    'GROW_CURVE_ATTACK_S4': 1,
    'GROW_CURVE_HP_S5': 2,
    'GROW_CURVE_ATTACK_S5': 3,
}

WEAPON_TYPE = {
    'WEAPON_SWORD_ONE_HAND': '单手剑',
    'WEAPON_CATALYST': '法器',
    'WEAPON_CLAYMORE': '双手剑',
    'WEAPON_BOW': '弓',
    'WEAPON_POLE': '长柄武器',
}

class ConvertWeapon(TypedDict):
    name: str
    weapontype: str
    rarity: str
    baseatk: float
    substat: str
    effect: str
    effectname: str
    level: int
    ascension: int
    attack: float
    specialized: float
    r1: List[str]
    r2: List[str]
    r3: List[str]
    r4: List[str]
    r5: List[str]

class Image(TypedDict):
    nameicon: str

class ConvertCharacter(TypedDict):
    name: str
    weapontype: str
    rarity: str
    baseatk: float
    substat: str
    effect: str
    effectname: str
    level: int
    ascension: int
    attack: float
    specialized: float
    title: str
    element: str
    images: Image
    hp: float
    defense: float

async def convert_ambr_to_weapon(
    weapon_id: Union[int, str]
) -> Optional[ConvertWeapon]:
    raw_data = await get_ambr_weapon_data(weapon_id)
    if raw_data is None:
        return None
    if raw_data['affix'] is None:
        effect = {
            'name': '无特效',
            'upgrade': {
                '0': '无特效',
                '1': '无特效',
                '2': '无特效',
                '3': '无特效',
                '4': '无特效',
            },
        }
    else:
        effect = list(raw_data['affix'].values())[0]
    effect_name = effect['name']
    effect_up = effect['upgrade']
    upgrade = raw_data['upgrade']
    baseatk = upgrade['prop'][0]['initValue']
    basesp = upgrade['prop'][-1]['initValue']
    if 'propType' in upgrade['prop'][1]:
        substat = PROP_MAP[upgrade['prop'][1]['propType']]
    else:
        substat = '无副词条'
    result = {
        'name': raw_data['name'],
        'weapontype': raw_data['type'],
        'rarity': str(raw_data['rank']),
        'baseatk': baseatk,
        'substat': substat,
        'effectname': effect_name,
        'level': 90,
        'ascension': 6,
    }
    for index, affix in enumerate(effect_up):
        effect_value = re.findall(
            r'<c[^\u4e00-\u9fa5]+>\d+?.?\d+[^\u4e00-\u9fa5]+r>',
            effect_up[affix],
        )
        attr_list = []
        if index == 0:
            result['effect'] = effect_up[affix]
        for i, v in enumerate(effect_value):
            if index == 0:
                result['effect'] = result['effect'].replace(v, f'{{{i}}}')
            r = re.search(r'>([0-9/.%]+)', v)
            if r:
                attr_list.append(r.group(1))
        result[f'r{index+1}'] = attr_list
    atk_curve_type = upgrade['prop'][0]['type']
    sp_curve_type = upgrade['prop'][1]['type']
    atk_curve = WEAPON_GROW_CURVE['90']['curveInfos'][atk_curve_type]
    sp_curve = WEAPON_GROW_CURVE['90']['curveInfos'][sp_curve_type]
    atk_promoto = upgrade['promote'][-1]['addProps']['FIGHT_PROP_BASE_ATTACK']
    result['attack'] = atk_curve * baseatk + atk_promoto
    result['specialized'] = sp_curve * basesp
    return cast(ConvertWeapon, result)

async def convert_ambr_to_minigg(
    char_id: Union[str, int]
) -> Optional[ConvertCharacter]:
    raw_data = await get_ambr_char_data(char_id)
    if raw_data is None:
        return
    result = {
        'name': raw_data['name'],
        'title': raw_data['fetter']['title'],
        'rarity': raw_data['rank'],
        'weapontype': WEAPON_TYPE[raw_data['weaponType']],
        'element': ELEMENT_MAP[raw_data['element']],
        'images': {'namesideicon': raw_data['icon']},  # 暂时适配
        'substat': PROP_MAP[
            list(raw_data['upgrade']['promote'][-1]['addProps'].keys())[-1]
        ],
        'hp': raw_data['upgrade']['prop'][0]['initValue']
        * GROW_CURVE_LIST[89]['curveInfos'][
            TYPE_TO_INT[raw_data['upgrade']['prop'][0]['type']]
        ]['value']
        + raw_data['upgrade']['promote'][-1]['addProps']['FIGHT_PROP_BASE_HP'],
        'attack': raw_data['upgrade']['prop'][1]['initValue']
        * GROW_CURVE_LIST[89]['curveInfos'][
            TYPE_TO_INT[raw_data['upgrade']['prop'][1]['type']]
        ]['value']
        + raw_data['upgrade']['promote'][-1]['addProps'][
            'FIGHT_PROP_BASE_ATTACK'
        ],
        'defense': raw_data['upgrade']['prop'][2]['initValue']
        * GROW_CURVE_LIST[89]['curveInfos'][
            TYPE_TO_INT[raw_data['upgrade']['prop'][2]['type']]
        ]['value']
        + raw_data['upgrade']['promote'][-1]['addProps'][
            'FIGHT_PROP_BASE_DEFENSE'
        ],
        'specialized': raw_data['upgrade']['promote'][-1]['addProps'][
            list(raw_data['upgrade']['promote'][-1]['addProps'].keys())[-1]
        ],
    }
    return cast(ConvertCharacter, result)

async def convert_ambr_to_talent(
    char_id: Union[str, int]
) -> Optional[CharacterTalents]:
    raw_data = await get_ambr_char_data(char_id)
    if raw_data is None:
        return
    talent_data = raw_data['talent']
    result = {}
    if '7' in talent_data:
        num = ['0', '1', '4']
    else:
        num = ['0', '1', '3']
    for index, i in enumerate(num):
        result[f'combat{index+1}'] = {
            'name': talent_data[i]['name'],
            'info': talent_data[i]['description'],
            'attributes': {
                'labels': [],
                'parameters': {},
            },
        }
        label_str = ''
        for label in talent_data[i]['promote']['1']['description']:
            if label:
                label_str += label
                result[f'combat{index+1}']['attributes']['labels'].append(
                    label
                )
        para_list = re.findall(r'{(param[0-9]+):', label_str)

        # 进行排序
        nums = [
            i
            for i in sorted(
                [
                    int(i[-2:]) if i[-2].isdigit() else int(i[-1])
                    for i in para_list
                ]
            )
        ]

        num_temp = 0
        new_nums = []
        for num in nums:
            if num != num_temp + 1:
                new_nums.append(num_temp + 1)
            num_temp = num
            new_nums.append(num)

        new_para_list = [f'param{i}' for i in new_nums]

        for ig, para in enumerate(new_para_list):
            for level in talent_data[i]['promote']:
                if (
                    para
                    not in result[f'combat{index+1}']['attributes'][
                        'parameters'
                    ]
                ):
                    result[f'combat{index+1}']['attributes']['parameters'][
                        para
                    ] = []
                result[f'combat{index+1}']['attributes']['parameters'][
                    para
                ].append(talent_data[i]['promote'][level]['params'][ig])
    return cast(CharacterTalents, result)


#!/usr/bin/env python3
#
# Jupyter Server documentation build configuration file, created by
# sphinx-quickstart on Mon Apr 13 09:51:11 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import os.path as osp
import shutil
import sys

HERE = osp.abspath(osp.dirname(__file__))
sys.path.insert(0, osp.join(HERE, "..", ""))
from jupyter_server._version import version_info

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    "myst_parser",
    "sphinx.ext.autodoc",
    "sphinx.ext.doctest",
    "sphinx.ext.intersphinx",
    "sphinx.ext.autosummary",
    "sphinx.ext.mathjax",
    "sphinx.ext.napoleon",
    "IPython.sphinxext.ipython_console_highlighting",
    "sphinxcontrib_github_alt",
    "sphinxcontrib.openapi",
    "sphinxemoji.sphinxemoji",
    "sphinx_autodoc_typehints",
]

try:
    import enchant  # type:ignore[import-not-found]  # noqa

    extensions += ["sphinxcontrib.spelling"]
except ImportError:
    pass

myst_enable_extensions = ["html_image"]

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = [".rst", ".ipynb"]

# The encoding of source files.
# source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = "index"

# General information about the project.
project = "Jupyter Server"
copyright = "2020, Jupyter Team, https://jupyter.org"
author = "The Jupyter Team"

# ghissue config
github_project_url = "https://github.com/jupyter/jupyter_server"

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = f"{version_info[0]}.{version_info[1]}"

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# exclude_patterns = []

# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = "literal"

# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "default"
# highlight_language = 'python3'

# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False

# # Add custom note for each doc page

# rst_prolog = ""

# rst_prolog += """
# .. important::
#     This documentation covers Jupyter Server, an **early developer preview**,
#     and is not suitable for general usage yet. Features and implementation are
#     subject to change.

#     For production use cases, please use the stable notebook server in the
#     `Jupyter Notebook repo <https://github.com/jupyter/notebook>`_
#     and `Jupyter Notebook documentation <https://jupyter-notebook.readthedocs.io/en/stable/public_server.html>`_.
# """

# -- Options for HTML output ----------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
# html_theme = 'sphinx_rtd_theme'
html_theme = "pydata_sphinx_theme"
html_logo = "_static/jupyter_server_logo.svg"

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
# html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
# html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# NOTE: Sphinx's 'make html' builder will throw a warning about an unfound
#       _static directory. Do not remove or comment out html_static_path
#       since it is needed to properly generate _static in the build directory
html_static_path = ["_static"]

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
# html_extra_path = []

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}

# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}

# If false, no module index is generated.
# html_domain_indices = True

# If false, no index is generated.
# html_use_index = True

# If true, the index is split into individual pages for each letter.
# html_split_index = False

# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None

# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
#   'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
#   'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
# html_search_language = 'en'

# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
# html_search_options = {'type': 'default'}

# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
# html_search_scorer = 'scorer.js'

# Output file base name for HTML help builder.
htmlhelp_basename = "JupyterServerdoc"

# -- Options for LaTeX output ---------------------------------------------

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
#  author, documentclass [howto, manual, or own class]).
latex_documents = [
    (
        master_doc,
        "JupyterServer.tex",
        "Jupyter Server Documentation",
        "https://jupyter.org",
        "manual",
    ),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False

# If true, show page references after internal links.
# latex_show_pagerefs = False

# If true, show URL addresses after external links.
# latex_show_urls = False

# Documents to append as an appendix to all manuals.
# latex_appendices = []

# If false, no module index is generated.
# latex_domain_indices = True

# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, "jupyterserver", "Jupyter Server Documentation", [author], 1)]

# If true, show URL addresses after external links.
# man_show_urls = False

# -- Options for link checks ----------------------------------------------

linkcheck_ignore = [r"http://127\.0\.0\.1/*"]

# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
    (
        master_doc,
        "JupyterServer",
        "Jupyter Server Documentation",
        author,
        "JupyterServer",
        "One line description of project.",
        "Miscellaneous",
    ),
]

# Documents to append as an appendix to all manuals.
# texinfo_appendices = []

# If false, no module index is generated.
# texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
# texinfo_no_detailmenu = False

intersphinx_mapping = {
    "python": ("https://docs.python.org/", None),
    "ipython": ("https://ipython.readthedocs.io/en/stable/", None),
    "nbconvert": ("https://nbconvert.readthedocs.io/en/stable/", None),
    "nbformat": ("https://nbformat.readthedocs.io/en/stable/", None),
    "jupyter_core": ("https://jupyter-core.readthedocs.io/en/stable/", None),
    "tornado": ("https://www.tornadoweb.org/en/stable/", None),
    "traitlets": ("https://traitlets.readthedocs.io/en/stable/", None),
}

spelling_lang = "en_US"
spelling_word_list_filename = "spelling_wordlist.txt"

# import before any doc is built, so _ is guaranteed to be injected
import jupyter_server.transutils  # noqa: F401

CONFIG_HEADER = """\
.. _other-full-config:

Config file and command line options
====================================

The Jupyter Server can be run with a variety of command line arguments.
A list of available options can be found below in the :ref:`options section
<options>`.

Defaults for these options can also be set by creating a file named
``jupyter_server_config.py`` in your Jupyter folder. The Jupyter
folder is in your home directory, ``~/.jupyter``.

To create a ``jupyter_server_config.py`` file, with all the defaults
commented out, you can use the following command line::

  $ jupyter server --generate-config

.. _options:

Options
-------

This list of options can be generated by running the following and hitting
enter::

  $ jupyter server --help-all

"""

def setup(app):
    dest = osp.join(HERE, "other", "changelog.md")
    shutil.copy(osp.join(HERE, "..", "..", "CHANGELOG.md"), dest)

    # Generate full-config docs.
    from jupyter_server.serverapp import ServerApp

    destination = os.path.join(HERE, "other/full-config.rst")
    with open(destination, "w") as f:
        f.write(CONFIG_HEADER)
        f.write(ServerApp().document_config_options())


import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications import InceptionResNetV2
from tensorflow.keras.layers import Dense, Dropout, Flatten, Activation, Concatenate, Lambda
from tensorflow.keras.models import Model
from tensorflow.keras.losses import BinaryCrossentropy, CategoricalCrossentropy
from tensorflow.keras.callbacks import ModelCheckpoint,Callback
from tensorflow.keras.optimizers import Adam
import os
from tensorflow.keras.applications.imagenet_utils import preprocess_input
from sklearn.metrics import roc_auc_score

import argparse
from sklearn.preprocessing import StandardScaler
from tensorflow.keras import Input

parser = argparse.ArgumentParser()
parser.add_argument('--gpu_node', type=str, help='specify gpu nodes')
parser.add_argument('--train_path', type=str, default='./data/classification/train_joint.csv')
parser.add_argument('--val_path', type=str, default='./data/classification/val_joint.csv')
parser.add_argument('--batch_size', type=int, help='batch size', default=256)
parser.add_argument('--image_size', type=int, help='image size', default=256)
parser.add_argument('--epoch', type=int, help='number of epochs', default=30)
parser.add_argument('--lr', type=float, help='learning rate', default=0.001)
args = parser.parse_args()

os.environ["CUDA_VISIBLE_DEVICES"]= args.gpu_node

### ImageTextDataGenerator class will process clinical info and img_files together during data generation process
### similar customization of DataGenerator class for joint inputs can follow this link https://gist.github.com/krxat/dda5351cd143fd052e63fe6c794e984c
class ImageTextDataGenerator(keras.utils.Sequence):
    """Generates data for joint input."""
    def __init__(self,
                 img_files=None,
                 clinical_info=None,
                 labels=None,
                 ave=None,
                 std=None,
                 batch_size=32,
                 dim=(300, 300),
                 n_channels=3,
                 n_classes=num_classes,
                 shuffle=True):
        """Initialization.
        Args:
            img_files: A list of path to image files.
            clinical_info: A dictionary of corresponding clinical variables.
            labels: A dictionary of corresponding labels.
        """
        self.img_files = img_files
        self.clinical_info = clinical_info
        self.labels = labels
        self.batch_size = batch_size
        self.dim = dim
        if ave is None:
            self.ave = np.zeros(n_channels)
        else:
            self.ave = ave
        if std is None:
            self.std = np.zeros(n_channels) + 1
        else:
            self.std = std
        self.n_channels = n_channels
        self.n_classes = n_classes
        self.shuffle = shuffle
        self.on_epoch_end()

    def __len__(self):
        """Denotes the number of batches per epoch."""
        return int(np.floor(len(self.img_files) / self.batch_size))

    def __getitem__(self, index):
        """Generate one batch of data."""
        # Generate indexes of the batch
        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]
        # Find list of IDs
        img_files_temp = [self.img_files[k] for k in indexes]
        # Generate data
        X, y = self.__data_generation(img_files_temp)
        return X, y

    def on_epoch_end(self):
        """Updates indexes after each epoch."""
        self.indexes = np.arange(len(self.img_files))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)

    def __data_generation(self, img_files_temp):
        """Generates data containing batch_size samples."""
        # X : (n_samples, *dim, n_channels)
        # X = [np.empty((self.batch_size, self.dim[0], self.dim[1], self.n_channels))]
        X_img = []
        X_clinical = []
        y = np.empty((self.batch_size), dtype=int)
        # Generate data
        for i, img_file in enumerate(img_files_temp):
            # Read image
            img = image.load_img(img_file, target_size=self.dim)
            # Convert to 3 channels
            img = image.img_to_array(img)
            # Preprocess_input and rescale images
            img = preprocess_input(img)
            img = img/255.0
            # Normalization
            for ch in range(self.n_channels):
                img[:, :, ch] = (img[:, :, ch] - self.ave[ch])/self.std[ch]
            X_img.append(img)

            df_cf = self.clinical_info[self.clinical_info['filename']== img_file]
            df_cf.set_index('filename',inplace=True)
            c_info = df_cf.values.flatten()
            if len(c_info) < 3:
                print(filename)
            X_clinical.append(c_info)
            y[i] = int(self.labels[self.labels.filename == img_file]['Consensus'])
        X = [np.array(X_img), np.array(X_clinical)]
        return X, keras.utils.to_categorical(y, num_classes=self.n_classes)

###build model function
def get_compiled_model():
    meta_input = Input(shape=(df_norm_train.shape[1]-1,), name='text') # 20 is the number of clinical variables
    meta = Dense(64,activation='relu')(meta_input) ## this is the MLP to train clinical variables
    meta = Dense(32,activation='relu')(meta)

    model_dir ="../RadImageNet_models/CT-IRV2-notop.h5" ###RadImageNet pretrained models can be downloaded at https://github.com/BMEII-AI/RadImageNet
    base_model = InceptionResNetV2(weights=model_dir, input_shape=(image_size, image_size, 3), include_top=False,pooling='avg')
    x = base_model.output
    x = Dense(1024, activation='relu')(x)
    x = Dense(512, activation='relu')(x)
    x = Dense(32, activation='relu')(x)

    concatenated = Concatenate(axis=-1)([x, meta]) ## combine image and cv
    concat = Dropout(0.5)(concatenated)

    logits = Dense(num_classes, activation='softmax')(concat)
    my_new_model = Model(inputs=[base_model.input,meta_input], outputs=logits)

    adam = Adam(lr=args.lr, beta_1=0.9, beta_2=0.999, decay=0.0001)
    my_new_model.compile(optimizer=adam, loss=CategoricalCrossentropy(), metrics=['accuracy'])
    return my_new_model

num_classes = 5
image_size = args.image_size
batch_size = args.batch_size
num_epoches = args.epoch

df_t=pd.read_csv(args.train_path)
df_v=pd.read_csv(args.val_path)

###clinical info variables for model development
train_variables = [
       'kvp','manufacturer','Home_O2','Occupation','CurrentSmoker','FormerSmoker','Hx_disease','sex','age',
          'pulm_HTN','Biopsy','FEV1','FVC','FEV1/FVC','DLCO','thickness']

ss = StandardScaler()
df_norm_train = pd.DataFrame(ss.fit_transform(df_t[train_variables]),columns = df_t[train_variables].columns)
df_norm_train['filename'] = df_t.filename
df_norm_val = pd.DataFrame(ss.fit_transform(df_v[train_variables]),columns = df_v[train_variables].columns)
df_norm_val['filename'] = df_v.filename

model = get_compiled_model()

train_steps =  df_norm_train.shape[0]/ batch_size
val_steps = df_norm_val.shape[0] / batch_size

filepath="./models/classification-joint-CNN.h5"
checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')

train_labels = df_t[['Consensus']]
val_labels = df_v[['Consensus']]
train_labels['filename'] = df_norm_train['filename']
val_labels['filename'] = df_norm_val['filename']

train_datagen = ImageTextDataGenerator(img_files=list(df_norm_train.filename),
                              clinical_info=df_norm_train,
                              dim=(image_size, image_size),
                              labels=train_labels,
                              batch_size=batch_size,
                                       shuffle=True)
val_datagen = ImageTextDataGenerator(img_files=list(df_norm_val.filename),
                                     clinical_info=df_norm_val,
                                     dim = (image_size, image_size),
                                     labels=val_labels,
                                     batch_size=batch_size,
                                     shuffle=True)

history = model.fit(
        train_datagen,
        epochs=num_epoches,
        steps_per_epoch=train_steps,
        validation_data=val_datagen,
        validation_steps=val_steps,
        use_multiprocessing=True,
        callbacks=[checkpoint])

train_acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
train_loss = history.history['loss']
val_loss = history.history['val_loss']
d_loss = pd.DataFrame({'train_acc':train_acc, 'val_acc':val_acc, 'train_loss':train_loss, 'val_loss':val_loss})
d_loss.to_excel("./loss/loss_classification_joint_CNN.xlsx", index=False)


import gym
import retro
import retrowrapper
import sys
import numpy as np
from PIL import Image
import cv2
import neat
import pickle
import pyautogui
import matplotlib.pyplot as plt

class PlotReporter(neat.reporting.BaseReporter):
    def __init__(self):
        self.fitnesses = []
        self.bests = []
        self.worsts = []
        self.avg = []

    def post_evaluate(self, config, population, species, best_genome):
        global all_fit
        generation = len(self.fitnesses) + 1
        fitnesses = [x.fitness for x in population.values()]
        self.fitnesses.append(fitnesses)

        best_fitness = max(fitnesses)
        self.bests.append(best_fitness)

        worst_fitness = min(fitnesses)
        self.worsts.append(worst_fitness)

        avg_fitness = sum(fitnesses) / len(fitnesses)
        self.avg.append(avg_fitness)

        plt.xticks(ticks=(range(0, generation)))

        plt.plot(self.bests, label='Best')
        plt.plot(self.worsts, label='Worst')
        plt.plot(self.avg, label='Average')
        plt.title('Fitnesses over generations')
        plt.xlabel('Generation')
        plt.ylabel('Fitness')
        plt.legend()
        plt.show()

        # Reset all_fit for each new generation
        all_fit = []

def eval_genomes(genomes, config):
    global all_fit
    img_array = []
    for genome_id, genome in genomes:
        ob = env.reset()
        action = env.action_space.sample()

        inx, iny, inc = env.observation_space.shape  # size of the image created
        # print(inx, iny, inc)

        inx = int(inx / 8)
        iny = int(iny / 8)

        net = neat.nn.recurrent.RecurrentNetwork.create(genome, config)

        current_max_fitness = 0
        fitness_current = 0
        frame = 0
        counter = 0
        xpos = 0
        max_xpos = 0

        coins = 0
        powerups = 0
        yoshiCoins = 0

        done = False
        cv2.namedWindow("main", cv2.WINDOW_NORMAL)

        while not done:
            # env.render()
            frame += 1

            scaled_img = cv2.cvtColor(ob, cv2.COLOR_BGR2RGB)

            computer_img = cv2.resize(scaled_img, (iny, inx))
            computer_img = cv2.cvtColor(computer_img, cv2.COLOR_BGR2GRAY)

            scaled_img_copy = scaled_img.copy()

            x_offset = y_offset = 10
            computer_img_resized = computer_img

            scaled_img_copy[y_offset:y_offset + computer_img_resized.shape[0],
            x_offset:x_offset + computer_img_resized.shape[1], :] = cv2.cvtColor(computer_img_resized,
                                                                                cv2.COLOR_GRAY2RGB)

            cv2.imshow('main', scaled_img_copy)
            cv2.waitKey(1)

            ob = cv2.resize(ob, (inx, iny))
            ob = cv2.cvtColor(ob, cv2.COLOR_BGR2GRAY)
            ob = np.reshape(ob, (inx, iny))

            # Reshape the 2D grayscale image to a flattened 1D array
            img_array = ob.reshape(-1)

            nn_output = net.activate(img_array)

            # print(nn_output)

            ob, rew, done, info = env.step(nn_output)

            # Clear the contents of img_array
            img_array = np.array([], dtype=np.uint8)

            xpos = info['x']

            if xpos > max_xpos:
                fitness_current += 5  # itll change to rew
                max_xpos = xpos

            if powerups > info['powerups']:
                fitness_current += 200
                fitness_current = info['powerups']

            if yoshiCoins > info['yoshiCoins']:
                fitness_current += 200
                yoshiCoins = info['yoshiCoins']

            if fitness_current > current_max_fitness:
                current_max_fitness = fitness_current
                counter = 0
            else:
                counter += 1

            fitness_current -= 0.4  # each frame lose

            # if the player doesn't move right in 250 frames, throw
            if done or counter == 250:
                done = True
                print(genome_id, round(fitness_current))

            all_fit.append(fitness_current)
            genome.fitness = fitness_current

# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
#  A  B  X  Y  L  R  ↑  ↓  ←  →  Select Start

# best_fitnesses = []
# avg_fitnesses = []
# worst_fitnesses = []
# log_fitness = []
all_fit = []

# game_path = retro.data.get_romfile_path(game='SuperMarioWorld-Snes')
game_path = r'C:\Users\Alon\PycharmProjects\NeuMario\venv\Lib\site-packages\retro\data\stable\SuperMarioWorld-Snes'
env = retro.make(game=game_path, state='YoshiIsland1.state', record=False)
obs = env.reset()

config = neat.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet,
                     neat.DefaultStagnation, 'config-feedfoward')

p = neat.Population(config)

p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()  # calls post_evaluate
p.add_reporter(stats)
p.add_reporter(neat.Checkpointer(10))  # every 10 generation - save
plot_reporter = PlotReporter()
p.add_reporter(plot_reporter)

winner = p.run(eval_genomes)

with open("winner.pkl", "wb") as output:
    pickle.dump(winner, output, 1)

with open("winner.pkl", "rb") as input_file:
    loaded_winner = pickle.load(input_file)

print("Loaded winner's fitness:", loaded_winner.fitness)