import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
import torch.nn.functional as F
import random
from sklearn.model_selection import train_test_split

import numpy as np
import os
from PIL import Image

from torch.utils.data import random_split
from dataLoader import loadDataFiles, getImageDataVectors
from dataCollector import getLinkDictFromCSV

from torch.utils.data import Dataset, DataLoader

'''
### use multiple frames to finally make a prediction

## for each podcast clip (20s long)
## do the naive approach:

## Make a prediction for each frame/img from the podcast clip and then classify it as the podcast name
## with the highest probability ***

## then for all the clips repeat *** and do naive bayes assuming that all the individual frames are independent

'''

class CNNClassifier(nn.Module):
    def __init__(self, height, width, channels, kernelSize=3, numClasses=10):
        super(CNNClassifier, self).__init__()

        self.model = nn.Sequential(
            nn.Conv2d(channels, 32, kernelSize), nn.ReLU(),
            nn.Conv2d(32, 64, kernelSize), nn.ReLU(),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(64, 128, kernelSize), nn.ReLU(),
            nn.Conv2d(128, 128, kernelSize), nn.ReLU(),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(128, 256, kernelSize), nn.ReLU(),
            nn.Conv2d(256, 256, kernelSize), nn.ReLU(),
            nn.MaxPool2d(2, 2),
        )

        fc1_input_dim = self.compute_fc1_input_dim(height, width, kernelSize)
        #print("fc1 input dims, ", fc1_input_dim)

        self.fc = nn.Sequential(
            nn.Linear(fc1_input_dim, 1024), nn.ReLU(),
            nn.Linear(1024, 512), nn.ReLU(),
            nn.Linear(512, numClasses)
        )

    def compute_fc1_input_dim(self, height, width, kernelSize):
        dimReduction = kernelSize - 1

        for _ in range(3):
            height = (height - 2 * dimReduction) // 2
            width = (width - 2 * dimReduction) // 2

        return 256 * height * width

    def forward(self, x):
        x = self.model(x)
        x = x.view(-1, x.shape[1] * x.shape[2] * x.shape[3])
        x = self.fc(x)
        x = torch.softmax(x, dim=1)
        return x

class CustomTensorDataset(Dataset):
    def __init__(self, x, y):
        self.x = x
        self.y = y.argmax(axis=1)  # Convert one-hot encoded labels to class indices

    def __len__(self):
        return len(self.x)

    def __getitem__(self, idx):
        x_i = self.x[idx]
        y_i = self.y[idx]
        return x_i, y_i

def train_op(model,x_data,y_data,device):
    model.train()
    running_loss = 0.0

    model_save_path = "model_weights/"
    os.makedirs(model_save_path, exist_ok=True)

    inputs, labels = x_data.to(device), y_data.to(device)

    # zero out the gradients that were previously attached to weights
    # to prevent accumulated gradients
    optimizer.zero_grad()

    # forward pass
    outputs = model(inputs)

    # Calculate loss using raw logits
    loss = F.cross_entropy(outputs, labels)

    loss.backward(retain_graph=True)

    optimizer.step()
    running_loss += loss.item()
    _, predicted = torch.max(outputs, 1)
    _, targets = torch.max(labels, 1)
    correct = (predicted == targets).sum().item()

    return running_loss, correct

def test(model, dataloader, device,):
    model.eval() # test mode
    running_loss = 0.0

    for i, data in enumerate(dataloader, 0):
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)
        outputs = model.forward(inputs)

        # Calculate loss using raw logits
        loss = F.cross_entropy(outputs, labels)

        # Calculate accuracy using class probabilities
        _, predicted = torch.max(outputs, 1)
        correct = (predicted == labels).sum().item()

        running_loss += loss.item()

    numElems = i + 1
    return running_loss / numElems

if __name__ == "__main__":
    num_classes = 2
    podcastDict = getLinkDictFromCSV('playlistLinks.csv')
    image_files, labels = loadDataFiles(num_classes = 2)
    height = 240
    width = 426
    channels = 3
    model = CNNClassifier(height, width, channels, numClasses=num_classes)

    #########################

    ## train-valid-test split: 0.7-0.15-0.15

    x_train_files, x_testvalid_files, y_train_labels, y_testvalid_labels = train_test_split(image_files, labels, test_size=0.3, random_state=69)
    x_valid_files, x_test_files, y_valid_labels, y_test_labels = train_test_split(x_testvalid_files, y_testvalid_labels, test_size=0.5, random_state=69)

    # train_ratio = 0.7
    # total_length = len(image_files)
    # train_length = int(train_ratio * total_length)
    # test_length = (total_length - train_length) // 2

    # x_train_files = image_files[:train_length]
    # y_train_labels = labels[:train_length]

    # x_test_files = image_files[train_length:train_length + test_length]
    # y_test_labels = labels[train_length: train_length + test_length]

    # x_valid_files = image_files[train_length+test_length:]
    # y_valid_labels = labels[train_length+test_length:]

    # train_dataset = CustomTensorDataset(x_train, y_train)
    # test_dataset = CustomTensorDataset(x_test, y_test)

    # train_dataloader = DataLoader(train_dataset, batch_size=1, shuffle=True)
    # test_dataloader = DataLoader(test_dataset, batch_size=1, shuffle=False)

    # setting the loss function and the training optimizer
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

    device = torch.device('cpu')
    model.to(device)

    num_epochs = 5

    import gzip
    import pickle

    model_save_path = "model_weights/"
    os.makedirs(model_save_path, exist_ok=True)

    epochsLis = np.arange(num_epochs)
    trainLossLis = np.empty(shape=(num_epochs))
    validLossLis = np.empty(shape=(num_epochs))

    train_accs = np.empty(shape=(num_epochs))
    valid_accs = np.empty(shape=(num_epochs))

    batch_size = 32
    num_iters = len(x_train_files) // batch_size

    for epoch in range(num_epochs):
        avg_train_loss = 0
        avg_valid_loss = 0
        train_acc = 0
        valid_acc = 0

        # run training

        train_indices = np.arange(len(x_train_files))
        np.random.shuffle(train_indices)

        for it in range(0, len(x_train_files), batch_size):
            print(it)
            batch_indices = train_indices[it:it+batch_size]
            x_batch, y_batch = getImageDataVectors(x_train_files, y_train_labels, batch_indices, num_classes)
            train_loss, acc = train_op(model, x_batch, y_batch, device)
            avg_train_loss += train_loss
            train_acc += acc

        avg_train_loss = avg_train_loss / num_iters
        train_acc = train_acc / len(x_train_files)

        trainLossLis[epoch] = avg_train_loss
        train_accs[epoch] = train_acc

        # run validation

        valid_indices = np.arange(len(x_valid_files))
        np.random.shuffle(valid_indices)

        for it in range(0, len(x_valid_files), batch_size):
            print(it)
            batch_indices = valid_indices[it:it+batch_size]
            x_batch, y_batch = getImageDataVectors(x_valid_files, y_valid_labels, batch_indices, num_classes)
            x_batch, y_batch = x_batch.to(device), y_batch.to(device)
            outputs = model(x_batch)

            # Calculate loss using raw logits
            running_loss = F.cross_entropy(outputs, y_batch).item()
            avg_valid_loss += running_loss
            _, predicted = torch.max(outputs, 1)
            _, targets = torch.max(y_batch, 1)
            correct = (predicted == targets).sum().item()
            valid_acc += correct

        avg_valid_loss = avg_valid_loss / len(x_valid_files)
        valid_acc = valid_acc / len(x_valid_files)

        validLossLis[epoch] = avg_valid_loss
        valid_accs[epoch] = valid_acc

        print(f"Epoch: {epoch} Training Loss: {avg_train_loss} Validation Loss: {avg_valid_loss}.Training Accuracy: {train_acc} Validation Accuracy: {valid_acc}")
        # Save model weights (for the last epoch only)
        with gzip.open(os.path.join(model_save_path, f"model_epoch_{epoch+1}_classes{num_classes}.pkl.gz"), 'wb') as f:
            pickle.dump(model.state_dict(), f)

    import matplotlib.pyplot as plt

    plt.title("Training vs Validation Loss")
    plt.plot(epochsLis, trainLossLis, label="Training")
    plt.plot(epochsLis, validLossLis, label="Validation")
    plt.xlabel("num epochs")
    plt.ylabel("loss")
    plt.legend(loc='best')
    plt.show()

    plt.title("Training vs Validation Accuracy")
    plt.plot(epochsLis, train_accs, label="Training")
    plt.plot(epochsLis, valid_accs, label="Validation")
    plt.xlabel("num epochs")
    plt.ylabel("accuracy")
    plt.legend(loc='best')
    plt.show()

    # Now test the model

    test_acc = 0
    test_indices = np.arange(len(x_test_files))
    np.random.shuffle(test_indices)

    for it in range(0, len(x_test_files), batch_size):
        batch_indices = test_indices[it:it+batch_size]
        x_batch, y_batch = getImageDataVectors(x_test_files, y_test_labels, batch_indices, num_classes)
        x_batch, y_batch = x_batch.to(device), y_batch.to(device)
        outputs = model(x_batch)

        _, predicted = torch.max(outputs, 1)
        _, targets = torch.max(y_batch, 1)
        correct = (predicted == targets).sum().item()
        test_acc += correct

    test_acc = test_acc / len(x_test_files)
    print(f"Test Accuracy: {test_acc}")

    # # CODE TO LOAD THE TRAINED MODEL
    # loaded_model = CNNClassifier(height, width, channels, numClasses=len(y_data[0]))

    # # load the saved weights - from a specific epoch # (in this case it is epoch 5 = num_epochs)
    # with gzip.open(f"model_weights/model_epoch_{num_epochs}.pkl.gz", 'rb') as f:
    #     loaded_weights = pickle.load(f)

    # loaded_model.load_state_dict(loaded_weights)
    # loaded_model.to(device)

    # # verifying that the model is loaded correctly
    # test_loss = test(loaded_model, test_dataloader, device,)
    # print(f"Epoch: {num_epochs}, Train Loss: {num_epochs:.4f}, Test Loss: {test_loss}")


"""srun -n 60 --cpu-bind=cores python pso_script.py 50 20
"""
from time import time
import argparse
from mpi4py import MPI
from jax import random as jran
import numpy as np
from mpipso import pso_update
from mpipso.tests.test_pso_update import get_random_initial_conditions

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument("n_steps", type=int)
    parser.add_argument("n_dim", type=int)
    parser.add_argument("-target_seed", type=int, default=0)
    parser.add_argument("-init_seed", type=int, default=1)
    parser.add_argument("-xlo", type=float, default=0)
    parser.add_argument("-xhi", type=float, default=1)
    args = parser.parse_args()
    n_steps, n_dim = args.n_steps, args.n_dim
    xlo, xhi = args.xlo, args.xhi

    comm = MPI.COMM_WORLD
    rank, nranks = comm.Get_rank(), comm.Get_size()

    rank_key = jran.PRNGKey(rank + args.init_seed)
    rank_key, init_key = jran.split(rank_key, 2)
    init_cond = get_random_initial_conditions(init_key, n_dim, xlo=xlo, xhi=xhi)
    xmin, xmax, x_init, v_init, __ = init_cond

    target_key = jran.PRNGKey(args.target_seed)
    x_target = jran.uniform(target_key, minval=xmin, maxval=xmax, shape=(n_dim,))
    np.save("x_target", x_target)

    x = np.copy(x_init)
    v = np.copy(v_init)

    np.save("x_init_{}".format(rank), x_init)

    loc_dsq_init = pso_update._euclid_dsq(x_init, x_target)
    loc_dsq_best = np.copy(loc_dsq_init)
    loc_x_best = np.copy(x)
    comm.Barrier()

    swarm_x_best, swarm_dsq_best = pso_update.get_global_best(comm, x, x_target)

    loc_dsq_best_history = []
    swarm_dsq_best_history = []
    loc_x_best_history = []
    swarm_x_best_history = []
    start = time()
    for istep in range(n_steps):
        rank_key, update_key = jran.split(rank_key, 2)
        x, v = pso_update.update_particle(
            update_key, x, v, xmin, xmax, loc_dsq_best, swarm_dsq_best
        )
        istep_dsq = float(pso_update._euclid_dsq(x, x_target))
        istep_x_best, istep_dsq_best = pso_update.get_global_best(comm, x, x_target)

        if istep_dsq_best < swarm_dsq_best:
            swarm_dsq_best = istep_dsq_best
            swarm_x_best = istep_x_best

        if istep_dsq < loc_dsq_best:
            loc_dsq_best = istep_dsq
            loc_x_best = x

        loc_x_best_history.append(loc_x_best)
        loc_dsq_best_history.append(loc_dsq_best)
        swarm_x_best_history.append(swarm_x_best)
        swarm_dsq_best_history.append(swarm_dsq_best)
        comm.Barrier()

    end = time()
    runtime = end - start
    np.save("loc_x_best_history_{0}".format(rank), loc_x_best_history)
    np.save("swarm_x_best_history_{0}".format(rank), swarm_x_best_history)
    np.save("loc_dsq_best_history_{0}".format(rank), loc_dsq_best_history)
    np.save("swarm_dsq_best_history_{0}".format(rank), swarm_dsq_best_history)


import torch
import torch.nn as nn

from .modules import Encoder
from .modules import Hippocampus

NUM_UNITS = 64
MASK_P = 0.2
SIZE = 16

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.num_units = NUM_UNITS
        self.size = SIZE
        self.encoder = Encoder(num_units=NUM_UNITS, dim_inputs=SIZE * SIZE, dim_hidden=128)
        self.hippocampus = Hippocampus(num_units=NUM_UNITS, dim_hidden=NUM_UNITS * 4, mask_p=MASK_P)
        self.temperature = nn.Parameter(torch.ones(NUM_UNITS))

    @staticmethod
    def gen_noise(x):
        noise = 0.1 * torch.randn_like(x)
        return noise

    def forward(self, x):
        x = x.view(-1, SIZE * SIZE)

        x1 = x + self.gen_noise(x)
        y1 = self.encoder(x1)  # s_b * n_u
        w, mask = self.hippocampus(y1)  # s_b(q) * s_b * num_units

        x2 = x + self.gen_noise(x)
        y2 = self.encoder(x2)

        return (y1, w), y2, mask

    def encode(self, x):
        x = x.view(-1, SIZE * SIZE)
        y = self.encoder(x)

        return y


from argparse import ArgumentParser
from pathlib import Path

from kaldiio import ReadHelper

SYMBOL_NA: str = "<na>"  # symbol denoting text is not available
SPEECH_RESOLUTION: float = 0.02  # resolution in seconds

def time2token(x: float) -> str:
    """Convert float time to timestamp token."""
    x = round(x / SPEECH_RESOLUTION) * SPEECH_RESOLUTION
    return f"<{x:.2f}>"

def get_parser():
    parser = ArgumentParser(description="Convert text to s2t format.")
    parser.add_argument("--data_dir", type=Path, help="Data directory")
    return parser

if __name__ == "__main__":
    parser = get_parser()
    args = parser.parse_args()

    utt2dur = {}
    with ReadHelper(f'scp:{str(args.data_dir / "wav.scp")}') as reader:
        for key, (rate, numpy_array) in reader:
            utt2dur[key] = numpy_array.shape[-1] / rate

    with (args.data_dir / "text.ctc").open("r") as f_text_ctc, (
        args.data_dir / "text"
    ).open("w") as f_text, (args.data_dir / "text.prev").open("w") as f_text_prev:
        for line in f_text_ctc:
            uttid, raw_text = line.strip().split(maxsplit=1)
            f_text.write(
                f"{uttid} <eng><asr><0.00> "
                f"{raw_text.strip()}{time2token(utt2dur[uttid])}\n"
            )
            f_text_prev.write(f"{uttid} {SYMBOL_NA}\n")


from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpRequest
from django.template import loader
from django.shortcuts import render, redirect, get_object_or_404

from django.utils import timezone

from .date_play import get_month_dates, get_next_seven_days, timeslots, TimeSlot, append_timeslot, booking_step

from django.core.urlresolvers import reverse

from .models import Classroom, Booking, Calendar, SelectDateTime, CancelBooking

from django.views import generic

from .email_management import send_encrypted_link, check_encription

import hashlib
import uuid
from .room_booking_exception import BookingError, TimeSlotError

"""
using the function render() to do the same thing as loading the template

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)
"""

class IndexView(generic.ListView):
    template_name = 'room_display/index.html'
    context_object_name = 'room_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Classroom.objects.all()

# class RoomView(generic.DetailView):
#    model = Classroom
#    template_name = 'room_display/room_view.html'

def roomview(request, room_name, counter_day=None, counter_time=None, time=None):
#    import ipdb; ipdb.set_trace()
    print("Room_view")
    print(request)
    try:
        room = Classroom.objects.get(name=room_name)

        # collect all the bookings made for that room
        booking_list = room.booking_set.all()

        # generate the calendar for future booking
        dates, weekdays, booktime_list = get_next_seven_days()

        # works out what time period is already booked
        conflict_list = room.is_booked(booktime_list)

        if not time == None:
            timeslot = time
        else:
            timeslot = None

        if request.method == 'POST':
            query_dict = dict(request.POST)

            print(query_dict)

            if "booking_slot" in query_dict.keys():

		#this needs to be in confirm booking view
                requested_bookings = request.POST.getlist("booking_slot")
                # append the timeslots together if they are concomittent
                booking_timeslots = append_timeslot(requested_bookings)

                if "email" in query_dict.keys():
                    email = request.POST["email"]

                return render(request, 'room_display/confirm_booking_view.html',
                  {"room": room, "booking_timeslots": booking_timeslots,"email": email})

            elif "clear bookings" in query_dict.keys():
                """ this should be removed in the published version """
                room.booking_set.all().delete()

    except Classroom.DoesNotExist:
        raise Http404("Room does not exist :" + str(room_name))

    return render(request, 'room_display/room_view.html',
                  {'room': room, 'booking_list': booking_list, 'dates': dates,
                   'weekdays': weekdays, "timeslots": timeslots,
                   "timeslot": timeslot, "booktime_list": [zip(bl, cl) for bl, cl in zip(booktime_list, conflict_list)]})

def userview(request,user_name):
    """This view should get a room name and a time (and an email),create a booking and assign it to the room"""

    print(user_name)

    bk = Booking.objects.filter(email = user_name)
    print(bk)
    return render(request, 'room_display/user_view.html', {'user_name': user_name,
                                                           'booking_list': bk})

def modify_booking_view(request, hashed_key = None):
    """
        this view should be accessible from cancel booking button next to each
        booking, it could also be accessible as a logon page, ie a user enters
        their email address and click a button to send an authentication email
        to their email inbox.

        The possibility to cancel one particular booking should be possible as
        well as seeing and managing all reservations (authentication scheme)
        One possible scheme would be to use a random booking associated with
        the user as a salt for encryption and add more information than just
        the email, for example email plus '101' for access one booking or '100'
        for all bookings. Tests should be implemented for that purpose. (we can
        fake the click by using the hashed_key to redirect to the view)
    """

    #for the view before authentication procedure (user need to identify)
    if hashed_key is None:

        #If the user sent their email address through the click
        if request.method == 'POST':

            query_dict = dict(request.POST)
            print("In modify (POST) now")
            print(query_dict)

            #This request comes from a particular set of bookings
            if "bk_key" in query_dict.keys():
                bk_key = request.POST["bk_key"]
                booking = Booking.objects.filter(key = bk_key)

                if len(booking) > 1:
                    print(booking)
                    raise ValueError("Each booking is supposed to be unique")

                    # we should check that the user is the same and the bookings are next to each other
                else:

                    booking = booking[0]

                if "send_email" in query_dict.keys():

                    sha_key = bk_key
                    title = "Soft-booking modification or cancellation"
                    send_encrypted_link("pfduc@physics.mcgill.ca", booking.email,
                                        title,
                                        sha_key,
                                        "http://%s/room_display/modify_booking/"%(request.META["HTTP_HOST"]))

            #if the user clicked on "modify/cancel button on the index
            if "send_email" in query_dict.keys():

                print("There is an email in the post querydict")
                #see comment in the description of the fonction

        #if the user clicked on "cancel booking button" next to a booking
        elif request.method == 'GET':

            modify_form = CancelBooking()

    #this is valid if the user clicked on the link sent to their email inbox
    else:

        all_bookings = Booking.objects.all()
        booking = None

        #browse through all bookings to find the corresponding one

        for bk in all_bookings:

            salt = bk.key

            information = "%s"%(bk.email)
            print(salt)
            print(information)

            if check_encription(hashed_key,information,salt):
                print("victory")

                timeslot = bk.display_timeslot()
                email = bk.email
                bk.delete()

    return render(request, 'room_display/modify_booking.html', locals())

def confirmbookingview(request, room_name):
    try:
        #get the room in the DB by its name
        room = Classroom.objects.get(name=room_name)

        #the way to get to this page is only through the POST method
        if request.method == 'POST':
            query_dict = dict(request.POST)
            print("Confirm Booking View")
            print(request)
            print(query_dict)
            print("")

            if "booking_slot" in query_dict.keys():
                #fetch the requested booking slots
                requested_bookings = request.POST.getlist("booking_slot")
                # append the timeslots together if they are concomittent
                booking_timeslots = append_timeslot(requested_bookings)

            else:
                #if the booking timeslots are not present we return to the page
                return redirect("http://%s/room_display/%s" % (request.META["HTTP_HOST"], room.name))

            if "email" in query_dict.keys():
                email = request.POST["email"]
            else:
                email = ""

            if "booking_decision" in query_dict.keys():
                #This key is present only if the user pressed on one of the
                #confirm or cancel booking buttons

#                if "booking_slot" in query_dict.keys():
#                    requested_bookings = request.POST.getlist("booking_slot")
#
#                    booking_timeslots = append_timeslot(requested_bookings)

                decision = request.POST["booking_decision"]

                if decision == "confirmed":
                    # add the bookings to the room
                    #TODO : make sure the booking wasn't already performed

                    #this is just for test purpouses
                    if "hard_book" in query_dict.keys():
                        for booking_timeslot in booking_timeslots:
                            room.make_hard_booking(booking_timeslot)
                    else: # soft booking
                        for booking_timeslot in booking_timeslots:
                            try:
                                room.make_soft_booking(booking_timeslot, email)
                            except TimeSlotError as e:
                                return render(request,
                                    'room_display/confirm_booking_view.html',
                                    {"room": room,
                                     "booking_timeslots": booking_timeslots,
                                     "email": email,
                                     "errorMessage" : e})
                            except BookingError as e:
                                return render(request,
                                    'room_display/confirm_booking_view.html',
                                    {"room": room,
                                     "booking_timeslots": booking_timeslots,
                                     "email": email,
                                     "errorMessage" : e})
                            except:
                                raise

                elif decision == "cancelled":
                    #do nothing
                    pass
                else:
                    #this should not happend because the method is POST and not GET but one never knows
                   raise Http404("The value of the booking confirmation is not confirmed nor cancelled")

                #In both cases return to the roomview
                #I couldn't make the f**** redirect function to work with the url name
                return redirect("http://%s/room_display/%s" % (request.META["HTTP_HOST"],room.name))

            else:
                #This key is not present then it means we arrived on this page from room_view
                return render(request, 'room_display/confirm_booking_view.html',
                  {"room": room, "booking_timeslots": booking_timeslots,"email": email})

        else:
            raise Http404(
            "this page should not be displayed on its own (it needs to be accessed through the 'book' button)")
    except Classroom.DoesNotExist:
        raise Http404("Room does not exist :" + str(room_name))

def availableroomsview(request):
    """the capacity value should be tested to be positive integer"""
    room_list = None
    capacity = None
    timecheck = SelectDateTime()
    requested_datetime = None

    try:
        if request.method == 'POST':
            query_dict = dict(request.POST)
            print(query_dict)

            #get the full list of the rooms
            room_list = Classroom.objects.all()

            if 'capacity' in query_dict.keys():
                #the user wanted to filter by capacity

                capacity = request.POST['capacity']
                if capacity == "":
                    capacity = None
                else:
                    room_list = room_list.filter(number_seats__gte=capacity)

            if 'timestart' and 'timestop' and 'date' in query_dict.keys():
                hourstart = float(request.POST['timestart'])
                hourstop = float(request.POST['timestop'])
                date = timezone.datetime.strptime(request.POST['date'],"%Y-%m-%d")

#                if "duration" in query_dict.keys():
#                    duration = float ()
#                import ipdb;ipdb.set_trace()
                try :
                    requested_datetime = TimeSlot(date, hourstart,
                                                  duration = hourstop - hourstart)
    #                print(requested_datetime)
                    cr = room_list
                    good_cr =[]
                    for c in cr:
                        if c.is_booked(requested_datetime):
                            pass
                        else:
                            good_cr.append(c)
                    room_list = good_cr
                except ValueError:
                    requested_datetime = "inconsistent"
                    print("Fuck you value error, fuck you") # made me laugh when I read this
				#print(room_list)

			# try to make the fields remember what was the inputs last time
            timecheck.fields['date'].initial = request.POST['date']
            timecheck.fields['timestart'].initial = hourstart
            timecheck.fields['timestop'].initial = hourstop

        elif request.method == 'GET':
            #get the full list of the rooms
            room_list = Classroom.objects.all()

    except Classroom.DoesNotExist:
        raise Http404(
            "The classroom you are looking for doesn't exist")

#    except ValueError or KeyError:
#        capacity = "ValueError"
#        room_list = None
#    else:
#        capacity = "None"
#        room_list = None
#        timecheck=SelectDateTime()
#    if capacity == None:
#            capacity = "None"
#    calendar = Calendar()

    return render(request, 'room_display/available_rooms_view.html',
                          {"room_list": room_list,
                          "capacity": capacity,
                          "time_slot": requested_datetime,
                          "timecheck": timecheck})


import numpy as np

import torch
import torch.nn as nn
import torch.optim as optim

from model import ActorCritic

device = torch.device("cpu")

BATCH_SIZE = 32    # minibatch size
GAMMA = 0.99       # discount rate
TAU = 0.95         # tau

GRADIENT_CLIP = 5   # gradient clip
NUM_EPOCHS = 10     # optimization epochs
CLIP = 0.2          # PPO clip

BETA = 0.01         # entropy coefficient
LR = 3e-4           # Adam learning rate
EPSILON = 1e-5      # Adam epsilon

class Agent(object):
    """Interacts and learns from the environment"""

    def __init__(self, num_agents, state_size, action_size):
        """ Initialize an Agent object

        Params
        ======
            num_agent (int): number of agents
            state_size (int): dimension of each state
            action_size (int): dimension of each action
        """
        self.num_agents = num_agents

        self.state_size = state_size
        self.action_size = action_size

        self.model = ActorCritic(state_size, action_size, 256)
        self.optimizer = optim.Adam(self.model.parameters(), LR, eps = EPSILON)

    def step(self, rollout, num_agents):
        """ Compute advantage estimates at each time steps given a trajectory"""

        storage = [None]* (len(rollout) - 1)

        shape = (num_agents, 1)
        advantage = torch.Tensor(np.zeros(shape))

        for i in reversed(range(len(rollout)-1)):
            # rollout --> tuple ( s, a, p(a|s), r, dones, V(s) ) FOR ALL AGENT
            # rollout --> last row (s, none, none, none, pending_value) FOR ALL AGENT
            state, action, log_prob, reward, done, value = rollout[i]

            # last step - next_return = pending_value
            if i == len(rollout) - 2:
                next_return = rollout[i+1][-1]

            state = torch.Tensor(state)
            action = torch.Tensor(action)
            reward = torch.Tensor(reward).unsqueeze(1)
            done = torch.Tensor(done).unsqueeze(1)
            next_value = rollout[i+1][-1]

            # G(t) = r + G(t+1)
            g_return = reward + GAMMA * next_return * done
            next_return = g_return
            # g_return = reward + GAMMA * g_return*done

            # Compute TD error
            td_error = reward + GAMMA * next_value - value
            # Compute advantages
            advantage = advantage * TAU * GAMMA * done + td_error

            # Add (s, a, p(a|s), g, advantage)
            storage[i] = [state, action, log_prob, g_return, advantage]

        state, action, log_prob, g_return, advantage = map(lambda x: torch.cat(x, dim=0), zip(*storage))
        advantage = (advantage - advantage.mean()) / advantage.std()

        # Check dimensions
        # print ("States :", states.size(0), " * ", states.size(1) )
        # print ("Actions :", actions.size(0), " * ", actions.size(1) )
        # print ("Log Prob :", log_prob.size(0), " * ", log_prob.size(1) )
        # print ("Return :", g_return.size(0), " * ", g_return.size(1) )
        # print ("Advantage :", advantage.size(0), " * ", advantage.size(1) )

        self.learn(state, action, log_prob, g_return, advantage, num_agents)

    def act(self, states):
        """Given state as per current policy model, returns action, log probabilities and estimated state values"""
        dist, values = self.model(states)
        actions = dist.sample()
        log_probs = dist.log_prob(actions)
        log_probs = torch.sum(log_probs, dim=1, keepdim=True)

        return actions, log_probs, values

    def sample(self, states, actions, log_probs, returns, advantages):
        """Randomly sample learning batches from trajectory"""
        rand_idx = np.random.randint(0, states.size(0), BATCH_SIZE)
        return states[rand_idx, :], actions[rand_idx, :], log_probs[rand_idx, :], returns[rand_idx, :], advantages[rand_idx, :]

    def learn(self, states, actions, log_probs_old, returns, advantages, num_agents):
        """ Optimize surrogate loss with policy and value parameters using given learning batches."""

        for _ in range(NUM_EPOCHS):
            for _ in range(states.size(0) // BATCH_SIZE):
                state_samples, action_samples, log_prob_samples, return_samples, advantage_samples = self.sample(states, actions, log_probs_old, returns, advantages)

                dist, values = self.model(state_samples)

                log_probs = dist.log_prob(action_samples)
                log_probs = torch.sum(log_probs, dim=1, keepdim=True)
                entropy = dist.entropy().mean()

                ratio = (log_probs - log_prob_samples).exp()

                # Surrogate Objctive
                obj = ratio * advantage_samples

                # Clipped Surrogate Objective
                obj_clipped = ratio.clamp(1.0 - CLIP, 1.0 + CLIP) * advantage_samples

                # Compute policy loss: L = min[ r(θ), clip ( r(θ), 1-Ɛ, 1+Ɛ )*A ] - β * entropy
                policy_loss = -torch.min(obj, obj_clipped).mean(0) - BETA * entropy

                # Compute value loss: L = ( V(s) - V_t )^2
                value_loss = (return_samples - values).pow(2).mean()

                # Optimize
                self.optimizer.zero_grad()
                (policy_loss + 0.5 * value_loss).backward()
                nn.utils.clip_grad_norm_(self.model.parameters(), GRADIENT_CLIP)
                self.optimizer.step()


import pygame
from pygame.sprite import Sprite
import game_settings as gs

class Shield(Sprite):
  """
  Shield for the player after 3 aliens are killed
  """
  def __init__(self, x, y):
    super().__init__()
    self.image = pygame.image.load("assets/shield.png")
    self.rect = self.image.get_rect()
    self.rect.centerx = x
    self.rect.centery = y
    self.velocity = gs.PLAYER_SPEED

  def update(self):
    keys = pygame.key.get_pressed()
    if (keys[pygame.K_LEFT] or keys[pygame.K_a]) and (self.rect.left > 0):
      self.rect.x -= self.velocity
    if (keys[pygame.K_RIGHT] or keys[pygame.K_d]) and (self.rect.right < gs.SCREEN_WIDTH):
      self.rect.x += self.velocity


###############
### IMPORTS ###
###############

import os,sys
from django.conf import settings
from django.urls import path
from django.core.management import execute_from_command_line
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.core.management.base import BaseCommand
from django.views.generic import View
from django.http import HttpResponse
from django.test import TestCase
from django.contrib import admin
from django.db import models

#####################
### CONFIGURATION ###
#####################

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

settings.configure(
    DEBUG=True,
    ROOT_URLCONF=sys.modules[__name__],
    BASE_DIR = BASE_DIR,
    STATIC_URL = '/static/',
    SECRET_KEY = 'delphi',
    SILENCED_SYSTEM_CHECKS = ["admin.W411", "models.W042"],
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        },
    },
    DEFAULT_CHAR_FIELD_MAX_LENGTH = 2**10
)

# -------------------
# Models
# -------------------

class Author(models.Model):
    name = models.CharField(max_length=settings.DEFAULT_CHAR_FIELD_MAX_LENGTH)

    class Meta:
        ordering = ('name',)

# -------------------
# Views and routes
# -------------------

# @route('', name='index')
# def show_index(request):
#     posts = Post.objects.all()
#     return render(request, 'index.html', {'posts': posts})

# @route('blog/<int:post_id>/', name='post')
# def show_post(request, post_id):
#     post = get_object_or_404(Post, id=post_id)
#     return render(request, 'post.html', {'post': post})

# @route(r'^regex/(.*)$', regex=True)
# def regex_view(request, value):
#     return HttpResponse(value)

# @route('class-based/')
# class ClassBasedView(View):
#     def get(self, request):
#         return HttpResponse('Hello from class-based view')

def index(request):
    return HttpResponse('
A minimal Django response!
')

urlpatterns = [
    path(r'', index),
]

# -------------------
# Admin interface
# -------------------

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    pass

route('admin/', admin.site.urls)

# -------------------
# Template tags
# -------------------

@template.simple_tag
def say_hello(name):
    return 'Hello, {}!'.format(name)

# --------------------
# Management commands
# --------------------

@command('print_hello')
class HelloCommand(BaseCommand):
    def handle(self, *args, **options):
        self.stdout.write('Hello, Django!')

@command()
def print_hello_func(cmd, **options):
    cmd.stdout.write('Hello from function-based command!')

# --------------------
# Tests
# --------------------

class TestIndexView(TestCase):
    def test_success(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)

# -------------------
# Expose application
# -------------------

application = run()

if __name__ == '__main__':
    execute_from_command_line(sys.argv)


from rest_framework import serializers
from .models import Transaction, PolicyRule, PolicyRuleDestination

class TransactionSerializer(serializers.ModelSerializer):

    class Meta:
        model = Transaction
        fields = ['id', 'amount', 'destination', 'outgoing']

class PolicyRuleDestinationSerializer(serializers.ModelSerializer):
    class Meta:
        model = PolicyRuleDestination
        fields = ['address']

    def to_internal_value(self, data):
        return {'address': data}

    def to_representation(self, instance):
        return instance.address

class PolicyRuleSerializer(serializers.ModelSerializer):
    destinations = PolicyRuleDestinationSerializer(many=True, required=False, allow_null=True)

    class Meta:
        model = PolicyRule
        fields = ['id', 'amount', 'destinations']

    def create(self, validated_data):
        dests_data = validated_data.pop('destinations')
        rule = PolicyRule.objects.create(**validated_data)
        if dests_data:
            for dest_data in dests_data:
                PolicyRuleDestination.objects.create(rule=rule, **dest_data)
        return rule

    def update(self, instance, validated_data):
        instance.amount = validated_data['amount']
        dests_data = validated_data.pop('destinations')

        # to support additions and deletions, clear out all destinations
        PolicyRuleDestination.objects.filter(rule_id=instance.id).delete()

        # re-add destinations according to request data
        if dests_data:
            for dest_data in dests_data:
                PolicyRuleDestination.objects.create(rule=instance, **dest_data)

        return instance


from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def form():
    dane = '''<form action="" method="POST">
                      Podaj kod pocztowy: <input type="text" name="code">

                      <input type="submit" value="Submit">

                  </form>'''
    if request.method == 'GET':
        return dane
    else:
        code = request.form.get("code")
        if "-" in code:
            s = code.split("-")
            if len(s[0]) == 2 and len(s[1]) == 3 and s[0].isdigit() and s[1].isdigit():
                return "Kod poprawny"
            else:
                return "Kod niepoprawny"
        else:
            return "Kod niepoprawny"

if __name__ == "__main__":
    app.run(debug=True)


#!/usr/bin/python3
"""
    Module connect to MySQL using MySQLdb Module
    – selects all states but filters by names
    starting with N using MySQL regex operator
"""

if __name__ == "__main__":
    import MySQLdb
    from sys import argv
    db = MySQLdb.connect("localhost", argv[1], argv[2], argv[3])
    cursor = db.cursor()
    cursor.execute(
        '''SELECT * FROM states WHERE states.name
        LIKE BINARY 'N%' ORDER BY states.id'''
    )
    result = cursor.fetchall()
    for row in result:
        print(row)


from BBcomment import *
import datetime
import random
from sql import SQLTool

class BulletinBoardSQL:
    def __init__(self):
        self.sqlHelper = SQLTool.sql_helper()

    def getCommentsN(self):
        comments = self.sqlHelper.getAllComments()
        return len(comments)

    def getAllComments(self):
        comments=self.sqlHelper.getAllComments()
        BBcomments=[]
        for comment in comments:
            if comment["wechat_name"]!="None":
                userName=comment["wechat_name"]
            else:
                userName = comment["discord_name"]
            bbcomment=BBcomment()
            bbcomment.load(0,0,userName,comment["comment"],comment["time"])
            bbcomment.rawData=comment
            BBcomments.append(bbcomment)
        return BBcomments

    def readSomeComments(self,n=1):
        BBcomments=self.getAllComments()
        if n>len(BBcomments):
            n=len(BBcomments)
        commentSamples=random.sample(BBcomments,n)
        commentContexts = []
        for c in commentSamples:
            print(c.readComment())
            commentContexts.append(c.readComment())
        back=""
        for i in commentContexts:
            back+=i+"\n"
        return back

    def addCommentFromWeChat(self,nickName,context):
        currentTime=datetime.datetime.now()
        self.sqlHelper.addCommentfromWeChat(nickName,context,currentTime)
        userCtt,usql=self.sqlHelper.getWeChatUser(nickName)
        back="评论成功!\n"
        back+=f"您目前有皮币{userCtt['pCoin']}个，皮币用处多多哦\n"
        back+=f"试试!read吧"
        return back

    def addCommentFromDiscord(self,discord_id,context):
        currentTime=datetime.datetime.now()
        self.sqlHelper.addCommentfromDiscord(discord_id,context,currentTime)
        userCtt,usql=self.sqlHelper.getDiscordUser(discord_id)
        back="评论成功!\n"
        back+=f"您目前有皮币{userCtt['pCoin']}个，皮币用处多多哦\n"
        back+=f"试试!read吧"
        return back


"""
================
TacOS AddTrac UI
================

Extends the TacOS Trac class to provide a UI to configure a Trac in the TacOS environment.

"""

from AnyQt.QtWidgets import QWidget, QPushButton,\
    QCheckBox, QComboBox, QLabel,\
    QHBoxLayout, QVBoxLayout
from AnyQt.QtGui import QIcon
from AnyQt.QtCore import Qt
from Objects import Config
from Objects.Trac import Trac
from Objects.LineEdit import LineEdit

class AddTracUI(QWidget):

    def __init__(self, parent):
        super(AddTracUI, self).__init__()
        self.title = 'Create TracControl Element'
        self.setLayout(QVBoxLayout(self))
        self.parent = parent
        self.trac = Trac(name='', outputPin=0, enabled=False, icon=Config.icon('tracControl', 'rearDiff'), momentary=False)
        self._nameControl = LineEdit('Name', self)
        self._nameControl.kb.connect(self.showOSK)
        self._outputPinControlLabel = QLabel('Output Pin', self)
        self._outputPinControl = QComboBox(self)
        for _pin in self.parent.availablePins():
            self._outputPinControl.addItem(str(_pin))
        self._outputPinControl.setCurrentIndex(self._outputPinControl.findText(str(self.trac.outputPin)))
        self._enabledControl = QCheckBox('Enabled', self)
        self._iconControlLabel = QLabel('Icon', self)
        self._iconControl = QComboBox(self)
        for _key in Config.icons['tracControl'].keys():
            icon = Config.icon('tracControl', _key)
            self._iconControl.addItem(icon['name'], _key)
            self._iconControl.setItemIcon(self._iconControl.count() - 1, QIcon(icon['path']))
        self._addTracBtn = QPushButton('Add TracControl Element', self)
        self._addTracBtn.clicked.connect(self.__createTracBtnAction)
        self._cancelBtn = QPushButton('Cancel', self)
        self._cancelBtn.clicked.connect(self.__cancel)
        _layout = [
            ['_nameControl'],
            ['_outputPinControlLabel', '_outputPinControl'],
            ['_enabledControl'],
            ['_iconControlLabel', '_iconControl'],
            ['_addTracBtn', '_cancelBtn']
        ]
        for _list in _layout:
            _panel = QWidget(self)
            _panel.setLayout(QHBoxLayout(_panel))
            _panel.layout().setAlignment(Qt.AlignCenter)
            for _control in _list:
                _panel.layout().addWidget(eval('self.%s' % _control))
            self.layout().addWidget(_panel)

    def __createTracBtnAction(self):
        self.trac.name = self._nameControl.text()
        self.trac.outputPin = int(self._outputPinControl.currentText())
        self.trac.enabled = self._enabledControl.isChecked()
        self.trac.icon = self._iconControl.currentData()
        self.parent.tracs.addTrac(self.trac)
        self.parent.tracs.save()
        self.parent.loadUI('config_trac')
        self.parent.enableConfigButtons()

    def __cancel(self):
        self.parent.loadUI('config_trac')
        self.parent.enableConfigButtons()

    def showOSK(self):
        self.window().dock.show()
        self.window().osk.rWidget = self._nameControl


from collections import Counter
import copy
import time
import torch
import random
import torch.optim as optim
import torch.nn.functional as F
import numpy as np
from agents.Base_Agent import Base_Agent
from exploration_strategies.Epsilon_Greedy_Exploration import Epsilon_Greedy_Exploration
from utilities.data_structures.Replay_Buffer import Replay_Buffer
from agents.DQN_agents.SWAG_DQN import SWAG

class DQN(Base_Agent):
    """A deep Q learning agent"""
    agent_name = "DQN"
    def __init__(self, config):
        Base_Agent.__init__(self, config)
        self.memory = Replay_Buffer(self.hyperparameters["buffer_size"], self.hyperparameters["batch_size"], config.seed, self.device)
        self.q_network_local = self.create_NN(input_dim=self.state_size, output_dim=self.action_size)
        self.q_network_optimizer = optim.Adam(self.q_network_local.parameters(),
                                              lr=self.hyperparameters["learning_rate"], eps=1e-4)
        self.exploration_strategy = Epsilon_Greedy_Exploration(config)

        self.collect_freq=self.hyperparameters["collect_freq"]
        self.sample_freq=self.hyperparameters["sample_freq"]
        self.collect_start=self.hyperparameters["collect_start"]
        self.sample_start=self.hyperparameters["sample_start"]

        self.epi_scores=[[],[],[]]

        self.q_swa=self.create_NN(input_dim=self.state_size, output_dim=self.action_size)
        self.q_swag=self.create_NN(input_dim=self.state_size, output_dim=self.action_size)
        self.swag_agent=SWAG(self.q_network_local)

    def run_n_episodes(self, num_episodes=None, show_whether_achieved_goal=True, save_and_print_results=True):
        """Runs game to completion n times and then summarises results and saves model (if asked to)"""
        if num_episodes is None: num_episodes = self.config.num_episodes_to_run
        start = time.time()
        while self.episode_number < num_episodes:
            self.reset_game()
            self.step()
            for i in range(3):
                if i==0:
                    self.epi_scores[i].append(self.total_episode_score_so_far)
                else:
                    self.epi_scores[i].append(self.other_scores[i-1])
        time_taken = time.time() - start
        if show_whether_achieved_goal: self.show_whether_achieved_goal()
        if self.config.save_model: self.locally_save_policy()
        return self.epi_scores, None, time_taken

    def update_learning_rate(self, starting_lr, optimizer):

        t = (self.episode_number) / self.config.num_episodes_to_run
        lr_ratio = 0.01 #self.swag_lr / starting_lr
        if t <= 0.5:
            factor = 1.0
        elif t <= 0.9:
            factor = 1.0 - (1.0 - lr_ratio) * (t - 0.5) / 0.4
        else:
            factor = lr_ratio
        new_lr=starting_lr * factor
        for g in optimizer.param_groups:
            g['lr'] = new_lr
        if random.random() < 0.001: self.logger.info("Learning rate {}".format(new_lr))

    def reset_game(self):
        """Resets the game information so we are ready to play a new episode"""
        self.environment[0].seed(self.config.seed)
        s = self.environment[0].reset()
        self.environment[1]=copy.deepcopy(self.environment[0])
        self.environment[2]=copy.deepcopy(self.environment[0])
        self.state=[s, copy.deepcopy(s), copy.deepcopy(s)]
        self.next_state = [None, None, None]
        self.actions = [None, None, None]
        self.reward = [None, None, None]
        self.done = [False, False, False]
        self.total_episode_score_so_far = 0
        self.other_scores=[0, 0]
        self.episode_states = []
        self.episode_rewards = []
        self.episode_actions = []
        self.episode_next_states = []
        self.episode_dones = []
        self.episode_desired_goals = []
        self.episode_achieved_goals = []
        self.episode_observations = []
        if "exploration_strategy" in self.__dict__.keys(): self.exploration_strategy.reset()
        self.logger.info("Reseting game -- New start state {}".format(self.state))

        self.update_learning_rate(self.hyperparameters["learning_rate"], self.q_network_optimizer)

    def conduct_action(self, actions):
        """Conducts an action in the environment"""
        for i in range(3):
            if not self.done[i]:
                self.next_state[i], self.reward[i], self.done[i], _ = self.environment[i].step(actions[i])
                if i==0:
                    self.total_episode_score_so_far+= self.reward[i]
                else:
                    self.other_scores[i-1]+=self.reward[i]
                if self.hyperparameters["clip_rewards"]: self.reward[i] =  max(min(self.reward[i], 1.0), -1.0)
            else:
                self.next_state[i]=None

    def save_experience(self, memory=None, experience=None):
        """Saves the recent experience to the memory buffer"""
        if memory is None: memory = self.memory
        if experience is None: experience = self.state[0], self.actions[0], self.reward[0], self.next_state[0], self.done[0]
        memory.add_experience(*experience)

    def step(self):
        """Runs a step within a game including a learning step if required"""
        while not all(self.done):
            if self.episode_number<self.collect_start:
                a = self.pick_action()
                self.actions=[a, copy.deepcopy(a), copy.deepcopy(a)]
            elif self.episode_number>=self.collect_start and self.episode_number<self.sample_start:
                self.actions=[self.pick_action(),self.pick_swa_action(),self.pick_action()]
            else:
                self.actions=[self.pick_action(),self.pick_swa_action(),self.pick_swag_action()]

            self.conduct_action(self.actions)
            if self.time_for_q_network_to_learn():
                for _ in range(self.hyperparameters["learning_iterations"]):
                    self.learn()
            if not self.done[0]:
                self.save_experience()
            for i in range(3):
                self.state[i] = self.next_state[i] #this is to set the state for the next iteration
            self.global_step_number += 1
        self.episode_number += 1
        if (self.episode_number>self.collect_start) and (self.episode_number%self.collect_freq==0):
            self.swag_agent.collect_model(self.q_network_local)
            self.swag_agent.sample(self.q_swa,add_swag=False)
        if (self.episode_number>self.sample_start) and (self.episode_number%self.sample_freq==0):
            self.swag_agent.sample(self.q_swag)
        if self.episode_number%10==0:
            print("EPISODE ",self.episode_number, self.total_episode_score_so_far,self.other_scores)
        self.other_scores=[0,0]

    def pick_action(self, state=None):
        """Uses the local Q network and an epsilon greedy policy to pick an action"""
        # PyTorch only accepts mini-batches and not single observations so we have to use unsqueeze to add
        # a "fake" dimension to make it a mini-batch rather than a single observation
        if state is None: state = self.state[0]
        if state is None: return
        if isinstance(state, np.int64) or isinstance(state, int): state = np.array([state])
        state = torch.from_numpy(state).float().unsqueeze(0).to(self.device)
        if len(state.shape) < 2: state = state.unsqueeze(0)
        self.q_network_local.eval() #puts network in evaluation mode
        with torch.no_grad():
            action_values = self.q_network_local(state)

        self.q_network_local.train() #puts network back in training mode
        action = self.exploration_strategy.perturb_action_for_exploration_purposes({"action_values": action_values,
                                                                                "turn_off_exploration": self.turn_off_exploration,
                                                                                "episode_number": self.episode_number})
        self.logger.info("Q values {} -- Action chosen {}".format(action_values, action))
        return action

    def pick_swa_action(self, state=None):
        if state is None: state = self.state[1]
        if state is None: return
        if isinstance(state, np.int64) or isinstance(state, int): state = np.array([state])
        state = torch.from_numpy(state).float().unsqueeze(0).to(self.device)
        if len(state.shape) < 2: state = state.unsqueeze(0)
        self.q_swa.eval() #puts network in evaluation mode
        with torch.no_grad():
            action_values = self.q_swa(state)
        return torch.argmax(action_values).item()

    def pick_swag_action(self, state=None):
        if state is None: state = self.state[2]
        if state is None: return
        if isinstance(state, np.int64) or isinstance(state, int): state = np.array([state])
        state = torch.from_numpy(state).float().unsqueeze(0).to(self.device)
        if len(state.shape) < 2: state = state.unsqueeze(0)
        self.q_swag.eval() #puts network in evaluation mode
        with torch.no_grad():
            action_values = self.q_swag(state)
        return torch.argmax(action_values).item()

    def learn(self, experiences=None):
        """Runs a learning iteration for the Q network"""
        if experiences is None: states, actions, rewards, next_states, dones = self.sample_experiences() #Sample experiences
        else: states, actions, rewards, next_states, dones = experiences
        loss = self.compute_loss(states, next_states, rewards, actions, dones)

        actions_list = [action_X.item() for action_X in actions ]
        self.logger.info("Action counts {}".format(Counter(actions_list)))
        self.take_optimisation_step(self.q_network_optimizer, self.q_network_local, loss, self.hyperparameters["gradient_clipping_norm"])

    def compute_loss(self, states, next_states, rewards, actions, dones):
        """Computes the loss required to train the Q network"""
        with torch.no_grad():
            Q_targets = self.compute_q_targets(next_states, rewards, dones)
        Q_expected = self.compute_expected_q_values(states, actions)
        loss = F.mse_loss(Q_expected, Q_targets)
        return loss

    def compute_q_targets(self, next_states, rewards, dones):
        """Computes the q_targets we will compare to predicted q values to create the loss to train the Q network"""
        Q_targets_next = self.compute_q_values_for_next_states(next_states)
        Q_targets = self.compute_q_values_for_current_states(rewards, Q_targets_next, dones)
        return Q_targets

    def compute_q_values_for_next_states(self, next_states):
        """Computes the q_values for next state we will use to create the loss to train the Q network"""
        Q_targets_next = self.q_network_local(next_states).detach().max(1)[0].unsqueeze(1)
        return Q_targets_next

    def compute_q_values_for_current_states(self, rewards, Q_targets_next, dones):
        """Computes the q_values for current state we will use to create the loss to train the Q network"""
        Q_targets_current = rewards + (self.hyperparameters["discount_rate"] * Q_targets_next * (1 - dones))
        return Q_targets_current

    def compute_expected_q_values(self, states, actions):
        """Computes the expected q_values we will use to create the loss to train the Q network"""
        Q_expected = self.q_network_local(states).gather(1, actions.long()) #must convert actions to long so can be used as index
        return Q_expected

    def locally_save_policy(self):
        """Saves the policy"""
        torch.save(self.q_network_local.state_dict(), "Models/{}_local_network.pt".format(self.agent_name))

    def time_for_q_network_to_learn(self):
        """Returns boolean indicating whether enough steps have been taken for learning to begin and there are
        enough experiences in the replay buffer to learn from"""
        return self.right_amount_of_steps_taken() and self.enough_experiences_to_learn_from()

    def right_amount_of_steps_taken(self):
        """Returns boolean indicating whether enough steps have been taken for learning to begin"""
        return self.global_step_number % self.hyperparameters["update_every_n_steps"] == 0

    def sample_experiences(self):
        """Draws a random sample of experience from the memory buffer"""
        experiences = self.memory.sample()
        states, actions, rewards, next_states, dones = experiences
        return states, actions, rewards, next_states, dones


import os
import argparse
import numpy as np
import torch
import random
import yaml
import pickle as pkl
from easydict import EasyDict as edict
from tqdm import tqdm
from tqdm.contrib.concurrent import process_map
import multiprocessing as mp
from functools import partial

from utils.graph_generators import *
from utils.arg_helper import mkdir
from utils.graph_utils import save_graph_list, load_graph_ts
import gc
from torch_geometric.utils.convert import from_networkx

def parse_arguments():
    parser = argparse.ArgumentParser(
        description="Script to generate the synthetic data for the DAMNETS experiments")
    parser.add_argument(
        '-n',
        '--num_workers',
        type=int,
        default=1,
        help='Number of workers used to generate the data'
    )
    parser.add_argument(
        '-p',
        '--data_path',
        type=str,
        default='data',
        help='The data directory.'
    )
    parser.add_argument(
        '-d',
        '--dataset_name',
        type=str,
        default='',
        help='The name of the pickled dataset in the directory, stored as lists of networkx graphs. '
             'Do not include .pkl.'
    )
    parser.add_argument(
        '-t',
        '--train_p',
        type=float,
        help='The proportion of total data to use for training. The remainder will be used for test.'
    )
    parser.add_argument(
        '-v',
        '--val_p',
        type=float,
        help='The proportion of the training data to use for validation.'
    )
    parser.add_argument(
        '-r',
        '--randomize',
        type=bool,
        help='If True, will randomly select the time series to use for training/test/validation.',
        default=True
    )
    args = parser.parse_args()
    return args

def format_data(graph_ts, n_workers, abs=False):
    '''
    Prepare the data. This involves computing the delta matrices for the
    network time series, inserting them into the TreeLib and then putting them into torch geometric
    format for computation.
    Args:
        graph_ts: The time series to pre-process.
        start_idx: If some time-series have already been processed, we want to start indexing
        from the index of the last one in the previous batch (as they are accessed
        via this index in the TreeLib underlying the bigg model). This is used for training and validation split.
    Returns: A pytorch dataloader that loads the previous network combined with the index in the TreeLib of the
    associated delta matrix we want to learn.
    '''
    print('Computing Deltas')
    delta_fn = partial(compute_adj_delta, abs=False)
    diffs = process_map(delta_fn, graph_ts, max_workers=n_workers)
    # Remove the last observation from training data.
    graph_ts = [ts[:-1] for ts in graph_ts]
    # Flatten (will go into treelib in this order).
    diffs = [nx.Graph(diff) for diff_ts in diffs for diff in diff_ts]
    graph_ts = [g for ts in graph_ts for g in ts]
    num_nodes = graph_ts[0].number_of_nodes()
    ix = np.array([(i,j) for i in range(1, num_nodes) for j in range(i)])
    prev_labels = [nx.to_numpy_array(g)[ix[:, 0], ix[:, 1]] for g in graph_ts]
    print('Converting to networkx format')
    data = process_map(from_networkx, graph_ts, max_workers=n_workers, chunksize=20)
    # data = [from_networkx(g) for g in tqdm(graph_ts)]  # convert to torch_geometric format w/ edgelists.
    one_hot = torch.eye(num_nodes)
    print('Setting attributes.')
    for d in tqdm(data):
        d.x = one_hot
        # data[i].graph_id = i + start_idx
    data = list(zip(prev_labels, data))
    return list(zip(data, diffs))

# def format_data(graph_ts, n_workers, start_idx=0):
#     '''
#     Prepare the data. This involves computing the delta matrices for the
#     network time series, inserting them into the TreeLib and then putting them into torch geometric
#     format for computation.
#     Args:
#         graph_ts: The time series to pre-process.
#         start_idx: If some time-series have already been processed, we want to start indexing
#         from the index of the last one in the previous batch (as they are accessed
#         via this index in the TreeLib underlying the bigg model). This is used for training and validation split.
#     Returns: A pytorch dataloader that loads the previous network combined with the index in the TreeLib of the
#     associated delta matrix we want to learn.
#     '''
#     print('Computing Deltas')
#     delta_fn = partial(compute_adj_delta, abs=False)
#     diffs = process_map(delta_fn, graph_ts, max_workers=n_workers)
#     graph_ts = [ts[:-1] for ts in graph_ts]
#     # Flatten (will go into treelib in this order).
#     diffs_pos = [[(d == 1).astype(np.int) for d in diff_ts] for diff_ts in diffs]
#     diffs_neg = [[(d == -1).astype(np.int) for d in diff_ts] for diff_ts in diffs]
#     diffs_pos = [nx.Graph(diff) for diff_ts in diffs_pos for diff in diff_ts]
#     diffs_neg = [nx.Graph(diff) for diff_ts in diffs_neg for diff in diff_ts]
#     graph_ts = [g for ts in graph_ts for g in ts]
#     num_nodes = graph_ts[0].number_of_nodes()
#     print('Converting to pyg format')
#     data = process_map(from_networkx, graph_ts, max_workers=n_workers, chunksize=20)
#     # data = [from_networkx(g) for g in tqdm(graph_ts)]  # convert to torch_geometric format w/ edgelists.
#     one_hot = torch.eye(num_nodes)
#     print('Setting attributes.')
#     for i in tqdm(range(len(data))):
#         data[i].x = one_hot
#         data[i].pos_id = (2 * i) + start_idx
#         data[i].neg_id = (2 * i + 1) + start_idx
#     return (data, diffs_pos, diffs_neg), data[-1].neg_id + 1

def main():
    c_args = parse_arguments()
    save_dir = c_args.data_path
    mkdir(save_dir)

    graphs_path = os.path.join(save_dir, f'{c_args.dataset_name}.pkl')
    graphs = load_graph_ts(graphs_path)
    if c_args.randomize:
        print('Randomizing')
        random.shuffle(graphs)
    train_ix = int(len(graphs) * c_args.train_p)
    if train_ix == 0:  # debugging
        train_graphs = test_graphs = graphs
    else:
        train_graphs = graphs[:train_ix]
        test_graphs = graphs[train_ix:]
    val_len = int(len(train_graphs) * c_args.val_p)
    val_graphs = train_graphs[:val_len] if val_len > 0 else train_graphs[val_len:]
    # Remove validation from training set
    train_graphs = train_graphs[val_len:]
    ## Set number of nodes for bigg model (keep names same for compatability)
    print('Number of Training TS: ', len(train_graphs))
    print('Number of Val TS: ', len(val_graphs))
    print('Number of Test TS: ', len(test_graphs))
    print('TS length (T): ', len(test_graphs[0]))
    print('Saving Graphs')
    save_graph_list(
        train_graphs, os.path.join(save_dir, f'{c_args.dataset_name}_train_graphs_raw.pkl'))
    save_graph_list(
        val_graphs, os.path.join(save_dir, f'{c_args.dataset_name}_val_graphs_raw.pkl'))
    save_graph_list(
        test_graphs, os.path.join(save_dir, f'{c_args.dataset_name}_test_graphs.pkl'))
    ## test doesn't need any pre-processing

    del test_graphs
    del graphs
    gc.collect()
    ## put into required format, save.
    train_processed = format_data(train_graphs, c_args.num_workers)
    save_graph_list(
        train_processed, os.path.join(save_dir, f'{c_args.dataset_name}_train_graphs.pkl'))
    del train_processed
    del train_graphs
    gc.collect()

    val_processed = format_data(val_graphs, c_args.num_workers)
    save_graph_list(
        val_processed, os.path.join(save_dir, f'{c_args.dataset_name}_val_graphs.pkl'))

    # args.experiment.graph_save_dir = self.args.save_dir

if __name__ == '__main__':
    main()


#
import csv
from importlib.resources import contents
import re
#
def ur1HausOpen(filename,searchTerm):

    with open(filename, newline='') as f:
        contents = csv.reader(f, delimiter=',')
        for skipped_line in range(9):
            next(contents)
            for keyword in searchTerm:
                for eachLine in contents:
                    x = re.findall(r"" + keyword, eachLine[3])
                for skipped_line in x:
# Don't edit this line. It is here to show how it is possible
# to remove the "tt" so programs don't convert the malicious
# domains to links that an be accidentally clicked on.
                    the_url = eachLine[2].replace("http","hxxp")
                    the_src = eachLine[4]
        print("""
        URL:
        Info:
        {}""",format(the_url, the_src,"*"+60))


import os, sys
import numpy as np
from utils import *
import matplotlib.pyplot as plt

if __name__=="__main__":

    matplotlib.rcParams.update({'font.size': 18})

    def assert_sum(p):
        assert abs(sum(p)-1.0)<0.0001

    def one_hot(i, n):
        tmp = np.zeros(n)
        tmp[i] = 1
        return tmp

    def KL(p, q):
        assert_sum(p)
        assert_sum(q)
        tmp = 0
        try:
            for i in range(len(p)):
                if p[i]>0:
                    tmp += p[i]*(np.log(p[i])-np.log(q[i]))
        except:
            assert False
        return tmp

    N = 100
    ymax = 5.0

    P_N = [np.ones(N) / float(N)]

    np.random.seed(12345)
    GaussianA = np.sort(abs(np.random.randn(N)))
    GaussianA /= np.sum(GaussianA)

    GaussianB = np.sort(abs(np.random.randn(N)))
    GaussianB /= np.sum(GaussianB)
    for i in range(int(N//2)):
        tmp = GaussianB[i]
        GaussianB[i] = GaussianB[N-1-i]
        GaussianB[N-1-i] = tmp

    P_N.append(GaussianA)
    P_N.append(GaussianB)

    NN = 1000

    Curves = []
    for test in range(len(P_N)):

        print(np.array2string(np.asarray(P_N[test]), formatter={'float_kind': lambda x: "%.2f" % x}))

        Curve = []
        for m in range(N):

            N_m = np.zeros(N)
            sum_density = 0
            for i in range(m + 1):
                N_m += one_hot(i, N) * P_N[test][i]
                sum_density += P_N[test][i]
            N_m /= sum_density
            assert_sum(N_m)

            KL_mean = 0
            for i in range(m + 1):
                KL_mean += KL(one_hot(i, N), N_m) * P_N[test][i] / sum_density
            print(N, m + 1, KL_mean)

            Curve.append(KL_mean)

        Curves.append(Curve)

        print('\n\n')

    Curve = []
    test = 1
    for m in range(N):

        scores = []

        for k in range(NN):

            sum_density = 0
            N_m = np.zeros(N)
            keep = np.zeros(N)
            for t in range(m + 1):
                i = np.random.randint(0, N - sum(keep))
                count = 0
                for j in range(N):
                    if not keep[j]:
                        if count == i:
                            i = j
                            break
                        count += 1
                sum_density += P_N[test][i]
                N_m += one_hot(i, N) * P_N[test][i]
                keep[i] = 1.0
            assert sum(keep) == m + 1
            N_m /= sum_density
            assert_sum(N_m)

            KL_mean = 0
            for i in range(N):
                if keep[i]:
                    KL_mean += KL(one_hot(i, N), N_m) * P_N[test][i] / sum_density * keep[i]

            scores.append(KL_mean)

        Curve.append(scores)

    #ymax = max(np.max(np.array(Curves)), np.max(np.array(Curve)))

    plt.figure()
    plt.xlim(0, N)
    plt.ylim(0, ymax)
    plt.ylabel('KL_Score')
    plt.errorbar(np.array(range(N)), [mean(scores) for scores in Curve],
                 [[max(scores) - mean(scores) for scores in Curve], [mean(scores) - min(scores) for scores in Curve]],
                 linestyle='--', fmt='kp', markersize=4)
    # plt.title('Random Drop with Gaussian Class Density', fontsize=14)
    plt.grid(True)
    plt.tight_layout()
    plt.savefig('../drop_random' + str(N) + '.pdf')

    plt.clf()
    plt.plot(Curves[0], 'kp-', markersize=4)
    plt.xlim(0, N)
    plt.ylim(0, ymax)
    plt.ylabel('kl_score')
    #plt.legend(['Uniform'])
    #plt.title('Random Drop with Uniform Class Density', fontsize=14)
    plt.grid(True)
    plt.tight_layout()
    plt.savefig('../drop_uniform'+str(N)+'.pdf')

    plt.clf()
    plt.plot(Curves[1], 'kp-', markersize=4)
    plt.plot(Curves[2], 'bp-', markersize=4)
    plt.xlim(0, N)
    plt.ylim(0, ymax)
    plt.ylabel('kl_score')
    plt.legend(['Gaussian-Inc', 'Gaussian-Dec'])
    plt.grid(True)
    plt.tight_layout()
    plt.savefig('../drop_gaussian'+str(N)+'.pdf')


# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(19680801)
std,mean=100,15
x = std+mean*np.random.randn(10000)
n,bins,patchse = plt.hist(x,50,density=True,facecolor ='g',alpha = 0.75)

plt.xlabel('')
plt.ylabel('Probability')
plt.title('Std,Mean')
plt.text(60,.025,r'$\std=100,\\mean=15$')
plt.xlim(40,160)
plt.ylim(0,0.03)
plt.grid(True)
plt.show()


import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget
from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout
from PyQt5.QtWidgets import QPushButton

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('Demo')
        self.setContentsMargins(0, 0, 0, 0)

        # 设置窗体尺寸
        self.resize(1080, 720)

        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)

        # 新建主窗口布局
        main_layout = QVBoxLayout()

        # 新建按钮
        start_btn = QPushButton('开始')
        start_btn.clicked.connect(self.start_btn_click)
        main_layout.addWidget(start_btn)

        self.setLayout(main_layout)

    def start_btn_click(self):
        print('开始')

if __name__ == '__main__':
    print('main')
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

"""dslr/more_features
    in addition to the 10 best features,
    exploring additonal features for training:

"""

def drop_columns(df: pd.DataFrame, drop_na: bool) -> pd.DataFrame:
    """ drop dataframe columns that are not useful for training:
        - non numeric data
        - numeric data that has colinearity
        - not meaningful variables should be included
        drop dataframe rows that contains NaN
    """
    df.drop(df.columns[0], inplace=True, axis=1)
    excluded_features = ["Arithmancy",
                         "Defense Against the Dark Arts",
                         "Care of Magical Creatures"]
    df.drop(excluded_features, inplace=True, axis=1)
    df.drop(df.columns[5:], inplace=True, axis=1)
    if drop_na:
        return df.dropna()
    else:
        return df.fillna(0)

def main():
    df = pd.read_csv('../datasets/dataset_train.csv')
    df2 = drop_columns(df, False)
    df2['Best Hand'].replace({"Left": 0, "Right": 1}, inplace=True)
    df2['First Initial'] = df2['First Name'].str[0]
    df2['First Initial'] = [ord(x) - 64 for x in df2['First Initial']]
    df2['Last Initial'] = df2['Last Name'].str[0]
    df2['Last Initial'] = [ord(x) - 64 for x in df2['Last Initial']]
    df2.drop(['First Name', 'Last Name'], inplace=True, axis=1)
    df2['Year'] = pd.DatetimeIndex(df2['Birthday']).year
    df2['Month'] = pd.DatetimeIndex(df2['Birthday']).month
    df2['Day'] = pd.DatetimeIndex(df2['Birthday']).day
    df2.drop(['Birthday'], inplace=True, axis=1)
    print(df2.head())
    sns.histplot(data=df2, x='Best Hand', hue='Hogwarts House', legend=True)
    plt.show()

if __name__ == "__main__":
    """ train model from file """
    main()