# -*- encoding: utf-8 -*-

# @Author : soarkey
# @Date   : 2022/3/7
# @Desc   : block-based cooperate attention module

import torch
import torch.nn as nn
import torch.nn.functional as F

from lib.core.config import config
from lib.models.dcn import DeformConvPack

# channel attention
class ChannelGate(nn.Module):
    def __init__(self, gate_channels, reduction_ratio=16, pool_types=['avg', 'max']):
        super(ChannelGate, self).__init__()
        self.gate_channels = gate_channels
        self.mlp = nn.Sequential(
            nn.Flatten(),
            nn.Linear(gate_channels, gate_channels // reduction_ratio),
            nn.ReLU(inplace=True),
            nn.Linear(gate_channels // reduction_ratio, gate_channels)
        )
        self.pool_types = pool_types

    def forward(self, x):
        """
        Args:
            x: [B,256,7,7]
        Returns:
            c_weight: [B,256,1,1]
        """
        channel_att_sum = None
        for pool_type in self.pool_types:
            if pool_type == 'avg':
                avg_pool = F.avg_pool2d(x, (x.size(2), x.size(3)), stride=(x.size(2), x.size(3)))
                channel_att_raw = self.mlp(avg_pool)
            elif pool_type == 'max':
                max_pool = F.max_pool2d(x, (x.size(2), x.size(3)), stride=(x.size(2), x.size(3)))
                channel_att_raw = self.mlp(max_pool)
            elif pool_type == 'lp':
                lp_pool = F.lp_pool2d(x, 2, (x.size(2), x.size(3)), stride=(x.size(2), x.size(3)))
                channel_att_raw = self.mlp(lp_pool)

            if channel_att_sum is None:
                channel_att_sum = channel_att_raw
            else:
                channel_att_sum = channel_att_sum + channel_att_raw

        scale = torch.sigmoid(channel_att_sum).unsqueeze(2).unsqueeze(3)
        return scale

# block-based cooperate attention
class BCA(nn.Module):
    def __init__(self, in_channel=256):
        super(BCA, self).__init__()

        self.in_channel = in_channel
        self.hidden_channel = in_channel // 2

        # feature extraction
        if config.TRAIN.ATTN.BLOCK_FEATURE:
            # template branch
            self.g1 = nn.Sequential(
                DeformConvPack(in_channel, self.hidden_channel, kernel_size=3, stride=1, padding=0),
                nn.BatchNorm2d(self.hidden_channel),
                nn.ReLU(inplace=True),
                DeformConvPack(self.hidden_channel, self.hidden_channel, kernel_size=3, stride=1, padding=0),
                nn.BatchNorm2d(self.hidden_channel),
                nn.ReLU(inplace=True),
            )

            # search branch
            self.g2 = nn.Sequential(
                DeformConvPack(in_channel, self.hidden_channel, kernel_size=3, stride=2, padding=0),
                nn.BatchNorm2d(self.hidden_channel),
                nn.ReLU(inplace=True),
            )

            self.theta = DeformConvPack(in_channel, self.hidden_channel, kernel_size=3, stride=2, padding=0)
            self.phi = DeformConvPack(in_channel, self.hidden_channel, kernel_size=3, stride=2, padding=0)

            self.Q = nn.Sequential(
                DeformConvPack(self.hidden_channel, 2 * in_channel, kernel_size=1, stride=1, padding=0),
                nn.BatchNorm2d(2 * in_channel),
                nn.ReLU(inplace=True),
                nn.PixelShuffle(2),
                nn.UpsamplingBilinear2d(size=(7, 7)),
                DeformConvPack(self.hidden_channel, in_channel, kernel_size=1, stride=1, padding=0),
                nn.BatchNorm2d(in_channel),
                nn.ReLU(inplace=True),
            )

            self.K1 = nn.Sequential(
                DeformConvPack(self.hidden_channel, 2 * in_channel, kernel_size=1, stride=1, padding=0),
                nn.BatchNorm2d(2 * in_channel),
                nn.ReLU(inplace=True),
                nn.PixelShuffle(upscale_factor=2),
            )

            self.K2 = nn.Sequential(
                DeformConvPack(self.hidden_channel, in_channel, kernel_size=1, stride=1, padding=0),
                nn.BatchNorm2d(in_channel),
                nn.ReLU(inplace=True),
            )

            self.alpha = nn.Parameter(1 * torch.ones(1).cuda())
            self.beta = nn.Parameter(1 * torch.ones(1).cuda())

        if config.TRAIN.ATTN.CHANNEL_ATTN:
            # channel attention
            self.ChannelGate = ChannelGate(in_channel)

    def forward(self, z, x):
        """
        args:
            z: [B,256,7,7]
            x: [B,256,31,31]
        returns:
            z: [B,256,7,7]
            x: [B,256,31,31]
        """

        b, _, z_height, z_width = z.shape
        _, _, x_height, x_width = x.shape

        if config.TRAIN.ATTN.BLOCK_FEATURE:
            zh, zw, xh, xw = [(x - 2) // 2 + 1 for x in [z_height, z_width, x_height, x_width]]

            zg = self.g1(z).view(b, self.hidden_channel, -1)
            zg = zg.permute(0, 2, 1).contiguous()

            xg = self.g2(x).view(b, self.hidden_channel, -1)
            xg = xg.permute(0, 2, 1).contiguous()

            z_theta = self.theta(z).view(b, self.hidden_channel, -1)
            z_theta = z_theta.permute(0, 2, 1)

            x_phi = self.phi(x).view(b, self.hidden_channel, -1)

            f = torch.matmul(z_theta, x_phi)  # [32,25,64]*[32,64,625]=[32,25,625]
            n = f.size(-1)
            fz_div_c = f / n

            f = f.permute(0, 2, 1).contiguous()
            n = f.size(-1)
            fx_div_c = f / n

            zn = torch.matmul(fz_div_c, xg)
            zn = zn.permute(0, 2, 1).contiguous().view(b, self.hidden_channel, zh, zw)
            zn = self.Q(zn)

            zq = self.alpha * zn + z

            xn = torch.matmul(fx_div_c, zg)
            xn = xn.permute(0, 2, 1).contiguous().view(b, self.hidden_channel, xh, xw)
            xn = self.K2(F.upsample_bilinear(self.K1(xn), size=(x_width, x_height)))  # [32,256,31,31]

            xk = self.beta * xn + x
        else:
            zq = z
            xk = x

        # response in channel weight
        if config.TRAIN.ATTN.CHANNEL_ATTN:
            # channel attention
            c_weight = self.ChannelGate(zq)
            zq = zq * c_weight
            xk = xk * c_weight

        return zq, xk

if __name__ == '__main__':
    kernel = torch.randn([32, 256, 7, 7]).cuda()
    search = torch.randn([32, 256, 31, 31]).cuda()

    # params & latency
    from thop.profile import profile
    from thop.utils import clever_format
    import time

    def calc_macs_and_params(name, model, kernel, search):
        model = model.cuda()
        macs, params = profile(model, inputs=(kernel, search), verbose=False)
        macs, params = clever_format([macs, params], "%3.3f")

        # test latency
        T_w = 20
        T_t = 100
        with torch.no_grad():
            for i in range(T_w):
                _, _ = model(kernel, search)
            start = time.time()
            for i in range(T_t):
                _, _ = model(kernel, search)
            end = time.time()
            latency = ((end - start) / T_t) * 1000

        print(f"{name.ljust(25)} | macs {macs} | params {params} | latency {latency}")

    calc_macs_and_params('bca', BCA(), kernel, search)


import os
import sys
import torch

from botorch.settings import debug
from botorch.test_functions.multi_objective import DTLZ1
from torch import Tensor
from typing import Callable

torch.set_default_dtype(torch.float64)
debug._set_state(True)

script_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
print(script_dir[:-12])
sys.path.append(script_dir[:-12])

from bopl.experiment_manager import experiment_manager
from bopl.utils import find_pointwise_optimums, find_true_optimal_menu
from bopl.utility.utility_model import GenericUtilityModel

# Objective function
input_dim = 5
output_dim = 3

dtlz1 = DTLZ1(dim=input_dim, num_objectives=output_dim, negate=True)

def get_objective_function(seed: int) -> Callable:

    def f(X: Tensor) -> Tensor:
        fX = dtlz1(X)
        return fX

    return f

# Utility's prior distribution
def utility_function(Y: Tensor, parameter: Tensor) -> Tensor:
    return torch.inner(parameter, Y)

def utility_prior_sampler(num_samples: int = 1, seed: int =None) -> Tensor:
    dirichlet = torch.distributions.dirichlet.Dirichlet(torch.ones(output_dim))
    if seed is None:
        samples = dirichlet.sample_n(num_samples)
    else:
        original_random_state = torch.random.get_rng_state()
        torch.manual_seed(seed)
        samples = dirichlet.sample_n(num_samples)
        torch.random.set_rng_state(original_random_state)

    return samples

utility_prior_model = GenericUtilityModel(
    utility_function=utility_function,
    prior_sampler=utility_prior_sampler,
    num_samples=32,
    seed=1,
)

# True underlying utility
def get_true_utility_function(seed:int) -> Callable:
    true_utility_parameter = utility_prior_sampler(num_samples=1, seed=seed)
    print(true_utility_parameter)
    def true_utility_function(Y: Tensor) -> Tensor:
        return utility_function(Y, true_utility_parameter)

    return true_utility_function

# Algos
algo = "MSC-EI-UU"
algo_params = {}

# Run experiment
if len(sys.argv) == 3:
    first_trial = int(sys.argv[1])
    last_trial =  int(sys.argv[2])
elif len(sys.argv) == 2:
    first_trial = int(sys.argv[1])
    last_trial =  int(sys.argv[1])

menu_size = 3
problem = "dtlz1_" + str(input_dim) + "_" + str(output_dim) + "_" + str(menu_size)

experiment_manager(
    problem = problem,
    get_objective_function=get_objective_function,
    get_true_utility_function=get_true_utility_function,
    utility_prior_model=utility_prior_model,
    input_dim=input_dim,
    menu_size=2,
    algo=algo,
    algo_params=algo_params,
    first_trial=first_trial,
    last_trial=last_trial,
    num_init_evals=2 * (input_dim + 1),
    num_bo_iter=20 * input_dim,
    restart=False,
    ignore_failures=False,
)


import re
import itertools

import jsonapi
import page.utils

def splitAndDeindentDocstring(item, level, default=None):
    if item.__doc__ is None:
        if default:
            return [default]
        return
    def inner():
        lines = item.__doc__.splitlines()
        yield lines[0]
        indentation_level = level * 4 + 3
        expected_indentation = " " * indentation_level
        for line in lines[1:]:
            assert not line or line.startswith(expected_indentation)
            yield line[indentation_level:]
    return list(inner())

def extractResourceSummary(resource_class):
    lines = list(splitAndDeindentDocstring(
        resource_class, level=1, default="Undocumented"))
    try:
        return " ".join(lines[:lines.index("")])
    except ValueError:
        return " ".join(lines)

def popParagraph(lines, include_empty=False):
    try:
        index = lines.index("")
    except ValueError:
        index = len(lines)
    paragraph = lines[:index]
    if len(paragraph) == 1 and " : " in paragraph[0]:
        return None
    if include_empty:
        paragraph.append("")
    del lines[:index + 1]
    return paragraph

def copyParagraph(destination, source, as_definition=False, include_empty=None):
    if include_empty is None:
        include_empty = not as_definition
    paragraph = popParagraph(source, include_empty=False)
    if paragraph is None:
        paragraph = ["Undocumented!"]
    if as_definition:
        paragraph = (["= " + paragraph[0]] +
                     ["  " + line for line in paragraph[1:]])
    if include_empty:
        paragraph.append("")
    destination.extend(paragraph)
    return True

def describeVersion():
    lines = ["Critic JSON API: Version 1",
             "==========================",
             "",
             "Path",
             "----",
             "/api/v1",
             "",
             "Top-level resources",
             "-------------------"]

    supported_resources = []

    for path, resource_class in jsonapi.HANDLERS.items():
        if path.startswith("v1/"):
            supported_resources.append(
                (path[3:], extractResourceSummary(resource_class)))

    supported_resources.sort()

    for path, summary in supported_resources:
        lines.extend(["? /api/v1/[%s][%s]" % (path, path),
                      "= " + summary])

    lines.append("")

    for path, _ in supported_resources:
        lines.append("[%s]: /api/v1?describe=%s" % (path, path))

    raise page.utils.DisplayFormattedText(lines)

def listAlternativePaths(resource_class):
    for context in getattr(resource_class, "contexts", (None,)):
        if context is None:
            yield resource_class.name
            continue
        for context_class in jsonapi.find(context):
            for context_path in listAlternativePaths(context_class):
                yield "%s/%s" % (context_path, resource_class.name)

def describeResource(resource_path):
    resource_class = jsonapi.lookup("v1/" + resource_path)

    # foo/bar/fie -> foo/A/bar/B/fie
    path_with_arguments = resource_path.split("/")
    placeholders = ("A", "B", "C", "D", "E", "F")
    for index in reversed(range(1, len(path_with_arguments))):
        path_with_arguments.insert(
            index, "%s" % placeholders[index - 1])
    path_with_arguments = "/".join(path_with_arguments)

    lines = [resource_class.name.capitalize(),
             "=" * len(resource_class.name),
             ""]

    lines.extend(["Description",
                  "-----------",
                  ""] +
                 splitAndDeindentDocstring(resource_class, level=1) +
                 [""])

    def search_and_filter_parameters(description, path=path_with_arguments):
        nparameters = 0
        while description:
            try:
                key, name, expected_type = description[0].split(" : ")
            except ValueError:
                break
            else:
                del description[0]
                if not nparameters:
                    lines.extend(["Search/filter parameters",
                                  "------------------------"])
                nparameters += 1
                if expected_type == "-":
                    expected_type = ""
                else:
                    expected_type = " (%s)" % expected_type
                lines.append("? api/v1/%s?%s=%s%s"
                             % (path, key, name, expected_type))
                assert not description.pop(0)
                copyParagraph(lines, description, as_definition=True)
        if nparameters > 1:
            lines.extend(
                ["",
                 "Note: Unless noted otherwise, search/filter parameters",
                 "      can be combined."])
        if nparameters > 0:
            lines.append("")
            return True
        return False

    if resource_class.single:
        lines.extend(["Single-resource access",
                      "----------------------",
                      ""])

        description = splitAndDeindentDocstring(resource_class.single, 2)

        if description is None:
            lines.append("Undocumented!")
        else:
            lines.append("? api/v1/%s/ARGUMENT[,ARGUMENT,...]"
                         % path_with_arguments)
            copyParagraph(
                lines, description, as_definition=True, include_empty=True)

            first_variant = True
            while description:
                try:
                    name, expected_type = description[0].split(" : ")
                except ValueError:
                    break
                else:
                    del description[0]
                    if first_variant:
                        lines.extend(["Resource argument",
                                      "-----------------"])
                        first_variant = False
                    lines.append("? api/v1/%s/%s (%s)"
                                 % (path_with_arguments, name, expected_type))
                    assert not description.pop(0)
                    copyParagraph(lines, description, as_definition=True)

            lines.append("")

            search_and_filter_parameters(
                description, path="%s/ARGUMENT" % path_with_arguments)

            lines.extend(description)

        lines.append("")

    if resource_class.multiple:
        lines.extend(["Multiple-resource access",
                      "------------------------",
                      ""])

        description = splitAndDeindentDocstring(resource_class.multiple, 2)

        if description is None:
            lines.extend(["Undocumented!",
                          ""])
        else:
            lines.append("? api/v1/%s" % path_with_arguments)
            copyParagraph(lines, description, as_definition=True)
            lines.append("")

            while description and not search_and_filter_parameters(description):
                copyParagraph(lines, description)

    lines.extend(["Resource structure",
                  "------------------",
                  ""])

    structure_lines = splitAndDeindentDocstring(resource_class.json, level=2)
    if structure_lines:
        def massage_line(line):
            if line.strip().startswith("// "):
                return "  // " + line.strip()[3:] + ""
            line, _, description = line.partition(" // ")
            if description:
                line += " %s" % description
            return line

        lines.extend("|| " + massage_line(line) for line in structure_lines)
        lines.append("")
    else:
        lines.extend(["Undocumented!",
                      ""])

    alternative_paths = sorted(
        set(listAlternativePaths(resource_class)) - set([resource_path]))

    if alternative_paths:
        lines.extend(["Alternative paths",
                      "-----------------",
                      "",
                      "This class of resources is also accessible as:",
                      ""])

        for alternative_path in alternative_paths:
            lines.extend(["* api/v1/[%s][%s]"
                          % (alternative_path, alternative_path),
                          ""])

        for alternative_path in alternative_paths:
            lines.append("[%s]: /api/v1?describe=%s"
                         % (alternative_path, alternative_path))
        lines.append("")

    subresources = []
    prefix = ".../" + resource_class.name + "/"

    for path, subresource_class in jsonapi.HANDLERS.items():
        if path.startswith(prefix):
            subresources.append(
                (path[len(prefix):], extractResourceSummary(subresource_class)))

    if subresources:
        lines.extend(["Sub-resources",
                      "-------------",
                      ""])

        for path, summary in sorted(subresources):
            lines.extend(["? /api/v1/%s/[%s][%s]"
                          % (path_with_arguments, path, path),
                          "= " + summary])

        lines.append("")

        for path, _ in subresources:
            lines.append("[%s]: /api/v1?describe=%s/%s"
                         % (path, resource_path, path))

    raise page.utils.DisplayFormattedText(lines)


import torch
from torch import nn

class MobileNet(nn.Module):

    def __init__(self, num_classes = 4):
        super().__init__()

        modules = [
            nn.Conv2d(3, 8, 3, 2, 1, bias=False),
            nn.BatchNorm2d(8),
            nn.ReLU(),
        ]

        # spec = (in_channel, out_channel, stride)
        spec = [(8, 16, 1),
                (16, 32, 2),
                (32, 32, 1),
                (32, 64, 2),
                (64, 64, 1),
                (64, 128, 2),
                (128, 128, 1),
                (128, 128, 1),
                (128, 128, 1),
                (128, 128, 1),
                (128, 128, 1),
                (128, 256, 2),
                (256, 256, 1)
        ]

        for in_channels, out_channels, stride in spec:
            modules += [
                nn.Conv2d(in_channels, in_channels, 3, stride, 1, groups=in_channels, bias=False),
                nn.BatchNorm2d(in_channels),
                nn.ReLU(),
                nn.Conv2d(in_channels, out_channels, 1, 1, 0, bias=False),
                nn.BatchNorm2d(out_channels),
                nn.ReLU()
            ]

        modules += [
            nn.AdaptiveAvgPool2d((1, 1)),
            nn.Flatten(),
            nn.Linear(256, num_classes)
        ]
        self.net = nn.Sequential(*modules)

    def forward(self, x):
        return self.net(x)

    def get_random_input(self):
        return torch.randn(1, 3, 96, 96)

if __name__ == '__main__':
    m = MobileNet()
    print(m)
    x = m.get_random_input()
    y = m(x)
    print(y.shape)


#! python

import torch
import torch.nn as nn

########################
## sub class
########################
class MultiHeadAttentionLayer(nn.Module):
    def __init__(self, hid_dim, n_heads, dropout, device):
        super().__init__()

        assert hid_dim % n_heads == 0
        self.hid_dim = hid_dim
        self.n_heads = n_heads
        self.head_dim = hid_dim // n_heads
        self.fc_q = nn.Linear(hid_dim, hid_dim)
        self.fc_k = nn.Linear(hid_dim, hid_dim)
        self.fc_v = nn.Linear(hid_dim, hid_dim)
        self.fc_o = nn.Linear(hid_dim, hid_dim)
        self.dropout = nn.Dropout(dropout)
        self.scale = torch.sqrt(torch.FloatTensor([self.head_dim])).to(device)

    def forward(self, query, key, value, mask = None):
        # query: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        # key: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        # value: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        # mask: [batch_size, 1, 1/num_token, num_token] (128, 1, 1/9, 78/9)
        #print('MultiHeadAttentionLayer(1) query: '+str(query.shape))
        #print('MultiHeadAttentionLayer(1) key: '+str(key.shape))
        #print('MultiHeadAttentionLayer(1) value: '+str(value.shape))
        #if mask is not None:
            #print('MultiHeadAttentionLayer(1) mask: '+str(mask.shape))

        batch_size = query.shape[0]

        Q = self.fc_q(query)
        K = self.fc_k(key)
        V = self.fc_v(value)
        # Q: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        # K: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        # V: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        #print('MultiHeadAttentionLayer(2) Q: '+str(Q.shape))
        #print('MultiHeadAttentionLayer(2) K: '+str(K.shape))
        #print('MultiHeadAttentionLayer(2) V: '+str(V.shape))

        Q = Q.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
        K = K.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
        V = V.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
        # Q: [batch_size, num_heads, num_token, head_dim] (128, 8, 78/9, 32)
        # K: [batch_size, num_heads, num_token, head_dim] (128, 8, 78/9, 32)
        # V: [batch_size, num_heads, num_token, head_dim] (128, 8, 78/9, 32)
        #print('MultiHeadAttentionLayer(3) Q: '+str(Q.shape))
        #print('MultiHeadAttentionLayer(3) K: '+str(K.shape))
        #print('MultiHeadAttentionLayer(3) V: '+str(V.shape))

        energy = torch.matmul(Q, K.permute(0, 1, 3, 2)) / self.scale
        # energy: [batch_size, num_heads, num_token, num_token] (128, 8, 78/9, 78/9)
        #print('MultiHeadAttentionLayer(4) energy: '+str(energy.shape))

        if mask is not None:
            energy = energy.masked_fill(mask == 0, -1e10)
        # energy: [batch_size, num_heads, num_token, num_token] (128, 8, 78/9, 78/9)
        #print('MultiHeadAttentionLayer(5) energy: '+str(energy.shape))

        attention = torch.softmax(energy, dim = -1)
        # attention: [batch_size, num_heads, num_token, num_token] (128, 8, 78/9, 78/9)
        #print('MultiHeadAttentionLayer(6) attention: '+str(attention.shape))

        x = torch.matmul(self.dropout(attention), V)
        # x: [batch_size, num_heads, num_token, head_dim] (128, 8, 78/9, 32)
        #print('MultiHeadAttentionLayer(7) x: '+str(x.shape))

        x = x.permute(0, 2, 1, 3).contiguous()
        # x: [batch_size, num_token, num_heads, head_dim] (128, 78/9, 8, 32)
        #print('MultiHeadAttentionLayer(8) x: '+str(x.shape))

        x = x.view(batch_size, -1, self.hid_dim)
        # x: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        #print('MultiHeadAttentionLayer(9) x: '+str(x.shape))

        x = self.fc_o(x)
        # x: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        #print('MultiHeadAttentionLayer(10) x: '+str(x.shape))

        return x, attention

class PositionwiseFeedforwardLayer(nn.Module):
    def __init__(self, hid_dim, pf_dim, dropout):
        super().__init__()

        self.fc_1 = nn.Linear(hid_dim, pf_dim)
        self.fc_2 = nn.Linear(pf_dim, hid_dim)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        # x: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        #print('PositionwiseFeedforwardLayer(1) x: '+str(x.shape))

        x = self.dropout(torch.relu(self.fc_1(x)))
        # x: [batch_size, num_token, pf_dim] (128, 78/9, 512)
        #print('PositionwiseFeedforwardLayer(2) x: '+str(x.shape))

        x = self.fc_2(x)
        # x: [batch_size, num_token, hid_dim] (128, 78/9, 256)
        #print('PositionwiseFeedforwardLayer(3) x: '+str(x.shape))

        return x


from django.conf.urls import url
from .views import *

urlpatterns=[
	url(r'^$',Index,name="Index"),
	url(r'^List_Products/(\w+)/(\w+)/$',List_Products,name="List_Products"),
	url(r'^Add_Cart/$',Add_Cart,name="Add_Cart"),
	url(r'^View_Shopping_Cart/$',View_Shopping_Cart,name="View_Shopping_Cart"),
	url(r'^Invoice/$',Invoice,name="Invoice"),
	url(r'^Login/$',Login,name="Login"),
	url(r'^Register/$',Register,name="Register"),
	url(r'^CheckOut/$',CheckOut,name="CheckOut"),
	url(r'^LogOut/$',LogOut,name="LogOut"),
]


'''
Given an array of numbers, find the maximum sum of any contiguous subarray of the array.

For example, given the array [34, -50, 42, 14, -5, 86], the maximum sum would be 137, since we would take elements 42, 14, -5, and 86.

Given the array [-5, -1, -8, -9], the maximum sum would be 0, since we would not take any elements.

Do this in O(N) time.
'''

from typing import List

def getMaxSum(arr: List):
    # List all negative or 0
    if max(arr) <= 0:
        return 0
    # Empty List
    if not arr:
        return 0

    max_sum = temp_max_sum = max(arr[0], 0)

    # Traverses the list and maintains a max sum, discarding it if a larger contiguous sum comes along.
    for num in arr[1:]:
        temp_max_sum = max(num, temp_max_sum + num)
        max_sum = max(max_sum, temp_max_sum)

    return max_sum

print(getMaxSum([34, -50, 42, 14, -5, 86]))
print(getMaxSum([-5, -1, -8, -9]))


#!/usr/bin/python3
# -*- coding: UTF-8 -*-
#
# Metrics push
# ============
# Environment: With access to internet
# Input:
# - Mandatory:
#   -- an API token for auth
#   -- API url (https://abiquo.example.com/api)
#   -- VApp name
# - Optional (configure in Main function):
#   source metric names, create metric names
#
# Requires a deployed VApp with a scaling group
#
# 1. Gets the VApp by name
# 2. Gets avg metrics for all VMs in the cloud
# 3. Create metrics for Vapp and Scaling group in VApp
#
# TODO: Optionally create metrics for all VApps in VDC
# and all scaling groups in the Vapps.
#
# Dependencies:
# abiquo-api installed with pip3
#
# import json
from abiquo.client import Abiquo
from abiquo.auth import TokenAuth
from abiquo.client import check_response
from itertools import cycle
import json
import random
# For test environment disable SSL warning
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def createMetadata(entity, metName, entType):
    # Create metadata for the metrics that don't have it
    mddesc = entType + " " + metName
    MetricMetadata = {'name': metName,
                      'description': mddesc,
                      'unit': 'percent',
                      'namespace': entType
                      }

    code, newMd = entity.follow('metricsmetadata').post(
        headers={'content-type':
                 'application/vnd.abiquo.metricmetadata+json',
                 'accept':
                 'application/vnd.abiquo.metricmetadata+json'
                 },
        data=json.dumps(MetricMetadata))
    print("Create metadata for", metName, "Response code is: ", code)
    return code

def getMetadata(entity):
    print ("entity name: ", entity.name)
    code, entitymd = entity.follow('metricsmetadata').get(
        headers={'Accept':
                 'application/vnd.abiquo.metricsmetadata+json'})
    print("Get MD of ", entity.name, "Response code is: ", code)
    return (code, entitymd)

def getAndCreateMetadata(entity, metricsCreate, entType):
    code, entityMd = getMetadata(entity)
    metNameWithMetadata = []
    # Get list of names of metrics names with metadata
    for md in entityMd:
        metNameWithMetadata.append(md.name)

    # Build list of metrics to create that don't have metadata
    metNamesNoMd = list(filter(
        lambda mcnmd: mcnmd not in metNameWithMetadata, metricsCreate))

    # Create metadata for the metrics that don't have it
    for metName in metNamesNoMd:
        ocode = createMetadata(entity, metName, entType)
        print ("Created metadata for", entity, "Code: ", ocode)

    code, entityMd = getMetadata(entity)
    return (code, entityMd)

def getMetricsFromVMs(vmsOn, metricsSource):
    metricsList = []
    for virtualMachine in vmsOn:
        code, metrics = getMetadata(virtualMachine)
        check_response(200, code, metrics)
        print("Get VM metrics, Response code is: ", code)
        print("VM name: ", virtualMachine.name)
        for vmLink in virtualMachine.json["links"]:
            if vmLink["rel"] == "virtualappliance":
                vappName = vmLink["title"]
                print("Belongs to VApp: ", vappName)

        metSource = list(filter(lambda me: me.name in metricsSource, metrics))
        for met in metSource:
            code, ame = met.metric.get(
                headers={'Accept':
                         'application/vnd.abiquo.metric+json'})
            check_response(200, code, ame)
            print("Get VM metric data, Response code is: ", code)
            if ame.datapoints:
                print("metric datapoints: ", ame.datapoints)
                metricsList.append(ame.datapoints)
            else:
                print("No metrics: ", virtualMachine.name)
    return metricsList

def getVappByName(inputVappName, vdcsList):
    # Assuming a unique name but just returning first instance of name
    for vdc in vdcsList:
        code, inputVapps = vdc.virtualappliances.get(
            headers={'accept':
                     'application/vnd.abiquo.virtualappliances+json'},
            params={'has': inputVappName})
        print("Get virtual appliances. Response code is: ", code)
        if inputVapps:
            for vapp in inputVapps:
                print("VApp name: ", vapp.name)
                return vapp

def pushDatapoints(entity, metricsCreate, dpPool, entType):
    code, entMdList = getAndCreateMetadata(entity, metricsCreate, entType)
    print("Get metadata", entity.name, "Response code is: ", code)
    print("Datapoint to push: ")
    metricsData = next(dpPool)
    print(json.dumps(metricsData, indent=2))
    for entm in entMdList:
        if entm.name in metricsCreate:
            code, resp = entm.follow('metric').post(
                headers={'content-type':
                         'application/vnd.abiquo.datapoints+json',
                         'accept':
                         'text/json,application/json'},
                data=json.dumps(metricsData))
            print("Create metric datapoints for ", entm.name,
                  " Response code is: ", code)

def main():
    # Abiquo API token
    token = input("Enter token: ")
    apiUrl = input("Enter API URL: ")
    # apiUrl = "https://abiquo.example.com/api"
    inVapp = input("Enter a unique VApp name: ")
    # inVapp = "vapp_mjs"
    api = Abiquo(apiUrl, auth=TokenAuth(token), verify=False)
    metricsSource = ["abq-cpu_usage", "abq-ram_usage"]
    metricsCreate = ["meta11", "meta22", "meta33"]
    # Get the virtual datacenters from the cloud
    code, vdcsList = api.cloud.virtualdatacenters.get(
        headers={'accept': 'application/vnd.abiquo.virtualdatacenters+json'})
    print("Get virtual datacenters. Response code is: ", code)

    # Get the VApp from the VDCs by its unique name
    theVapp = getVappByName(inVapp, vdcsList)
    # print ("vapp json", theVapp.json)

    # Get the Scaling groups from the VApp
    code, scalingGroups = theVapp.follow("scalinggroups").get()

    getAndCreateMetadata(theVapp, metricsCreate, "virtualappliance")
    for scalingGroup in scalingGroups:
        print ("sgname", scalingGroup.name)
        getAndCreateMetadata(scalingGroup, metricsCreate, "scalinggroup")

    # Get the virtualmachines from the cloud to use their metrics
    # as the source of the fake metrics
    code, virtualMachinesList = api.cloud.virtualmachines.get(
        headers={'accept': 'application/vnd.abiquo.virtualmachines+json'})
    check_response(200, code, virtualMachinesList)
    print("Get virtualmachines. Response code is: ", code)

    # Get selected metrics from all of the user's VMs that are powered ON
    vmsOn = list(filter(lambda vm: vm.state == "ON", virtualMachinesList))
    metricsList = getMetricsFromVMs(vmsOn, metricsSource)

    # Create some datapoints for the metrics
    datapointsList = []
    metPool = cycle(metricsList)
    for mc in metricsCreate:
        datapoints = next(metPool)["average"][:]
        for dp in datapoints:
            dp["value"] = ((dp["value"] + random.random()) * 50) % 100
        datapointData = {'dimensions': {},
                         'links': [],
                         'collection': datapoints}
        datapointsList.append(datapointData)

    dpPool = cycle(datapointsList)
    pushDatapoints(theVapp, metricsCreate, dpPool, "virtualappliance")
    pushDatapoints(scalingGroup, metricsCreate, dpPool, "scalinggroup")

# Calls the main() function
if __name__ == '__main__':
    main()


'''
Example using the MAX22007PMB

Created on 13.10.2021

@author:
'''
##############################################################################
import time
from pyb import Pin
from  PyTrinamicMicro.platforms.motionpy2.modules.max import max22007

#For readability
SECONDS = 1

#Pmod Connectors
pmod0 = dict({
    "pin_intb"  : Pin.cpu.C6,
    "pin_cs"    : Pin.cpu.A4,
    "spi" : 1
    })

pmod1 = dict({
    "pin_intb"  : Pin.cpu.C2,
    "pin_cs"    : Pin.cpu.B12,
    "spi" : 2
    })

connector = pmod0
print("Initializing MAX22007PMB...")
max22007pmb = max22007.MAX22007PMB(**connector)

#Read and print Rev ID & Status (binary strings)
temp = max22007pmb.dac.read(max22007pmb.dac.MAX22007_REV_adr)
print("MAX22007 Rev#:" + str(temp))

temp = max22007pmb.dac.read(max22007pmb.dac.MAX22007_STAT_adr)
print("MAX22007 Status:" + str(temp))

#Toggle LEDs and set to 5 V for each channel.
channels_on = [0,0,0,0]
while(True):
    for i in (1,2,3,4):
        if (channels_on[i-1] == 0):
            data = max22007pmb.set_LED(i)
            data = max22007pmb.set_channel_voltage(i, 5.0)
            channels_on[i-1] = 1
        else:
            data = max22007pmb.clear_LED(i)
            data = max22007pmb.set_channel_voltage(i, 0.0)
            channels_on[i-1] = 0
        time.sleep(0.5*SECONDS)


# Scrape list of YA authors from wikipedia and save to CSV file
# Author list is broken into sections alphabetically
#
# Key HTML Structure:
#

#

#       : List of books...
#

#

#
# Note: The "section" with a class="mf-section-26" has list items we don't want
#       to capture.

import requests
from bs4 import BeautifulSoup
import pandas as pd

url = 'https://en.m.wikipedia.org/wiki/List_of_young_adult_fiction_writers'
output_file = "data/raw/authors.csv"

data = requests.get(url)
soup = BeautifulSoup(data.content, "html.parser")
sections = soup.find_all("section", {"class":"collapsible-block"})

authors = []
author_index = []
index_val = 1

for section in sections:
    if "mf-section-26" not in section["class"]: # don't capture the last block
        author_list = section.find_all("li")
        for author in author_list:
            authors.append(author.find_next("a").get("title"))
            author_index.append(index_val)
            index_val += 1

df = pd.DataFrame(authors, index= author_index, columns=['Name'])

remove_list = [
    '(author)',
    '(writer)',
    '(novelist)',
    '(author, born 1954)',
    '(TV producer)',
    '(Irish author)',
    '(young adult author)',
    '(historian)']

for item in remove_list:
    df['Name'] = df['Name'].str.replace(item, '', regex= False)

df.to_csv(output_file)


from .targets.target import FilePath, Target
from .targets.wildcard import find_matching_target
from typing import Awaitable, Optional, Union, Set, Dict
from .cache import TimestampCache
import asyncio
from pathlib import Path
import os
import glob
import time
from .processpoolexecutor import ProcessPoolExecutor

def make_sync(
    target: Target,
    *,
    cache: Optional[Union[TimestampCache, FilePath]] = '.pymake-cache',
    targets: Optional[Dict[str, Target]] = None,
    prefix_dir: FilePath = ''
):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(make(
        target, cache=cache, targets=targets, prefix_dir=prefix_dir))

# technically not 'uncatchable', but most except clauses catch Exception
# which is a subclass of BaseException. Therefore BaseExceptions won't be caught

async def make(
    target: Target,
    *,
    cache: Optional[Union[TimestampCache, FilePath]] = '.pymake-cache',
    targets: Optional[Dict[str, Target]] = None,
    prefix_dir: FilePath = ''
):
    assert targets  # TODO: import from calling module
    _targets = targets
    _prefix_dir = Path(prefix_dir)

    _cache = cache if cache is None or isinstance(cache, TimestampCache) \
        else TimestampCache(_prefix_dir / cache, targets) if targets else None

    scheduled: Dict[Target, Awaitable[float]] = {}

    try:
        with ProcessPoolExecutor() as multiprocessor:
            async def maybe_remake(target: Target) -> bool:
                "Recursively schedule target remakes if needed, returns if the target was remade"
                if target in scheduled:
                    await scheduled[target]
                    return True

                if not any(target.deps):
                    needs_remake = True

                target_edited = await target.edited()
                needs_remake = target_edited == float('inf')
                maybe_remaking: Set[Awaitable[bool]] = set()
                for dep in target.deps:
                    if isinstance(dep, Path):
                        if not dep.is_absolute():
                            dep = _prefix_dir / dep

                        try:
                            # we use glob.iglob over dep.glob as dep.glob never follows symlinks
                            for f in glob.iglob(str(dep)):
                                if Path(f).stat().st_mtime > target_edited:
                                    needs_remake = True
                                    break
                            continue
                        except FileNotFoundError:
                            dep = find_matching_target(dep, _targets)

                    maybe_remaking.add(
                        asyncio.ensure_future(maybe_remake(dep)))

                if any(await asyncio.gather(*maybe_remaking)):
                    needs_remake = True

                if needs_remake:
                    scheduled[target] = asyncio.wrap_future(
                        multiprocessor.submit(_remake, target))
                    time = await scheduled[target]
                    if _cache and target.do_cache:
                        _cache[target] = time
                    return True

                else:
                    return False

            await maybe_remake(target)

    finally:
        if _cache is not None:
            _cache.save()

def _remake(target: Target) -> float:
    "Remake the given target, ensuring envvars and cwd is as expected. Returns the time the target was remade"

    env_before = os.environ.copy()
    os.environ.clear()
    os.environ.update(target.env)

    if not Path.cwd().samefile(target.cwd):
        os.chdir(target.cwd)

    async def process():
        after = None
        if target.target:
            target_path = Path(target.target)
            if target_path.exists():
                before = target_path.stat().st_mtime
                await target.make()
                after = target_path.stat().st_mtime
                # TODO: custom errors
                assert after != before, "output file did not change"
                assert after > before, "output file went back in time"

        if not after:
            await target.make()
            after = time.time()
        return after

    try:
        made_time = asyncio.new_event_loop() \
            .run_until_complete(process())
    except:
        raise
    finally:
        os.environ.clear()
        os.environ.update(env_before)

    return made_time


# 在电话数字键上面, 利用骑士的走法, 有几种走法。看来又是 DP 题。
# 骑士可以在任何地方开始, 走n-1次, 也就是会按出 n 个数字。
# 每个位置,能往下走的地点是固定的, 可以用 array 来决定“能到哪里”
class Solution:
    def knightDialer(self, n: int) -> int:
        table = [1]*10 # 一开始都有1种可能
        table2 = [0]*10 # 另一个用来交换的表格
        # 下面是个对照表，了解有 fromN[i] 代表“数字i” 可从哪里过来
        fromN = {0:(4,6), 1:(6,8), 2:(7,9), 3:(4,8), 4:(3,9,0), 5:(), 6:(0,7,1), 7:(6,2), 8:(3,1), 9:(4,2)}

        MOD = 10**9+7
        for s in range(n-1): # 要走 n-1 步
            for i in range(10): # 数字键i
                table2[i] = 0
                for k in fromN[i]: # 可以从 k 走过来
                    table2[i] = (table2[i] + table[k]) % MOD
            # 完成后，要交换 table 及 table2
            table, table2 = table2, table

        return sum(table) % MOD


import logging
from enum import Enum

from gi.repository import Gdk, Gio, GLib, GObject, Gtk, GtkSource, Pango

from meld.meldbuffer import MeldBuffer
from meld.settings import bind_settings, get_meld_settings, settings
from meld.style import colour_lookup_with_fallback, get_common_theme

log = logging.getLogger(__name__)

def get_custom_encoding_candidates():
    custom_candidates = []
    try:
        for charset in settings.get_value('detect-encodings'):
            encoding = GtkSource.Encoding.get_from_charset(charset)
            if not encoding:
                log.warning('Invalid charset "%s" skipped', charset)
                continue
            custom_candidates.append(encoding)
        if custom_candidates:
            custom_candidates.extend(
                GtkSource.Encoding.get_default_candidates())
    except AttributeError:
        # get_default_candidates() is only available in GtkSourceView 3.18
        # and we'd rather use their defaults than our old detect list.
        pass
    return custom_candidates

class LanguageManager:

    manager = GtkSource.LanguageManager()

    @classmethod
    def get_language_from_file(cls, gfile):
        try:
            info = gfile.query_info(
                Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 0, None)
        except (GLib.GError, AttributeError):
            return None
        content_type = info.get_content_type()
        return cls.manager.guess_language(gfile.get_basename(), content_type)

    @classmethod
    def get_language_from_mime_type(cls, mime_type):
        content_type = Gio.content_type_from_mime_type(mime_type)
        return cls.manager.guess_language(None, content_type)

class TextviewLineAnimationType(Enum):
    fill = 'fill'
    stroke = 'stroke'

class TextviewLineAnimation:
    __slots__ = ("start_mark", "end_mark", "start_rgba", "end_rgba",
                 "start_time", "duration", "anim_type")

    def __init__(self, mark0, mark1, rgba0, rgba1, duration, anim_type):
        self.start_mark = mark0
        self.end_mark = mark1
        self.start_rgba = rgba0
        self.end_rgba = rgba1
        self.start_time = GLib.get_monotonic_time()
        self.duration = duration
        self.anim_type = anim_type

class SourceViewHelperMixin:

    def get_y_for_line_num(self, line):
        buf = self.get_buffer()
        it = buf.get_iter_at_line(line)
        y, h = self.get_line_yrange(it)
        if line >= buf.get_line_count():
            return y + h
        return y

    def get_line_num_for_y(self, y):
        return self.get_line_at_y(y)[0].get_line()

class MeldSourceView(GtkSource.View, SourceViewHelperMixin):

    __gtype_name__ = "MeldSourceView"

    __gsettings_bindings_view__ = (
        ('highlight-current-line', 'highlight-current-line-local'),
        ('indent-width', 'tab-width'),
        ('insert-spaces-instead-of-tabs', 'insert-spaces-instead-of-tabs'),
        ('enable-space-drawer', 'draw-spaces-bool'),
        ('wrap-mode', 'wrap-mode'),
        ('show-line-numbers', 'show-line-numbers'),
    )

    # Named so as not to conflict with the GtkSourceView property
    highlight_current_line_local = GObject.Property(type=bool, default=False)

    def get_show_line_numbers(self):
        return self._show_line_numbers

    def set_show_line_numbers(self, show):
        if show == self._show_line_numbers:
            return

        if getattr(self, 'line_renderer', None):
            self.line_renderer.set_visible(show)

        self._show_line_numbers = bool(show)
        self.notify("show-line-numbers")

    show_line_numbers = GObject.Property(
        type=bool, default=False, getter=get_show_line_numbers,
        setter=set_show_line_numbers)

    wrap_mode_bool = GObject.Property(
        type=bool, default=False,
        nick="Wrap mode (Boolean version)",
        blurb=(
            "Mirror of the wrap-mode GtkTextView property, reduced to "
            "a single Boolean for UI ease-of-use."
        ),
    )

    draw_spaces_bool = GObject.Property(
        type=bool, default=False,
        nick="Draw spaces (Boolean version)",
        blurb=(
            "Mirror of the draw-spaces GtkSourceView property, "
            "reduced to a single Boolean for UI ease-of-use."
        ),
    )

    overscroll_num_lines = GObject.Property(
        type=int, default=5, minimum=0, maximum=100,
        nick="Overscroll line count",
        flags=(
            GObject.ParamFlags.READWRITE |
            GObject.ParamFlags.CONSTRUCT
        ),
    )

    replaced_entries = (
        # We replace the default GtkSourceView undo mechanism
        (Gdk.KEY_z, Gdk.ModifierType.CONTROL_MASK),
        (Gdk.KEY_z, Gdk.ModifierType.CONTROL_MASK |
            Gdk.ModifierType.SHIFT_MASK),

        # We replace the default line movement behaviour of Alt+Up/Down
        (Gdk.KEY_Up, Gdk.ModifierType.MOD1_MASK),
        (Gdk.KEY_KP_Up, Gdk.ModifierType.MOD1_MASK),
        (Gdk.KEY_KP_Up, Gdk.ModifierType.MOD1_MASK |
            Gdk.ModifierType.SHIFT_MASK),
        (Gdk.KEY_Down, Gdk.ModifierType.MOD1_MASK),
        (Gdk.KEY_KP_Down, Gdk.ModifierType.MOD1_MASK),
        (Gdk.KEY_KP_Down, Gdk.ModifierType.MOD1_MASK |
            Gdk.ModifierType.SHIFT_MASK),
        # ...and Alt+Left/Right
        (Gdk.KEY_Left, Gdk.ModifierType.MOD1_MASK),
        (Gdk.KEY_KP_Left, Gdk.ModifierType.MOD1_MASK),
        (Gdk.KEY_Right, Gdk.ModifierType.MOD1_MASK),
        (Gdk.KEY_KP_Right, Gdk.ModifierType.MOD1_MASK),
        # ...and Ctrl+Page Up/Down
        (Gdk.KEY_Page_Up, Gdk.ModifierType.CONTROL_MASK),
        (Gdk.KEY_KP_Page_Up, Gdk.ModifierType.CONTROL_MASK),
        (Gdk.KEY_Page_Down, Gdk.ModifierType.CONTROL_MASK),
        (Gdk.KEY_KP_Page_Down, Gdk.ModifierType.CONTROL_MASK),
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.drag_dest_add_uri_targets()

        # Most bindings are on SourceView, except the Page Up/Down ones
        # which are on TextView.
        binding_set_names = ('GtkSourceView', 'GtkTextView')
        for set_name in binding_set_names:
            binding_set = Gtk.binding_set_find(set_name)
            for key, modifiers in self.replaced_entries:
                Gtk.binding_entry_remove(binding_set, key, modifiers)

        self.anim_source_id = None
        self.animating_chunks = []
        self.syncpoints = []
        self._show_line_numbers = None

        buf = MeldBuffer()
        inline_tag = GtkSource.Tag.new("inline")
        inline_tag.props.draw_spaces = True
        buf.get_tag_table().add(inline_tag)
        buf.create_tag("dimmed")
        self.set_buffer(buf)
        self.connect('notify::overscroll-num-lines', self.notify_overscroll)

    @property
    def line_height(self) -> int:
        if not getattr(self, '_approx_line_height', None):
            context = self.get_pango_context()
            layout = Pango.Layout(context)
            layout.set_text('X', -1)
            _width, self._approx_line_height = layout.get_pixel_size()

        return self._approx_line_height

    def notify_overscroll(self, view, param):
        self.props.bottom_margin = self.overscroll_num_lines * self.line_height

    def do_paste_clipboard(self, *args):
        # This is an awful hack to replace another awful hack. The idea
        # here is to sanitise the clipboard contents so that it doesn't
        # contain GtkTextTags, by requesting and setting plain text.

        def text_received_cb(clipboard, text, *user_data):
            # On clipboard failure, text will be None
            if not text:
                return

            # Manual encoding is required here, or the length will be
            # incorrect, and the API requires a UTF-8 bytestring.
            utf8_text = text.encode('utf-8')
            clipboard.set_text(text, len(utf8_text))
            self.get_buffer().paste_clipboard(
                clipboard, None, self.get_editable())

        clipboard = self.get_clipboard(Gdk.SELECTION_CLIPBOARD)
        clipboard.request_text(text_received_cb)

    def add_fading_highlight(
            self, mark0, mark1, colour_name, duration,
            anim_type=TextviewLineAnimationType.fill, starting_alpha=1.0):

        if not self.get_realized():
            return

        rgba0 = self.fill_colors[colour_name].copy()
        rgba1 = self.fill_colors[colour_name].copy()
        rgba0.alpha = starting_alpha
        rgba1.alpha = 0.0
        anim = TextviewLineAnimation(
            mark0, mark1, rgba0, rgba1, duration, anim_type)
        self.animating_chunks.append(anim)

    def on_setting_changed(self, settings, key):
        if key == 'font':
            self.override_font(settings.font)
            self._approx_line_height = None
        elif key == 'style-scheme':
            self.highlight_color = colour_lookup_with_fallback(
                "meld:current-line-highlight", "background")
            self.syncpoint_color = colour_lookup_with_fallback(
                "meld:syncpoint-outline", "foreground")
            self.fill_colors, self.line_colors = get_common_theme()

            buf = self.get_buffer()
            buf.set_style_scheme(settings.style_scheme)

            tag = buf.get_tag_table().lookup("inline")
            tag.props.background_rgba = colour_lookup_with_fallback(
                "meld:inline", "background")
            tag = buf.get_tag_table().lookup("dimmed")
            tag.props.foreground_rgba = colour_lookup_with_fallback(
                "meld:dimmed", "foreground")

    def do_realize(self):
        bind_settings(self)

        def wrap_mode_from_bool(binding, from_value):
            if from_value:
                settings_mode = settings.get_enum('wrap-mode')
                if settings_mode == Gtk.WrapMode.NONE:
                    mode = Gtk.WrapMode.WORD
                else:
                    mode = settings_mode
            else:
                mode = Gtk.WrapMode.NONE
            return mode

        def wrap_mode_to_bool(binding, from_value):
            return bool(from_value)

        self.bind_property(
            'wrap-mode-bool', self, 'wrap-mode',
            GObject.BindingFlags.BIDIRECTIONAL,
            wrap_mode_from_bool,
            wrap_mode_to_bool,
        )
        self.wrap_mode_bool = wrap_mode_to_bool(None, self.props.wrap_mode)

        self.bind_property(
            'draw-spaces-bool', self.props.space_drawer, 'enable-matrix',
            GObject.BindingFlags.DEFAULT | GObject.BindingFlags.SYNC_CREATE,
        )

        meld_settings = get_meld_settings()

        self.on_setting_changed(meld_settings, 'font')
        self.on_setting_changed(meld_settings, 'style-scheme')
        self.get_buffer().set_style_scheme(meld_settings.style_scheme)

        meld_settings.connect('changed', self.on_setting_changed)

        return GtkSource.View.do_realize(self)

    def do_unrealize(self):
        if self.anim_source_id:
            GLib.source_remove(self.anim_source_id)
        return GtkSource.View.do_unrealize(self)

    def do_draw_layer(self, layer, context):
        if layer != Gtk.TextViewLayer.BELOW_TEXT:
            return GtkSource.View.do_draw_layer(self, layer, context)

        context.save()
        context.set_line_width(1.0)

        _, clip = Gdk.cairo_get_clip_rectangle(context)
        clip_end = clip.y + clip.height
        bounds = (
            self.get_line_num_for_y(clip.y),
            self.get_line_num_for_y(clip_end),
        )

        x = clip.x - 0.5
        width = clip.width + 1

        # Paint chunk backgrounds and outlines
        for change in self.chunk_iter(bounds):
            ypos0 = self.get_y_for_line_num(change[1])
            ypos1 = self.get_y_for_line_num(change[2])
            height = max(0, ypos1 - ypos0 - 1)

            context.rectangle(x, ypos0 + 0.5, width, height)
            if change[1] != change[2]:
                context.set_source_rgba(*self.fill_colors[change[0]])
                context.fill_preserve()
                if self.current_chunk_check(change):
                    highlight = self.fill_colors['current-chunk-highlight']
                    context.set_source_rgba(*highlight)
                    context.fill_preserve()

            context.set_source_rgba(*self.line_colors[change[0]])
            context.stroke()

        textbuffer = self.get_buffer()

        # Check whether we're drawing past the last line in the buffer
        # (i.e., the overscroll) and draw a custom background if so.
        end_y, end_height = self.get_line_yrange(textbuffer.get_end_iter())
        end_y += end_height
        visible_bottom_margin = clip_end - end_y
        if visible_bottom_margin > 0:
            context.rectangle(x + 1, end_y, width - 1, visible_bottom_margin)
            context.set_source_rgba(*self.fill_colors['overscroll'])
            context.fill()

        # Paint current line highlight
        if self.props.highlight_current_line_local and self.is_focus():
            it = textbuffer.get_iter_at_mark(textbuffer.get_insert())
            ypos, line_height = self.get_line_yrange(it)
            context.rectangle(x, ypos, width, line_height)
            context.set_source_rgba(*self.highlight_color)
            context.fill()

        # Draw syncpoint indicator lines
        for syncpoint in self.syncpoints:
            if syncpoint is None:
                continue
            syncline = textbuffer.get_iter_at_mark(syncpoint).get_line()
            if bounds[0] <= syncline <= bounds[1]:
                ypos = self.get_y_for_line_num(syncline)
                context.rectangle(x, ypos - 0.5, width, 1)
                context.set_source_rgba(*self.syncpoint_color)
                context.stroke()

        # Overdraw all animated chunks, and update animation states
        new_anim_chunks = []
        for c in self.animating_chunks:
            current_time = GLib.get_monotonic_time()
            percent = min(
                1.0, (current_time - c.start_time) / float(c.duration))
            rgba_pairs = zip(c.start_rgba, c.end_rgba)
            rgba = [s + (e - s) * percent for s, e in rgba_pairs]

            it = textbuffer.get_iter_at_mark(c.start_mark)
            ystart, _ = self.get_line_yrange(it)
            it = textbuffer.get_iter_at_mark(c.end_mark)
            yend, _ = self.get_line_yrange(it)
            if ystart == yend:
                ystart -= 1

            context.set_source_rgba(*rgba)
            context.rectangle(x, ystart, width, yend - ystart)
            if c.anim_type == TextviewLineAnimationType.stroke:
                context.stroke()
            else:
                context.fill()

            if current_time <= c.start_time + c.duration:
                new_anim_chunks.append(c)
            else:
                textbuffer.delete_mark(c.start_mark)
                textbuffer.delete_mark(c.end_mark)
        self.animating_chunks = new_anim_chunks

        if self.animating_chunks and self.anim_source_id is None:
            def anim_cb():
                self.queue_draw()
                return True
            # Using timeout_add interferes with recalculation of inline
            # highlighting; this mechanism could be improved.
            self.anim_source_id = GLib.idle_add(anim_cb)
        elif not self.animating_chunks and self.anim_source_id:
            GLib.source_remove(self.anim_source_id)
            self.anim_source_id = None

        context.restore()

        return GtkSource.View.do_draw_layer(self, layer, context)

class CommitMessageSourceView(GtkSource.View):

    __gtype_name__ = "CommitMessageSourceView"

    __gsettings_bindings_view__ = (
        ('indent-width', 'tab-width'),
        ('insert-spaces-instead-of-tabs', 'insert-spaces-instead-of-tabs'),
        ('enable-space-drawer', 'enable-space-drawer'),
    )

    enable_space_drawer = GObject.Property(type=bool, default=False)

    def do_realize(self):
        bind_settings(self)

        self.bind_property(
            'enable-space-drawer', self.props.space_drawer, 'enable-matrix',
            GObject.BindingFlags.DEFAULT | GObject.BindingFlags.SYNC_CREATE,
        )

        return GtkSource.View.do_realize(self)

class MeldSourceMap(GtkSource.Map, SourceViewHelperMixin):

    __gtype_name__ = "MeldSourceMap"

    compact_view = GObject.Property(
        type=bool,
        nick="Limit the view to a fixed width",
        default=False,
    )

    COMPACT_MODE_WIDTH = 40

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.connect('notify::compact-view', lambda *args: self.queue_resize())

    def do_draw_layer(self, layer, context):
        if layer != Gtk.TextViewLayer.BELOW_TEXT:
            return GtkSource.Map.do_draw_layer(self, layer, context)

        # Handle bad view assignments and partial initialisation
        parent_view = self.props.view
        if not hasattr(parent_view, 'chunk_iter'):
            return GtkSource.Map.do_draw_layer(self, layer, context)

        context.save()
        context.set_line_width(1.0)

        _, clip = Gdk.cairo_get_clip_rectangle(context)
        x = clip.x - 0.5
        width = clip.width + 1
        bounds = (
            self.get_line_num_for_y(clip.y),
            self.get_line_num_for_y(clip.y + clip.height),
        )

        # Paint chunk backgrounds
        for change in parent_view.chunk_iter(bounds):
            if change[1] == change[2]:
                # We don't have room to paint inserts in this widget
                continue

            ypos0 = self.get_y_for_line_num(change[1])
            ypos1 = self.get_y_for_line_num(change[2])
            height = max(0, ypos1 - ypos0 - 1)

            context.rectangle(x, ypos0 + 0.5, width, height)
            context.set_source_rgba(*parent_view.fill_colors[change[0]])
            context.fill()

        context.restore()

        return GtkSource.Map.do_draw_layer(self, layer, context)

    def do_get_preferred_width(self):
        if self.props.compact_view:
            return (self.COMPACT_MODE_WIDTH, self.COMPACT_MODE_WIDTH)
        else:
            return GtkSource.Map.do_get_preferred_width(self)


matrix = [[int(x) for x in input().split()] for _ in range(int(input()))]

while True:
    token = input()
    if token == 'END':
        [print(*row) for row in matrix]
        exit()
    try:
        com, row, col, val = list(map(lambda x: int(x) if x.isdigit() else x, token.split()))

        if com == 'Add':
            matrix[row][col] += val
        elif com == 'Subtract':
            matrix[row][col] -= val
    except:
        print('Invalid coordinates')

'''
4
1 2 3 4
5 6 7 8
8 7 6 5
4 3 2 1
Add 4 4 100
Add 3 3 100
Subtract -1 -1 42
Subtract 0 0 42
END
------------------------------

Invalid coordinates
-41 2 3 4
5 6 7 8
8 7 6 5
4 3 2 101
'''

3.2 Multidimensional Lists - Exercise 2/02. Matrix Modification.py


import torch
import sklearn.preprocessing

def binarize(T, nb_classes):
    T = T.cpu().numpy()
    T = sklearn.preprocessing.label_binarize(
        T, classes=range(0, nb_classes)
    )
    T = torch.FloatTensor(T)  # .cuda()
    return T

def l2_norm(x):
    input_size = x.size()
    buffer = torch.pow(x, 2)
    normp = torch.sum(buffer, 1).add_(1e-12)
    norm = torch.sqrt(normp)
    _output = torch.div(x, norm.view(-1, 1).expand_as(x))
    output = _output.view(input_size)
    return output

class LinearProjection(torch.nn.Module):
    def __init__(
            self,
            normalize=True,
            nb_classes=10,
            noise="rand",  # rand, dropout
            k=0.1,
            device="cuda"
    ):

        super().__init__()

        self.normalize = normalize
        self.nb_classes = nb_classes
        self.noise = noise
        self.k = k
        self.device = device

    def forward (
            self,
            z1: torch.Tensor,
            labels: torch.Tensor,
    ) -> torch.Tensor:

        linear = torch.nn.Linear(in_features=z1.shape[-1],
                                 out_features=z1.shape[0], bias=False)

        labels_bin = binarize(labels, self.nb_classes).to(self.device)

        # solve with exact solution and append new weights
        z1 = l2_norm(z1) if self.normalize else z1
        with torch.no_grad():
            linear.weight = torch.nn.Parameter(torch.matmul(torch.pinverse(z1), labels_bin).T.detach())

        # add augmentation to the vector
        if self.noise=="rand":
            z2 = torch.rand_like(z1)
            z2 = l2_norm(z2) if self.normalize else z2
            z2 = z1 + (z2 * self.k).detach()
            z2 = l2_norm(z2) if self.normalize else z2
        elif self.noise=="dropout":
            z2 = torch.nn.functional.dropout1d(z1, p=self.k, training=True)
            z2 = l2_norm(z2) if self.normalize else z2

        # run inference and calculate cross-entropy loss
        loss = torch.nn.functional.cross_entropy(input=linear(z2), target=labels)

        return loss


import pandas as pd
from source import Source
from antenna import Antenna
import geometry
from parameters import *

class SourceAntenna(Source, Antenna):
    '''

    :param radar_fn: The path address of the input file of the antenna
    :type radar_fn: str
    :param source_fn: The path address of the input file of the source
    :type source_fn: str
    :param dipole: If the source is a dipole or not. default value is False
    :type dipole: bool
    '''
    def __init__(self,source_fn:str , radar_fn:str , dipole=False):

        # To pass values to parent classes
        Source.__init__(self, source_fn, dipole)
        Antenna.__init__(self,radar_fn)

        # Source to antenna distances
        self.distance, self.path_vec = self.multi_dist()
        print("\x1b[1;31mDistance:\n\x1b[0m", self.distance,
              "\n\x1b[1;31mVector:\n\x1b[0m", self.path_vec )

    def multi_dist(self)->(pd.DataFrame , pd.DataFrame):
        '''
        This function calculates the distance between source/s and antenna/s and also returns a vector of
        source-antenna for every set of source-antenna.

        :returns:
            - dist_arr: the distances from the source to the antenna
            - sa_vec:  the vector from source to the antenna in Cartesian coordinate system (x,y,z).
                        each elements are a list of vector components
        :rtype: pandas.Dataframe
        '''

        dist_arr = pd.DataFrame(np.zeros((self.radar_n, self.n_source)),
                                columns=self.s_columns)
        sa_vec = pd.DataFrame(np.zeros((self.radar_n, self.n_source)),
                              columns=self.s_columns)

        for i in range(self.radar_n):
            for j in range(self.n_source):
                dist_arr.iloc[i, j] = geometry.dist(self.source_location[j, :], self.antenna_location[i, :])
                sa_vec.iloc[[i], j] = pd.Series([-self.source_location[j, :] + self.antenna_location[i, :]], index=[i])
        return dist_arr, sa_vec

    def dipole_transmitter(self):
        '''
        For a far feild a radiation pattern whose electric field of a half-wave dipole antenna  is given by
        https://en.wikipedia.org/wiki/Dipole_antenna#Short_dipole

        we assume that all sources are a dipole which has an angle of theta between
         the direction of dipole and the z direction.
        If you have another assumption you can add it to define theta for each source

        :return:
            - phase: phase part of the generated wave related to the position of the antenna respect to the reference frame
            - e_theta: Generated wave form
        :rtype: Dataframe
        '''

        # the data frame to find the angle of eache dipoles respect to the ray path
        theta = pd.DataFrame(np.zeros([self.radar_n, self.n_source]), columns=self.s_columns)
        for i_s in range(self.n_source):
            for i_a in range(self.radar_n):
                s = self.source_location[i_s]  # The location of sources
                a = self.antenna_location[i_a]  # The location of antennas

                # DE = DC - CE  = DC- AC sin(self.theta_x)
                #               = S_y - S_z * tan(self.theta_z) * sin(self.theta_x)
                dy = s[1] - s[2] * np.tan(self.theta_z) * np.sin(self.theta_x)

                # AK = OD - AE  = OD - AC * cos(self.theta_x)
                #               = S_x - S_z * tan(theta_z) * cos(self.theta_x)
                dx = s[0] - s[2] * np.tan(self.theta_z) * np.cos(self.theta_x)

                p_z0 = np.array([dx, dy, 0])  # The cros section of dipole line and XY plane
                print('XY plane intesection:\n', p_z0)
                dipole_line = p_z0 - s  # Dipole vector

                print('Dipole vector:\n', dipole_line)

                # the angle between the dipole direction and ray path
                # theta = arcsin( a.b / |a| |b|)

                # inner product of dipole vector and the source-antenna vector
                arcsin = np.inner(dipole_line, self.path_vec.iloc[i_a, i_s])
                # |a|= √ (a.a)
                a_len = np.sum(np.square(dipole_line))
                # |b|= √ (b.b)
                b_len = np.sum(np.square(self.path_vec.iloc[i_a, i_s]))
                theta.iloc[i_a, i_s] = np.arcsin(arcsin / np.sqrt(a_len * b_len))

        e_theta = eta * self.I0 * np.cos(0.5 * np.pi * np.cos(theta)) \
                  / (2 * np.pi * np.sin(theta) * self.distance)

        phase = np.cos(0.5 * np.pi * np.cos(theta))/ np.sin(theta)

        print('\x1b[1;31mAangles of dipoles:\n\x1b[0m', np.degrees(theta))

        return e_theta, phase


# Sequence
# There are three basic sequence types: lists, tuples, and range objects.
# Additional sequence types tailored for processing of binary data and text strings are described in dedicated sections.

sequence_list = list([i for i in range(10)])
sequence_tuple = tuple((i for i in range(10)))
sequence_range = range(10)

print('\nSequence')
print('list: {}'.format(sequence_list))
print('tuple: {}'.format(sequence_tuple))
print('range: {}'.format(sequence_range))

# operations

item_to_check = -1

# in
if item_to_check in sequence_list:
    print('{} is in the list'.format(item_to_check))
else:
    print('{} is NOT in the list'.format(item_to_check))

# not in
if item_to_check not in sequence_list:
    print('{} is NOT in the list'.format(item_to_check))
else:
    print('{} is in the list'.format(item_to_check))

# +
list_a = list([i for i in range(10)])
list_b = list([i*10 for i in range(10)])
concatenated = list_a + list_b
print('concatenated list is {}'.format(concatenated))

# *
multiplied = list_a * 2
print('multiplied is {}'.format(multiplied))

# slicing
index = 0
item_at_index = list_a[index]
print('{}th index in the {} is {}'.format(index, list_a, item_at_index))

start_ind = 2
end_ind = 6
sliced_list = list_a[start_ind:end_ind]
print('{} is extracted from {}th to {}th index of the {}'.format(sliced_list, start_ind, end_ind-1, list_a))

step = 2
sliced_list = list_a[start_ind:end_ind:step]
print('{} is every {}th items from {}th to {}th index of the {}'.format(sliced_list, step, start_ind, end_ind-1, list_a))

# muting
replacement = 100
index_to_replace = 3
list_a[index_to_replace] = replacement
print(list_a)

replacement = list([i*100 for i in range(1, 4)])
start_index_to_replace = 3
end_index_to_replace = 6
list_a[start_index_to_replace:end_index_to_replace] = replacement
print(list_a)

start_index_to_delete = 3
end_index_to_delete = 6
del list_a[start_index_to_delete:end_index_to_delete]
print(list_a)

times_to_repeat = 3
list_a *= times_to_repeat
print(list_a)


import simplegui
import random

def arr_len(arr):
    if isinstance(arr, list):
        return len(arr)
    size, _ = arr.buffer_info()
    element_size = arr.itemsize
    length = size // element_size
    return length

class IVector:
    def __init__(self, values):
        self.values = list(values)

    def norm(self):
        return sum(x**2 for x in self.values) ** 0.5

    def __add__(self, other):
        if len(self.values) != len(other.values):
            raise ValueError("Vectors must be the same length")
        return IVector([x + y for x, y in zip(self.values, other.values)])

    def __sub__(self, other):
        if len(self.values) != len(other.values):
            raise ValueError("Vectors must be the same length")
        return IVector([x - y for x, y in zip(self.values, other.values)])

    def __mul__(self, scalar):
        return IVector([x * scalar for x in self.values])

    def __truediv__(self, scalar):
        return IVector([x / scalar for x in self.values])

    def dot(self, other):
        if len(self.values) != len(other.values):
            raise ValueError("Vectors must be the same length")
        return sum(x * y for x, y in zip(self.values, other.values))

    def __str__(self):
        return "Vector({})".format(self.values)

    def cross(self, other):
        if len(self.values) != 3 or len(other.values) != 3:
            raise ValueError("Cross product is only defined for 3-dimensional vectors")
        x1, y1, z1 = self.values
        x2, y2, z2 = other.values
        return IVector([y1 * z2 - y2 * z1, z1 * x2 - z2 * x1, x1 * y2 - x2 * y1])

    def get_values(self):
        return self.values.copy()

    def get_value(self, index):
        return self.values[index]

    def set_value(self, index, new_val):
        self.values[index] = new_val

class Boid:
    def __init__(self, x, y, width, height, color=255):
        self.color = color
        self.width = width
        self.height = height
        self.max_speed = 10
        self.perception = 100
        self.max_force = 1
        self.position = IVector([x, y])
        vec = list([(random.random() - 0.5) * 10, (random.random() - 0.5) * 10])
        self.velocity = IVector(vec)
        vec = list([(random.random() - 0.5) * 10, (random.random() - 0.5) * 10])
        self.acceleration = IVector(vec)

    def update(self):
        self.position += self.velocity
        self.velocity += self.acceleration  # limit
        if self.velocity.norm() > self.max_speed:
            self.velocity = self.velocity / self.velocity.norm() * self.max_speed
        self.acceleration = IVector(list([0, 0]))

    def show(self, canvas):
        color = (
            "rgb("
            + str(self.color)
            + ","
            + str(self.color)
            + ","
            + str(self.color)
            + ")"
        )
        canvas.draw_circle(
            [self.position.get_value(0), self.position.get_value(1)],
            10,
            2,
            "Black",
            color,
        )
        #  stroke(self.color)
        # circle(, 10)

    def edges(self):
        if self.position.get_value(0) > self.width:
            self.position.set_value(0, 0)
        elif self.position.get_value(0) < 0:
            self.position.set_value(0, self.width)
        if self.position.get_value(1) > self.height:
            self.position.set_value(1, 0)
        elif self.position.get_value(1) < 0:
            self.position.set_value(1, self.height)

    def align(self, boids):
        steering = IVector(list([0, 0]))
        total = 0
        avg_vec = IVector(list([0, 0]))
        for boid in boids:
            if (boid.position - self.position).norm() < self.perception:
                avg_vec += boid.velocity
                total += 1
        if total > 0:
            avg_vec /= total
            avg_vec = IVector(avg_vec.get_values())
            avg_vec = (avg_vec / avg_vec.norm()) * self.max_speed
            steering = avg_vec - self.velocity
        return steering

    def cohesion(self, boids):
        steering = IVector(list([0, 0]))
        total = 0
        center_of_mass = IVector(list([0, 0]))
        for boid in boids:
            if (boid.position - self.position).norm() < self.perception:
                center_of_mass += boid.position
                total += 1
        if total > 0:
            center_of_mass /= total
            center_of_mass = IVector(center_of_mass.get_values())
            vec_to_com = center_of_mass - self.position
            if vec_to_com.norm() > 0:
                vec_to_com = (vec_to_com / vec_to_com.norm()) * self.max_speed
            steering = vec_to_com - self.velocity
            if steering.norm() > self.max_force:
                steering = (steering / steering.norm()) * self.max_force
        return steering

    def separation(self, boids):
        steering = IVector(list([0, 0]))
        total = 0
        avg_vector = IVector(list([0, 0]))
        for boid in boids:
            distance = (boid.position - self.position).norm()
            if self.position != boid.position and distance < self.perception:
                diff = self.position - boid.position
                diff /= distance
                avg_vector += diff
                total += 1
        if total > 0:
            avg_vector /= total
            avg_vector = IVector(avg_vector.get_values())
            if steering.norm() > 0:
                avg_vector = (avg_vector / steering.norm()) * self.max_speed
            steering = avg_vector - self.velocity
            if steering.norm() > self.max_force:
                steering = (steering / steering.norm()) * self.max_force
        return steering

    def calm_flocking(self, boids):
        alignment = self.align(boids)
        cohesion = self.cohesion(boids)
        separation = self.separation(boids)
        return alignment * 0.04 + cohesion * 0.02 + separation * 0.02

boids = list()

MAX_WIDTH = 320
MAX_HEIGHT = 240
text_msg = "_"

# Handler for mouse click
def click_separation():
    global text_msg
    text_msg = "Separation"
    pass
def click_alignment():
    global text_msg
    text_msg = "Alignment"
    pass
def click_cohesion():
    global text_msg
    text_msg = "Cohesion"
    pass
def click_calm_flocking():
    global text_msg
    text_msg = "Calm flocking"
    pass
def click_reset():
    global text_msg
    text_msg = "_"
    pass

# Handler to draw on canvas
def draw(canvas):
    canvas.draw_text(text_msg, [MAX_WIDTH - 120, MAX_HEIGHT - 10], 14, "Red")
    for i in range(len(boids)):
        boids[i].update()

        if text_msg == "Separation":
            separation = boids[i].separation(boids)
            boids[i].acceleration += separation * 0.03
        elif text_msg == "Alignment":
            alignment = boids[i].align(boids)
            boids[i].acceleration += alignment * 0.03
        elif text_msg == "Cohesion":
            cohesion = boids[i].cohesion(boids)
            boids[i].acceleration += cohesion * 0.03
        elif text_msg == "Calm flocking":
            calm_flocking = boids[i].calm_flocking(boids)
            boids[i].acceleration += calm_flocking

        boids[i].edges()
        boids[i].show(canvas)

def mouse_handler(pos):
    print("Mouse clicked at", pos[0], pos[1])
    boids.append(Boid(pos[0], pos[1], MAX_WIDTH, MAX_HEIGHT, random.randint(50, 255)))

frame = simplegui.create_frame("Home", MAX_WIDTH, MAX_HEIGHT)
frame.add_button("Separation", click_separation)
frame.add_button("Alignment", click_alignment)
frame.add_button("Cohesion", click_cohesion)
frame.add_button("Calm flocking", click_calm_flocking)
frame.add_button("Reset", click_reset)
frame.set_mouseclick_handler(mouse_handler)
frame.set_draw_handler(draw)

# Start the frame animation
frame.start()


import pygame
import random

pygame.init()
window_size = (900, 600)

screen = pygame.display.set_mode(window_size)
pygame.display.set_caption("Christmas Greeting")
screen.fill((255, 0, 0))
font_color = (255, 255, 255)
font = pygame.font.SysFont("comicsansms", 56)

text = font.render("Merry Christmas!", True, font_color)
text_size = text.get_size()
text_x = (window_size[0] - text_size[0]) // 2
text_y = (window_size[1] - text_size[1]) // 2

snowflakes = []
num_snowflakes = 100
snowflake_size = 5
snowflake_speed = 1

for i in range(num_snowflakes):
    x = random.randint(0, window_size[0])
    y = random.randint(0, window_size[1])

    dx = random.uniform(-snowflake_speed, snowflake_speed)
    dy = random.uniform(snowflake_speed,  3 * snowflake_speed)

    snowflake = (x, y, dx, dy)
    snowflakes.append(snowflake)

running = True
while running:
    screen.fill((255, 0, 0))
    screen.blit(text, (text_x, text_y))
    for snowflake in snowflakes:
        x, y, dx, dy = snowflake
        pygame.draw.circle(screen, (255, 255, 255), (int(x), int(y)), snowflake_size)
    for i in range(num_snowflakes):
        x, y, dx, dy = snowflakes[i]
        x += dx
        y += dy
        if x < 0 or x > window_size[0]:
            dx = -dx
        if y > window_size[1]:
            y = 0
        snowflakes[i] = (x, y, dx, dy)

    pygame.display.flip()