import dash
import dash_leaflet as dl
import dash_leaflet.express as dlx
from dash import dcc, html,Input, Output, callback
import geopandas as gpd
import json
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
from shapely.geometry import box, Point, Polygon
from dash_extensions.javascript import arrow_function, assign
import dash_bootstrap_components as dbc
from dash_loading_spinners import Hash
from pages.ranking_ambiental.bases_mapa import bsas,VAR_PUNTAJE,  classes

# Establecer el renderizador predeterminado para Plotly.
pio.renderers.default = 'browser'

# Agregar informacion de etiquetas
bsas["tooltip"] = bsas["nam"]

#Transformar a geobuf
bsas_geojson = json.loads(bsas.to_json(na="keep"))
geobuf = dlx.geojson_to_geobuf(bsas_geojson)

# Definir colores para las clases.
colorscale = ['#F5BBCB', '#F2A4B6', '#EF8DA1', '#ED769C', '#EB5F87', '#E94872', '#E7315D', '#E51A48']
style = dict(weight=2, opacity=1, color='white', dashArray='3', fillOpacity=0.7)

# Crear colorbar.
ctg = ["{}+".format(cls, classes[i + 1]) for i, cls in enumerate(classes[:-1])] + ["{}+".format(classes[-1])]

# # Barra de colores categóricos personalizada
# colorbar = dlx.categorical_colorbar(
#     categories=ctg,
#     colorscale=colorscale,
#     width=200,  # Ancho personalizado
#     height=20,  # Altura personalizada
#     position="bottomleft",  # Posición
# )

# Lógica de representación del GeoJSON.
style_handle =  assign("""function(feature, context){
    const {classes, colorscale, style, colorProp} = context.props.hideout;
    const value = feature.properties[colorProp];
    if (value === null || isNaN(value)) {
        // Asigna color gris para observaciones sin datos
        style.fillColor = 'rgb(128, 128, 128)';
        style.weight = 1;
        style.dashArray = false;
    } else {
        for (let i = 0; i < classes.length; ++i) {
            if (value > classes[i]) {
                style.fillColor = colorscale[i];
                style.weight = 1;
                style.dashArray = false;
            }
        }
    }
    return style;
}""")

# Crear la figura rectangular con degradé de colores
color_bar = html.Div(
    style={
        'width': '100%',
        'height': '25px',
        'background': f'linear-gradient(to right, {", ".join(colorscale)})'
    }
)

colorscale_reference = html.Div(
    id='colorscale-reference',
    children=[dbc.Col([
                dbc.Row([html.Div("PROTECCIÓN", style={'text-align': 'center','font-size': '12px','color': 'black', 'font-weight': 'bold'})]),
                dbc.Row([dbc.Col([html.Div("MENOR", style={'text-align':'right','color': 'black'})], md=3),
                       dbc.Col([color_bar], md=6),
                       dbc.Col([html.Div("MAYOR", style={'text-align': 'left','color': 'black'})], md=3),
                    ]),
            ]),
        ],

    style={
        'font-size': '12px',
    }
)

Mapa =dl.Map(
                            id="mapa",
                            zoom=15,
                            dragging=False,
                            # touchZoom=False,
                            zoomControl=False,
                            scrollWheelZoom=False,
                            doubleClickZoom=False,
                            children=[

                                dl.GeoJSON(
                                    data=geobuf,
                                    format='geobuf',
                                    zoomToBounds=True,
                                    zoomToBoundsOnClick=False,
                                    options=dict(style=style_handle),
                                    hoverStyle=arrow_function(dict(weight=5, dashArray='')),
                                    hideout=dict(colorscale=colorscale, classes=classes, style=style, colorProp=VAR_PUNTAJE)
                                ),

                            ],
                            className="min-vh-50 bg-white"
                        )

titulo_del_mapa_1 = html.H6(
    "PROVINCIA DE BUENOS AIRES",
    style={
        'font-weight': 'bold',
        'color': 'black',
        'white-space': 'pre-line',  # Forzar el salto de línea
    },
    className="d-flex justify-content-center align-items-center"
)
titulo_del_mapa_2 = html.H6(
    "CONURBANO",
    style={
        'font-weight': 'bold',  # Hacer que el texto sea negrita
        'color': 'black',
    },
    className="d-flex justify-content-center align-items-center"
)

mapa_layout = html.Div(
    id="mapa-container",
    children=[
        dbc.Row([
            dbc.Row([dbc.Col([titulo_del_mapa_1], md=7), dbc.Col([titulo_del_mapa_2], md=2)]),
            dbc.Row([dbc.Col([Mapa], md=12)]),
            dbc.Row([dbc.Col([html.Div()], md=3),dbc.Col([colorscale_reference], md=6),dbc.Col([html.Div()], md=3) ]),
            ])
    ],
)

# Crea la tarjeta centrada
mapa_card = dbc.Card(
    [
        dbc.CardBody(mapa_layout),
    ],
    color="light",
    class_name="shadow",
    outline=True,
    id="censo-empleo"
)


from __future__ import division
import math
import time
import tqdm
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import torchvision
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

def to_cpu(tensor):
    return tensor.detach().cpu()

def load_classes(path):
    """
    Loads class labels at 'path'
    """
    fp = open(path, "r")
    names = fp.read().split("\n")[:-1]
    return names

def weights_init_normal(m):
    classname = m.__class__.__name__
    if classname.find("Conv") != -1:
        torch.nn.init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find("BatchNorm2d") != -1:
        torch.nn.init.normal_(m.weight.data, 1.0, 0.02)
        torch.nn.init.constant_(m.bias.data, 0.0)

def rescale_boxes(boxes, current_dim, original_shape):
    """ Rescales bounding boxes to the original shape """
    orig_h, orig_w = original_shape
    # The amount of padding that was added
    pad_x = max(orig_h - orig_w, 0) * (current_dim / max(original_shape))
    pad_y = max(orig_w - orig_h, 0) * (current_dim / max(original_shape))
    # Image height and width after padding is removed
    unpad_h = current_dim - pad_y
    unpad_w = current_dim - pad_x
    # Rescale bounding boxes to dimension of original image
    boxes[:, 0] = ((boxes[:, 0] - pad_x // 2) / unpad_w) * orig_w
    boxes[:, 1] = ((boxes[:, 1] - pad_y // 2) / unpad_h) * orig_h
    boxes[:, 2] = ((boxes[:, 2] - pad_x // 2) / unpad_w) * orig_w
    boxes[:, 3] = ((boxes[:, 3] - pad_y // 2) / unpad_h) * orig_h
    return boxes

def xywh2xyxy(x):
    y = x.new(x.shape)
    y[..., 0] = x[..., 0] - x[..., 2] / 2
    y[..., 1] = x[..., 1] - x[..., 3] / 2
    y[..., 2] = x[..., 0] + x[..., 2] / 2
    y[..., 3] = x[..., 1] + x[..., 3] / 2
    return y

def xywh2xyxy_np(x):
    y = np.zeros_like(x)
    y[..., 0] = x[..., 0] - x[..., 2] / 2
    y[..., 1] = x[..., 1] - x[..., 3] / 2
    y[..., 2] = x[..., 0] + x[..., 2] / 2
    y[..., 3] = x[..., 1] + x[..., 3] / 2
    return y

def ap_per_class(tp, conf, pred_cls, target_cls):
    """ Compute the average precision, given the recall and precision curves.
    Source: https://github.com/rafaelpadilla/Object-Detection-Metrics.
    # Arguments
        tp:    True positives (list).
        conf:  Objectness value from 0-1 (list).
        pred_cls: Predicted object classes (list).
        target_cls: True object classes (list).
    # Returns
        The average precision as computed in py-faster-rcnn.
    """

    # Sort by objectness
    i = np.argsort(-conf)
    tp, conf, pred_cls = tp[i], conf[i], pred_cls[i]

    # Find unique classes
    unique_classes = np.unique(target_cls)

    # Create Precision-Recall curve and compute AP for each class
    ap, p, r = [], [], []
    for c in tqdm.tqdm(unique_classes, desc="Computing AP"):
        i = pred_cls == c
        n_gt = (target_cls == c).sum()  # Number of ground truth objects
        n_p = i.sum()  # Number of predicted objects

        if n_p == 0 and n_gt == 0:
            continue
        elif n_p == 0 or n_gt == 0:
            ap.append(0)
            r.append(0)
            p.append(0)
        else:
            # Accumulate FPs and TPs
            fpc = (1 - tp[i]).cumsum()
            tpc = (tp[i]).cumsum()

            # Recall
            recall_curve = tpc / (n_gt + 1e-16)
            r.append(recall_curve[-1])

            # Precision
            precision_curve = tpc / (tpc + fpc)
            p.append(precision_curve[-1])

            # AP from recall-precision curve
            ap.append(compute_ap(recall_curve, precision_curve))

    # Compute F1 score (harmonic mean of precision and recall)
    p, r, ap = np.array(p), np.array(r), np.array(ap)
    f1 = 2 * p * r / (p + r + 1e-16)

    return p, r, ap, f1, unique_classes.astype("int32")

def compute_ap(recall, precision):
    """ Compute the average precision, given the recall and precision curves.
    Code originally from https://github.com/rbgirshick/py-faster-rcnn.

    # Arguments
        recall:    The recall curve (list).
        precision: The precision curve (list).
    # Returns
        The average precision as computed in py-faster-rcnn.
    """
    # correct AP calculation
    # first append sentinel values at the end
    mrec = np.concatenate(([0.0], recall, [1.0]))
    mpre = np.concatenate(([0.0], precision, [0.0]))

    # compute the precision envelope
    for i in range(mpre.size - 1, 0, -1):
        mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])

    # to calculate area under PR curve, look for points
    # where X axis (recall) changes value
    i = np.where(mrec[1:] != mrec[:-1])[0]

    # and sum (\Delta recall) * prec
    ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
    return ap

def get_batch_statistics(outputs, targets, iou_threshold):
    """ Compute true positives, predicted scores and predicted labels per sample """
    batch_metrics = []
    for sample_i in range(len(outputs)):

        if outputs[sample_i] is None:
            continue

        output = outputs[sample_i]
        pred_boxes = output[:, :4]
        pred_scores = output[:, 4]
        pred_labels = output[:, -1]

        true_positives = np.zeros(pred_boxes.shape[0])

        annotations = targets[targets[:, 0] == sample_i][:, 1:]
        target_labels = annotations[:, 0] if len(annotations) else []
        if len(annotations):
            detected_boxes = []
            target_boxes = annotations[:, 1:]

            for pred_i, (pred_box, pred_label) in enumerate(zip(pred_boxes, pred_labels)):

                # If targets are found break
                if len(detected_boxes) == len(annotations):
                    break

                # Ignore if label is not one of the target labels
                if pred_label not in target_labels:
                    continue

                iou, box_index = bbox_iou(pred_box.unsqueeze(0), target_boxes).max(0)
                if iou >= iou_threshold and box_index not in detected_boxes:
                    true_positives[pred_i] = 1
                    detected_boxes += [box_index]
        batch_metrics.append([true_positives, pred_scores, pred_labels])
    return batch_metrics

def bbox_wh_iou(wh1, wh2):
    wh2 = wh2.t()
    w1, h1 = wh1[0], wh1[1]
    w2, h2 = wh2[0], wh2[1]
    inter_area = torch.min(w1, w2) * torch.min(h1, h2)
    union_area = (w1 * h1 + 1e-16) + w2 * h2 - inter_area
    return inter_area / union_area

def bbox_iou(box1, box2, x1y1x2y2=True):
    """
    Returns the IoU of two bounding boxes
    """
    if not x1y1x2y2:
        # Transform from center and width to exact coordinates
        b1_x1, b1_x2 = box1[:, 0] - box1[:, 2] / 2, box1[:, 0] + box1[:, 2] / 2
        b1_y1, b1_y2 = box1[:, 1] - box1[:, 3] / 2, box1[:, 1] + box1[:, 3] / 2
        b2_x1, b2_x2 = box2[:, 0] - box2[:, 2] / 2, box2[:, 0] + box2[:, 2] / 2
        b2_y1, b2_y2 = box2[:, 1] - box2[:, 3] / 2, box2[:, 1] + box2[:, 3] / 2
    else:
        # Get the coordinates of bounding boxes
        b1_x1, b1_y1, b1_x2, b1_y2 = box1[:, 0], box1[:, 1], box1[:, 2], box1[:, 3]
        b2_x1, b2_y1, b2_x2, b2_y2 = box2[:, 0], box2[:, 1], box2[:, 2], box2[:, 3]

    # get the corrdinates of the intersection rectangle
    inter_rect_x1 = torch.max(b1_x1, b2_x1)
    inter_rect_y1 = torch.max(b1_y1, b2_y1)
    inter_rect_x2 = torch.min(b1_x2, b2_x2)
    inter_rect_y2 = torch.min(b1_y2, b2_y2)
    # Intersection area
    inter_area = torch.clamp(inter_rect_x2 - inter_rect_x1 + 1, min=0) * torch.clamp(
        inter_rect_y2 - inter_rect_y1 + 1, min=0
    )
    # Union Area
    b1_area = (b1_x2 - b1_x1 + 1) * (b1_y2 - b1_y1 + 1)
    b2_area = (b2_x2 - b2_x1 + 1) * (b2_y2 - b2_y1 + 1)

    iou = inter_area / (b1_area + b2_area - inter_area + 1e-16)

    return iou

def build_targets(pred_boxes, pred_cls, target, anchors, ignore_thres):

    BoolTensor = torch.cuda.BoolTensor if pred_boxes.is_cuda else torch.BoolTensor
    FloatTensor = torch.cuda.FloatTensor if pred_boxes.is_cuda else torch.FloatTensor

    nB = pred_boxes.size(0)
    nA = pred_boxes.size(1)
    nC = pred_cls.size(-1)
    nG = pred_boxes.size(2)

    # Output tensors
    obj_mask = BoolTensor(nB, nA, nG, nG).fill_(0)
    noobj_mask = BoolTensor(nB, nA, nG, nG).fill_(1)
    class_mask = FloatTensor(nB, nA, nG, nG).fill_(0)
    iou_scores = FloatTensor(nB, nA, nG, nG).fill_(0)
    tx = FloatTensor(nB, nA, nG, nG).fill_(0)
    ty = FloatTensor(nB, nA, nG, nG).fill_(0)
    tw = FloatTensor(nB, nA, nG, nG).fill_(0)
    th = FloatTensor(nB, nA, nG, nG).fill_(0)
    tcls = FloatTensor(nB, nA, nG, nG, nC).fill_(0)

    # Convert to position relative to box
    target_boxes = target[:, 2:6] * nG
    gxy = target_boxes[:, :2]
    gwh = target_boxes[:, 2:]
    # Get anchors with best iou
    ious = torch.stack([bbox_wh_iou(anchor, gwh) for anchor in anchors])
    best_ious, best_n = ious.max(0)
    # Separate target values
    b, target_labels = target[:, :2].long().t()
    gx, gy = gxy.t()
    gw, gh = gwh.t()
    gi, gj = gxy.long().t()
    # Set masks
    obj_mask[b, best_n, gj, gi] = 1
    noobj_mask[b, best_n, gj, gi] = 0

    # Set noobj mask to zero where iou exceeds ignore threshold
    for i, anchor_ious in enumerate(ious.t()):
        noobj_mask[b[i], anchor_ious > ignore_thres, gj[i], gi[i]] = 0

    # Coordinates
    tx[b, best_n, gj, gi] = gx - gx.floor()
    ty[b, best_n, gj, gi] = gy - gy.floor()
    # Width and height
    tw[b, best_n, gj, gi] = torch.log(gw / anchors[best_n][:, 0] + 1e-16)
    th[b, best_n, gj, gi] = torch.log(gh / anchors[best_n][:, 1] + 1e-16)
    # One-hot encoding of label
    tcls[b, best_n, gj, gi, target_labels] = 1
    # Compute label correctness and iou at best anchor
    class_mask[b, best_n, gj, gi] = (pred_cls[b, best_n, gj, gi].argmax(-1) == target_labels).float()
    iou_scores[b, best_n, gj, gi] = bbox_iou(pred_boxes[b, best_n, gj, gi], target_boxes, x1y1x2y2=False)

    tconf = obj_mask.float()
    return iou_scores, class_mask, obj_mask, noobj_mask, tx, ty, tw, th, tcls, tconf

def box_iou(box1, box2):
    # https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py
    """
    Return intersection-over-union (Jaccard index) of boxes.
    Both sets of boxes are expected to be in (x1, y1, x2, y2) format.
    Arguments:
        box1 (Tensor[N, 4])
        box2 (Tensor[M, 4])
    Returns:
        iou (Tensor[N, M]): the NxM matrix containing the pairwise
            IoU values for every element in boxes1 and boxes2
    """

    def box_area(box):
        # box = 4xn
        return (box[2] - box[0]) * (box[3] - box[1])

    area1 = box_area(box1.T)
    area2 = box_area(box2.T)

    # inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)
    inter = (torch.min(box1[:, None, 2:], box2[:, 2:]) - torch.max(box1[:, None, :2], box2[:, :2])).clamp(0).prod(2)
    return inter / (area1[:, None] + area2 - inter)  # iou = inter / (area1 + area2 - inter)

def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, labels=()):
    """Performs Non-Maximum Suppression (NMS) on inference results
    Returns:
         detections with shape: nx6 (x1, y1, x2, y2, conf, cls)
    """

    nc = prediction.shape[2] - 5  # number of classes
    xc = prediction[..., 4] > conf_thres  # candidates

    # Settings
    min_wh, max_wh = 2, 4096  # (pixels) minimum and maximum box width and height
    max_det = 300  # maximum number of detections per image
    max_nms = 30000  # maximum number of boxes into torchvision.ops.nms()
    time_limit = 1.0  # seconds to quit after
    redundant = True  # require redundant detections
    multi_label = nc > 1  # multiple labels per box (adds 0.5ms/img)
    merge = False  # use merge-NMS

    t = time.time()
    output = [torch.zeros((0, 6), device=prediction.device)] * prediction.shape[0]
    for xi, x in enumerate(prediction):  # image index, image inference
        # Apply constraints
        # x[((x[..., 2:4] < min_wh) | (x[..., 2:4] > max_wh)).any(1), 4] = 0  # width-height
        x = x[xc[xi]]  # confidence

        # Cat apriori labels if autolabelling
        if labels and len(labels[xi]):
            l = labels[xi]
            v = torch.zeros((len(l), nc + 5), device=x.device)
            v[:, :4] = l[:, 1:5]  # box
            v[:, 4] = 1.0  # conf
            v[range(len(l)), l[:, 0].long() + 5] = 1.0  # cls
            x = torch.cat((x, v), 0)

        # If none remain process next image
        if not x.shape[0]:
            continue

        # Compute conf
        x[:, 5:] *= x[:, 4:5]  # conf = obj_conf * cls_conf

        # Box (center x, center y, width, height) to (x1, y1, x2, y2)
        box = xywh2xyxy(x[:, :4])

        # Detections matrix nx6 (xyxy, conf, cls)
        if multi_label:
            i, j = (x[:, 5:] > conf_thres).nonzero(as_tuple=False).T
            x = torch.cat((box[i], x[i, j + 5, None], j[:, None].float()), 1)
        else:  # best class only
            conf, j = x[:, 5:].max(1, keepdim=True)
            x = torch.cat((box, conf, j.float()), 1)[conf.view(-1) > conf_thres]

        # Filter by class
        if classes is not None:
            x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]

        # Apply finite constraint
        # if not torch.isfinite(x).all():
        #     x = x[torch.isfinite(x).all(1)]

        # Check shape
        n = x.shape[0]  # number of boxes
        if not n:  # no boxes
            continue
        elif n > max_nms:  # excess boxes
            x = x[x[:, 4].argsort(descending=True)[:max_nms]]  # sort by confidence

        # Batched NMS
        c = x[:, 5:6] * (0 if agnostic else max_wh)  # classes
        boxes, scores = x[:, :4] + c, x[:, 4]  # boxes (offset by class), scores
        i = torchvision.ops.nms(boxes, scores, iou_thres)  # NMS
        if i.shape[0] > max_det:  # limit detections
            i = i[:max_det]
        if merge and (1 < n < 3E3):  # Merge NMS (boxes merged using weighted mean)
            # update boxes as boxes(i,4) = weights(i,n) * boxes(n,4)
            iou = box_iou(boxes[i], boxes) > iou_thres  # iou matrix
            weights = iou * scores[None]  # box weights
            x[i, :4] = torch.mm(weights, x[:, :4]).float() / weights.sum(1, keepdim=True)  # merged boxes
            if redundant:
                i = i[iou.sum(1) > 1]  # require redundancy

        output[xi] = x[i]
        if (time.time() - t) > time_limit:
            print(f'WARNING: NMS time limit {time_limit}s exceeded')
            break  # time limit exceeded

    return output


# ----------------------------------------------------------------------------
# "34 Amazing Games in Python from the 1K ZX81"
# Python Code redevelopment Kevin Phillips, 2015
#
# Recreation of classic ZX81 games using python and pygame
# ----------------------------------------------------------------------------
# Requires:
# ----------------------------------------------------------------------------
# Python 2.7	-	www.python.org
# pygame 1.91	-	www.pygame.org
# ZXBasic.py	-	ZX Basic class (import module)
# ZX81.ttf		-	ZX81 Font (http://www.dafont.com/zx81.font) - installed
# g1.png, etc	-	A collection of 20 .png files representing key graphics
# ----------------------------------------------------------------------------
#
# GAME:			UFO, page 8
# DESCRIPTION:	Use 0 and 8 to move your laser beneath the descending UFO
#				You score when you hit it by pressing 1. Game over when it lands
#
# From the book "34 Amazing games for the 1K ZX81"
# Original book and game design (C) 1982, Alastair Gourlay, Mark Ramshaw and
# Interface publishing.
#
# ----------------------------------------------------------------------------
import ZXBasic
from random import randint
from pygame.locals import *
import pygame.time

# Note that all pygame functionality is managed in class.  We do however need
# to import the pygame.time module here to control the speed of the game
fpsClock = pygame.time.Clock()

zx = ZXBasic.ZXBasic()
zx.createScreen()
zx.CLS()

# Define game as a function
# We will use functions for all games, as some of the games have
# options to restart.  This makes more sense if called from a games loop
# in the main program.
def ufo():
	# define variables.  P is player position, L is length of river
	P = 1
	Q = 7
	S = 0
	X = 1

	zx.PRINT_AT(0,0,"|i               ")
	for x in range(1,15):
		zx.PRINT_AT(x,0,"|i |t             |i ")

	# Refresh the screen
	zx.screenRefresh()

	while True:

		# wipe the player and UFO
		zx.PRINT_AT(int(P),int(Q),'|t ')
		zx.PRINT_AT(16,X,'|t ')

		# Work out the movement of our barrel by checking the keys
		X = X + (zx.INKEY('0') - zx.INKEY('8'))

		# Move the alien
		P = P + zx.RND() / 3
		Q = Q + 2 * zx.RND() - 1

		# if the UFO has landed, we exit
		if P > 15:
			return True

		# Check for bounds
		if Q < 1 or Q > 13:
			Q = 7
		if X < 1 or X > 13:
			X = 1

		# Print our game graphics
		zx.PRINT_AT(int(P),int(Q),'|tX')
		zx.PRINT_AT(16,X,'|g7')

		# Check if we fired and hit
		if zx.INKEY('1') and X == int(Q + 0.5):
			S = S + 10
			zx.PRINT_AT(int(P),int(Q),'|iX')
			zx.PRINT_AT(0,5,'|t%s' % S)

		# Refresh the screen and loop
		zx.screenRefresh()
		fpsClock.tick(4)

while True:
	ufo()

	# Refresh the display
	zx.screenRefresh()

	# When the game has completed, wait here until the space bar is pressed.
	# Because of the key press repeat, we may find that allowing any key (like the ZX81)
	# will instantly restart the game.  We need to also keep an eye on events here for
	# QUIT as well.

	# Lets just set a flag and use a while loop to keep the game paused
	replay = True

	while replay:
		for event in pygame.event.get():
			if event.type == KEYDOWN:
				if event.key == K_SPACE:
					replay = False
			if event.type == QUIT:
				pygame.quit()
				sys.exit()

	zx.CLS()
	# The game will now return to the top of the while loop (ie start a new game)
	# Easily done


import numpy as np
from scipy.special import expit
from scipy.misc import logsumexp

def sigmoid(x):
    return expit(x)

def sigmoidForData(X, coef, intercept=None, returnFull=False):
    if coef.ndim == 1:  # coef is 1d array
        if intercept is None:
            linearTerms = X.dot(coef)
        else:
            if isinstance(intercept, float):
                linearTerms = X.dot(coef) + intercept  # intercept should be a float
            else:
                raise("'coef' is 1-dimensional, which requires a scalar intercept."
                      "Non-scalar intercept is not yet implemented.")

        sigmoids = sigmoid(linearTerms)
        if returnFull:
            return np.vstack((sigmoids, 1-sigmoids)).T
        else:
            return sigmoids
    else:  # coef is 2d array
        if intercept is None:
            linearTerms = X.dot(coef)
        else:
            if len(intercept) == coef.shape[1]:
                linearTerms = X.dot(coef) + intercept
            else:
                ValueError("The shapes of 'coef' and 'intercept' are not conformable. "
                           "'coef' has shape %s and 'intercept' has shape %s." % (coef.shape, intercept.shape))
        return sigmoid(linearTerms)

def softmax(x, addDefaultBase=True, axis=1, returnLog=False):
    # x is a 1d or 2d array
    if x.ndim == 1:
        if addDefaultBase:
            x = np.append(x, 0)
        logSumExp = logsumexp(x)
        logSoftMax = x - logSumExp
        if returnLog:
            return logSoftMax
        else:
            return np.exp(logSoftMax)
    else:
        if addDefaultBase:
            x = np.append(x, np.zeros((x.shape[0], 1)), axis=1)
        logSumExp = logsumexp(x, axis, keepdims=True)
        logSoftMax = x - logSumExp
        if returnLog:
            return logSoftMax
        else:
            return np.exp(logSoftMax)

def softmaxForData(X, Coef, intercepts=None, addDefaultBase=True, returnLog=False):
    if intercepts is None:
        linearTerms = X.dot(Coef)
    else:
        linearTerms = X.dot(Coef) + intercepts

    return softmax(linearTerms, addDefaultBase, returnLog=returnLog)


#!/usr/bin/env python
# coding=utf-8
import sys
sys.path.append('../')
import torch
import torch.nn as nn
from transformer.attention import MultiHeadAttention
from transformer.positionwise_feedforward import PositionwiseFeedForward

class EncoderLayer(nn.Module):
    """
    EncoderLayer = self_attention with sublayerconnection + feedforward with sublayerconnection
    """
    def __init__(self, d_model, d_hidden, n_heads, dropout=0.3):
        """
        Args:
            d_model: hidden size of transformer
            d_hidden: feed forward hidden size, usually 4 * d_model
            n_heads: number of heads in multi-head attention
            dropout: dropout rate
        """
        super(EncoderLayer, self).__init__()
        self.self_attention = MultiHeadAttention(n_heads=n_heads, d_model=d_model, dropout=dropout)
        self.pos_feedforward = PositionwiseFeedForward(d_model=d_model, d_hidden=d_hidden, dropout=dropout)
        self.dropout = nn.Dropout(p=dropout)

    def forward(self, encoder_input, mask=None):
        encoder_input, encoder_attn = self.self_attention(encoder_input, encoder_input, encoder_input, mask=mask)
        encoder_output = self.pos_feedforward(encoder_input)
        return encoder_output, encoder_attn

class DecoderLayer(nn.Module):
    """
    DecoderLayer = self_attention + enc_attention + feedforward
    """
    def __init__(self, d_model, d_hidden, n_heads, dropout=0.3):
        """
        Args:
            d_model: hidden size of transformer
            d_hidden: feed forward hidden size, usually 4 * d_model
            n_heads: number of heads in multi-head attention
            dropout: dropout rate
        """
        super(DecoderLayer, self).__init__()
        self.self_attention = MultiHeadAttention(n_heads=n_heads, d_model=d_model, dropout=dropout)
        self.enc_attention = MultiHeadAttention(n_heads=n_heads, d_model=d_model, dropout=dropout)
        self.pos_feedforward = PositionwiseFeedForward(d_model=d_model, d_hidden=d_hidden, dropout=dropout)

    def forward(self, encoder_output, decoder_input, self_attn_mask=None, enc_attn_mask=None):
        decoder_output, dec_self_attn = self.self_attention(decoder_input, decoder_input, decoder_input, mask=self_attn_mask)
        decoder_output, dec_enc_attn = self.enc_attention(decoder_output, encoder_output, encoder_output, mask=enc_attn_mask)
        decoder_output = self.pos_feedforward(decoder_output)
        return decoder_output, dec_self_attn, dec_enc_attn

if __name__ == '__main__':
    d_model = 512
    d_hidden = 2048
    n_heads = 8
    batch_size = 16
    len_frames = 20

    encoder_input = torch.ones(batch_size, len_frames, d_model)
    decoder_output = torch.ones(batch_size, len_frames // 2, d_model)
    encoder_mask = torch.ones(batch_size, 1, len_frames)
    self_attn_mask = (1 - torch.triu(torch.ones(1, len_frames // 2, len_frames // 2), diagonal=1))
    dec_attn_mask = encoder_mask.clone()

    temp_encoder = EncoderLayer(d_model=d_model, d_hidden=d_hidden, n_heads=n_heads)
    temp_decoder = DecoderLayer(d_model=d_model, d_hidden=d_hidden, n_heads=n_heads)

    encoder_output = temp_encoder(encoder_input=encoder_input, mask=encoder_mask)
    print(encoder_output.shape)
    decoder_output, *_ = temp_decoder(encoder_output=encoder_output, decoder_input=decoder_output,
                                      self_attn_mask=self_attn_mask, dec_attn_mask=dec_attn_mask)
    print(decoder_output.shape)


from mock import MagicMock, patch
from django.test import TestCase

from auth_backend.resources import base
from auth_backend.resources.base import ObjectResource, Action

from auth_backend.tests.mock_path import *  # noqa

class ObjectResourceTestCase(TestCase):
    def setUp(self):
        self.rtype = 'type_token'
        self.name = 'name_token'
        self.scope_type = 'scope_type_token'
        self.scope_name = 'scope_name_token'
        self.actions = [Action(id='view', name='view', is_instance_related=True),
                        Action(id='edit', name='edit', is_instance_related=True)]
        self.inspect = MagicMock()
        self.scope_id = 'scope_id_token'
        self.parent = MagicMock()
        self.parent.rtype = 'parent_type_token'
        self.operations = [{
            'operate_id': 'view',
            'actions_id': ['view'],
        }, {
            'operate_id': 'edit',
            'actions_id': ['view', 'edit']
        }]
        self.backend = MagicMock()

    def tearDown(self):
        base.resource_type_lib = {}

    @patch(RESOURCE_CLEAN_INSTANCE, MagicMock())
    def test_clean_instances__is_resource_cls(self):
        resource = ObjectResource(rtype=self.rtype,
                                  name=self.name,
                                  scope_type=self.scope_type,
                                  scope_name=self.scope_name,
                                  actions=self.actions,
                                  inspect=self.inspect,
                                  scope_id=self.scope_id,
                                  parent=self.parent,
                                  operations=self.operations,
                                  backend=self.backend,
                                  resource_cls=str)

        instance = 'instance'
        self.assertEqual(resource.clean_instances(instance), instance)
        super(ObjectResource, resource).clean_instances.assert_not_called()

    @patch(RESOURCE_CLEAN_INSTANCE, MagicMock())
    def test_clean_instances__fall_back_to_super(self):
        resource = ObjectResource(rtype=self.rtype,
                                  name=self.name,
                                  scope_type=self.scope_type,
                                  scope_name=self.scope_name,
                                  actions=self.actions,
                                  inspect=self.inspect,
                                  scope_id=self.scope_id,
                                  parent=self.parent,
                                  operations=self.operations,
                                  backend=self.backend,
                                  resource_cls=list)

        instance = 'instance'
        self.assertIsNotNone(resource.clean_instances(instance))
        super(ObjectResource, resource).clean_instances.assert_called_once_with(instance)


from django.core.cache import cache
import uuid

def namespace_get(logger, key):
	"""Acquire the current namespace for a specified set of keys

	"""

	logger.debug('Checking namespace for %s' % key)

	# Check the cache for the key in question
	# e.g. 'events_ns'
	ns = cache.get(key)

	# If the namespace does not exist, set it with a unique number
	# created with UUID
	if ns == None:
		logger.debug('cache miss: %s' % key)

		# Create the unique namespace
		ns = uuid.uuid4().hex
		logger.debug('Unique namespace created for %s: %s' % (key, ns))

		# We'll use add here instead of set just in case someone beat us
		# to adding it
		ns_add = cache.add(key, ns)
		if not ns_add:
			logger.debug('Could not add unique namespace for %s: %s.  The key was already added' % (key, ns))
			# Ok then get it from memcached
			ns = cache.get(key)
		else:
			logger.debug('Unique namespace successfully added for %s: %s.' % (key, ns))
	else:
		logger.debug('cache hit: %s' % key)

	logger.debug('Namespace for %s: %s' % (key, ns))
	return ns


import torch
import torch.nn as nn
import torch.distributions as dist
import torch.nn.functional as F

class LinearVariational(nn.Module):
    """
    Mean field approximation of nn.Linear
    """
    def __init__(self, in_features, out_features, parent, n_batches, bias=True):
        super().__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.include_bias = bias
        self.parent = parent
        self.n_batches = n_batches

        if getattr(parent, 'accumulated_kl_div', None) is None:
            parent.accumulated_kl_div = 0

        # Initialize the variational parameters.
        # Q(w)=N(mu_theta,sigma2_theta)
        # Do some random initialization with sigma=0.001
        self.w_mu = nn.Parameter(
            torch.FloatTensor(in_features, out_features).normal_(mean=0, std=0.1)
        )
        # proxy for variance
        # log(1 + exp(ρ))* eps
        self.w_p = nn.Parameter(
            torch.FloatTensor(in_features, out_features).normal_(mean=-3., std=0.1)
        )
        # # Prior mean
        # self.w_mu_pr = nn.Parameter(
        #     torch.FloatTensor(in_features, out_features).normal_(mean=0, std=0.1)
        # )

        if self.include_bias:
            self.b_mu = nn.Parameter(
                #torch.zeros(out_features)
                torch.FloatTensor(out_features).normal_(mean=0., std=0.1)
            )
            # proxy for variance
            self.b_p = nn.Parameter(
                #torch.zeros(out_features)
                torch.FloatTensor(out_features).normal_(mean=-3., std=0.1)
            )
            # # bias prior mean
            # self.b_mu_pr = nn.Parameter(
            #     #torch.zeros(out_features)
            #     torch.FloatTensor(out_features).normal_(mean=0., std=0.1)
            # )

    def reparameterize(self, mu, p):
        sigma = torch.log(1 + torch.exp(p))
        eps = torch.randn_like(sigma)
        return mu + (eps * sigma)

    def kl_divergence(self, mu_theta, p_theta, mu_prior, prior_sd=1.):
        # log_prior = dist.Normal(mu_prior, prior_sd).log_prob(z)
        # log_p_q = dist.Normal(mu_theta, torch.log(1 + torch.exp(p_theta))).log_prob(z)

        # return (log_p_q - log_prior).sum() / self.n_batches
        postr = dist.Normal(mu_theta, torch.log(1 + torch.exp(p_theta)))
        prior = dist.Normal(mu_prior, prior_sd)
        return dist.kl.kl_divergence(postr,prior).sum() / self.n_batches

    # def forward(self, x):
    #     w = self.reparameterize(self.w_mu, self.w_p)

    #     if self.include_bias:
    #         b = self.reparameterize(self.b_mu, self.b_p)
    #     else:
    #         b = 0

    #     z = x @ w + b

    #     z_mu, z_var = self.calcPredDist(x)

    #     self.parent.accumulated_kl_div += self.kl_divergence(w, self.w_mu, self.w_p, 0., 1.)
    #     if self.include_bias:
    #         self.parent.accumulated_kl_div += self.kl_divergence(b, self.b_mu, self.b_p, 0., 1.)
    #     return z, z_mu, z_var

    def forward(self, x):
        # sampling delta_W
        sigma_weight = torch.log1p(torch.exp(self.w_p))
        delta_weight = (sigma_weight * torch.randn_like(sigma_weight))

        if self.include_bias:
            sigma_bias = torch.log1p(torch.exp(self.b_p))
            bias = (sigma_bias * torch.randn_like(sigma_bias))
        else:
            bias = torch.zeros(self.out_features)

        # get kl divergence
        self.parent.accumulated_kl_div += self.kl_divergence(self.w_mu, self.w_p, 0., 1.)
        if self.include_bias:
            self.parent.accumulated_kl_div += self.kl_divergence(self.b_mu, self.b_p, 0., 1.)

        #print(self.w_mu,self.b_mu)
        #print(self.w_mu.size(),self.b_mu.size())
        # linear outputs
        outputs = F.linear(x, self.w_mu.transpose(0,1), self.b_mu)

        sign_input = x.clone().uniform_(-1, 1).sign()
        sign_output = outputs.clone().uniform_(-1, 1).sign()

        perturbed_outputs = F.linear(x * sign_input, delta_weight.transpose(0,1), bias) * sign_output

        z_mu, z_var = self.calcPredDist(x)

        # returning outputs + perturbations
        return outputs + perturbed_outputs, z_mu, z_var

    def calcPredDist(self, x):
        if self.include_bias:
            z_mu = x @ self.w_mu + self.b_mu
            #z_var = (x @ self.w_p)**2 + self.b_p**2
            z_var = x**2 @ torch.log(1 + torch.exp(self.w_p))**2 + torch.log(1 + torch.exp(self.b_p))**2
        else:
            z_mu = x @ self.w_mu
            z_var = x**2 @ torch.log(1 + torch.exp(self.w_p))**2
        return z_mu, z_var


from django.db import models
from django.forms import CharField, DateField

# Create your models here.

class article_ids(models.Model):
    verge_ids = models.IntegerField(("verge_ids"), max_length=20)

class Verge_data(models.Model):

    verge_ids = models.ForeignKey(article_ids, on_delete=models.CASCADE, primary_key=True)

    https_links = models.CharField(("https_links"), max_length=510)

    verge_articles = models.CharField(("verge_articles"), max_length=510)

    verge_authors = models.CharField(("verge_authors"), max_length=100)

    article_dates = models.DateField(("article_dates"), max_length=20)


import zipfile
from zipfile import ZipFile

from PIL import Image, ImageDraw
import pytesseract
import cv2 as cv
import numpy as np

pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe "

# loading the face detection classifier
face_cascade = cv.CascadeClassifier('D:/Python/tesseract_final_project/haarcascade_frontalface_default.xml')
data={}

with ZipFile("D:/Python/tesseract_final_project/small_img.zip", "r") as files:
        for file in files.infolist():
            with files.open(file, "r") as image:
                img=Image.open(image).convert("RGB")
                data[file.filename]={"pillow":img}

for entry in data.keys():
    image=data[entry]['pillow']
    text=pytesseract.image_to_string(image)
    data[entry]['text']=text

for entry in data.keys():
    image=data[entry]["pillow"]

    img_array=np.array(image)
    gray=cv.cvtColor(img_array, cv.COLOR_BGR2GRAY)

    faces=face_cascade.detectMultiScale(gray)
    data[entry]["faces"]=[]

    for x,y,w,h in faces:
        face=image.crop((x,y, x+w, y+h))
        data[entry]["faces"].append(face)

for entry in data.keys():
    for image in data[entry]["faces"]:
        image.thumbnail((100, 100), Image.ANTIALIAS)

def search(word):
    for entry in data.key():
        if word in data[entry]["text"]:
            if len(data[entry]["faces"] !=0):
                print("Result found in file {}".format(entry))
                row=round(len(data[entry]["faces"])/5,0)
                c_sheet=Image.new("RGB", (500, 100*row))

                x=0
                y=0

                for image in data[entry]["faces"]:
                    c_sheet.paste(image, (x,y))

                    if x+100==c_sheet.width:
                        x=0
                        y+=100
                    else:
                        x+=100

                    c_sheet.show()

            else:
                print("Result found in file {} \nBut there were no faces in that file\n\n".format(entry))

    return

search("Christopher")


import numpy as np
import matplotlib.pyplot as plt
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop

#自作パッケージ
from data_manager import DataManager as dm

#各種パラメータ

batch_size = 128  # 訓練データを128ずつのデータに分けて学習させる
num_classes = 24 # 分類させる数。今回のコードの総数は24種類
epochs = 20 # 訓練データを繰り返し学習させる数
x_output_path = "./output/x/"
y_output_path = "./output/y/"

codeFiles = [
  "c",
  "c#",
  "d",
  "d#",
  "e",
  "f",
  "f#",
  "g",
  "g#",
  "a",
  "a#",
  "b",
  "cm",
  "c#m",
  "dm",
  "d#m",
  "em",
  "fm",
  "f#m",
  "gm",
  "g#m",
  "am",
  "a#m",
  "bm"
]

# クロマベクトルのデータとその教師データを取得する
dm = dm()
train_range = [1,2,3,4,5,6,7,8,9,10]
test_range = [1,2,3,4,5,6,7,8,9,10]
x_train, y_train, x_test, y_test = dm.get_chromas(train_range=train_range, test_range=test_range)

# y(教師データ)にはコードの名前が文字列として入っているが、Kerasで扱いやすい形(0 or 1)に変換する
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

# モデルの作成
model = Sequential()
model.add(Dense(48, activation='sigmoid', input_shape=(None,12)))
model.add(Dense(48, activation='sigmoid'))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss='categorical_crossentropy',
 optimizer=RMSprop(),
 metrics=['accuracy'])

model.summary()

# 学習
history = model.fit(x_train, y_train,
 batch_size=batch_size,
 epochs=epochs,
 verbose=1,
 validation_data=(x_test, y_test))

# 評価はevaluateで行う
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

# 結果をプロットする
fig, (loss_plot, accuracy_plot) = plt.subplots(ncols=2)

accuracy_plot.plot(history.history['accuracy'])
accuracy_plot.plot(history.history['val_accuracy'])
accuracy_plot.set_title('Model accuracy')
accuracy_plot.set_ylabel('Accuracy')
accuracy_plot.set_xlabel('Epoch')
accuracy_plot.set_ylim(0, 1.00)
accuracy_plot.legend(['Train', 'Test'], loc='upper left')

loss_plot.plot(history.history['loss'])
loss_plot.plot(history.history['val_loss'])
loss_plot.set_title('Model loss')
loss_plot.set_ylabel('Loss')
loss_plot.set_xlabel('Epoch')
loss_plot.legend(['Train', 'Test'], loc='upper left')

fig.tight_layout()
plt.show()


import os
import json
import logging
import boto3

from secrets import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
from constants import FLASK_NAME

logger = logging.getLogger(FLASK_NAME)

S3_BUCKET_NAME = "archival-project"
AWS_SESSION = boto3.Session(aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
STATE_FILENAME = os.environ.get("STATE_FILENAME", "state.json")

class ArchivalState:

    def __init__(self, entries=None):
        self.entries = entries if entries else []

    def add_entry(self, entry):
        self.entries.append(entry)
        _update_state()

    @staticmethod
    def from_json(json_dict):
        entries = json_dict.get("entries", [])
        entries = [ArchivalEntry.from_json(e) for e in entries]
        return ArchivalState(entries)

    def to_json(self) -> dict:
        return {
            "entries": [e.to_json() for e in self.entries]
        }

class ArchivalEntry:

    def __init__(self, trend_name, trend_location, num_tweets, filename, duration, timestamp):
        self.trend_name = trend_name
        self.trend_location = trend_location
        self.num_tweets = num_tweets
        self.filename = filename
        self.duration = duration
        self.timestamp = timestamp

    @staticmethod
    def from_json(json_dict):
        trend_name = json_dict.get("trendName", "")
        trend_location = json_dict.get("trendLocation", "")
        num_tweets = json_dict.get("numTweets", 0)
        filename = json_dict.get("filename", "")
        duration = json_dict.get("duration", 0.0)
        timestamp = json_dict.get("timestamp", 0.0)
        return ArchivalEntry(trend_name, trend_location, num_tweets, filename, duration, timestamp)

    def to_json(self) -> dict:
        return {
            "trendName": self.trend_name,
            "trendLocation": self.trend_location,
            "numTweets": self.num_tweets,
            "filename": self.filename,
            "duration": self.duration,
            "timestamp": self.timestamp
        }

def upload_file(filename, key, **kwargs):
    s3 = AWS_SESSION.resource('s3')
    with open(filename, 'rb') as file_obj:
        s3.Object(S3_BUCKET_NAME, key).put(Body=file_obj, **kwargs)

def _upload_bytes(b, key):
    s3 = AWS_SESSION.resource('s3')
    s3.Object(S3_BUCKET_NAME, key).put(Body=b)

def _get_state() -> ArchivalState:
    logger.debug("fetching state from S3")
    s3 = AWS_SESSION.resource('s3')
    state_object = s3.Object(S3_BUCKET_NAME, STATE_FILENAME).get()
    state_dict = json.load(state_object["Body"])
    return ArchivalState.from_json(state_dict)

def _update_state():
    global state

    if not state:
        logger.warning("update_state: state not yet defined")
        return

    logger.debug("updating state in S3")
    state_json = state.to_json()
    state_json_bytes = json.dumps(state_json).encode("utf-8")
    _upload_bytes(state_json_bytes, STATE_FILENAME)

# Populate state from S3
state = _get_state()


from crab.response.generic import BaseResponse, JsonResponse, XmlResponse, PDFResponse, ImageResponse
from crab.utiles.register import Error404Handler, Error403Handler, Error500Handler, Error400Handler
from crab.utiles.register import post, get
from crab.utiles.serializer import add_time, fun_execution_logger, validate_arguments
from crab.server.handlers import ViewHandler
import json
from datetime import datetime, timedelta
from models import *

@add_time
def home(request):
    response = JsonResponse(json.dumps({'message': 'Hello World!'}))
    expiration_time = datetime.now() + timedelta(days=7)
    response.set_cookie('username', 'john', expires=expiration_time)

    return response

@get
@validate_arguments(ViewHandler, str)
def hello(request, name):
    response_data = {'message': f'Hello {name}'}
    return JsonResponse(json.dumps(response_data))

@fun_execution_logger
def request(request):
    return JsonResponse(json.dumps({
        'status_code': request.status_code,
    }))

def xml(request):
    return XmlResponse('<?xml version="1.0" encoding="ISO-8859-1"?><catalog><title>Empire Burlesque</title></catalog>')

def image(request):
    image_path = 'example.png'
    return ImageResponse(image_path)

@post
def only_post(request):
    response_data = {'message': 'Only user who post data can access this data'}
    return JsonResponse(response_data)

def return_error(request, name):
    response_data = {'message': f'Hello {name}'}
    return JsonResponse(response_data)

def database(request):

    def datetime_encoder(obj):
        if isinstance(obj, datetime):
            return obj.isoformat()

    Addresses.create()
    Residents.create()
    if len(Addresses.read()) < 15:
        addresses_dict = [{'street': 'Krakowska', 'city': 'Krakow', 'province': 'Malopolska', 'zip_code': '30-320'},
                        {'street': 'Mazowiecka', 'city': 'Krakow', 'province': 'Malopolska', 'zip_code': '30-424'},
                        {'street': 'Zalewska', 'city': 'Krakow', 'province': 'Malopolska', 'zip_code': '30-333'},
                        {'street': 'Brzozowa', 'city': 'Krakow', 'province': 'Malopolska', 'zip_code': '30-222'},
                        {'street': 'Kremowa', 'city': 'Krakow', 'province': 'Malopolska', 'zip_code': '30-111'},]
        Addresses.bulk_create(addresses_dict)

    # Addresses.clear()
    data = Addresses.read()

    result = ''
    for i in data:
        data_dict = {'id': i.id, 'created_at': i.created_at, 'updated_at': i.updated_at, 'street': i.street,
                     'city': i.city, 'province': i.province, 'zip_code': i.zip_code}
        result += json.dumps(data_dict, default=datetime_encoder)

    return JsonResponse(json.dumps(result))

# Error handlers
@Error404Handler
def error404_view(request):
    return JsonResponse(json.dumps({'status_code': 'test404'}))

@Error403Handler
def error403_view(request):
    return JsonResponse(json.dumps({'status_code': 'test403'}))

@Error500Handler
def error500_view(request):
    return JsonResponse(json.dumps({'status_code': 'test500'}))

@Error400Handler
def error400_view(request):
    return JsonResponse(json.dumps({'status_code': 'test500'}))


from typing import Dict, List, Optional, Sequence, Any, Union
import numpy as np
import logging
log = logging.getLogger(__name__)

import zhinst.utils
import qcodes as qc
from qcodes.instrument.base import Instrument
import qcodes.utils.validators as vals

class HF2LI(Instrument):
    """Qcodes driver for Zurich Instruments HF2LI lockin amplifier.

    This driver is meant to emulate a single-channel lockin amplifier,
    so one instance has a single demodulator, a single sigout channel,
    and multiple auxout channels (for X, Y, R, Theta, or an arbitrary manual value).
    Multiple instances can be run simultaneously as independent lockin amplifiers.

    This instrument has a great deal of additional functionality that is
    not currently supported by this driver.

    Args:
        name: Name of instrument.
        device: Device name, e.g. "dev204", used to create zhinst API session.
        demod: Index of the demodulator to use.
        sigout: Index of the sigout channel to use as excitation source.
        auxouts: Dict of the form {output: index},
            where output is a key of HF2LI.OUTPUT_MAPPING, for example {"X": 0, "Y": 3}
            to use the instrument as a lockin amplifier in X-Y mode with auxout channels 0 and 3.
        num_sigout_mixer_channels: Number of mixer channels to enable on the sigouts. Default: 1.
    """
    OUTPUT_MAPPING = {-1: 'manual', 0: 'X', 1: 'Y', 2: 'R', 3: 'Theta'}
    def __init__(self, name: str, device: str, demod: int, sigout: int,
        auxouts: Dict[str, int], num_sigout_mixer_channels: int=1, **kwargs) -> None:
        super().__init__(name, **kwargs)
        instr = zhinst.utils.create_api_session(device, 1, required_devtype='HF2LI')
        self.daq, self.dev_id, self.props = instr
        self.demod = demod
        self.sigout = sigout
        self.auxouts = auxouts
        log.info(f'Successfully connected to {name}.')

        for ch in self.auxouts:
            self.add_parameter(
                name=ch,
                label=f'Scaled {ch} output value',
                unit='V',
                get_cmd=lambda channel=ch: self._get_output_value(channel),
                get_parser=float,
                docstring=f'Scaled and demodulated {ch} value.'
            )
            self.add_parameter(
                name=f'gain_{ch}',
                label=f'{ch} output gain',
                unit='V/Vrms',
                get_cmd=lambda channel=ch: self._get_gain(channel),
                get_parser=float,
                set_cmd=lambda gain, channel=ch: self._set_gain(gain, channel),
                vals=vals.Numbers(),
                docstring=f'Gain factor for {ch}.'
            )
            self.add_parameter(
                name=f'offset_{ch}',
                label=f'{ch} output offset',
                unit='V',
                get_cmd=lambda channel=ch: self._get_offset(channel),
                get_parser=float,
                set_cmd=lambda offset, channel=ch: self._set_offset(offset, channel),
                vals=vals.Numbers(-2560, 2560),
                docstring=f'Manual offset for {ch}, applied after scaling.'
            )
            self.add_parameter(
                name=f'output_{ch}',
                label=f'{ch} outptut select',
                get_cmd=lambda channel=ch: self._get_output_select(channel),
                get_parser=str
            )
            # Making output select only gettable, since we are
            # explicitly mapping auxouts to X, Y, R, Theta, etc.
            self._set_output_select(ch)

        self.add_parameter(
            name='phase',
            label='Phase',
            unit='deg',
            get_cmd=self._get_phase,
            get_parser=float,
            set_cmd=self._set_phase,
            vals=vals.Numbers(-180,180)
        )
        self.add_parameter(
            name='time_constant',
            label='Time constant',
            unit='s',
            get_cmd=self._get_time_constant,
            get_parser=float,
            set_cmd=self._set_time_constant,
            vals=vals.Numbers()
        )
        self.add_parameter(
            name='frequency',
            label='Frequency',
            unit='Hz',
            get_cmd=self._get_frequency,
            get_parser=float
        )
        self.add_parameter(
            name='sigout_range',
            label='Signal output range',
            unit='V',
            get_cmd=self._get_sigout_range,
            get_parser=float,
            set_cmd=self._set_sigout_range,
            vals=vals.Enum(0.01, 0.1, 1, 10)
        )
        self.add_parameter(
            name='sigout_offset',
            label='Signal output offset',
            unit='V',
            get_cmd=self._get_sigout_offset,
            get_parser=float,
            set_cmd=self._set_sigout_offset,
            vals=vals.Numbers(-1, 1),
            docstring='Multiply by sigout_range to get actual offset voltage.'
        )
        for i in range(num_sigout_mixer_channels):
            self.add_parameter(
                name=f'sigout_enable{i}',
                label=f'Signal output mixer {i} enable',
                get_cmd=lambda mixer_channel=i: self._get_sigout_enable(mixer_channel),
                get_parser=float,
                set_cmd=lambda amp, mixer_channel=i: self._set_sigout_enable(mixer_channel, amp),
                vals=vals.Enum(0,1,2,3),
                docstring="""\
                0: Channel off (unconditionally)
                1: Channel on (unconditionally)
                2: Channel off (will be turned off on next change of sign from negative to positive)
                3: Channel on (will be turned on on next change of sign from negative to positive)
                """
            )
            self.add_parameter(
                name=f'sigout_amplitude{i}',
                label=f'Signal output mixer {i} amplitude',
                unit='Gain',
                get_cmd=lambda mixer_channel=i: self._get_sigout_amplitude(mixer_channel),
                get_parser=float,
                set_cmd=lambda amp, mixer_channel=i: self._set_sigout_amplitude(mixer_channel, amp),
                vals=vals.Numbers(-1, 1),
                docstring='Multiply by sigout_range to get actual output voltage.'
            )

    def _get_phase(self) -> float:
        path = f'/{self.dev_id}/demods/{self.demod}/phaseshift/'
        return self.daq.getDouble(path)

    def _set_phase(self, phase: float) -> None:
        path = f'/{self.dev_id}/demods/{self.demod}/phaseshift/'
        self.daq.setDouble(path, phase)

    def _get_gain(self, channel: str) -> float:
        path = f'/{self.devid}/auxouts/{self.auxouts[channel]}/scale/'
        return self.daq.getDouble(path)

    def _set_gain(self, gain: float, channel: str) -> None:
        path = f'/{self.dev_id}/auxouts/{self.auxouts[channel]}/scale/'
        self.daq.setDouble(path, gain)

    def _get_offset(self, channel: str) -> float:
        path = f'/{self.dev_id}/auxouts/{self.auxouts[channel]}/offset/'
        return self.daq.getDouble(path)

    def _set_offset(self, offset: float, channel: str) -> None:
        path = f'/{self.dev_id}/auxouts/{self.auxouts[channel]}/offset/'
        self.daq.setDouble(path, offset)

    def _get_output_value(self, channel: str) -> float:
        path = f'/{self.dev_id}/auxouts/{self.auxouts[channel]}/value/'
        return self.daq.getDouble(path)

    def _get_output_select(self, channel: str) -> str:
        path = f'/{self.dev_id}/auxouts/{self.auxouts[channel]}/outputselect/'
        idx = self.daq.getInt(path)
        return self.OUTPUT_MAPPING[idx]

    def _set_output_select(self, channel: str) -> None:
        path = f'/{self.dev_id}/auxouts/{self.auxouts[channel]}/outputselect/'
        keys = list(self.OUTPUT_MAPPING.keys())
        idx = keys[list(self.OUTPUT_MAPPING.values()).index(channel)]
        self.daq.setInt(path, idx)

    def _get_time_constant(self) -> float:
        path = f'/{self.dev_id}/demods/{self.demod}/timeconstant/'
        return self.daq.getDouble(path)

    def _set_time_constant(self, tc: float) -> None:
        path = f'/{self.dev_id}/demods/{self.demod}/timeconstant/'
        self.daq.setDouble(path, tc)

    def _get_sigout_range(self) -> float:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/range/'
        return self.daq.getDouble(path)

    def _set_sigout_range(self, rng: float) -> None:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/range/'
        self.daq.setDouble(path, rng)

    def _get_sigout_offset(self) -> float:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/offset/'
        return self.daq.getDouble(path)

    def _set_sigout_offset(self, offset: float) -> None:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/offset/'
        self.daq.setDouble(path, offset)

    def _get_sigout_amplitude(self, mixer_channel: int) -> float:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/amplitudes/{mixer_channel}/'
        return self.daq.getDouble(path)

    def _set_sigout_amplitude(self, mixer_channel: int, amp: float) -> None:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/amplitudes/{mixer_channel}/'
        self.daq.setDouble(path, amp)

    def _get_sigout_enable(self, mixer_channel: int) -> int:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/enables/{mixer_channel}/'
        return self.daq.getInt(path)

    def _set_sigout_enable(self, mixer_channel: int, val: int) -> None:
        path = f'/{self.dev_id}/sigouts/{self.sigout}/enables/{mixer_channel}/'
        self.daq.setInt(path, val)

    def _get_frequency(self) -> float:
        path = f'/{self.dev_id}/demods/{self.demod}/freq/'
        return self.daq.getDouble(path)

    def sample(self) -> dict:
        path = f'/{self.dev_id}/demods/{self.demod}/sample/'
        return self.daq.getSample(path)


import yaml

def _parse_args(config_parser, parser):
    # Do we have a config file to parse?
    args_config, remaining = config_parser.parse_known_args()
    if args_config.config:
        with open(args_config.config, 'r') as f:
            cfg = yaml.safe_load(f)
            parser.set_defaults(**cfg)

    # The main arg parser parses the rest of the args, the usual
    # defaults will have been overridden if config file specified.
    args = parser.parse_args(remaining)
    print(args)

    # Cache the args as a text string to save them in the output dir later
    args_text = yaml.safe_dump(args.__dict__, default_flow_style=False)
    return args, args_text


from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.utils.html import format_html
from .models import Topic, Author, UserExt, Task, Lesson, Stage, Edge

import collections

########################### Topics ###########################

class TopicInline(admin.StackedInline):
    fields = ['name']
    model = Topic
    extra = 1

@admin.register(Topic)
class TopicAdmin(admin.ModelAdmin):
    fields = ['name', 'supertopic']
    list_display = ('display_name', 'supertopic_name', 'topo_order')
    # readonly_fields = ('supertopic',)
    # list_select_related = ('supertopic',)

    inlines = [TopicInline]
    actions = ['topo_sort']

    @admin.action(description="Recompute topological order")
    def topo_sort(self, request, queryset):
        Topic.objects.get(name="__root__").topo_sort()

########################### Users ###########################

admin.site.unregister(User)

class UserExtInline(admin.StackedInline):
    model = UserExt
    fieldsets = (
        (None, {'fields': ('codeforces', 'infoarena', 'varena'), }),
        # ('Progress', {'fields': ('current_lesson',)}),
    )
    readonly_fields = ('codeforces', 'infoarena', 'varena')

@admin.register(User)
class UserCustomAdmin(UserAdmin):
    inlines = UserAdmin.inlines + [UserExtInline]

########################### Authors ###########################

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    fields = ['name', 'user']
    list_display = ('name', 'user_link')
    list_display_links = ('name', 'user_link')

    # In case you want to link an author to their account, comment this line
    # readonly_fields = ('user',)

    def user_link(self, obj):
        if obj.user is None:
            return None
        return format_html("{username}", pk=obj.user.pk, username=obj.user)

########################### Tasks ###########################

@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
    list_display = ('title', 'source', 'description', 'task_link', 'solution_link')
    list_display_links = ('title', 'task_link', 'solution_link')
    fieldsets = (
        (None, {'fields': ('title', 'source', 'link', 'description', 'solution', 'tags')}),
        ('Hints', {
            'fields': ('hints', ('hint1', 'hint2', 'hint3')),
            'classes': ('collapse',),
        }),
    )

    def task_link(self, obj):
        return format_html("{url}", url=obj.link)
    task_link.short_description = "Link to task"

    def solution_link(self, obj):
        if obj.solution is None:
            return None
        return format_html("Solution", url=obj.solution)
    solution_link.short_description = "Link to solution"

########################### Lessons ###########################

def topo_sort(stages=None):
    if stages is None:
        stages = Stage.objects.all().order_by('index')
    for stage in stages:
        start = []
        dep_count = {}

        for lesson in Lesson.objects.filter(stage=stage):
            if lesson.ins.filter(src__stage=stage).count() == 0:
                upper = 0
                for edge in lesson.ins.all():
                    upper = max(upper, edge.src.stage.index)
                start.append((lesson, upper))
                print(lesson, upper)
            else:
                dep_count[lesson] = lesson.ins.filter(src__stage=stage).count()
                # print(lesson, dep_count[lesson])

        print(start)
        q = collections.deque([x[0] for x in sorted(start, key=lambda item: item[1])])
        lvl = 0
        count_lvl = 0
        while q:
            node = q.popleft()

            if count_lvl == 3:
                lvl += 1
                count_lvl = 0
            else:
                for edge in node.ins.all():
                    dep = edge.src
                    if dep.stage == stage and dep.level == lvl:
                        lvl += 1
                        count_lvl = 0
                        break

            node.level = lvl
            node.save()
            count_lvl += 1

            for edge in node.outs.all():
                if edge.dest.stage == stage:
                    next = edge.dest
                    dep_count[next] -= 1
                    if dep_count[next] == 0:
                        q.append(next)

class LessonInline(admin.TabularInline):
    fields = ['src', 'hidden']
    model = Edge
    fk_name = 'dest'
    extra = 1

@admin.register(Lesson)
class LessonAdmin(admin.ModelAdmin):
    list_display = ('title', 'stage', 'level', 'topic', 'author')
    fieldsets = (
        (None, {'fields': (('title', 'author'), 'topic', 'stage', 'level')}),
        ('Content', {'fields': ('duration', 'content')}),
        ('Extra', {'fields': ('tasks',)}),
    )
    readonly_fields = ['level']
    inlines = [LessonInline]

    actions = ['topo_sort_all', 'topo_sort_stage']
    list_filter = ['stage', 'author']

    @admin.action(description="Recompute ALL topological order")
    def topo_sort_all(self, request, queryset):
        Lesson.objects.all().update(level=None)
        topo_sort()

    @admin.action(description="Recompute SINGLE topological order")
    def topo_sort_stage(self, request, queryset):
        stage = queryset.all()[0].stage
        Lesson.objects.filter(stage=stage).update(level=None)
        topo_sort([stage])

########################### Stages ###########################

# admin.site.register(Stage)

@admin.register(Stage)
class StageAdmin(admin.ModelAdmin):
    list_display = ('name', 'index')


import utils
from data import DATA

def repCols(cols):
    cols = utils.copy(cols)
    for _,col in enumerate(cols):
        col[len(col)-1] = col[0] + ":" + col[len(col)-1]
        for j in range(1,len(col)):
            col[j-1]=col[j]
        # col[len(col)-1]=None
        col.pop()
    processed_cols1 = []
    for i in range(len(cols[1])-1):
        processed_cols1.append("Num{}".format(i+1))
    processed_cols1.append('thingX')
    cols.insert(0, processed_cols1)
    return DATA(cols)

def repRows(t,rows):
    rows = utils.copy(rows)
    for j,s in enumerate(rows[-1]):
        rows[0][j]=str(rows[0][j])+":"+str(s)
    rows.pop()
    for n,row in enumerate(rows):
        if(n==0):
            row.append("thingX")
        else:
            u=t["rows"][len(t["rows"])-n]
            row.append(u[len(u)-1])

    return DATA(rows)

def repgrid(sFile):
    t = utils.dofile(sFile)
    rows = repRows(t, utils.transpose(t['cols']))
    cols = repCols(t['cols'])
    utils.show(rows.cluster(),"mid",rows.cols.all,1)
    utils.show(cols.cluster(),"mid",rows.cols.all,1)
    repPlace(rows)

def repPlace(data):
    n=20
    g={}
    for i in range(1,n+1):
        g[i]={}
        for j in range(1,n+1):
            g[i][j]=" "

    maxy=0
    print("")
    for r,row in enumerate(data.rows):
        c=chr(97+r).upper()
        print(c,utils.last(row.cells))
        x=int(row.x*n/1)
        y=int(row.y*n/1)
        maxy=max(maxy,y+1)
        g[y+1][x+1]=c
    print("")
    for y in range(1,maxy+1):
        print(" ".join(g[y].values()))


from flask import Flask, render_template,request
from flask_socketio import SocketIO,join_room, leave_room,send, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

@app.route('/', methods = ['GET','POST'])
def index():
    return render_template('index.html')

@app.route('/chat', methods = ['GET','POST'])
def chat():
    name1 = request.form.get("Name")

    return render_template('chat.html', name = name1)

@socketio.on('message')
def handle_message(data):
    print('received message: ' + data['data'])

@socketio.on('snd-message')
def send_message(data):
    print(data['name']+" kewthkelrt "+data["message"])

@socketio.on('join')
def on_join(data):
    username = data['username']
    room = data['room']
    join_room(room)
    send(username + ' has entered the room.', to=room)

@socketio.on('leave')
def on_leave(data):
    username = data['username']
    room = data['room']
    leave_room(room)
    send(username + ' has left the room.', to=room)

if __name__ == '__main__':
    socketio.run(app)


import xml.etree.ElementTree as ET
# use this file
xmlDoc = ET.parse("Files chapter 9/plants.xml")
# Find the root <catalog> in this case
root = xmlDoc.getroot()
count = 0

# Lets you look in the child elements of "plant"
for common in root.findall("plant"):
    if common[3].text == "SUN": # oefb - Ony show plant that are best in the sun
        count += 1
        name = common[0].text # .text to print the words inside
        botanical = common[1].text
        print("plant", str(count), ":", name, " (" + botanical + ")")


from keras.utils import to_categorical
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import pickle
import os
from google.colab import files

# iMPORTING DATA ===========================================================================
def readPickleData():
    file_path = "./processed data"
    data_dict = {}
    if os.path.exists(file_path):
        pickle_dir = os.path.join(os.path.dirname(__file__), file_path[2:])
        pickle_files = [f for f in os.listdir(pickle_dir) if f.endswith('.pickle')]

        for i, pickle_file in enumerate(pickle_files):
            with open(os.path.join(pickle_dir, pickle_file), 'rb') as f:
                data = pickle.load(f)
                data_dict[f'data_{i + 1}'] = data
    else:
        with open('test_data.pickle', 'rb') as p:
            test_data = pickle.load(p)
        with open('test_labels.pickle', 'rb') as i:
            test_labels = pickle.load(i)
        with open('train_data.pickle', 'rb') as c:
            train_data = pickle.load(c)
        with open('train_labels.pickle', 'rb') as k:
            train_labels = pickle.load(k)
        with open('val_data.pickle', 'rb') as l:
            val_data = pickle.load(l)
        with open('val_labels.pickle', 'rb') as e:
            val_labels = pickle.load(e)

            test_data = np.reshape(test_data, (test_data.shape[0], 64, 64, 1))
            train_data = np.reshape(train_data, (train_data.shape[0], 64, 64, 1))
            val_data = np.reshape(val_data, (val_data.shape[0], 64, 64, 1))

            data_dict['data_1'] = test_data
            data_dict['data_2'] = test_labels
            data_dict['data_3'] = train_data
            data_dict['data_4'] = train_labels
            data_dict['data_5'] = val_data
            data_dict['data_6'] = val_labels

        return data_dict

data_dict = readPickleData()

test_data = data_dict["data_1"]
test_data = tf.keras.utils.normalize(test_data, axis=1)
test_labels = data_dict["data_2"]
train_data = data_dict["data_3"]
train_data = tf.keras.utils.normalize(train_data, axis=1)
train_labels = data_dict["data_4"]
val_data = data_dict["data_5"]
val_data = tf.keras.utils.normalize(val_data, axis=1)
val_labels = data_dict["data_6"]

# CONVERTING STRING TYPE LABELS TO INT
def convert_strings_to_integers(array):
    # Create a dictionary to map strings to index integers
    string_to_index = {
        "0": 0,
        "1": 1,
        "2": 2,
        "3": 3,
        "4": 4,
        "5": 5,
        "6": 6,
        "7": 7,
        "8": 8,
        "9": 9,
        "add": 10,
        "dec": 11,
        "eq": 12,
        "div": 13,
        "mul": 14,
        "sub": 15,
        "x": 16,
        "y": 17,
        "z": 18,
    }

    # Loop through the array and convert each string to its index integer
    integer_array = []
    for string in array:
        integer_array.append(string_to_index[string])

    return integer_array

train_labels = convert_strings_to_integers(train_labels)
test_labels = convert_strings_to_integers(test_labels)
val_labels = convert_strings_to_integers(val_labels)

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
val_labels = to_categorical(val_labels)

# BUILDING THE MODEL ===========================================================================
model = tf.keras.Sequential([
  tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(64, 64,1)),
  tf.keras.layers.MaxPooling2D((2,2)),
  tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
  tf.keras.layers.MaxPooling2D((2,2)),
  tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
  tf.keras.layers.MaxPooling2D((2,2)),
  tf.keras.layers.Conv2D(256, (3,3), activation='relu'),
  tf.keras.layers.MaxPooling2D((2,2)),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dropout(0.5),
  tf.keras.layers.Dense(512, activation='relu'),
  tf.keras.layers.Dense(19, activation='softmax')
])

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

model.summary()

history = model.fit(train_data, train_labels,
                    batch_size=32,
                    epochs=40,
                    validation_data=(val_data, val_labels))

model.save('DigitClassifier.h5')


from django.contrib import messages
from django.http import Http404
from django.shortcuts import render, redirect
from django.views.generic.edit import CreateView, FormView
from django.views.generic.detail import DetailView
from  django.views.generic.list import ListView
# Create your views here.

from .forms import AddressForm, UserAddressForm
from .mixins import CartOrderMixin, LoginRequiredMixin
from .models import UserAddress, UserCheckout, Order

class OrderDetail(DetailView):
	model = Order

	def dispatch(self, request, *args, **kwargs):
		try:
			user_check_id = self.request.session.get("user_checkout_id")
			user_checkout = UserCheckout.objects.get(id=user_check_id)
		except UserCheckout.DoesNotExist:
			user_checkout = UserCheckout.objects.get(user=request.user)
		except:
			user_checkout = None

		obj = self.get_object()
		if obj.user == user_checkout and user_checkout is not None:
			return super(OrderDetail, self).dispatch(request, *args, **kwargs)
		else:
			raise Http404

class OrderList(LoginRequiredMixin, ListView):
	queryset = Order.objects.all()

	def get_queryset(self):
		user_check_id = self.request.user.id
		user_checkout = UserCheckout.objects.get(id=user_check_id)
		return super(OrderList, self).get_queryset().filter(user=user_checkout)

class UserAddressCreateView(CreateView):
	form_class = UserAddressForm
	template_name = "forms.html"
	success_url = "/checkout/address/"

	def get_checkout_user(self):
		user_check_id = self.request.session.get("user_checkout_id")
		user_checkout = UserCheckout.objects.get(id=user_check_id)
		return user_checkout

	def form_valid(self, form, *args, **kwargs):
		form.instance.user = self.get_checkout_user()
		return super(UserAddressCreateView, self).form_valid(form, *args, **kwargs)

class AddressSelectFormView(CartOrderMixin, FormView):
	form_class = AddressForm
	template_name = "orders/address_select.html"

	def dispatch(self, *args, **kwargs):
		b_address, s_address = self.get_addresses()
		if b_address.count() == 0:
			messages.success(self.request, "Please add a billing address before continuing")
			return redirect("user_address_create")
		elif s_address.count() == 0:
			messages.success(self.request, "Please add a shipping address before continuing")
			return redirect("user_address_create")
		else:
			return super(AddressSelectFormView, self).dispatch(*args, **kwargs)

	def get_addresses(self, *args, **kwargs):
		user_check_id = self.request.session.get("user_checkout_id")
		user_checkout = UserCheckout.objects.get(id=user_check_id)
		b_address = UserAddress.objects.filter(
				user=user_checkout,
				type='billing',
			)
		s_address = UserAddress.objects.filter(
				user=user_checkout,
				type='shipping',
			)
		return b_address, s_address

	def get_form(self, *args, **kwargs):
		form = super(AddressSelectFormView, self).get_form(*args, **kwargs)
		b_address, s_address = self.get_addresses()

		form.fields["billing_address"].queryset = b_address
		form.fields["shipping_address"].queryset = s_address
		return form

	def form_valid(self, form, *args, **kwargs):
		billing_address = form.cleaned_data["billing_address"]
		shipping_address = form.cleaned_data["shipping_address"]
		order = self.get_order()
		order.billing_address = billing_address
		order.shipping_address = shipping_address
		order.save()
		return  super(AddressSelectFormView, self).form_valid(form, *args, **kwargs)

	def get_success_url(self, *args, **kwargs):
		return "/checkout/"


from pymongo import MongoClient
from bson.objectid import ObjectId

class AnimalShelter(object):
    """ CRUD Operations for Animal Collection in MongoDB """

    # Declare one's self into existence
    def __init__(self, username, password):
        self.client = MongoClient('mongodb://%s:%s@localhost:48219/?authMechanism=DEFAULT&authSource=admin'%(username, password))
        self.database = self.client['AAC']

    # Insert data into the animals collection
    def create(self, data):

        # Double-check the user actually provided data to be created
        if data is None:
            raise Exception("PLEASE NOTE: Data must be provided in order to be saved.")

        # Instantiate a variable for the created data to utilize as an "existence check"
        saved = self.database.animals.insert_one(data)

        # Subsequently, check if the created data is null within the animals collection
        # Return False or True depending on the result
        return False if saved is None else True

    # Search for data within the animals collection
    def read(self, query):

        # Double-check the user actually provided a query to be filtered with
        if query is None:
            raise Exception("PLEASE NOTE: Cannot search for something that is not requested.")

        # Return the data that results from the query search
        return self.database.animals.find_one(query)

    # Pull all data within the animals collection
    def readAll(self, data):

        # Return a cursor that acts like a stopping point of all data before it
        cursor = self.database.animals.find(data, {"_id":False})
        return cursor

    # Update data that is already present in the animals collection
    def update(self, query, data):

        # Double-check the user actually provided data to be updated
        if data is None:
            raise Exception("PLEASE NOTE: In order to update, new information must be provided.")

        # Double-check the user wishes to update information that can be updated instead of created
        if query is None:
            raise Exception("PLEASE NOTE: In order to update, present information must be provided.\nOtherwise, create data instead.")

        # Updating is involved.  TRY to see if it is successful
        try:
            updated = self.database.animals.find_one_and_update(query, {"$set":data}, {"upsert":True, "new":True})

            # Check if the update was successful or not based on if the newly updated document was returned...
            if updated is not None:

                # ... if so, return the data as a JSON
                print("PLEASE NOTE: Successful update.")
                return updated
            else:

                # ... and if not, let the user know
                raise Exception("ERROR: Could not update the query.")

        except Exception as exc:
            print("ERROR: Something went wrong in the updating process:", exc)

    # Delete data from the animals collection
    def delete(self, data):

        # Double-check the user actually provided data to be deleted
        if data is None:
            raise Exception("PLEASE NOTE: To delete one's self, one's self must present one's self to be deleted.")

        # Deleting is involved; TRY it to see if it is successful
        try:
            preDeleted = self.database.animals.find_one(data)
            deleted = self.database.animals.find_one_and_delete(data, {"new":False})

            # Check if the deletion registers...
            if deleted is not None:

                # ... if so, let the user know and return the deleted data as affirmation...
                print("PLEASE NOTE: Deletion successful.")
                return preDeleted
            else:

                # ... otherwise, let the user know deletion did not occur
                raise Exception("PLEASE NOTE: Nothing could be deleted with the given parameters.")

        # If the deletion attempt was unsuccessful for any reason, showcase the error to the user
        except Exception as exc:
            print("ERROR: Something went wrong in the deletion process:", exc)