import os
import requests
from bs4 import BeautifulSoup, Tag
from collections import Counter
import re
import string
import nltk
from nltk.corpus import stopwords
from nltk.corpus import words
from nltk.tokenize import word_tokenize
from gensim.models import Word2Vec
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import tempfile
import gradio as gr
import openai
from googlesearch import search
from pytrends.request import TrendReq
from sklearn.manifold import MDS, TSNE
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.cluster import KMeans
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from IPython.display import HTML
import numpy as np
import matplotlib.cm as cm
from urllib.parse import urlparse, urljoin
import os
from celery import Celery

nltk.download('stopwords')
nltk.download('punkt')
nltk.download('words')

# Set your OpenAI API key here
openai.api_key = os.environ['OPENAI_API_KEY']

#@title Define functions

def get_image_html(fig):
    buf = io.BytesIO()
    fig.savefig(buf, format='png')
    buf.seek(0)
    return ''.format(base64.b64encode(buf.getvalue()).decode('ascii'))

def search_top_competitors(keywords, num_results=10):
    competitors = set()
    for keyword in keywords:
        for url in search(keyword, num_results=num_results):
            competitors.add(url)
    return list(competitors)

def get_page_content(url):
    response = requests.get(url)
    return BeautifulSoup(response.text, 'html.parser')

def get_meta_tags(soup):
    meta_tags = soup.find_all('meta')
    return {tag.get('name'): tag.get('content') for tag in meta_tags if tag.get('name')}

def get_heading_tags(soup):
    headings = {}
    for tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']:
        headings[tag] = [heading.text for heading in soup.find_all(tag)]
    return headings

def analyze_keywords(keywords_counter, top_n=10):
    return keywords_counter.most_common(top_n)

def visualize_keywords(keywords_counter, top_n=10):
    common_keywords = analyze_keywords(keywords_counter, top_n)
    df = pd.DataFrame(common_keywords, columns=['Keyword', 'Count'])
    df.set_index('Keyword', inplace=True)
    df.plot(kind='bar', figsize=(12, 6))
    plt.title('Top Keywords')
    plt.xlabel('Keywords')
    plt.ylabel('Frequency')

    fig = plt.gcf()  # Get the current figure

    plt.tight_layout()
    temp_image_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
    plt.savefig(temp_image_file.name, format='png')
    plt.close()
    return temp_image_file.name

def plot_trends(keywords):
  pytrends = TrendReq(hl='en-US', tz=360, retries=3)
  pytrends.build_payload(keywords, cat=0, timeframe='today 12-m', geo='', gprop='')
  trends_data = pytrends.interest_over_time()
  return trends_data

def preprocess_text(text, min_word_length=3):
    stop_words = set(stopwords.words('english'))
    words = word_tokenize(text.lower())
    words = [word for word in words if word.isalnum()]
    words = [word for word in words if len(word) >= min_word_length and word not in stop_words]
    return words

def visualize_clusters(words, model):
    matrix = np.zeros((len(words), model.vector_size))

    for i, word in enumerate(words):
        matrix[i, :] = model.wv[word]

    mds = MDS(n_components=2, dissimilarity='precomputed', random_state=42)
    distance_matrix = 1 - cosine_similarity(matrix)
    coords = mds.fit_transform(distance_matrix)

    x, y = coords[:, 0], coords[:, 1]

    for i, word in enumerate(words):
        plt.scatter(x[i], y[i], alpha=0.5)
        plt.text(x[i], y[i], word, fontsize=10)

    plt.title('Word Clusters based on Thematic Relatedness')
    plt.show()

def create_cluster_table(words, model, clusters):
    matrix = np.zeros((len(words), model.vector_size))

    for i, word in enumerate(words):
        matrix[i, :] = model.wv[word]

    # Create a dictionary to store words per cluster
    cluster_dict = {}
    for i, word in enumerate(words):
        cluster_id = clusters[i]
        if cluster_id not in cluster_dict:
            cluster_dict[cluster_id] = []
        cluster_dict[cluster_id].append(word)

    # Create a DataFrame from the dictionary
    max_words = max(len(cluster_words) for cluster_words in cluster_dict.values())
    num_clusters = len(cluster_dict)
    data = {f"Cluster {i}": cluster_dict.get(i, []) + [None] * (max_words - len(cluster_dict.get(i, [])))
            for i in range(num_clusters)}

    df = pd.DataFrame(data)
    return df

def clean_text(text):
    # Separate words that are meant to be separated
    text = re.sub(r'([a-z])([A-Z])', r'\1 \2', text)

    # Tokenize the text
    tokens = nltk.word_tokenize(text)

    # Remove nonsensical words
    try:
      english_words = set(words)
    except:
      english_words = set(words.words())
    clean_tokens = [token for token in tokens if token.lower() in english_words or token.istitle()]

    # Join tokens back into a string
    clean_text = ' '.join(clean_tokens)

    return clean_text

def visualize_clusters_og(words, model):
    matrix = np.zeros((len(words), model.vector_size))

    for i, word in enumerate(words):
        matrix[i, :] = model.wv[word]

    n_clusters = 5
    kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
    clusters = kmeans.fit_predict(matrix)

    tsne = TSNE(n_components=2, random_state=42)
    coords = tsne.fit_transform(matrix)

    x, y = coords[:, 0], coords[:, 1]

    colors = cm.rainbow(np.linspace(0, 1, n_clusters))

    plt.figure(figsize=(8, 8))
    for i, word in enumerate(words):
        plt.scatter(x[i], y[i], c=[colors[clusters[i]]], alpha=0.7)
        plt.text(x[i], y[i], word, fontsize=10)

    plt.xticks([])
    plt.yticks([])
    plt.title('Word Clusters based on Thematic Relatedness')
    plt.show()

def visualize_clusters_plot(words, model):
    matrix = np.zeros((len(words), model.vector_size))

    for i, word in enumerate(words):
        matrix[i, :] = model.wv[word]

    n_clusters = 4
    kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init=10)
    clusters = kmeans.fit_predict(matrix)

    try:
        tsne = TSNE(n_components=2, random_state=42)
        coords = tsne.fit_transform(matrix)
    except ValueError:
        max_perplexity = len(words) - 1
        tsne = TSNE(n_components=2, random_state=42, perplexity=max_perplexity)
        coords = tsne.fit_transform(matrix)

    x, y = coords[:, 0], coords[:, 1]

    colors = cm.rainbow(np.linspace(0, 1, n_clusters))

    fig, axs = plt.subplots(2, 2, figsize=(8, 8), gridspec_kw={'width_ratios': [sum(clusters == 0) + sum(clusters == 1), sum(clusters == 2) + sum(clusters == 3)], 'height_ratios': [sum(clusters == 0) + sum(clusters == 2), sum(clusters == 1) + sum(clusters == 3)]})
    fig.subplots_adjust(wspace=0, hspace=0)

    for ax in axs.ravel():
        ax.axis('off')

    for i, word in enumerate(words):
        cluster_idx = clusters[i]
        ax = axs[cluster_idx // 2, cluster_idx % 2]
        ax.scatter(x[i], y[i], c=[colors[cluster_idx]], alpha=0.7)
        ax.text(x[i], y[i], word, fontsize=10)

    plt.legend(loc="best", fontsize=13)
    plt.tight_layout()
    temp_image_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
    plt.savefig(temp_image_file.name, format='png')
    plt.close()
    return temp_image_file.name, clusters

def sanitize_url(url):
    if not re.match('^(http|https)://', url):
        url = 'http://' + url

    if not re.match('^(http|https)://www\.', url):
        url = re.sub('^(http|https)://', r'\g<0>www.', url)

    return url

# Configure the Celery app
app = Celery("tasks", broker=os.environ['REDIS_URL'], backend=os.environ['REDIS_URL'])

# Define the inputs and outputs
competitor_url_input = gr.inputs.Textbox(label="Competitor URL", placeholder="Enter a competitor URL")

full_site_scrape_checkbox = gr.inputs.Checkbox(label="Tick for full site scrape (otherwise landing page only)")

meta_tags_output = gr.outputs.Textbox(label="Meta Tags")
heading_tags_output = gr.outputs.Textbox(label="Heading Tags")
top10keywords_output = gr.outputs.Textbox(label="Top 10 Keywords")
cluster_table_output = gr.outputs.HTML(label="Cluster Table")
cluster_plot_output = gr.outputs.Image(type='filepath', label="Cluster Plot")
keyword_plot_output = gr.outputs.Image(type='filepath', label="Keyword Plot")
seo_analysis_output = gr.outputs.Textbox(label="SEO Analysis")

def append_unique_elements(source, target):
    for element in source:
        if isinstance(element, Tag) and element not in target:
            target.append(element)

def get_internal_links(url: str):
    response = requests.get(url)
    soup = BeautifulSoup(response.content, "html.parser")
    internal_links = set()

    for link in soup.find_all("a"):
        href = link.get("href")

        if href:
            joined_url = urljoin(url, href)
            parsed_url = urlparse(joined_url)

            if parsed_url.netloc == urlparse(url).netloc:
                internal_links.add(joined_url)

    return internal_links

def analyze_single_page(competitor_url: str):
    sanitized_url = sanitize_url(competitor_url)
    soup = get_page_content(sanitized_url)

    # Scrape and analyze meta tags
    meta_tags = get_meta_tags(soup)
    topmetatags = ""
    for name, content in meta_tags.items():
        if "description" in name.lower():
            topmetatags += (f"{name}: {content}\n")

    # Scrape and analyze heading tags
    heading_tags = get_heading_tags(soup)
    topheadingtags = ""
    for tag, headings in heading_tags.items():
        filtered_headings = [heading for heading in headings if len(heading) > 2]
        if filtered_headings:
            topheadingtags += (f"{tag}: {', '.join(filtered_headings)}\n")

    # Scrape, analyze, and visualize keywords from page content
    page_text = soup.get_text()
    page_text_cleaned = clean_text(page_text)
    preprocessed_text = preprocess_text(page_text_cleaned)

    keywords_counter = Counter(preprocessed_text)
    top10keywords = ""

    for keyword, count in analyze_keywords(keywords_counter, top_n=10):
        top10keywords += (f"{keyword}: {count}\n")

    # Semantic clustering and visualization
    sentences = [preprocessed_text[i:i+10] for i in range(0, len(preprocessed_text), 10)]
    model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4)

    words = [word for word, _ in analyze_keywords(keywords_counter, top_n=50)]
    clusters = [model.wv.doesnt_match(words)] * len(words)

    cluster_plot,clusters = visualize_clusters_plot(words, model)
    cluster_table = create_cluster_table(words, model, clusters)
    keyword_plot = visualize_keywords(keywords_counter, top_n=10)

    table_string = cluster_table.to_string(index=False)
    SEO_prompt = f"""The following information is given about a company's website:

      Meta Tags:
      {{meta_tags}}

      Heading Tags:
      {{heading_tags}}

      Top 10 Keywords:
      {{top10keywords}}

      The following table represents clusters of thematically related words identified using NLP and clustering techniques. Each column represents a different cluster, and the words in each column are thematically related.

      {table_string}

      Please analyze the provided information and perform the following tasks:
      1. Predict what the website is all about (the market sector).
      2. Based on the market sector of the company, give a name to each cluster based on the theme it represents. The name needs to be the best summary of all the words in the cluster.
      3. Perform a SWOT analysis (Strengths, Weaknesses, Opportunities, and Threats) from an SEO perspective for the company as a whole, taking into account the meta tags, heading tags, top 10 keywords, and the clusters.
      Please provide your analysis in a clear and concise manner.
      4. Lastly, suggest a list of 5 single words and 5 phrases (no longer than 3 words each) that the company should be using to improve their SEO
      """.format(meta_tags=meta_tags, heading_tags=heading_tags, top10keywords=top10keywords, table_string=table_string)

    def analyse_SEO(SEO_prompt):
      response = openai.Completion.create(
      model="text-davinci-003",
      prompt = SEO_prompt,
      temperature=0.7,
      max_tokens=1000,
      top_p=1,
      frequency_penalty=0,
      presence_penalty=0
      )
      gpt3_response = response.get('choices')[0].text
      return gpt3_response,response

    seo_analysis = analyse_SEO(SEO_prompt)

    return topmetatags, topheadingtags, top10keywords, cluster_table.to_html(), cluster_plot, keyword_plot, seo_analysis[0]

# Wrap the analyze_website function with the Celery app.task decorator
@app.task
def analyze_website_task(competitor_url: str, full_site_scrape: bool = False):
    if not full_site_scrape:
        topmetatags, topheadingtags, top10keywords, cluster_table, cluster_plot, keyword_plot, seo_analysis = analyze_single_page(competitor_url)
        return topmetatags, topheadingtags, top10keywords, cluster_table, cluster_plot, keyword_plot, seo_analysis

    sanitized_url = sanitize_url(competitor_url)
    internal_links = get_internal_links(sanitized_url)
    soup_collection = BeautifulSoup("", "html.parser")

    for link in internal_links:
        try:
            soup = get_page_content(link)
            append_unique_elements(soup.head, soup_collection.head)
            append_unique_elements(soup.body, soup_collection.body)
        except Exception as e:
            print(f"Failed to analyze link: {link}. Error: {e}")

    print('got all the links')

    # Scrape and analyze meta tags
    meta_tags = get_meta_tags(soup_collection)
    topmetatags = ""
    for name, content in meta_tags.items():
        if "description" in name.lower():
            topmetatags += (f"{name}: {content}\n")

    print('fetched metatags')

    # Scrape and analyze heading tags
    heading_tags = get_heading_tags(soup_collection)
    topheadingtags = ""
    for tag, headings in heading_tags.items():
        filtered_headings = [heading for heading in headings if len(heading) > 2]
        if filtered_headings:
            topheadingtags += (f"{tag}: {', '.join(filtered_headings)}\n")

    print("fetched heading tags")

    # Scrape, analyze, and visualize keywords from page content
    page_text = soup_collection.get_text()
    page_text_cleaned = clean_text(page_text)
    preprocessed_text = preprocess_text(page_text_cleaned)

    keywords_counter = Counter(preprocessed_text)
    top10keywords = ""

    for keyword, count in analyze_keywords(keywords_counter, top_n=10):
        top10keywords += (f"{keyword}: {count}\n")

    print("fetched keywords")

    # Semantic clustering and visualization
    sentences = [preprocessed_text[i:i+10] for i in range(0, len(preprocessed_text), 10)]
    model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4)

    words = [word for word, _ in analyze_keywords(keywords_counter, top_n=50)]
    clusters = [model.wv.doesnt_match(words)] * len(words)

    print("calculated clusters")

    cluster_plot,clusters = visualize_clusters_plot(words, model)
    cluster_table = create_cluster_table(words, model, clusters)
    keyword_plot = visualize_keywords(keywords_counter, top_n=10)

    print("plotted figures")

    table_string = cluster_table.to_string(index=False)

    print("created table string")

    heading_tags_compressed = {}

    for key, values in heading_tags.items():
        count = Counter(values)
        sorted_values = sorted(count.keys(), key=lambda x: count[x], reverse=True)
        filtered_values = [value for value in sorted_values if value.strip() != ""]
        heading_tags_compressed[key] = filtered_values[:10]

    heading_tags_clean = {}

    for key, values in heading_tags.items():
        count = Counter(values)
        sorted_values_clean = sorted(count.keys(), key=lambda x: count[x], reverse=True)
        heading_tags_clean = [value for value in sorted_values_clean if value.strip() != ""]

    print("cleaned up heading tags")

    SEO_prompt = f"""The following information is given about a company's website:

      Meta Tags:
      {{meta_tags}}

      Heading Tags:
      {{heading_tags_compressed}}

      Top 10 Keywords:
      {{top10keywords}}

      The following table represents clusters of thematically related words identified using NLP and clustering techniques. Each column represents a different cluster, and the words in each column are thematically related.

      {table_string}

      Please analyze the provided information and perform the following tasks:
      1. Predict what the website is all about (the market sector).
      2. Based on the market sector of the company, give a name to each cluster based on the theme it represents. The name needs to be the best summary of all the words in the cluster.
      3. Perform a SWOT analysis (Strengths, Weaknesses, Opportunities, and Threats) from an SEO perspective for the company as a whole, taking into account the meta tags, heading tags, top 10 keywords, and the clusters.
      Please provide your analysis in a clear and concise manner.
      4. Lastly, suggest a list of 10 words and 10 phrases that the company should be using to improve their SEO
      """.format(meta_tags=meta_tags, heading_tags_compressed=heading_tags_compressed, top10keywords=top10keywords, table_string=table_string)

    print("defined SEO prompt")

    def analyse_SEO(SEO_prompt):
      response = openai.Completion.create(
      model="text-davinci-003",
      prompt = SEO_prompt,
      temperature=0.7,
      max_tokens=1000,
      top_p=1,
      frequency_penalty=0,
      presence_penalty=0
      )
      gpt3_response = response.get('choices')[0].text
      return gpt3_response,response

    seo_analysis = analyse_SEO(SEO_prompt)

    print("ran seo analysis")

    print(topmetatags, heading_tags_clean,top10keywords,cluster_table.to_html(), cluster_plot, keyword_plot,seo_analysis[0])

    return topmetatags, heading_tags_clean, top10keywords, cluster_table.to_html(), cluster_plot, keyword_plot, seo_analysis[0]

gr.Interface(
    fn=analyze_website_task,
    inputs=[competitor_url_input, full_site_scrape_checkbox],
    outputs=[
        meta_tags_output,
        heading_tags_output,
        top10keywords_output,
        cluster_table_output,
        cluster_plot_output,
        keyword_plot_output,
        seo_analysis_output,
    ],
    title="SEO Analysis Tool",
    description="Enter a competitor URL to perform a SEO analysis (some javascript pages will deny full scrape).",
    layout="vertical"
).launch(share=True,debug=True)


#!python
"""
The number 145 is well known for the property that the sum of the factorial of its digits is equal to 145:

1! + 4! + 5! = 1 + 24 + 120 = 145

Perhaps less well known is 169, in that it produces the longest chain of numbers that link back to 169; it turns out that there are only three such loops that exist:

169 → 363601 → 1454 → 169
871 → 45361 → 871
872 → 45362 → 872

It is not difficult to prove that EVERY starting number will eventually get stuck in a loop. For example,

69 → 363600 → 1454 → 169 → 363601 (→ 1454)
78 → 45360 → 871 → 45361 (→ 871)
540 → 145 (→ 145)

Starting with 69 produces a chain of five non-repeating terms, but the longest non-repeating chain with a starting number below one million is sixty terms.

How many chains, with a starting number below one million, contain exactly sixty non-repeating terms?
"""

from math import factorial

def next_term(n):
	return sum(map(factorial, map(int, list(str(n)))))

def non_repeating_term_count(n):
	terms = set([])
	while n not in terms:
		terms.add(n)
		n = next_term(n)
	return len(terms)

targets = []

for i in range(1000000):
	if non_repeating_term_count(i)==60:
		print(i)
		targets.append(i)

print(len(targets))


import tkinter as tk

import customtkinter as ctk
from customtkinter import ThemeManager

from View.GUI.CustomWidgets.NotebookCloseableTabs import NotebookCloseableTabs
from View.GUI.Windows.ResultWindow.ComputationStatusBoard import ComputationStatusBoard
from View.Observer import Observer

class ComputationNotebook(NotebookCloseableTabs, Observer):

    def __init__(self, parent, computation, controller):
        fg_color = ThemeManager.theme["color_scale"]["inner"]
        super().__init__(parent, color_notebook_bg=fg_color)

        self.add_widget(ComputationStatusBoard(self, computation, controller), "Status Board")
        self.results = []
        self.handler_id = None
        self.subscribed_results = []

        Observer.__init__(self, computation)
        for result in computation.results:
            if result.is_finished:
                self.results.append(result)
            else:
                result.subscribe(self)
                self.subscribed_results.append(result)
        self.handle_tasks()

    def update_(self, updated_component):
        if updated_component[1] == "finished_result":
            result = updated_component[0]
            self.results.append(result)

    def start_task_handler(self):
        """
        Starts the task handler.
        """
        self.handler_id = self.after(2000, self.handle_tasks)

    def handle_tasks(self):
        """
        Handles received results.
        """
        for result in list(self.results):
            self.add_result(result)
            self.results.remove(result)

        self.start_task_handler()

    def destroy(self):
        self.after_cancel(self.handler_id)
        self.observed_subject.unsubscribe(self)
        self.observed_subject = None
        for result in self.subscribed_results:
            result.unsubscribe(self)
        self.subscribed_results.clear()
        super().destroy()

    def add_result(self, result):
        """
        Adds results to the notebook.

        :param result: result object
        """
        fg_color = ThemeManager.theme["color_scale"]["inner"]
        textbox = ctk.CTkTextbox(self, fg_color=fg_color, bg_color=fg_color, wrap="word")
        textbox.insert(tk.END, result.result_text)
        self.add_widget(textbox, result.configuration_name)


def bub(l1: list):
    n = len(l1)
    for i in range(n):
        flag = True
        for j in range(n-1-i):
            if l1[j] > l1[j+1]:
                l1[j], l1[j+1] = l1[j+1], l1[j]
                flag = False
        if flag:
            break
    return l1

if __name__ == "__main__":
    l = ['12', '34', '5']

    t = tuple(map(list, list(set(l))))
    print(t)

    # print(bub([4, 3, 8, 2, 6]))
    a = ["hacker", "earth", "1", "2", "python", "language", "10"]
    b = a[0::2]
    c = a[1::2]
    d = zip(b,c)
    #print(dict(d))


from ply.lex import LexToken

from windyquery.validator import ValidationError
from ._base import Base

TOKEN = 'SCHEMA'

class SchemaToken(LexToken):
    def __init__(self, value):
        self.type = TOKEN
        self.value = value
        self.lineno = 0
        self.lexpos = 0

class Schema(Base):
    def schema(self, s: str):
        try:
            s = self.validator.validate_schema(s)
        except ValidationError as err:
            raise UserWarning(f'invalid schema: {err}') from None
        self.append(SchemaToken(s))


import time
from datetime import timedelta

import requests
from celery import Celery
from celery.utils.log import get_task_logger

app = Celery('parsing')
app.conf.update(broker_url='amqp://guest:guest@rabbitmq:5672', broker_connection_retry_on_startup=True)
app.conf.beat_schedule = {
    'add-every-monday-morning': {
        'task': 'parsing',
        'schedule': timedelta(seconds=15)
    },
}
# crontab(seconds='*/15')
celery_logger = get_task_logger(__name__)

@app.task(name='parsing')
def parse_excel_task():
    time.sleep(5)
    print('zalupa')
    celery_logger.info('parsing')
    requests.post('http://api:8000/api/v1/parser/parse-excel')


"""
Programma per la determinazione delle tautologie
"""

L = ["&","%",">","-","!"] #And, Or, Implica, Se e solo se (bicondizionale), Negazione
F = []
semF = {"&" : [ [False,True],[True,False], [False,False] ],
       "%" : [ [False,False] ],
       ">" : [ [True,False] ],
       "-" : [ [False,True],[True,False] ],
       "!" : [ [True] ]
    } #Dominio delle coppie di valori che danno valori falsi alle cinque funzioni logiche

semV = {"&" : [ [True,True] ],
       "%" : [ [True,False], [False, True], [True,True] ],
       ">" : [ [True,True], [False, True], [False, False] ],
       "-" : [ [True,True], [False,False] ],
       "!" : [ [False] ]
    } #Dominio delle coppie di valori che danno valori falsi alle cinque funzioni logiche

lettereEnunciativeF = []
global checkAssegnamenti
checkAssegnamenti = False

def isLenun(p): #Determina se p è una lettera enunciativa
    for i in L: #Se non vi sono connettori la formula è una lettera enunciativa
        if i in p:
            return False
    return True

def creaAssegnamento(lettere):
    #Crea un assegnamento con tutte le lettere enunciative, di default settate su True
    #Questa funzione serve solitamente per creare un assegnamento qualsiasi per testare se una formula è sempre vera o sempre falsa.
    ass = {}
    for i in lettere:
        ass[i]=True
    return ass

def leggiAssegnamento(ass):
    #Legge un assegnamento che è una stringa del tipo a:0 - b:1 - ecc // 0 è False e 1 è true
    ass = ass.replace(" ", "") #fa il trim
    assegnamento = dict()
    ass = ass.split("-") #trasforma ass in una lista
    for i in ass:
        i = i.split(":")
        assegnamento[i[0]] = bool(int(i[1])) #In Pyton il bool di una stringa è riferito alla sua lunghezza e quindi è sempre True a meno che non sia nulla
    return assegnamento

def lettereEnunciative(p):
    #Crea un assegnamento contenente tutte le lettere enunciative di p
     p = p.replace(" ", "") #Fa un trim sulla stringa
     lenuns = []
     start= 0
     control = False
     for i in range(len(p)):
         print("len p=", len(p))
         print("ciclo ",i, "control = ", control)
         if p[i] in (["(",")"] + L):
            print("Trovato simbolo")
            if control:
                print("lettera enunciativa")

                lenuns.append(p[start:i])
                start = i+1
                control = False
            continue
         if not control: start = i
         control = True
     if control: #Se termina senza parentesi lascia fuori l'ultima lettera enunciativa
         lenuns.append(p[start:len(p)])
     return lenuns

def checkParentesi(p):
    #Controlla se non ci siano delle parentesi esterne superflue
    barra = 0
    parSup = True
    if not(p.startswith("(") and p.endswith(")") ): return p #se non inizia e finisce con delle parentesi certamente non è chiuso tra partentesi superflue
    test = p[1:len(p)-1] #elimina la prima e l'ultima partentesi e controlla se la formula ha ancora senso
    for i in test:
        if not i in ["(",")"]: continue
        if i == "(":
            barra+=1
        elif i == ")":
            barra-=1
        if barra<0:
            parSup = False
            break

##    if parSup: #Se le parentesi esterne erano superflue, restituisce la versione senza di esse, altrimenti restituisce p
##        print("Parentesi superflue. Versione migliorata: ", test)
##    else:
##        print("Parentesi non superflue. Restituisco ", p)

    if parSup: #Se le parentesi esterne erano superflue, restituisce la versione senza di esse, altrimenti restituisce p
        return test
    else:
        return p

def computa(p): #p è la formula, f l'insieme delle formule
    counter=0
    start = 0
    index=0
    par =False

    f = []

    p = p.replace(" ", "") #Fa un trim sulla stringa

    if isLenun(p): #Se la formula è una lettera enunciativa allora ritorna False
        f.append(p)
        if checkAssegnamenti and not p in lettereEnunciativeF :
            lettereEnunciativeF.append(p) #Inserisce la lettera nella lista relativa per il check finale
        return False

    p = checkParentesi(p)

    if p[0] == "!": #Se il primo simbolo è la negazione allora si risolve tutto immediatamente
        f.append(p[1:])
        f.append("!")
        return f

    for i in p:
        index+=1
        if i=="(":
            if not par: start= index #Se è la prima parentesi aperta allora posiziona lo start in quel punto.
            par = True #Indica che ha trovato parentesi aperte
            counter+=1
        elif i==")":
            counter-=1
        if counter == 0 and par:
            par = False
            counter = 0
            f.append(p[start:index-1]) #Aggiunge la funzione alla lista delle funzioni
            #Se ha appena inserito una formula, significa che subito dopo ci deve essere un operatore, altrimenti la formula non è ben formata
            if len(f)==1:
                if p[index] in L:
                    f.append(p[index]) #Aggiunge l'operatore
                    start = index
                else:
                    print("ERRORE: formula non ben formata")
                    return None
    if len(f)<3:
        f.append(p[start+1:index])

    return f

def computaricorsiva(f):
    #f deve essere un vettore di due o tre elementi del tipo (a, operatore binario, b) o (a, negazione)
    x = computa(f[0]) #Primo ramo
    if x != False:
        f[0] = x
        f[0] = computaricorsiva(f[0])
    if len(f)>2: #Se non si tratta di una negazione valuta anche la seconda formula
        x = computa(f[2])
        if x != False:
            f[2] = x
            f[2] = computaricorsiva(f[2])
    return f

def isTautologia(f, val): #f è la funzione da valutare, val il valore che deve avere, dominio è l'insieme dei valori necessari delle lettere enunciative
    #La funzione ritorna True se è una tautologia, o il dominio se non lo è

    if isLenun(f): #Se è una lettera enunciativa l'unico assegnamento è il suo valore
        return [ {f : val} ]

    assegnamenti = []
    condizione = []
    if val:
        condizione = semV[f[1]]
    else:
        condizione = semF[f[1]]

    print("\nLe condizioni per ", (f,val), " sono: ", condizione)

    for cond in condizione: #Cond è una lista di coppie ordinate di True, False e None. None sta ad indicare che non importa il valore di quell'assegnamento
        print("\nEsamino la condizione: ", cond, " per ", f)
        x = isTautologia(f[0], cond[0])
        if x == []: #Se x è un insieme vuoto allora f[0] è una tautologia o una formula sempre falsa. Questo implica che non è nemmeno necessario valutare l'altra formula. f non può sostenere questa configurazione
            continue

        if len(f) <= 2 or cond[1] == None: #Se la funzione è solo una negazione, allora non possiede un altro ramo da valutare. Anche se non è necessario valoutare il ramo (cond = None) si passa avanti
            assegnamenti += x #Inserisce direttamente l'assegnamento tra quelli coerenti
            continue
        y = isTautologia(f[2], cond[1])
        if y == []: #Se y è un insieme vuoto allora f[0] è una tautologia o una formula sempre falsa.
            continue

        print("\nConfronto assegnamenti per", f, "\nGli assegnamenti sono:",x,y)
        ass = confrontaAssegnamenti([x,y])

        assegnamenti += ass
        print("\nAssegnamenti coerenti: ", ass)

    print("\nAssegnamenti: ", assegnamenti)
    #Infine si passa a valutare la compatibilità degli assegnamenti

    return assegnamenti

def confrontaAssegnamenti(d):
    #Da una lista di due classi di assegnamenti, d, opera un confronto e restituisce soltanto gli assegnameti compatibili tra loro
    # d è composto da assegnamenti parziali, che non ricopriono tutti i valori delle lettere enunciative
    ass = []

    if d[0] == []: #E' possibile che uno dei due tronconi sia completamente vuoto. In questo caso restituisce direttamente gli assegnamenti
        return d[1]
    elif d[1] == []:
        return d[0]

    for a1 in d[0]:
        for a2 in d[1]:
            assegnamento = dict()
            incompatibile = False

            for i in a1:
                #print(i, a1[i], a2[i])
                if (not(i in a2)) or (a1[i] == a2[i]): #Se in a2 non c'è la lettera enunciativa, o se ha lo stesso valore
                    assegnamento[i] = a1[i]
                else: #Se vi è una contraddizione tra i valori necessari allora i due assegnamenti a1 e a2 sono incompatibili
                    incompatibile = True
                    break #Passa al prossimo dizionario da confrontare

            if not incompatibile: #Esamina anche gli elementi di a2, che potrebbero non essere nell'assegnamento
                for i in a2:
                    if (not(i in a1)): #Se in a1 non c'è la lettera enunciativa
                        assegnamento[i] = a2[i]
            if not incompatibile:
                ass.append(assegnamento)
    return ass

def Valuta(f, ass): #valuta una formula usando l'assegnamento dato

    if isLenun(f):
        return ass[f]

    #Primo ramo
    A = Valuta(f[0], ass)

    if len(f) <=2:  #Se è una negazione, il suo valore sarà necessariamente il contrario valore di A
        return not A

    #Secondo ramo
    B = Valuta(f[0],ass)

    #Valuta il valore finale. f[1] è il connettivo
    if [A,B] in semV[f[1]]:
        return True
    else:
        return False

# FUNZIONI DI TEST

def testcomputa():
    frase = input("Frase: ")
    formule = computaricorsiva(computa(frase))
    #formule = computa(frase, [])
    print(formule)

def testvalore():
     global checkAssegnamenti
     checkAssegnamenti = True
     frase = input("Frase: ")
     formule = computaricorsiva(computa(frase))
     print ("L'albero è: ", formule)
     print("Le lettere enunciative sono", lettereEnunciativeF)
     x = isTautologia(formule, False)
     if len(x)>0:
         print("I contromodelli sono: ", x, "\nNon è una tautologia")
     else:
         if Valuta(formule, creaAssegnamento(lettereEnunciativeF)):
             print("\nNon ci sono contromodelli: ", x, "\nE' una tautologia")
         else:
             print("\nNon ci sono modelli che la rendano vera: ", x, "\nE' sempre falsa")

def testparentesi():
    frase = input("Frase: ")
    checkParentesi(frase)

def testvaluta():
    global checkAssegnamenti
    checkAssegnamenti = True
    frase = input("Frase: ")
    ass = input("Scrivere l'assegnamento rispettando la seguente forma: a:1 - b:0 - ecc\nRicorda che 0 è False e 1 è True\n Assegnamento: ")
    ass = leggiAssegnamento(ass)
    print("L'assegnamento è ", ass)
    formule = computaricorsiva(computa(frase))
    x = Valuta(formule, ass)
    print("\nIl valore finale è ", x)

def main():
    while(True):
        global checkAssegnamenti
        checkAssegnamenti = False
        testvalore()
        if input("Continua? y/n") !="y": break

main()


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

t = np.linspace(0, 2*np.pi, 20)
p = np.linspace(0,   np.pi, 10)

theta,phi = np.meshgrid(t,p)

x = np.cos(theta)*np.sin(phi)
y = np.sin(theta)*np.sin(phi)
z = np.cos(phi)

fig = plt.figure(figsize=(10,4))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122, projection='3d')

ax1.plot(theta.flatten(), phi.flatten(), 'o')
ax1.set_xlabel("$\\theta$")
ax1.set_ylabel("$\\phi$")

ax2.plot_surface(x,y,z, edgecolors='0.2')

plt.show()


# ----------------------------------------------------------------------
# |
# |  Setup_custom.py
# |
# |  David Brownell <db@DavidBrownell.com>
# |      2022-10-14 12:37:50
# |
# ----------------------------------------------------------------------
# |
# |  Copyright David Brownell 2022
# |  Distributed under the Boost Software License, Version 1.0. See
# |  accompanying file LICENSE_1_0.txt or copy at
# |  http://www.boost.org/LICENSE_1_0.txt.
# |
# ----------------------------------------------------------------------
# pylint: disable=missing-module-docstring

import copy
import os
import uuid
import sys
import textwrap

from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union

from semantic_version import Version as SemVer          # pylint: disable=unused-import

from Common_Foundation.ContextlibEx import ExitStack                        # type: ignore  # pylint: disable=import-error,unused-import
from Common_Foundation import PathEx                                        # type: ignore  # pylint: disable=import-error,unused-import
from Common_Foundation.Shell.All import CurrentShell                        # type: ignore  # pylint: disable=import-error,unused-import
from Common_Foundation.Shell import Commands                                # type: ignore  # pylint: disable=import-error,unused-import
from Common_Foundation.Streams.DoneManager import DoneManager               # type: ignore  # pylint: disable=import-error,unused-import
from Common_Foundation import SubprocessEx                                  # type: ignore  # pylint: disable=import-error,unused-import
from Common_Foundation import TextwrapEx                                    # type: ignore  # pylint: disable=import-error,unused-import
from Common_Foundation import Types                                         # type: ignore  # pylint: disable=import-error,unused-import

from RepositoryBootstrap import Configuration                               # type: ignore  # pylint: disable=import-error,unused-import
from RepositoryBootstrap import Constants                                   # type: ignore  # pylint: disable=import-error,unused-import
from RepositoryBootstrap.SetupAndActivate.Installers.DownloadNSISInstaller import DownloadNSISInstaller             # type: ignore  # pylint: disable=import-error,unused-import
from RepositoryBootstrap.SetupAndActivate.Installers.DownloadSevenZipInstaller import DownloadSevenZipInstaller     # type: ignore  # pylint: disable=import-error,unused-import
from RepositoryBootstrap.SetupAndActivate.Installers.DownloadZipInstaller import DownloadZipInstaller               # type: ignore  # pylint: disable=import-error,unused-import
from RepositoryBootstrap.SetupAndActivate.Installers.Installer import Installer                                     # type: ignore  # pylint: disable=import-error,unused-import
from RepositoryBootstrap.SetupAndActivate.Installers.LocalSevenZipInstaller import LocalSevenZipInstaller           # type: ignore  # pylint: disable=import-error,unused-import

# ----------------------------------------------------------------------
from _install_data import GRCOV_VERSIONS, LLVM_VERSIONS
del sys.modules["_install_data"]

# ----------------------------------------------------------------------
def GetConfigurations() -> Union[
    Configuration.Configuration,
    Dict[
        str,                                # configuration name
        Configuration.Configuration,
    ],
]:
    configurations: Dict[str, Configuration.Configuration] = {}

    if CurrentShell.family_name == "Windows":
        target_architectures = ["x64", ] # TODO: "x86"
    else:
        target_architectures = [CurrentShell.current_architecture, ]

    common_foundation_dependency = Configuration.Dependency(
        uuid.UUID("DD6FCD30-B043-4058-B0D5-A6C8BC0374F4"),
        "Common_Foundation",
        "python310",
        "https://github.com/davidbrownell/v4-Common_Foundation.git",
    )

    for llvm_version in LLVM_VERSIONS.keys():
        version_specs = Configuration.VersionSpecs(
            [Configuration.VersionInfo("LLVM", SemVer(llvm_version)), ],
            {},
        )

        if CurrentShell.family_name == "Windows":
            for target_architecture in target_architectures:
                configurations["{}-mingw-{}".format(llvm_version, target_architecture)] = Configuration.Configuration(
                    """Uses LLVM 'v{}' (using mingw (aka "Msys2 MinGW Clang" at https://blog.conan.io/2022/10/13/Different-flavors-Clang-compiler-Windows.html)) targeting '{}'.""".format(llvm_version, target_architecture),
                    [common_foundation_dependency, ],
                    version_specs,
                )

            for msvc_version in [
                "17.4",
            ]:
                for target_architecture in target_architectures:
                    configurations["{}-msvc-{}-{}".format(llvm_version, msvc_version, target_architecture)] = Configuration.Configuration(
                        """Uses LLVM 'v{}' (using Microsoft Visual Studio 'v{}' (aka "LLVM/Clang" at https://blog.conan.io/2022/10/13/Different-flavors-Clang-compiler-Windows.html)) targeting '{}'.""".format(
                            llvm_version,
                            msvc_version,
                            target_architecture,
                        ),
                        [
                            Configuration.Dependency(
                                uuid.UUID("6e6cbb2c-6512-470f-ba88-a6e4ad85fed0"),
                                "Common_cpp_MSVC",
                                "{}-{}".format(msvc_version, target_architecture),
                                "https://github.com/davidbrownell/v4-Common_cpp_MSVC.git",
                            ),
                        ],
                        version_specs,
                    )

        else:
            for target_architecture in target_architectures:
                configurations["{}-{}".format(llvm_version, target_architecture)] = Configuration.Configuration(
                    "Uses LLVM 'v{}' (without any external dependencies) targeting '{}'.".format(
                        llvm_version,
                        target_architecture,
                    ),
                    [common_foundation_dependency, ],
                    version_specs,
                )

    return configurations

# ----------------------------------------------------------------------
def GetCustomActions(
    # Note that it is safe to remove any parameters that are not used
    dm: DoneManager,
    explicit_configurations: Optional[List[str]],
    force: bool,
    interactive: Optional[bool],
) -> List[Commands.Command]:

    commands: List[Commands.Command] = []

    root_dir = Path(__file__).parent
    assert root_dir.is_dir(), root_dir

    # Create a link to the foundation's .pylintrc file
    foundation_root_file = Path(Types.EnsureValid(os.getenv(Constants.DE_FOUNDATION_ROOT_NAME))) / ".pylintrc"
    assert foundation_root_file.is_file(), foundation_root_file

    commands.append(
        Commands.SymbolicLink(
            root_dir / foundation_root_file.name,
            foundation_root_file,
            remove_existing=True,
            relative_path=True,
        ),
    )

    with dm.Nested("\nProcessing 'Common_LLVM' tools...") as extract_dm:
        with extract_dm.Nested("Processing 'grcov'...") as grcov_dm:
            for index, (grcov_version, install_data) in enumerate(GRCOV_VERSIONS.items()):
                with grcov_dm.Nested("'{}' ({} of {})...".format(grcov_version, index + 1, len(GRCOV_VERSIONS))) as version_dm:
                    install_data.installer.Install(
                        version_dm,
                        force=force,
                        prompt_for_interactive=install_data.prompt_for_interactive,
                        interactive=interactive,
                    )

        with extract_dm.Nested("Processing 'LLVM'...") as llvm_dm:
            for index, (version, install_data_items) in enumerate(LLVM_VERSIONS.items()):
                with llvm_dm.Nested(
                    "'{}' ({} of {})...".format(
                        version,
                        index + 1,
                        len(LLVM_VERSIONS),
                    ),
                ) as version_dm:
                    if explicit_configurations and not any(explicit_configuration.startswith(version) for explicit_configuration in explicit_configurations):
                        version_dm.WriteVerbose("The version was skipped.\n")
                        continue

                    for install_data_item in install_data_items:
                        with version_dm.Nested("'{}'...".format(install_data_item.name)) as this_dm:
                            install_data_item.installer.Install(
                                this_dm,
                                force=force,
                                prompt_for_interactive=install_data_item.prompt_for_interactive,
                                interactive=interactive,
                            )

                        if CurrentShell.family_name != "Windows":
                            # Create a simple test program to ensure that LLVM was installed correctly
                            with version_dm.Nested("Validating installation...") as validate_dm:
                                temp_directory = CurrentShell.CreateTempDirectory()

                                was_successful = False

                                # ----------------------------------------------------------------------
                                def OnExit():
                                    if was_successful:
                                        PathEx.RemoveTree(temp_directory)
                                        return

                                    validate_dm.WriteInfo("The temporary directory '{}' has not been deleted.".format(temp_directory))

                                # ----------------------------------------------------------------------

                                with ExitStack(OnExit):
                                    source_filename = temp_directory / "test.cpp"

                                    with validate_dm.Nested("Creating source file..."):
                                        with source_filename.open("w") as f:
                                            f.write(
                                                textwrap.dedent(
                                                    """\
                                                    #include <iostream>

                                                    int main() {
                                                        std::cout << "Hello world!\\n";
                                                        return 0;
                                                    }
                                                    """,
                                                ),
                                            )

                                    with validate_dm.Nested("Compiling...") as compile_dm:
                                        command_line = 'clang++ "{}"'.format(source_filename.name)

                                        compile_dm.WriteVerbose("Command Line: {}\n\n".format(command_line))

                                        modified_env = copy.deepcopy(os.environ)

                                        modified_env["PATH"] = "{}:{}".format(
                                            modified_env["PATH"],
                                            install_data_item.installer.output_dir / "bin",
                                        )

                                        modified_env["LD_LIBRARY_PATH"] = "{}".format(
                                            install_data_item.installer.output_dir / "lib" / "x86_64-unknown-linux-gnu",
                                        )

                                        result = SubprocessEx.Run(
                                            command_line,
                                            cwd=temp_directory,
                                            env=modified_env,  # type: ignore
                                        )

                                        compile_dm.result = result.returncode

                                        if compile_dm.result != 0:
                                            compile_dm.WriteError(
                                                textwrap.dedent(
                                                    """\
                                                    Errors here generally indicate that glibc has not been installed (especially if the error is associated with 'features.h').
                                                    Visit https://www.gnu.org/software/libc/ for more information.

                                                    Please install glibc using your distro's favorite package manager.

                                                    Examples:
                                                        Ubuntu:     `apt-get install -y libc6-dev`

                                                    COMPILER ERROR
                                                    --------------
                                                    {}

                                                    """,
                                                ).format(
                                                    TextwrapEx.Indent(result.output.strip(), 4),
                                                ),
                                            )

                                            return []

                                        with compile_dm.YieldVerboseStream() as stream:
                                            stream.write(result.output)

                                    with validate_dm.Nested("Testing...") as testing_dm:
                                        command_line = "./a.out"

                                        testing_dm.WriteVerbose("Command Line: {}\n\n".format(command_line))

                                        result = SubprocessEx.Run(
                                            command_line,
                                            cwd=temp_directory,
                                        )

                                        testing_dm.result = result.returncode

                                        if testing_dm.result == 0:
                                            testing_dm.result = 0 if result.output == "Hello world!\n" else -1

                                        if testing_dm.result != 0:
                                            compile_dm.WriteError(result.output)
                                            return []

                                        with testing_dm.YieldVerboseStream() as stream:
                                            stream.write(result.output)

                                        was_successful = True

    return commands


import fileinput
from typing import List

from number import Number

def solve(input_file):
    n = Number.parse(input_file.readline().strip())
    for line in input_file:
        n += Number.parse(line.strip())
        n.reduce()
    return n.magnitude

if __name__ == "__main__":
    print(solve(fileinput.FileInput()))

2021 - submarine/18 - snailfish numbers/solution1.py


#/usr/bin/env python

import yaml
import os, sys, re
import subprocess
import argparse

## Arguments
parser = argparse.ArgumentParser(description='Create a shared cuda.yml for docker-compose')
parser.add_argument('--gpu', '-g',
	action='append',
	dest='gpus',
	default=[])
parser.add_argument('--verbose',
	action='store_true',
	help='Verbose logging')
parser.add_argument('--out', '-o',
	dest='save_directory',
	default='shared/',
	help='Directory to write the shared docker-compose')

args = parser.parse_args()

cuda_version = '7.0'

nv_device = '/dev/nvidia'
uvm_device = '{0}-uvm'.format(nv_device)
ctl_device = '{0}ctl'.format(nv_device)

cuda_version_label = 'com.nvidia.cuda.version'

nv_bins_volume = '/usr/local/bin'

nv_bins = ['nvidia-cuda-mps-control',
         'nvidia-cuda-mps-server',
         'nvidia-debugdump',
         'nvidia-persistenced',
         'nvidia-smi'
         ]

nv_libs_volume = '/usr/local/nvidia'
nv_libs_cuda = ['cuda', 'nvcuvid', 'nvidia-compiler', 'nvidia-encode', 'nvidia-ml']

def log(msg, **kwargs):
	print('DEBUG: {0}'.format(msg));
	if kwargs.get('body'):
		print(kwargs.get('body', ''))

def no_error(cmds):
	try:
		for cmd in cmds.split():
			subprocess.Popen([cmd], stdout=open(os.devnull, "w"), stderr=subprocess.STDOUT)
	except subprocess.CalledProcessError:
		return False

def grep(cmd, grp):
	grep = subprocess.Popen(['grep', grp], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
	orig = subprocess.Popen(cmd, stdout=grep.stdin)
	output, errs = grep.communicate()
	orig.wait()
	if output:
		return output.decode('ascii')

def query_nvsmi(section, gpu_id=False):
	cmd = ['nvidia-smi','-q']
	if gpu_id:
		cmd.extend(['-i', gpu_id])

	res = grep(cmd, section)
	return res.split()[-1]

def library_path(lib):
	pat = grep(['ldconfig', '-p'], 'lib{0}.so'.format(lib))
	if pat:
		return pat.split('=>')[-1].strip(' \t\n\r')
	else:
		print('Could not find library: {0}'.format(lib))

def library_arch(lib):
	proc = subprocess.Popen(['file', '-L', lib], stdout=subprocess.PIPE)
	out, errs = proc.communicate()

	if errs:
		print('There was an error with `which {0}`: {1}'.format(b, errs))
	elif out:
		return re.sub('-bit', '', out.decode('ascii').split()[2])

def which(b):
	proc = subprocess.Popen(['which', b], stdout=subprocess.PIPE)
	out, errs = proc.communicate()
	if errs:
		print('There was an error with `which {0}`: {1}'.format(b, errs))
	elif out:
		return out.decode('ascii').strip(' \n\t\r')

def format_mount(a, b=None):
	if not b:
		b = a
	return '{0}:{1}'.format(a, b)

driver_version = query_nvsmi('Driver Version')
no_error('nvidia-smi')
#no_error('nvidia-smi nvidia-modprobe')

d = {
	'devices': [],
	'volumes': []
}

## Add devices
devices = [ctl_device, uvm_device]
d['devices'] = [format_mount(dev) for dev in devices]

if args.gpus:
	for gpu in args.gpus:
		gpu_minor_version = query_nvsmi('Minor Number', gpu)
		if gpu_minor_version:
			d['devices'].append(format_mount('{0}{1}'.format(nv_device, gpu_minor_version)))
		else:
			print('Could not find minor version for gpu: {0}'.format(gpu))

library_paths = [library_path(lib) for lib in nv_libs_cuda]

for lib in library_paths:
	if lib:
		basename = os.path.basename(lib)
		arch = library_arch(lib)
		if arch:
			mount = None
			if arch == '32':
				mount = format_mount(lib, '{0}/lib/{1}'.format(nv_libs_volume, basename))
			if arch == '64':
				mount = format_mount(lib, '{0}/lib64/{1}'.format(nv_libs_volume, basename))
			if mount:
				d['volumes'].append(mount)

for binary in nv_bins:
	b = which(binary)
	if b:
		d['volumes'].append(format_mount(b, '{0}/{1}'.format(nv_bins_volume, binary)))

cuda_dir = '/usr/local/cuda-{0}/lib64'.format(cuda_version)
files = [x for x in os.listdir(cuda_dir) if os.path.isfile(cuda_dir+os.sep+x)]
for lib in files:
	local_file = os.path.join(cuda_dir, lib)
	remote_volume = '{0}/{1}'.format(nv_libs_volume, lib)
	d['volumes'].append(format_mount(local_file, remote_volume))

d['environment'] = {}
d['environment'].update({'LD_LIBRARY_PATH': '$LD_LIBRARY_PATH:{0}:{1}'.format(cuda_dir, nv_libs_volume)})

out = yaml.safe_dump({'cuda_base': d},
	indent=4,
	allow_unicode=True,
	default_flow_style=False)

log('Writing cuda file', body=out)

with open('{0}/cuda.yml'.format(args.save_directory), 'w') as outfile:
    outfile.write(out)


# -*- coding: utf-8 -*-

"""Главный и единственный модуль в игре.

Игра специально написана в минималистичном стиле, мне
хотелось воплотить текстовый движок настолько лаконично,
насколько это вообще возможно.

Подкладывая этому скрипту различные json с метаданными, можно
запускать произвольные текстовые истории.
"""
import json
import os
import textwrap
from collections import defaultdict
from typing import Dict, Any, NewType

Context = NewType('Context', Dict[str, Any])
Location = NewType('Location', Dict[str, Any])
Locations = Dict[str, Location]

BASE_PATH = os.path.join('game', 'locations')

def clear_screen_windows() -> None:
    """Очистить содержимое экрана на Windows.
    """
    os.system('cls')

def clear_screen_nix() -> None:
    """Очистить содержимое экрана на *nix.
    """
    os.system('clear')

def get_locations() -> Locations:
    """Загрузить локации с жёсткого диска и вернуть в виде словаря.

    Пример данных на выходе:
    {
        'start':
        {
            'title': 'Стартовая локация',
            'options': ...,
        },
        ...
    }
    """
    locations = {}

    for path, dirs, filenames in os.walk(BASE_PATH):
        for filename in filenames:
            full_path = os.path.join(path, filename)

            with open(full_path, mode='r', encoding='utf-8') as file:
                contents = json.load(file)
                for name, content in contents.items():
                    locations[name] = Location(content)

    return locations

def get_context() -> Context:
    """Вернуть набор переменных игры.

    Здесь можно заполнить параметры по умолчанию.
    """
    return Context({
        'times_visited': defaultdict(int),
    })

def get_header(position: str, location: Location, context: Context) -> str:
    """Извлечь заголовок локации.

    Текст зависит от того, бывали ли мы тут раньше.
    """
    if all([context['times_visited'][position] == 0,
            'initial_header' in location]):
        return location['initial_header']
    return location['header']

def is_visible(option: dict, context: Context) -> bool:
    """Вернуть True если мы можем видеть эту позицию.
    """
    condition = option.get('condition')

    if condition is None:
        return True

    return bool(eval(condition, {}, context))

def get_input_from_user(variants: dict) -> str:
    """Получить от пользователя вариант ответа, который он хочет выбрать.
    """
    while True:
        variant = input('>')

        if variant.strip().lower() in variants:
            return variant

        print('Выберите один из предоставленных вариантов')

def apply_side_effect(chosen_option: dict, context: Context) -> None:
    """Применить побочныё эффект выбора.

    Мутируем переменные контекста, чтобы управлять логикой.
    Сами решения принимаются на этапе разработки JSON и в данном
    скрипте никак не представлены.
    """
    side_effect = chosen_option.get('side_effect')

    if side_effect:
        exec(side_effect, {}, context)

def enter_location(position: str, locations: Locations,
                   context: Context) -> Location:
    """Применить операции входа в новую локацию и вернуть её экземпляр.
    """
    clear_screen()
    location: Location = locations[position]
    output_location(position, location, context)
    context['times_visited'][position] += 1
    return location

def ask_user(location: Location, context: Context) -> dict:
    """Получить обратную связь от пользователя и вернуть экземпляр опции.

    Пример данных на выходе:
    {
        'condition': 'True',
        'label': 'Вариант 2',
        'goto': 'end',
        ...
    }

    Приходится использовать отдельную переменную number из-за
    невидимых вариантов в меню выбора опций. Без него нумерация
    будет не по порядку.
    """
    visible_choices = {}
    number = 0

    for option in location['options']:
        if is_visible(option, context):
            number += 1
            visible_choices[str(number)] = option

        print(f'[{number}] {option["label"]}')

    user_choice_number = get_input_from_user(visible_choices)
    chosen_option = visible_choices[user_choice_number]

    return chosen_option

def output_location(position: str, location: Location, context: Context,
                    terminal_width: int = 80) -> None:
    """Вывести на экран заголовок локации и краткое описание входа.
    """
    print('-' * terminal_width)

    header = get_header(position, location, context)

    for substring in header.split('\n'):
        if substring:
            lines = textwrap.wrap(text=substring,
                                  width=terminal_width)
            for line in lines:
                print(line)

    print('-' * terminal_width)

def main():
    """Главный событийный цикл игры.

    В бесконечном цикле крутит JSON-ы, пор пока игрок не нажмёт
    Ctrl+C или не доберётся до локации с именем end.
    """
    locations = get_locations()
    context = get_context()
    position = 'start'

    while position != 'end':
        location = enter_location(position, locations, context)
        option = ask_user(location, context)
        apply_side_effect(option, context)
        position = option['goto']

    print('Спасибо за игру!')

if __name__ == '__main__':

    if os.name == 'nt':
        clear_screen = clear_screen_windows
    else:
        clear_screen = clear_screen_nix

    try:
        main()
    except KeyboardInterrupt:
        print('Выход по команде с клавиатуры')


"""
Place to register all blueprints
"""

def customize_social_auth():
    """
    Customize certain routes of social auth
    """
    from datetime import datetime

    from flask import Blueprint, current_app, g
    from flask_user import login_required, signals
    from social_core.actions import do_auth, do_complete, do_disconnect
    from social_flask.routes import do_login as base_do_login
    from social_flask.utils import psa

    social_auth = Blueprint("social", "social_flask")

    def do_login(backend, user, social_user):
        ret = base_do_login(backend=backend, user=user, social_user=social_user)
        # Set email_confirmed_at if not already set, is assuming that a
        # user only have one email, that is, the User is the UserMailClass
        if ret and not user.email_confirmed_at:
            user.email_confirmed_at = datetime.utcnow()
            user.save()

            # Send confirmed_email signal
            signals.user_confirmed_email.send(
                current_app._get_current_object(), user=user
            )

        return ret

    @social_auth.route("/sign-in/<string:backend>", methods=("GET", "POST"))
    @psa("social.complete")
    def auth(backend):
        return do_auth(g.backend)

    @social_auth.route("/complete/<string:backend>", methods=("GET", "POST"))
    @psa("social.complete")
    def complete(backend, *args, **kwargs):
        """Overrided view to auto confirm emails due to being confirmed by
        auth provider inside login"""

        return do_complete(g.backend, login=do_login, user=g.user, *args, **kwargs)

    @social_auth.route("/disconnect/<string:backend>", methods=("POST",))
    @social_auth.route(
        "/disconnect/<string:backend>/<int:association_id>", methods=("POST",)
    )
    @social_auth.route(
        "/disconnect/<string:backend>/<string:association_id>", methods=("POST",)
    )
    @login_required
    @psa()
    def disconnect(backend, association_id=None):
        """Disconnects given backend from current logged in user."""
        return do_disconnect(g.backend, g.user, association_id)

    return social_auth

def register_blueprint(app):
    """
    Given an app register all blueprints for the application
    """
    from .apps import api, chat, media, posts, user

    # Register Blueprints
    app.register_blueprint(customize_social_auth(), uri_prefix="oauth")
    app.register_blueprint(api.bp, url_prefix="/api")
    app.register_blueprint(chat.bp, url_prefix="/chat")
    app.register_blueprint(media.bp, url_prefix="/media")
    app.register_blueprint(posts.bp, url_prefix="/post")
    app.register_blueprint(user.bp, url_prefix="/user")

    if app.config["DEBUG"]:
        from .apps import showroom

        app.register_blueprint(showroom.bp, url_prefix="/showroom")


def perm(s, k):
    n = len(s)
    def perm_helper(a=None, stamploc=0, used=None):
        if a is None:
            a = [None] * k
        if used is None:
            used = [False] * n
        if stamploc == k-1:
            for i in range(n):
                if not used[i]:
                    a[stamploc] = s[i]
                    res.append(''.join(a))
            return
        for i in range(n):
            if not used[i]:
                a[stamploc] = s[i]
                used[i] = True
                perm_helper(a, stamploc+1, used)
                used[i] = False
    if k == 0:
        return [None]
    res = []
    perm_helper()
    return res

assert perm('abc', 1) == ['a', 'b', 'c']
assert perm('ab', 2) == ['ab', 'ba']
assert len(perm('abcdefg', 3)) == 210
assert perm('abc', 0) == [None]


import re

def isValidEmail(email):
    regex = re.compile(
        r"([A-Za-z0-9]+[.-_])*[A-Za-z0-9]+@[A-Za-z0-9-]+(\.[A-Z|a-z]{2,})+"
    )
    if re.fullmatch(regex, email):
        return True
    else:
        return False

def isValidPhone(phone):
    regex = re.compile(r"^\+?[0-9]{10,}$")
    if re.fullmatch(regex, phone):
        return True
    else:
        return False


i=0
Fib = [1,1]
n = int(input("Welche Fibonaccizahl willst du?="))
while i < n:
    fib = Fib[i]+Fib[i+1]
    Fib.append(fib)
    i=i+1
print(f"Die Fibonacci Zahl F_{i+1} ist = {Fib[i]}")
print(Fib)
a=1
b=1
fibo=0
i=0
while i < n:
    fibo=a+b
    a=b
    b=fibo
    i=i+1
print(fibo)
def f(p):
    if p==1:
        return 1
    else:
        return f(p-1)*p

print(f(10))


import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor

# 공개 데이터셋에서 학습 데이터를 내려받습니다.
training_data = datasets.FashionMNIST(
  root="Fashion_MNIST_Data",
  train=True,
  download=True,
  transform=ToTensor(),
)

# 공개 데이터셋에서 테스트 데이터를 내려받습니다.
test_data = datasets.FashionMNIST(
  root="Fashion_MNIST_Data",
  train=False,
  download=True,
  transform=ToTensor(),
)

batch_size = 64

# 데이터로더를 생성합니다.
train_dataloader = DataLoader(training_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)

for X, y in test_dataloader:
  print(f"Shape of X [N, C, H, W]: {X.shape}")
  print(f"Shape of y: {y.shape} {y.dtype}")
  break

# 학습에 사용할 CPU나 GPU, MPS 장치를 얻습니다.
device = (
  "cuda"
  if torch.cuda.is_available()
  else "mps"
  if torch.backends.mps.is_available()
  else "cpu"
)
print(f"Using {device} device")

# 모델을 정의합니다.
class NeuralNetwork(nn.Module):
  def __init__(self):
    super().__init__()
    self.flatten = nn.Flatten()
    self.linear_relu_stack = nn.Sequential(
        nn.Linear(28*28, 512),
        nn.ReLU(),
        nn.Linear(512, 512),
        nn.ReLU(),
        nn.Linear(512, 10)
    )

  def forward(self, x):
    x = self.flatten(x)
    logits = self.linear_relu_stack(x)
    return logits

model = NeuralNetwork().to(device)
print(model)

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

def train(dataloader, model, loss_fn, optimizer):
  size = len(dataloader.dataset)
  for batch, (X, y) in enumerate(dataloader):
    X, y = X.to(device), y.to(device)

    # 예측 오류 계산
    pred = model(X)
    loss = loss_fn(pred, y)

    # 역전파
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if batch % 100 == 0:
      loss, current = loss.item(), (batch + 1) * len(X)
      print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

def test(dataloader, model, loss_fn):
  size = len(dataloader.dataset)
  num_batches = len(dataloader)
  model.eval()
  test_loss, correct = 0, 0
  with torch.no_grad():
    for X, y in dataloader:
      X, y = X.to(device), y.to(device)
      pred = model(X)
      test_loss += loss_fn(pred, y).item()
      correct += (pred.argmax(1) == y).type(torch.float).sum().item()
  test_loss /= num_batches
  correct /= size
  print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

epochs = 5
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)
print("Done!")

torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")


from common import execute_sh
from retry import retry
import os
import logging
import json

"""
Issue kubectl commands on the running linode cluster
"""

WEATHER_API_TOKEN = os.environ.get("WEATHER_API_TOKEN")
KUBERNETES_NODE_COUNT = "2"

@retry(tries=60, delay=30)
def get_nodes():
    # Verify kubectl is communicating with cluster
    cmd = ["kubectl", "--output=json", "get", "nodes"]
    output = execute_sh(cmd)
    json_object = json.loads(output)
    nodes = json_object["items"]
    if len(nodes) != int(KUBERNETES_NODE_COUNT):
        raise Exception(f"kubectl expected {KUBERNETES_NODE_COUNT} nodes but found {len(nodes)}")
    logging.info(f"kubectl OK: Retrieved node count: {len(nodes)}")
    return

@retry(tries=5, delay=10)
def apply_deployment():
    cmd = ["kubectl", "--output=json", "apply", "-f", "resources/deployment.yaml"]
    output = None
    try:
        output = execute_sh(cmd)
    except Exception as e:
        raise Exception(f"retrying {cmd}")
    json_object = json.loads(output)
    logging.debug(f"json ==> {json_object}")
    logging.info(f"kubectl deployment applied OK")
    return

def apply_service():
    cmd = ["kubectl", "--output=json", "apply", "-f", "resources/service.yaml"]
    output = execute_sh(cmd)
    json_object = json.loads(output)
    logging.debug(f"json ==> {json_object}")
    logging.info(f"kubectl service applied OK")
    return

@retry(tries=5, delay=10)
def delete_service():
    cmd = ["kubectl", "delete", "svc", "gwa"]
    execute_sh(cmd)

def create_secrets():
    """Create k8s secret for the api key etc"""
    cmd = [
        "kubectl",
        "create",
        "secret",
        "generic",
        "gws-secret",
        f"--from-literal=WEATHER_API_TOKEN={WEATHER_API_TOKEN}",
    ]
    execute_sh(cmd)

@retry(tries=20, delay=10)
def get_ingress_ip():
    cmd = ["kubectl", "--output=json", "get", "svc", "gwa"]
    output = execute_sh(cmd)
    json_object = json.loads(output)
    logging.debug(f"json ==> {json_object}")
    ingress_ip = json_object["status"]["loadBalancer"]["ingress"][0]["ip"]
    if not ingress_ip:
        raise Exception(f"Ingress IP is empty in the returned json")
    logging.info(f"Load Balance Ingress is: {ingress_ip}")
    return ingress_ip

def apply_argocd():
    cmd = ["ls", "-al"]
    output = execute_sh(cmd)

    cmd = ["kubectl", "create", "namespace", "argocd"]
    output = execute_sh(cmd)

    # cmd = ["kubectl", "apply", "--namespace=argocd", "--dry-run=server", "-k", "."]
    # output = execute_sh(cmd, "./resources")
    return


from .keywords import K_SET_1

class Program:
    def __init__(self, inputLines):
        self.inputLines = inputLines
        self.comment = False
        self.indent = 0
        self.brackets = []
        self.programlines = []

    def __repr__(self):
        return '\n'.join(self.programlines)

    def generate(self, path):
        temp = []
        for line in self.inputLines:
            if line == '\n':
                continue
            elif '/*' in line:
                t = line.split('/*')
                temp.extend([t[0], '/*'+t[1]])
            elif '//' in line:
                if line.strip()[:2] == '//':
                    temp.append(line)
                else:
                    count = 0
                    for i in line:
                        if i == ' ':
                            count += 1
                        else:
                            break
                    t = line.split('//')
                    temp.extend([t[0], (' '*count)+'//'+t[1]])
            else:
                temp.append(line)
        self.inputLines = list(filter(lambda x: False if x=='\n' or x == '' else True, temp))
        for line in self.inputLines:
            if self.comment:
                if '*/' in line:
                    self.comment = False
                self.programlines.append(line)
            else:
                if line == '\n' or '//' in line:
                    self.programlines.append(line)
                elif '/*' in line:
                    self.programlines.append(line)
                    self.comment = True
                else:
                    line = line.strip('\n').rstrip()
                    if line == '':
                        continue
                    line = self._indent(line)
                    line, linetype = self._checkKeywords(line)
                    if linetype:
                        line, linetype = self._colon(line)
                        if linetype:
                            line = self._semicolon(line)

        if self.indent > 0:
            self.programlines.extend(['}']*int(self.indent))

        with open(path.split('.tr')[0] + '.c', 'w') as outfile:
            for line in self.programlines:
                outfile.write(line + '\n')

    def _indent(self, line):
        count = 0
        for i in line:
            if i == ' ':
                count += 1
            else:
                break
        if (count/4).is_integer():
            if count/4 < self.indent:
                bracketCount = self.indent - count/4
                self.programlines.extend([' '*(int(self.indent)*4-1) + '}']*int(bracketCount))
                self.indent = count/4
            elif count/4 > self.indent:
                raise SyntaxError()
        return line

    def _checkKeywords(self, line):
        linetype = True
        for words in K_SET_1:
            if words in line:
                linetype = False
                self.programlines.append('#' + line.strip())
                return '#' + line.strip(), linetype
        return line, linetype

    def _semicolon(self, line):
        finalline = line.rstrip() + ';'
        self.programlines.append(finalline)
        return finalline

    def _colon(self, line):
        if line[-1] == ':':
            self.indent += 1
            self.programlines.append(line[:-1])
            self.programlines.append(' '*(int(self.indent)*4-1) + '{')
            return line.replace(':', ''), False
        return line, True


import geopy

bairros_list = [
        "Boa Vista",
        "Bom Pastor",
        "Centro",
        "Granbery",
        "Jardim Glória",
        "Santa Helena",
        "São Mateus",
        "Teixeiras",
        "Bairu",
        "Bonfim",
        "Botanágua",
        "Centenário",
        "Cesário Alvim",
        "Grajaú",
        "Linhares",
        "Manoel Honório",
        "Marumbi",
        "Nossa Senhora Aparecida",
        "Progresso",
        "Santa Rita",
        "Santa Cândida",
        "São Benedito",
        "São Bernardo",
        "Vitorino Braga",
        "Eldorado",
        "Granjas Betânea",
        "Jardim Bom Clima",
        "Mariano Procópio",
        "Grama",
        "Jardim Emaús",
        "Parque Independência",
        "Santa Therezinha",
        "Filgueiras",
        "Vale dos Bandeirantes",
        "Barbosa Lage",
        "Barreira do Triunfo",
        "Benfica",
        "Milho Branco",
        "Carlos Chagas",
        "Cerâmica",
        "Esplanada",
        "Francisco Bernardino",
        "Industrial",
        "Jardim Natal",
        "Jóquei Clube",
        "Nova Era",
        "Paula Lima",
        "Remonta",
        "Represa",
        "Santa Cruz",
        "São Dimas",
        "Vila Esperança",
        "Aeroporto",
        "Borboleta",
        "Cruzeiro Santo Antônio",
        "Martelos",
        "Morro do Imperador",
        "Nova Califórnia",
        "Novo Horizonte",
        "São Pedro",
        "Serro Azul",
        "Barão do Retiro",
        "Floresta",
        "Nossa Senhora de Lourdes",
        "Santo Antônio",
        "Vila Furtado de Menezes",
        "Vila Olavo Costa",
        "Niterói",
        "Costa Carvalho",
        "Bomba de Fogo",
        "Cascatinha",
        "Graminha",
        "Ipiranga",
        "Jardim Laranjeiras",
        "Sagrado Coração de Jesus",
        "Salvaterra",
        "Santa Efigênia",
        "Santa Luzia",
        "São Geraldo",
      ]

location_dict = {}

for bairro in bairros_list:
    geolocator = geopy.geocoders.Nominatim(user_agent="geolocalização")
    location = geolocator.geocode(bairro + ', Juiz de Fora - MG')

    try:
        lat = location.latitude
        lon = location.longitude
        location_dict[bairro]={
            'latitude': lat,
            'logitude': lon,
        }
        print(bairro + ', Juiz de Fora - MG.')

    except:
        print(bairro + ', não funciona.')

print(location_dict)


from __future__ import print_function
from __future__ import absolute_import
import socket
import struct
import sys
import warnings

from . import constants as tc
from .exceptions import TraCIException, FatalTraCIError
from .domain import _defaultDomains
from .storage import Storage
from .step import StepManager

_DEBUG = False
_RESULTS = {0x00: "OK", 0x01: "Not implemented", 0xFF: "Error"}

class Connection(StepManager):

    """Contains the socket, the composed message string
    together with a list of TraCI commands which are inside.
    """

    def __init__(self, host, port, process, traceFile, traceGetters):
        StepManager.__init__(self)
        if sys.platform.startswith('java'):
            # working around jython 2.7.0 bug #2273
            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
        else:
            self._socket = socket.socket()
        self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        try:
            self._socket.connect((host, port))
        except socket.error:
            self._socket.close()
            raise
        self._process = process
        self._string = bytes()
        self._queue = []
        self._subscriptionMapping = {}
        if traceFile is not None:
            self.startTracing(traceFile, traceGetters, _defaultDomains)
        for domain in _defaultDomains:
            domain._register(self, self._subscriptionMapping)

    def _recvExact(self):
        try:
            result = bytes()
            while len(result) < 4:
                t = self._socket.recv(4 - len(result))
                if not t:
                    return None
                result += t
            length = struct.unpack("!i", result)[0] - 4
            result = bytes()
            while len(result) < length:
                t = self._socket.recv(length - len(result))
                if not t:
                    return None
                result += t
            return Storage(result)
        except socket.error:
            return None

    def _sendExact(self):
        if self._socket is None:
            raise FatalTraCIError("Connection already closed.")
        length = struct.pack("!i", len(self._string) + 4)
        if _DEBUG:
            print("sending", Storage(length + self._string).getDebugString())
        self._socket.send(length + self._string)
        result = self._recvExact()
        if _DEBUG:
            print("receiving", result.getDebugString())
        if not result:
            self._socket.close()
            del self._socket
            raise FatalTraCIError("connection closed by SUMO")
        for command in self._queue:
            prefix = result.read("!BBB")
            err = result.readString()
            if prefix[2] or err:
                self._string = bytes()
                self._queue = []
                raise TraCIException(err, prefix[1], _RESULTS[prefix[2]])
            elif prefix[1] != command:
                raise FatalTraCIError("Received answer %s for command %s." % (prefix[1], command))
            elif prefix[1] == tc.CMD_STOP:
                length = result.read("!B")[0] - 1
                result.read("!%sx" % length)
        self._string = bytes()
        self._queue = []
        return result

    def _pack(self, format, *values):
        packed = bytes()
        for f, v in zip(format, values):
            if f == "i":
                packed += struct.pack("!Bi", tc.TYPE_INTEGER, int(v))
            elif f == "I":  # raw int for setOrder
                packed += struct.pack("!i", int(v))
            elif f == "d":
                packed += struct.pack("!Bd", tc.TYPE_DOUBLE, float(v))
            elif f == "D":  # raw double for some base commands like simstep
                packed += struct.pack("!d", float(v))
            elif f == "b":
                packed += struct.pack("!Bb", tc.TYPE_BYTE, int(v))
            elif f == "B":
                packed += struct.pack("!BB", tc.TYPE_UBYTE, int(v))
            elif f == "u":  # raw unsigned byte needed for distance command and subscribe
                packed += struct.pack("!B", int(v))
            elif f == "s":
                v = str(v)
                packed += struct.pack("!Bi", tc.TYPE_STRING, len(v)) + v.encode("latin1")
            elif f == "p":  # polygon
                if len(v) <= 255:
                    packed += struct.pack("!BB", tc.TYPE_POLYGON, len(v))
                else:
                    packed += struct.pack("!BBi", tc.TYPE_POLYGON, 0, len(v))
                for p in v:
                    packed += struct.pack("!dd", *p)
            elif f == "t":  # tuple aka compound
                packed += struct.pack("!Bi", tc.TYPE_COMPOUND, v)
            elif f == "c":  # color
                packed += struct.pack("!BBBBB", tc.TYPE_COLOR, int(v[0]), int(v[1]), int(v[2]),
                                      int(v[3]) if len(v) > 3 else 255)
            elif f == "l":  # string list
                packed += struct.pack("!Bi", tc.TYPE_STRINGLIST, len(v))
                for s in v:
                    packed += struct.pack("!i", len(s)) + s.encode("latin1")
            elif f == "f":  # float list
                packed += struct.pack("!Bi", tc.TYPE_DOUBLELIST, len(v))
                for x in v:
                    packed += struct.pack("!d", x)
            elif f == "o":
                packed += struct.pack("!Bdd", tc.POSITION_2D, *v)
            elif f == "O":
                packed += struct.pack("!Bddd", tc.POSITION_3D, *v)
            elif f == "g":
                packed += struct.pack("!Bdd", tc.POSITION_LON_LAT, *v)
            elif f == "G":
                packed += struct.pack("!Bddd", tc.POSITION_LON_LAT_ALT, *v)
            elif f == "r":
                packed += struct.pack("!Bi", tc.POSITION_ROADMAP, len(v[0])) + v[0].encode("latin1")
                packed += struct.pack("!dB", v[1], v[2])
        return packed

    def _sendCmd(self, cmdID, varID, objID, format="", *values):
        self._queue.append(cmdID)
        packed = self._pack(format, *values)
        length = len(packed) + 1 + 1  # length and command
        if varID is not None:
            if isinstance(varID, tuple):  # begin and end of a subscription
                length += 8 + 8 + 4 + len(objID)
            else:
                length += 1 + 4 + len(objID)
        if length <= 255:
            self._string += struct.pack("!BB", length, cmdID)
        else:
            self._string += struct.pack("!BiB", 0, length + 4, cmdID)
        if varID is not None:
            if isinstance(varID, tuple):
                self._string += struct.pack("!dd", *varID)
            else:
                self._string += struct.pack("!B", varID)
            self._string += struct.pack("!i", len(objID)) + objID.encode("latin1")
        self._string += packed
        return self._sendExact()

    def _readSubscription(self, result):
        if _DEBUG:
            print("reading subscription", result.getDebugString())
        result.readLength()
        response = result.read("!B")[0]
        isVariableSubscription = ((response >= tc.RESPONSE_SUBSCRIBE_INDUCTIONLOOP_VARIABLE and
                                   response <= tc.RESPONSE_SUBSCRIBE_BUSSTOP_VARIABLE) or
                                  (response >= tc.RESPONSE_SUBSCRIBE_PARKINGAREA_VARIABLE and
                                   response <= tc.RESPONSE_SUBSCRIBE_OVERHEADWIRE_VARIABLE))
        objectID = result.readString()
        if not isVariableSubscription:
            domain = result.read("!B")[0]
        numVars = result.read("!B")[0]
        if isVariableSubscription:
            while numVars > 0:
                varID, status = result.read("!BB")
                if status:
                    print("Error!", result.readTypedString())
                elif response in self._subscriptionMapping:
                    self._subscriptionMapping[response].add(objectID, varID, result)
                else:
                    raise FatalTraCIError(
                        "Cannot handle subscription response %02x for %s." % (response, objectID))
                numVars -= 1
        else:
            objectNo = result.read("!i")[0]
            for _ in range(objectNo):
                oid = result.readString()
                if numVars == 0:
                    self._subscriptionMapping[response].addContext(
                        objectID, self._subscriptionMapping[domain], oid)
                for __ in range(numVars):
                    varID, status = result.read("!BB")
                    if status:
                        print("Error!", result.readTypedString())
                    elif response in self._subscriptionMapping:
                        self._subscriptionMapping[response].addContext(
                            objectID, self._subscriptionMapping[domain], oid, varID, result)
                    else:
                        raise FatalTraCIError(
                            "Cannot handle subscription response %02x for %s." % (response, objectID))
        return objectID, response

    def _subscribe(self, cmdID, begin, end, objID, varIDs, parameters):
        format = "u"
        args = [len(varIDs)]
        for v in varIDs:
            format += "u"
            args.append(v)
            if parameters is not None and v in parameters:
                if isinstance(parameters[v], tuple):
                    format += parameters[v][0]
                    for a in parameters[v][1:]:
                        args.append(a)
                elif isinstance(parameters[v], int):
                    format += "i"
                    args.append(parameters[v])
                elif isinstance(parameters[v], float):
                    format += "d"
                    args.append(parameters[v])
                else:
                    format += "s"
                    args.append(parameters[v])
        result = self._sendCmd(cmdID, (begin, end), objID, format, *args)
        if varIDs:
            objectID, response = self._readSubscription(result)
            if response - cmdID != 16 or objectID != objID:
                raise FatalTraCIError("Received answer %02x,%s for subscription command %02x,%s." % (
                    response, objectID, cmdID, objID))

    def _getSubscriptionResults(self, cmdID):
        return self._subscriptionMapping[cmdID]

    def _subscribeContext(self, cmdID, begin, end, objID, domain, dist, varIDs, parameters=None):
        result = self._sendCmd(cmdID, (begin, end), objID, "uDu" + (len(varIDs) * "u"),
                               domain, dist, len(varIDs), *varIDs)
        if varIDs:
            objectID, response = self._readSubscription(result)
            if response - cmdID != 16 or objectID != objID:
                raise FatalTraCIError("Received answer %02x,%s for context subscription command %02x,%s." % (
                    response, objectID, cmdID, objID))

    def _addSubscriptionFilter(self, filterType, params=None):
        if filterType in (tc.FILTER_TYPE_NONE, tc.FILTER_TYPE_NOOPPOSITE,
                          tc.FILTER_TYPE_LEAD_FOLLOW):
            # filter without parameter
            assert params is None
            self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "u", filterType)
        elif filterType in (tc.FILTER_TYPE_DOWNSTREAM_DIST, tc.FILTER_TYPE_UPSTREAM_DIST,
                            tc.FILTER_TYPE_TURN, tc.FILTER_TYPE_FIELD_OF_VISION,
                            tc.FILTER_TYPE_LATERAL_DIST):
            # filter with float parameter
            self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "ud", filterType, params)
        elif filterType in (tc.FILTER_TYPE_VCLASS, tc.FILTER_TYPE_VTYPE):
            # filter with list(string) parameter
            self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None, "ul", filterType, params)
        elif filterType == tc.FILTER_TYPE_LANES:
            # filter with list(byte) parameter
            # check uniqueness of given lanes in list
            lanes = set()
            for i in params:
                lane = int(i)
                if lane < 0:
                    lane += 256
                lanes.add(lane)
            if len(lanes) < len(list(params)):
                warnings.warn("Ignoring duplicate lane specification for subscription filter.")
            self._sendCmd(tc.CMD_ADD_SUBSCRIPTION_FILTER, None, None,
                          (len(lanes) + 2) * "u", filterType, len(lanes), *lanes)

    def hasGUI(self):
        try:
            self.gui.getIDList()
            return True
        except TraCIException:
            return False

    def load(self, args):
        """
        Load a simulation from the given arguments.
        """
        if self._traceFile:
            self._traceFile.write("traci.load(%s)\n" % repr(args))
        self._sendCmd(tc.CMD_LOAD, None, None, "l", args)

    def simulationStep(self, step=0.):
        """
        Make a simulation step and simulate up to the given second in sim time.
        If the given value is 0 or absent, exactly one step is performed.
        Values smaller than or equal to the current sim time result in no action.
        """
        if self._traceFile:
            args = "" if step == 0 else str(step)
            self._traceFile.write("traci.simulationStep(%s)\n" % args)
        if type(step) is int and step >= 1000:
            warnings.warn("API change now handles step as floating point seconds", stacklevel=2)
        result = self._sendCmd(tc.CMD_SIMSTEP, None, None, "D", step)
        for subscriptionResults in self._subscriptionMapping.values():
            subscriptionResults.reset()
        numSubs = result.readInt()
        responses = []
        while numSubs > 0:
            responses.append(self._readSubscription(result))
            numSubs -= 1
        self.manageStepListeners(step)
        return responses

    def getVersion(self):
        command = tc.CMD_GETVERSION
        result = self._sendCmd(command, None, None)
        result.readLength()
        response = result.read("!B")[0]
        if response != command:
            raise FatalTraCIError("Received answer %s for command %s." % (response, command))
        return result.readInt(), result.readString()

    def setOrder(self, order):
        self._sendCmd(tc.CMD_SETORDER, None, None, "I", order)

    def close(self, wait=True):
        StepManager.close(self, True)
        for listenerID in list(self._stepListeners.keys()):
            self.removeStepListener(listenerID)
        if self._socket is not None:
            self._sendCmd(tc.CMD_CLOSE, None, None)
            self._socket.close()
            self._socket = None
        if wait and self._process is not None:
            self._process.wait()


import telegram
from twilio.rest import Client
from twilio.base.exceptions import TwilioRestException
import threading

class MessageSender:
    def __init__(self, config):
        self.lock = threading.Lock()
        self.telegram_bot = None
        if config["telegram"] is not None:
            self.telegram_chat_id = config["telegram"]["chat_id"]
            self.telegram_bot = telegram.Bot(token=config["telegram"]["token"])

        self.twilio_client = None
        if config["twilio"] is not None:
            self.toNumber = config["twilio"]["toNumber"]
            self.fromNumber = config["twilio"]["fromNumber"]
            self.accountSid = config["twilio"]["accountSid"]
            self.authToken = config["twilio"]["authToken"]
            self.twilio_client = Client(self.accountSid, self.authToken)

    def send_message(self, content, sender=None):
        with self.lock:
            if sender is not None:
                content = "Sender: " + sender + ": " + content
            if self.telegram_bot is not None:
                self.telegram_bot.send_message(chat_id=self.telegram_chat_id, text=content)
            if self.twilio_client is not None:
                try:
                    self.twilio_client.messages.create(to=self.toNumber, from_=self.fromNumber,
                                           body=content)
                except (NameError, TwilioRestException):
                    pass


from collections import defaultdict
from typing import ClassVar, Self

from discord import Message, Thread
from discord.errors import HTTPException
from pydis_core.utils import scheduling
from pydis_core.utils.logging import get_logger

import bot
from bot.constants import Channels
from bot.exts.filtering._filter_context import Event, FilterContext
from bot.exts.filtering._settings_types.settings_entry import ActionEntry
from bot.exts.filtering._utils import FakeContext
from bot.utils.messages import send_attachments

log = get_logger(__name__)

SUPERSTAR_REASON = (
    "Your nickname was found to be in violation of our code of conduct. "
    "If you believe this is a mistake, please let us know."
)

async def upload_messages_attachments(ctx: FilterContext, messages: list[Message]) -> None:
    """Re-upload the messages' attachments for future logging."""
    if not messages:
        return
    destination = messages[0].guild.get_channel(Channels.attachment_log)
    for message in messages:
        if message.attachments and message.id not in ctx.uploaded_attachments:
            ctx.uploaded_attachments[message.id] = await send_attachments(message, destination, link_large=False)

class RemoveContext(ActionEntry):
    """A setting entry which tells whether to delete the offending message(s)."""

    name: ClassVar[str] = "remove_context"
    description: ClassVar[str] = (
        "A boolean field. If True, the filter being triggered will cause the offending context to be removed. "
        "An offending message will be deleted, while an offending nickname will be superstarified."
    )

    remove_context: bool

    async def action(self, ctx: FilterContext) -> None:
        """Remove the offending context."""
        if not self.remove_context:
            return

        if ctx.event in (Event.MESSAGE, Event.MESSAGE_EDIT):
            await self._handle_messages(ctx)
        elif ctx.event == Event.NICKNAME:
            await self._handle_nickname(ctx)
        elif ctx.event == Event.THREAD_NAME:
            await self._handle_thread(ctx)

    @staticmethod
    async def _handle_messages(ctx: FilterContext) -> None:
        """Delete any messages involved in this context."""
        if not ctx.message or not ctx.message.guild:
            return

        # If deletion somehow fails at least this will allow scheduling for deletion.
        ctx.messages_deletion = True
        channel_messages = defaultdict(set)  # Duplicates will cause batch deletion to fail.
        for message in {ctx.message} | ctx.related_messages:
            channel_messages[message.channel].add(message)

        success = fail = 0
        deleted = list()
        for channel, messages in channel_messages.items():
            try:
                await channel.delete_messages(messages)
            except HTTPException:
                fail += len(messages)
            else:
                success += len(messages)
                deleted.extend(messages)
        scheduling.create_task(upload_messages_attachments(ctx, deleted))

        if not fail:
            if success == 1:
                ctx.action_descriptions.append("deleted")
            else:
                ctx.action_descriptions.append("deleted all")
        elif not success:
            if fail == 1:
                ctx.action_descriptions.append("failed to delete")
            else:
                ctx.action_descriptions.append("all failed to delete")
        else:
            ctx.action_descriptions.append(f"{success} deleted, {fail} failed to delete")

    @staticmethod
    async def _handle_nickname(ctx: FilterContext) -> None:
        """Apply a superstar infraction to remove the user's nickname."""
        alerts_channel = bot.instance.get_channel(Channels.mod_alerts)
        if not alerts_channel:
            log.error(f"Unable to apply superstar as the context channel {alerts_channel} can't be found.")
            return
        command = bot.instance.get_command("superstar")
        if not command:
            user = ctx.author
            await alerts_channel.send(f":warning: Could not apply superstar to {user.mention}: command not found.")
            log.warning(f":warning: Could not apply superstar to {user.mention}: command not found.")
            ctx.action_descriptions.append("failed to superstar")
            return

        await command(FakeContext(ctx.message, alerts_channel, command), ctx.author, None, reason=SUPERSTAR_REASON)
        ctx.action_descriptions.append("superstarred")

    @staticmethod
    async def _handle_thread(ctx: FilterContext) -> None:
        """Delete the context thread."""
        if isinstance(ctx.channel, Thread):
            try:
                await ctx.channel.delete()
            except HTTPException:
                ctx.action_descriptions.append("failed to delete thread")
            else:
                ctx.action_descriptions.append("deleted thread")

    def union(self, other: Self) -> Self:
        """Combines two actions of the same type. Each type of action is executed once per filter."""
        return RemoveContext(remove_context=self.remove_context or other.remove_context)


def maxProfit(prices):
    """
    :type prices: List[int]
    :rtype: int
    """
    total = 0
    for i in range(len(prices) - 1):
        total += max(prices[i + 1] - prices[i], 0)
    return total

Input = [7,1,5,3,6,4]
print(maxProfit(Input))
# Output: 7
# Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
#              Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
Input = [1,2,3,4,5]
print(maxProfit(Input))
# Output: 4
# Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
#              Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
#              engaging multiple transactions at the same time. You must sell before buying again.
Input = [7,6,4,3,1]
print(maxProfit(Input))
# Output: 0
# Explanation: In this case, no transaction is done, i.e. max profit = 0.


# -*- coding: utf-8 -*-
"""
Created on Mon Mar 16 08:45:54 2020

@author: rishav
"""
minPer = 100
dict = {'Krishna':[67,68,69]
        ,'Arjun':[45,98,63]
        ,'Malika':[52,56,60]}
for i in dict:
    x=sum(dict[i])/3
    if(x<minPer):
        minPer=x
        index = i
print(index)