from collections import OrderedDict
import os
from argparse import Namespace
import random

import torch
from path import Path
from rich.console import Console
from rich.progress import track
import pickle
from tqdm import tqdm

_CURRENT_DIR = Path(__file__).parent.abspath()

import sys

sys.path.append(_CURRENT_DIR.parent)

from utils.models import CNNWithBatchNorm, CNNWithoutBatchNorm
from utils.util import (
    LOG_DIR,
    TEMP_DIR,
    clone_parameters,
    fix_random_seed,
    get_client_id_indices,
)
from client.base import ClientBase

class ServerBase:
    def __init__(self, args: Namespace, algo: str):
        self.algo = algo
        self.args = args
        # default log file format
        self.log_name = "{}_{}_{}_{}.html".format(
            self.algo,
            self.args.dataset,
            self.args.global_epochs,
            self.args.local_epochs,
        )
        self.device = torch.device(
            "cuda" if self.args.gpu and torch.cuda.is_available() else "cpu"
        )
        fix_random_seed(self.args.seed)
        self.backbone = (
            CNNWithBatchNorm
            if self.args.dataset in ["cifar10", "cifar100"]
            else CNNWithoutBatchNorm
        )
        self.logger = Console(record=True, log_path=False, log_time=False,)
        self.client_id_indices, self.client_num_in_total = get_client_id_indices(
            self.args.dataset
        )
        self.temp_dir = TEMP_DIR / self.algo
        if not os.path.isdir(self.temp_dir):
            os.makedirs(self.temp_dir)

        _dummy_model = self.backbone(self.args.dataset)
        passed_epoch = 0
        self.global_params_dict: OrderedDict[str : torch.Tensor] = None
        if os.listdir(self.temp_dir) != []:
            if os.path.exists(self.temp_dir / "global_model.pt"):
                self.global_params_dict = torch.load(self.temp_dir / "global_model.pt")
                self.logger.log("Find existed global model...")

            if os.path.exists(self.temp_dir / "epoch.pkl"):
                with open(self.temp_dir / "epoch.pkl", "rb") as f:
                    passed_epoch = pickle.load(f)
                self.logger.log(f"Have run {passed_epoch} epochs already.",)
        else:
            self.global_params_dict = OrderedDict(_dummy_model.state_dict())

        self.global_epochs = self.args.global_epochs - passed_epoch
        self.logger.log("Backbone:", _dummy_model)

        self.trainer: ClientBase = None
        self.all_clients_stats = {i: {} for i in self.client_id_indices}

    def train(self):
        self.logger.log("=" * 30, "TRAINING", "=" * 30, style="bold green")
        progress_bar = (
            track(
                range(self.global_epochs),
                "[bold green]Training...",
                console=self.logger,
            )
            if not self.args.log
            else tqdm(range(self.global_epochs), "Training...")
        )
        for E in progress_bar:

            if E % self.args.verbose_gap == 0:
                self.logger.log("=" * 30, f"ROUND: {E}", "=" * 30)

            selected_clients = random.sample(
                self.client_id_indices, self.args.client_num_per_round
            )
            updated_params_cache = []
            weights_cache = []
            for client_id in selected_clients:
                client_local_params = clone_parameters(self.global_params_dict)
                (updated_params, weight), stats = self.trainer.train(
                    client_id=client_id,
                    model_params=client_local_params,
                    verbose=(E % self.args.verbose_gap) == 0,
                )

                updated_params_cache.append(updated_params)
                weights_cache.append(weight)
                self.all_clients_stats[client_id][f"ROUND: {E}"] = (
                    f"{stats['loss_before']:.4f} -> {stats['loss_after']:.4f}",
                )

            self.aggregate_parameters(updated_params_cache, weights_cache)

            if E % self.args.save_period == 0:
                torch.save(
                    self.global_params_dict, self.temp_dir / "global_model.pt",
                )
                with open(self.temp_dir / "epoch.pkl", "wb") as f:
                    pickle.dump(E, f)
        self.logger.log(self.all_clients_stats)

    @torch.no_grad()
    def aggregate_parameters(self, updated_params_cache, weights_cache):
        weight_sum = sum(weights_cache)
        weights = torch.tensor(weights_cache, device=self.device) / weight_sum

        aggregated_params = []

        for params in zip(*updated_params_cache):
            aggregated_params.append(
                torch.sum(weights * torch.stack(params, dim=-1), dim=-1)
            )

        self.global_params_dict = OrderedDict(
            zip(self.global_params_dict.keys(), aggregated_params)
        )

    def test(self) -> None:
        self.logger.log("=" * 30, "TESTING", "=" * 30, style="bold blue")
        all_loss = []
        all_acc = []
        for client_id in track(
            self.client_id_indices,
            "[bold blue]Testing...",
            console=self.logger,
            disable=self.args.log,
        ):
            client_local_params = clone_parameters(self.global_params_dict)
            stats = self.trainer.test(
                client_id=client_id, model_params=client_local_params,
            )

            self.logger.log(
                f"client [{client_id}]  [red]loss: {stats['loss']:.4f}    [magenta]accuracy: {stats['acc']:.2f}%"
            )
            all_loss.append(stats["loss"])
            all_acc.append(stats["acc"])

        self.logger.log("=" * 20, "RESULTS", "=" * 20, style="bold green")
        self.logger.log(
            "loss: {:.4f}    accuracy: {:.2f}%".format(
                sum(all_loss) / len(all_loss), sum(all_acc) / len(all_acc),
            )
        )

    def run(self):
        self.logger.log("Arguments:", dict(self.args._get_kwargs()))
        self.train()
        self.test()
        if self.args.log:
            if not os.path.isdir(LOG_DIR):
                os.mkdir(LOG_DIR)
            self.logger.save_html(LOG_DIR / self.log_name)

        # delete all temporary files
        if os.listdir(self.temp_dir) != []:
            os.system(f"rm -rf {self.temp_dir}")


from flask import render_template
from flask import request

from app import app
from app import admin
from app import database as db
from app.models.content import Note
from app.models.books import Book
from app.models.books import Subject
from app.models.contact import Contact
from app.models.blogs import Posts
from app.models import Db_Handler
from app.models import Blogs_Manager
from app.utils.admin import Authenticate
from app.utils.url_maker import make_title_from_url

brand = "Book Store"

@app.errorhandler(404)
def page_not_found(e):
    """ Handling page_not_found 404 error """
    return (
        render_template(
            "error.html",
            head=404,
            message_1="Sorry, You are Lost",
            message_2="Page is not available",
            title="404",
        ),
        404,
    )

@app.errorhandler(500)
def page_not_found(e):
    """ Handling page_not_found 404 error """
    return (
        render_template(
            "error.html",
            head=500,
            message_1="Internal Server Error",
            message_2="Sorry for Inconvince",
            title="500",
        ),
        500,
    )

@app.route("/")
@app.route("/index")
def index():

    return render_template("index.html", title="Book Store", head=brand ,notes=Db_Handler.return_notes())

@app.route("/books/<sub_>")
def book_section(sub_):
    sub = make_title_from_url(sub_)
    return render_template(
        "book.html",
        subs=Db_Handler.all_subjects(),
        posts=Db_Handler.all_books_of(sub),
        head=sub,
        title=sub,
        content=sub,
    )

@app.route("/books")
def books():
    return render_template(
        "subjects.html",
        subs=Db_Handler.all_subjects(),
        head="Books",
        title="Books - " + brand,
        content="Books - " + brand,
    )

@app.route("/about")
def about():
    return render_template(
        "about.html",
        head="About",
        title="About - " + brand,
        content="Books - " + brand,
    )

@app.route("/contact", methods=["POST", "GET"])
def contact():

    if request.method == "POST":
        name = request.form.get("name")
        email = request.form.get("email")
        message = request.form.get("message")
        a = Db_Handler.PostData(name, email, message)
        return render_template("contact.html", head=a["message"])
    return render_template("contact.html", head="Contact" , title="Contact - " + brand, content="Contact - "+ brand)

@app.route("/post/<title_>")
def post_title(title_):
    """
    Route for post with particular Title
    """
    title = make_title_from_url(title_)
    if title in Blogs_Manager.TablePost.all_title():
        return render_template(
            "post.html",
            post=Blogs_Manager.TablePost.query_by_title(title),
            content=title,
            title=title,
            head=title,
        )
    else:
        return page_not_found(404)

@app.route("/posts")
def posts():
    """ Route for all posts """
    return render_template(
        "posts.html",
        posts=Blogs_Manager.TablePost.all_query(),
        head="Blogs",
        title="Blogs - " + brand,
    )

admin.add_view(Authenticate(Subject, db.session))
admin.add_view(Authenticate(Book, db.session))
admin.add_view(Authenticate(Contact, db.session))
admin.add_view(Authenticate(Posts, db.session))
admin.add_view(Authenticate(Note, db.session))

import os
from flask import url_for

@app.context_processor
def override_url_for():
    return dict(url_for=dated_url_for)

def dated_url_for(endpoint, **values):
    if endpoint == 'static':
        filename = values.get('filename', None)
        if filename:
            file_path = os.path.join(app.root_path,
                                 endpoint, filename)
            values['q'] = int(os.stat(file_path).st_mtime)
    return url_for(endpoint, **values)


#!/usr/bin/env python

__author__ = "Adeel Ahmad"
__email__ = "adeelahmad14@hotmail.com"
__status__ = "Production"

import numpy as np

def findMaxima(acc):
    """
    :param acc: accumulator array
    :return:
        maxval: maximum value found
        ridx: row index of the maxval
        cidx: column index of the maxval
    """
    ridx, cidx = np.unravel_index(acc.argmax(), acc.shape)
    return [acc[ridx, cidx], ridx, cidx]


import paho.mqtt.client as mqtt
import time

cliente = mqtt.Client(client_id='devpy')

cliente.connect('localhost', port=1883)
cliente.subscribe('casa/sala/lampada/1')

print('Subscriber connected')

def on_message(cliente, userdata, message):
    print(message.payload.decode('uft.8'))

cliente.on_message = on_message_callback

cliente.loop_forever()
# cliente.loop_star()
# time.sleep(100)
# cliente.loop_stop()


dev_requires = [
    "pypitools",
]
install_requires = [
    "google-api-python-client",
    "google-auth-httplib2",
    "google-auth-oauthlib",
    "pytconf",
]
make_requires = [
    "pymakehelper",
    "pydmt",
    "pyclassifiers",
]
test_requires = [
    "pylint",
    "pytest",
    "pytest-cov",
    "pyflakes",
    "flake8",
    "mypy",
]


import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
from IPython.display import display
from math import pi, ceil

def make_radar(row, title, color, dframe, num_clusters):
    # number of variable
    categories=list(dframe)[1:]
    N = len(categories)

    # What will be the angle of each axis in the plot? (we divide the plot / number of variable)
    angles = [n / float(N) * 2 * pi for n in range(N)]
    angles += angles[:1]

    # Initialise the radar plot
    #ax = plt.subplot(4,ceil(num_clusters/4),row+1, polar=True, )
    ax = plt.subplot(2,ceil(num_clusters/2),row+1, polar=True, )

    # If you want the first axis to be on top:
    ax.set_theta_offset(pi / 2)
    ax.set_theta_direction(-1)

    # Draw one axe per variable + add labels labels yet
    plt.xticks(angles[:-1], categories, color='grey', size=14)

    # Draw ylabels
    ax.set_rlabel_position(0)
    plt.yticks([0.2,0.4,0.6,0.8], ["0.2","0.4","0.6","0.8"], color="grey", size=8)
    plt.ylim(0,1)

    # Ind1
    values=dframe.loc[row].drop('cluster').values.flatten().tolist()
    values += values[:1]
    ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
    ax.fill(angles, values, color=color, alpha=0.4)

    # Add a title
    plt.title(title, size=16, color=color, y=1.06)

class KMeanCollaborative:

    def __init__(self, data):
        self.initial_data = data
        self.data = pd.DataFrame()
        self.user_playlist = pd.DataFrame()
        self.initial_scaled_data = None
        self.initial_user_scaled = None
        self.model = None
        self.no_clusters = 0
        self.columns_scaled = None

    def scale_data_with_user(self, user_playlist):
        self.user_playlist = user_playlist
        x_df = self.initial_data[['danceability', 'energy', 'acousticness', 'valence', 'tempo']].values
        x_user = user_playlist[['danceability', 'energy','acousticness', 'valence', 'tempo']].values
        min_max_scaler = MinMaxScaler()
        x_df_scaled = min_max_scaler.fit_transform(x_df)
        x_user_scaled = min_max_scaler.fit_transform(x_user)

        self.columns_scaled = ['danceability_scaled', 'energy_scaled', 'acousticness_scaled','valence_scaled', 'tempo_scaled']

        self.initial_scaled_data = x_df_scaled
        self.initial_user_scaled = x_user_scaled
        self.data = pd.DataFrame(x_df_scaled, columns=self.columns_scaled)
        # self.user_playlist = pd.DataFrame(x_user_scaled, columns=self.columns_scaled)

    def analyze_data(self):
        n_clusters = range(2,21)
        ssd = []
        sc = []

        for n in n_clusters:
            km = KMeans(n_clusters=n, max_iter=300, n_init=10, init='k-means++', random_state=42)
            km.fit(self.initial_scaled_data)
            preds = km.predict(self.initial_scaled_data)
            centers = km.cluster_centers_
            ssd.append(km.inertia_)
            score = silhouette_score(self.initial_scaled_data, preds, metric='euclidean')
            sc.append(score)
            print("Number of Clusters = {}, Silhouette Score = {}".format(n, score))

        # Analyze the Silhouette scores
        plt.plot(n_clusters, sc, marker='.', markersize=12, color='red')
        plt.xlabel('Number of clusters')
        plt.ylabel('Silhouette score')
        plt.title('Silhouette score behavior over the number of clusters')
        plt.show()

        # Get the Within-Cluster sum of squares
        for n, s in zip(n_clusters, ssd):
            print('Number of Clusters = {}, Sum of Squared Distances = {}'.format(n, s))

        plt.plot(n_clusters, ssd, marker='.', markersize=12)
        plt.xlabel('Number of clusters')
        plt.ylabel('Sum of squared distances')
        plt.title('Elbow method for optimal K')
        plt.show()

    def create_clustering_model(self, k=6):
        self.no_clusters = k
        self.model = KMeans(n_clusters=k, random_state=42).fit(self.initial_scaled_data)
        pred = self.model.predict(self.initial_scaled_data)
        self.data['cluster'] = self.model.labels_

    def visualize_clusters(self):
        self.data['cluster'].value_counts().plot(kind='bar')
        plt.xlabel('Cluster')
        plt.ylabel('Amount of songs')
        plt.title('Amount of songs per cluster')
        plt.show()

        df_songs_joined = pd.concat([self.data, self.initial_data], axis=1).set_index('cluster')

        for cluster in range(self.no_clusters):
            display(df_songs_joined.loc[cluster, ['artist_name','track_name']].sample(frac=1).head(10))

        df_radar = self.data.groupby('cluster').mean().reset_index()

        plt.figure(figsize=(24,15))
        my_palette = plt.cm.get_cmap("brg", len(df_radar.index))
        # Create cluster name
        title_list = ['Speech-Energy', 'Slow-Acoustic', 'Moderate-Instrumental-Voice-Happy', 'Voice-Moderate',
                    'Voice-Dancy', 'Moderate-Instrumental-Voice-Sad']

        # Loop to plot
        for row in range(0, len(df_radar.index)):
            make_radar(row=row, title=str(df_radar['cluster'][row]) + ' : ' + title_list[row],
                    color=my_palette(row), dframe=df_radar, num_clusters=len(df_radar.index))

    def predict_users_playlist(self, show_reports = False):
        user_pred = self.model.predict(self.initial_user_scaled)
        print('User Playlist clusters: ', user_pred)

        user_cluster = pd.DataFrame(self.initial_user_scaled, columns=self.columns_scaled)
        user_cluster['cluster'] = user_pred

        user_play_r = self.user_playlist.reset_index(drop=True)
        df_user_songs_joined = pd.concat([user_cluster,user_play_r], axis=1).set_index('cluster')

        df_user_songs_joined.reset_index(inplace=True)
        cluster_pct = df_user_songs_joined.cluster.value_counts(normalize=True)*20

        if int(cluster_pct.round(0).sum()) < 20:
            cluster_pct[cluster_pct < 0.5] = cluster_pct[cluster_pct < 0.5] + 1.0

        df_user_songs_joined['cluster_pct'] = df_user_songs_joined['cluster'].apply(lambda c: cluster_pct[c])
        df_user_songs_joined.drop(columns=self.columns_scaled, inplace=True)

        df_songs_joined = pd.concat([self.data,self.initial_data], axis=1).set_index('cluster')
        df_songs_joined = df_songs_joined.reset_index(drop=False)
        playlist = pd.DataFrame()

        for ncluster, pct in cluster_pct.items():
            songs = df_songs_joined[df_songs_joined['cluster'] == ncluster].sample(n=int(round(pct, 0)))
            playlist = pd.concat([playlist,songs], ignore_index=True)
            if len(playlist) > 20 :
                flag = 20 - len(playlist)
                playlist = playlist[:flag]

        if show_reports:
            user_cluster['cluster'].value_counts().plot(kind='bar', color='green')
            plt.xlabel('Cluster')
            plt.ylabel('Amount of songs')
            plt.title('Amount of songs in the users clusters')
            plt.show()

            for cluster in user_cluster['cluster'].unique():
                display(df_user_songs_joined.loc[cluster, ['artist_name','track_name']].sample(frac=1))

            display(cluster_pct)

        return playlist[['id', 'artist_name', 'track_name', 'cluster']]


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

import pandas as pd
import numpy as np

# https://elstat-outsourcers.statistics.gr/Census2022_GR.pdf
# POPULATION_SIZE = 211593

# https://www.ypes.gr/eklogika-tmimata/
# https://www.statistics.gr/documents/20181/17286366/APOF_APOT_MON_DHM_KOIN.pdf/41ae8e6c-5860-b58e-84f7-b64f9bc53ec4
# απογραφή Πάτρας 2021: 187486
# εγγεγραμμένοι ψηφοφόροι στην Πάτρα: 132102
# εγγεγραμμένοι ψηφοφόροι στο 4ο ΔΔ Κέντρο Πάτρας: 62143
# ==> πληθυσμός 4ου ΔΔ Πάτρας: 88225

# TOTAL_SCHOOLS = 150
# NUM_WORKPLACES = 12500
# POPULATION_SIZE = 10000
POPULATION_SIZE = 88225

TOTAL_SCHOOLS = 8 * 8
NUM_WORKPLACES = 600 * 8

# Create a dataframe with POPULATION_SIZE rows and 5 columns
df = pd.DataFrame(np.random.randint(0,100,size=(POPULATION_SIZE, 5)), columns=['Gender', 'Age', 'Family_ID', 'Work_ID', 'School_ID'])

# Display the dataframe
print(df)

"""read an external csv file "PatrasPopulation.csv" in a new dataframe 'rdf' and keep the columns ['age_group', 'population', 'Mpop', 'Fpop']"""

# Read the CSV file into a dataframe, keeping only the desired columns
rdf = pd.read_csv("PatrasPopulation.csv", usecols=['age_group', 'population', 'Mpop', 'Fpop'])

# Display the dataframe
print(rdf.head())

"""calculate female ratio from rdf dataframe, if 'Fpop' is the total number of females and 'population' is the total population"""

# Calculate the female ratio
rdf['female_ratio'] = rdf['Fpop'] / rdf['population']

# Display the dataframe
print(rdf)

"""in the df dataframe, replace the elements of the 'Gender' column, according to their df['Age'] and rdf['female_ratio'], as follows: if df['Gender'] is below rdf['female_ratio'], than make it 0 (thus female), else make it 1 (thus male)

"""

# import numpy as np

# Define a function that takes a row of the dataframe and returns a new value for the 'Gender' column
def update_gender(row):
    # Get the female ratio for the corresponding age group
    p = rdf[rdf['age_group'] == row['Age']]['female_ratio'].iloc[0]

    # Sample from a binomial distribution with probability p
    return np.random.binomial(1, p)

# Apply the function to each row of the dataframe
df['Gender'] = df.apply(update_gender, axis=1)

# Display the dataframe
# df

# df.describe()

# df

import random

# Calculate the total population and the population weights
age_groups = rdf['age_group']
population = rdf['population']
total_population = sum(population)
population_weights = population / total_population

population_weights.plot()

# Sample from the categorical distribution defined by the age groups and population weights
samples = random.choices(age_groups, population_weights, k=POPULATION_SIZE)

# Round the values in the 'Age' column to the nearest integer
df['Age'] = round(df['Age'])

# Map the values in the 'Age' column to the corresponding age groups
df['Age'] = df['Age'].map(age_groups)

# df

"""now, read an external scv file "familySizeGreece.csv" and specifically the columns 'family_size' and 'family_sum'. Calculate the percentage of being a member of a family size from 1 to 10

"""

# import pandas as pd

# Read the CSV file into a dataframe
psdf = pd.read_csv('familySizeGreece.csv')

# Select the 'family_size' and 'family_sum' columns
psdf = psdf[['family_size', 'family_sum']]

# Calculate the percentage of being a member of each family size
psdf['percentage'] = psdf['family_sum'] / psdf['family_sum'].sum()

# Filter the dataframe to include only family sizes from 1 to 10
psdf = psdf[psdf['family_size'].between(1, 10)]

# Save the resulting dataframe as a variable named 'population_weights'
population_weights = psdf

# Display the 'population_weights' dataframe
population_weights

# import random

# Extract the family sizes and percentages from the 'population_weights' dataframe
family_sizes = population_weights['family_size'].tolist()
family_weights = population_weights['percentage'].tolist()

# Iterate over the 'df' dataframe
for index, row in df.iterrows():
    # Sample a family size from the categorical distribution defined by the family sizes and percentages
    family_size = random.choices(family_sizes, family_weights)[0]

    # Assign the same 'Family_ID' value to the members of the same family
    df.at[index, 'Family_ID'] = index // family_size + 1

df = df.sort_values('Family_ID')

# Display the resulting dataframe
df

# import pandas as pd

# Find the maximum 'Family_ID' value
max_family_id = df['Family_ID'].max()

# Replace the missing values in the 'Family_ID' column with a sequence of integers from 1 to the maximum 'Family_ID' value
df['Family_ID'] = df['Family_ID'].fillna(pd.Series(range(1, max_family_id+1)))

# Display the resulting dataframe
df

# Count the number of unique 'Family_ID' values in the 'df' dataframe
num_families = df['Family_ID'].nunique()

# Print the result
print(f"Number of families: {num_families}")

# import numpy as np
# import random

# https://www.kathimerini.gr/economy/562220620/eurostat-sto-11-4-i-anergia-ton-noemvrio/
UNEMPLOYMENT_RATE = 0.114

# Create a new column in the 'df' dataframe called 'Work_Status'
df['Work_Status'] = np.nan

# Assign a 'Work_Status' value of -1 to members of the population under 18 years old
df['Work_Status'] = np.where(df['Age'] < 18, -1, df['Work_Status'])

# Assign a 'Work_Status' value of -2 to members of the population over 65 years old
df['Work_Status'] = np.where(df['Age'] > 65, -2, df['Work_Status'])

# Iterate over the 'df' dataframe
for index, row in df.iterrows():
    # Generate a random number between 0 and 1
    rnd = random.random()

    # If the random number is less than the unemployment rate and the 'Work_Status' value is 'NaN', assign a 'Work_Status' value of 0 (unemployed)
    if (rnd < UNEMPLOYMENT_RATE) & np.isnan(df.at[index, 'Work_Status']):
        df.at[index, 'Work_Status'] = 0
    # Otherwise, if the 'Work_Status' value is 'NaN', assign a 'Work_Status' value of 1 (employed)
    elif np.isnan(df.at[index, 'Work_Status']):
        df.at[index, 'Work_Status'] = 1

# Cast the 'Work_Status' column to the 'int' type
df['Work_Status'] = df['Work_Status'].astype(int)

# Display the resulting dataframe
df

"""assign each member a school status based on the following rules:
if 'Age' >= 18 then 'School_Status' is 0
else if 'Age' >= 15 then 'School_Status' is 1
else if 'Age' >= 12 then 'School_Status' is 2
else if 'Age' >= 6 then 'School_Status' is 3
else if 'Age' >= 4 then 'School_Status' is 4
else if 'Age' >= 2 then 'School_Status' is 5
else 'School_Status' is 6

"""

# import numpy as np

# Create a new column in the 'df' dataframe called 'School_Status'
df['School_Status'] = np.nan

# Assign a 'School_Status' value of 0 to members of the population 18 years old or older
df['School_Status'] = np.where(df['Age'] >= 18, 0, df['School_Status'])

# Assign a 'School_Status' value of 1 to members of the population 15 to 17 years old
df['School_Status'] = np.where((df['Age'] >= 15) & (df['Age'] < 18), 1, df['School_Status'])

# Assign a 'School_Status' value of 2 to members of the population 12 to 14 years old
df['School_Status'] = np.where((df['Age'] >= 12) & (df['Age'] < 15), 2, df['School_Status'])

# Assign a 'School_Status' value of 3 to members of the population 6 to 11 years old
df['School_Status'] = np.where((df['Age'] >= 6) & (df['Age'] < 12), 3, df['School_Status'])

# Assign a 'School_Status' value of 4 to members of the population 4 to 5 years old
df['School_Status'] = np.where((df['Age'] >= 4) & (df['Age'] < 6), 4, df['School_Status'])

# Assign a 'School_Status' value of 5 to members of the population 2 to 3 years old
df['School_Status'] = np.where((df['Age'] >= 2) & (df['Age'] < 4), 5, df['School_Status'])

# Assign a 'School_Status' value of 6 to members of the population under 2 years old
df['School_Status'] = np.where(df['Age'] < 2, 6, df['School_Status'])

df['School_Status'] = df['School_Status'].astype(int)

# Display the resulting dataframe
df

# Create a new column in the 'df' dataframe called 'Work_ID'
# df['Work_ID'] = np.nan

# Assign a 'Work_ID' value of NaN to members of the population with a 'Work_Status' value of -2, -1, or 0
df['Work_ID'] = np.where((df['Work_Status'] == -2) | (df['Work_Status'] == -1) | (df['Work_Status'] == 0), np.nan, df['Work_ID'])

df

# Calculate the total number of employees in the 'df' dataframe
total_num_employees = df[df['Work_Status'] == 1]['Work_Status'].sum()

# Print the total number of employees
print(f'Total number of employees: {total_num_employees}')

"""create a new dataframe wdf
Poisson distribution of workers in workplaces based on number / workplace
we make these assumptions:
i. average employee 4.1 arbitrary
ii. minimum number of employees: 1 and maximum: 15 arbitrary
iii. the total number of employees is equal to total_num_employees
"""

# import numpy as np
# import pandas as pd

# Set the mean number of employees per workplace
mean_employees_per_workplace = 4.1

# Set the minimum and maximum number of employees per workplace
min_employees_per_workplace = 1
max_employees_per_workplace = 15

# Calculate the number of workplaces based on the total number of employees and the mean number of employees per workplace
num_workplaces = int(total_num_employees / mean_employees_per_workplace)

# Generate random numbers that follow a Poisson distribution with the mean number of employees per workplace
employees_per_workplace = np.random.poisson(mean_employees_per_workplace, size=num_workplaces)

# Ensure that the number of employees per workplace is within the specified range
employees_per_workplace = np.clip(employees_per_workplace, min_employees_per_workplace, max_employees_per_workplace)

# Create the 'wdf' dataframe with the number of employees per workplace
wdf = pd.DataFrame({'Workplace_ID': np.arange(num_workplaces), 'Num_Employees': employees_per_workplace})

# Display the 'wdf' dataframe
wdf

# Calculate the total number of employees in the 'wdf' dataframe
total_num_employees = wdf['Num_Employees'].sum()

# Print the total number of employees
print(f'Total number of employees: {total_num_employees}')

# import pandas as pd
# Create a list of the possible school IDs
school_ids = [i for i in range(1, TOTAL_SCHOOLS+1)]

# Create a list of the possible work IDs
work_ids = [i for i in range(1, NUM_WORKPLACES+1)]

# Initialize the school and work IDs for each person to be 'None'
df['School_ID'] = None
df['Work_ID'] = None

# Set the school and work IDs for each person based on their age and work status
for i, row in df.iterrows():
    if row['Work_Status'] == 1:
    # For working people, assign a random work ID
        df.at[i, 'Work_ID'] = random.choice(work_ids)
        df.at[i, 'School_ID'] = None

    elif row['Age'] < 18:
    # For people under 18, assign a random school ID
        df.at[i, 'School_ID'] = random.choice(school_ids)
        df.at[i, 'Work_ID'] = None

    else:
    # For people over 65, assign a 'pension' work ID
        df.at[i, 'Work_ID'] = None
        df.at[i, 'School_ID'] = None
df

df[df['School_ID'] == 77].head(10)

# Check that all people have a Work_ID or School_ID
print((df['Work_ID'].isnull() & df['School_ID'].isnull()).any())

# Count the number of people with each Work_ID
work_id_counts = df['Work_ID'].value_counts()

# Print the count of people with each Work_ID
print(work_id_counts)

# Count the number of people with each School_ID
school_id_counts = df['School_ID'].value_counts()

# Print the count of people with each School_ID
print(school_id_counts)

df.to_csv('df.csv', index=False)
df

df.describe()


import regex as re
from typing import List

PUNC_SET= {'!', '"', "'", '(', ')', ',', '-', '.', ':', ';', '<', '>', '?', '[', ']', '{', '}', \
           '·', '—', '‘', '’', '“', '”', '、', '。', '《', '》', '「', '」', '『', '』', '【', '】', \
           '〔', '〕', '﹃', '﹄', '！', '（', '）', '，', '：', '；', '？'}

def lang_detect(text):
    ''' 语种识别: 中文(zh)/英文(en)
    '''
    def is_contains_chinese(strs):
        for _char in strs:
            if '\u4e00' <= _char <= '\u9fa5':
                return True
        return False

    if is_contains_chinese(text):
        return 'zh'
    else:
        return 'en'

def split_sentence(document: str, flag: str = "all", limit: int = 510) -> List[str]:
    """
    Args:
        document:
        flag: Type:str, "all" 中英文标点分句，"zh" 中文标点分句，"en" 英文标点分句
        limit: 默认单句最大长度为510个字符
    Returns: Type:list
    """
    sent_list = []
    try:
        if flag == "zh":
            document = re.sub('(?P<quotation_mark>([。？！…](?![”’"\'])))',
                               r'\g<quotation_mark>\n', document)  # 单字符断句符
            document = re.sub('(?P<quotation_mark>([。？！]|…{1,2})[”’"\'])',
                               r'\g<quotation_mark>\n', document)  # 特殊引号
        elif flag == "en":
            document = re.sub('(?P<quotation_mark>([.?!](?![”’"\'])))',
                               r'\g<quotation_mark>\n', document)  # 英文单字符断句符
            document = re.sub('(?P<quotation_mark>([?!.]["\']))',
                               r'\g<quotation_mark>\n', document)  # 特殊引号
        else:
            document = re.sub('(?P<quotation_mark>([。？！….?!](?![”’"\'])))',
                               r'\g<quotation_mark>\n', document)  # 单字符断句符
            document = re.sub('(?P<quotation_mark>(([。？！.!?]|…{1,2})[”’"\']))',
                               r'\g<quotation_mark>\n', document)  # 特殊引号

        sent_list_ori = document.splitlines()
        for sent in sent_list_ori:
            sent = sent.strip()
            if not sent:
                continue
            else:
                while len(sent) > limit:
                    temp = sent[0:limit]
                    sent_list.append(temp)
                    sent = sent[limit:]
                sent_list.append(sent)
    except:
        sent_list.clear()
        sent_list.append(document)

    merge_list = []
    sent_list_length = len(sent_list)
    i = 0
    while i<sent_list_length:
        if len(sent_list[i]) <= 4 and i<(sent_list_length-1):
            merge_list.append(sent_list[i]+sent_list[i+1])
            i += 2
        else:
            merge_list.append(sent_list[i])
            i += 1

    return merge_list


import pytest
from django.db import connection, transaction

from .helpers import DjangoPytester

from pytest_django_test.app.models import Item, SecondItem

def db_supports_reset_sequences() -> bool:
    """Return if the current db engine supports `reset_sequences`."""
    ret: bool = (
        connection.features.supports_transactions
        and connection.features.supports_sequence_reset
    )
    return ret

def test_noaccess() -> None:
    with pytest.raises(RuntimeError):
        Item.objects.create(name="spam")
    with pytest.raises(RuntimeError):
        Item.objects.count()

@pytest.fixture
def noaccess() -> None:
    with pytest.raises(RuntimeError):
        Item.objects.create(name="spam")
    with pytest.raises(RuntimeError):
        Item.objects.count()

def test_noaccess_fixture(noaccess: None) -> None:
    # Setup will fail if this test needs to fail
    pass

@pytest.fixture
def non_zero_sequences_counter(db: None) -> None:
    """Ensure that the db's internal sequence counter is > 1.

    This is used to test the `reset_sequences` feature.
    """
    item_1 = Item.objects.create(name="item_1")
    item_2 = Item.objects.create(name="item_2")
    item_1.delete()
    item_2.delete()

class TestDatabaseFixtures:
    """Tests for the different database fixtures."""

    @pytest.fixture(params=[
        "db",
        "transactional_db",
        "django_db_reset_sequences",
        "django_db_serialized_rollback",
    ])
    def all_dbs(self, request: pytest.FixtureRequest) -> None:
        if request.param == "django_db_reset_sequences":
            request.getfixturevalue("django_db_reset_sequences")
        elif request.param == "transactional_db":
            request.getfixturevalue("transactional_db")
        elif request.param == "db":
            request.getfixturevalue("db")
        elif request.param == "django_db_serialized_rollback":
            request.getfixturevalue("django_db_serialized_rollback")
        else:
            assert False  # pragma: no cover

    def test_access(self, all_dbs: None) -> None:
        Item.objects.create(name="spam")

    def test_clean_db(self, all_dbs: None) -> None:
        # Relies on the order: test_access created an object
        assert Item.objects.count() == 0

    def test_transactions_disabled(self, db: None) -> None:
        if not connection.features.supports_transactions:
            pytest.skip("transactions required for this test")

        assert connection.in_atomic_block

    def test_transactions_enabled(self, transactional_db: None) -> None:
        if not connection.features.supports_transactions:
            pytest.skip("transactions required for this test")

        assert not connection.in_atomic_block

    def test_transactions_enabled_via_reset_seq(
        self, django_db_reset_sequences: None,
    ) -> None:
        if not connection.features.supports_transactions:
            pytest.skip("transactions required for this test")

        assert not connection.in_atomic_block

    def test_django_db_reset_sequences_fixture(
        self, db: None, django_pytester: DjangoPytester, non_zero_sequences_counter: None,
    ) -> None:

        if not db_supports_reset_sequences():
            pytest.skip(
                "transactions and reset_sequences must be supported "
                "by the database to run this test"
            )

        # The test runs on a database that already contains objects, so its
        # id counter is > 1. We check for the ids of newly created objects.
        django_pytester.create_test_module(
            """
            import pytest
            from .app.models import Item

            def test_django_db_reset_sequences_requested(
                    django_db_reset_sequences):
                item = Item.objects.create(name='new_item')
                assert item.id == 1
        """
        )

        result = django_pytester.runpytest_subprocess("-v", "--reuse-db")
        result.stdout.fnmatch_lines(
            ["*test_django_db_reset_sequences_requested PASSED*"]
        )

    def test_serialized_rollback(self, db: None, django_pytester: DjangoPytester) -> None:
        django_pytester.create_app_file(
            """
            from django.db import migrations

            def load_data(apps, schema_editor):
                Item = apps.get_model("app", "Item")
                Item.objects.create(name="loaded-in-migration")

            class Migration(migrations.Migration):
                dependencies = [
                    ("app", "0001_initial"),
                ]

                operations = [
                    migrations.RunPython(load_data),
                ]
            """,
            "migrations/0002_data_migration.py",
        )

        django_pytester.create_test_module(
            """
            import pytest
            from .app.models import Item

            @pytest.mark.django_db(transaction=True, serialized_rollback=True)
            def test_serialized_rollback_1():
                assert Item.objects.filter(name="loaded-in-migration").exists()

            @pytest.mark.django_db(transaction=True)
            def test_serialized_rollback_2(django_db_serialized_rollback):
                assert Item.objects.filter(name="loaded-in-migration").exists()
                Item.objects.create(name="test2")

            @pytest.mark.django_db(transaction=True, serialized_rollback=True)
            def test_serialized_rollback_3():
                assert Item.objects.filter(name="loaded-in-migration").exists()
                assert not Item.objects.filter(name="test2").exists()
            """
        )

        result = django_pytester.runpytest_subprocess("-v")
        assert result.ret == 0

    @pytest.fixture
    def mydb(self, all_dbs: None) -> None:
        # This fixture must be able to access the database
        Item.objects.create(name="spam")

    def test_mydb(self, mydb: None) -> None:
        if not connection.features.supports_transactions:
            pytest.skip("transactions required for this test")

        # Check the fixture had access to the db
        item = Item.objects.get(name="spam")
        assert item

    def test_fixture_clean(self, all_dbs: None) -> None:
        # Relies on the order: test_mydb created an object
        # See https://github.com/pytest-dev/pytest-django/issues/17
        assert Item.objects.count() == 0

    @pytest.fixture
    def fin(self, request: pytest.FixtureRequest, all_dbs: None) -> None:
        # This finalizer must be able to access the database
        request.addfinalizer(lambda: Item.objects.create(name="spam"))

    def test_fin(self, fin: None) -> None:
        # Check finalizer has db access (teardown will fail if not)
        pass

    def test_durable_transactions(self, all_dbs: None) -> None:
        with transaction.atomic(durable=True):
            item = Item.objects.create(name="foo")
        assert Item.objects.get() == item

class TestDatabaseFixturesAllOrder:
    @pytest.fixture
    def fixture_with_db(self, db: None) -> None:
        Item.objects.create(name="spam")

    @pytest.fixture
    def fixture_with_transdb(self, transactional_db: None) -> None:
        Item.objects.create(name="spam")

    @pytest.fixture
    def fixture_with_reset_sequences(self, django_db_reset_sequences: None) -> None:
        Item.objects.create(name="spam")

    @pytest.fixture
    def fixture_with_serialized_rollback(self, django_db_serialized_rollback: None) -> None:
        Item.objects.create(name="ham")

    def test_trans(self, fixture_with_transdb: None) -> None:
        pass

    def test_db(self, fixture_with_db: None) -> None:
        pass

    def test_db_trans(self, fixture_with_db: None, fixture_with_transdb: None) -> None:
        pass

    def test_trans_db(self, fixture_with_transdb: None, fixture_with_db: None) -> None:
        pass

    def test_reset_sequences(
        self,
        fixture_with_reset_sequences: None,
        fixture_with_transdb: None,
        fixture_with_db: None,
    ) -> None:
        pass

    # The test works when transactions are not supported, but it interacts
    # badly with other tests.
    @pytest.mark.skipif('not connection.features.supports_transactions')
    def test_serialized_rollback(
        self,
        fixture_with_serialized_rollback: None,
        fixture_with_db: None,
    ) -> None:
        pass

class TestDatabaseMarker:
    "Tests for the django_db marker."

    @pytest.mark.django_db
    def test_access(self) -> None:
        Item.objects.create(name="spam")

    @pytest.mark.django_db
    def test_clean_db(self) -> None:
        # Relies on the order: test_access created an object.
        assert Item.objects.count() == 0

    @pytest.mark.django_db
    def test_transactions_disabled(self) -> None:
        if not connection.features.supports_transactions:
            pytest.skip("transactions required for this test")

        assert connection.in_atomic_block

    @pytest.mark.django_db(transaction=False)
    def test_transactions_disabled_explicit(self) -> None:
        if not connection.features.supports_transactions:
            pytest.skip("transactions required for this test")

        assert connection.in_atomic_block

    @pytest.mark.django_db(transaction=True)
    def test_transactions_enabled(self) -> None:
        if not connection.features.supports_transactions:
            pytest.skip("transactions required for this test")

        assert not connection.in_atomic_block

    @pytest.mark.django_db
    def test_reset_sequences_disabled(self, request: pytest.FixtureRequest) -> None:
        marker = request.node.get_closest_marker("django_db")
        assert not marker.kwargs

    @pytest.mark.django_db(reset_sequences=True)
    def test_reset_sequences_enabled(self, request: pytest.FixtureRequest) -> None:
        marker = request.node.get_closest_marker("django_db")
        assert marker.kwargs["reset_sequences"]

    @pytest.mark.django_db(transaction=True, reset_sequences=True)
    def test_transaction_reset_sequences_enabled(self, request: pytest.FixtureRequest) -> None:
        marker = request.node.get_closest_marker("django_db")
        assert marker.kwargs["reset_sequences"]

    @pytest.mark.django_db(databases=['default', 'replica', 'second'])
    def test_databases(self, request: pytest.FixtureRequest) -> None:
        marker = request.node.get_closest_marker("django_db")
        assert marker.kwargs["databases"] == ['default', 'replica', 'second']

    @pytest.mark.django_db(databases=['second'])
    def test_second_database(self, request: pytest.FixtureRequest) -> None:
        SecondItem.objects.create(name="spam")

    @pytest.mark.django_db(databases=['default'])
    def test_not_allowed_database(self, request: pytest.FixtureRequest) -> None:
        with pytest.raises(AssertionError, match='not allowed'):
            SecondItem.objects.count()
        with pytest.raises(AssertionError, match='not allowed'):
            SecondItem.objects.create(name="spam")

    @pytest.mark.django_db(databases=['replica'])
    def test_replica_database(self, request: pytest.FixtureRequest) -> None:
        Item.objects.using('replica').count()

    @pytest.mark.django_db(databases=['replica'])
    def test_replica_database_not_allowed(self, request: pytest.FixtureRequest) -> None:
        with pytest.raises(AssertionError, match='not allowed'):
            Item.objects.count()

    @pytest.mark.django_db(transaction=True, databases=['default', 'replica'])
    def test_replica_mirrors_default_database(self, request: pytest.FixtureRequest) -> None:
        Item.objects.create(name='spam')
        Item.objects.using('replica').create(name='spam')

        assert Item.objects.count() == 2
        assert Item.objects.using('replica').count() == 2

    @pytest.mark.django_db(databases='__all__')
    def test_all_databases(self, request: pytest.FixtureRequest) -> None:
        Item.objects.count()
        Item.objects.create(name="spam")
        SecondItem.objects.count()
        SecondItem.objects.create(name="spam")

    @pytest.mark.django_db
    def test_serialized_rollback_disabled(self, request: pytest.FixtureRequest):
        marker = request.node.get_closest_marker("django_db")
        assert not marker.kwargs

    # The test works when transactions are not supported, but it interacts
    # badly with other tests.
    @pytest.mark.skipif('not connection.features.supports_transactions')
    @pytest.mark.django_db(serialized_rollback=True)
    def test_serialized_rollback_enabled(self, request: pytest.FixtureRequest):
        marker = request.node.get_closest_marker("django_db")
        assert marker.kwargs["serialized_rollback"]

    @pytest.mark.django_db
    def test_available_apps_disabled(self, request: pytest.FixtureRequest) -> None:
        marker = request.node.get_closest_marker("django_db")
        assert not marker.kwargs

    @pytest.mark.django_db(available_apps=['pytest_django_test.app'])
    def test_available_apps_enabled(self, request: pytest.FixtureRequest) -> None:
        marker = request.node.get_closest_marker("django_db")
        assert marker.kwargs["available_apps"] == ['pytest_django_test.app']

    @pytest.mark.django_db
    def test_available_apps_default(self, request: pytest.FixtureRequest) -> None:
        from django.apps import apps
        from django.conf import settings

        for app in settings.INSTALLED_APPS:
            assert apps.is_installed(app)

    @pytest.mark.django_db(available_apps=['pytest_django_test.app'])
    def test_available_apps_limited(self, request: pytest.FixtureRequest) -> None:
        from django.apps import apps
        from django.conf import settings

        assert apps.is_installed("pytest_django_test.app")

        for app in settings.INSTALLED_APPS:
            if app != "pytest_django_test.app":
                assert not apps.is_installed(app)

def test_unittest_interaction(django_pytester: DjangoPytester) -> None:
    "Test that (non-Django) unittests cannot access the DB."

    django_pytester.create_test_module(
        """
        import pytest
        import unittest
        from .app.models import Item

        class TestCase_setupClass(unittest.TestCase):
            @classmethod
            def setUpClass(cls):
                Item.objects.create(name='foo')

            def test_db_access_1(self):
                Item.objects.count() == 1

        class TestCase_setUp(unittest.TestCase):
            @classmethod
            def setUp(cls):
                Item.objects.create(name='foo')

            def test_db_access_2(self):
                Item.objects.count() == 1

        class TestCase(unittest.TestCase):
            def test_db_access_3(self):
                Item.objects.count() == 1
    """
    )

    result = django_pytester.runpytest_subprocess("-v", "--reuse-db")
    result.stdout.fnmatch_lines(
        [
            "*test_db_access_1 ERROR*",
            "*test_db_access_2 FAILED*",
            "*test_db_access_3 FAILED*",
            "*ERROR at setup of TestCase_setupClass.test_db_access_1*",
            '*RuntimeError: Database access not allowed, use the "django_db" mark, '
            'or the "db" or "transactional_db" fixtures to enable it.',
        ]
    )

class Test_database_blocking:
    def test_db_access_in_conftest(self, django_pytester: DjangoPytester) -> None:
        """Make sure database access in conftest module is prohibited."""

        django_pytester.makeconftest(
            """
            from tpkg.app.models import Item
            Item.objects.get()
        """
        )

        result = django_pytester.runpytest_subprocess("-v")
        result.stderr.fnmatch_lines(
            [
                '*RuntimeError: Database access not allowed, use the "django_db" mark, '
                'or the "db" or "transactional_db" fixtures to enable it.*'
            ]
        )

    def test_db_access_in_test_module(self, django_pytester: DjangoPytester) -> None:
        django_pytester.create_test_module(
            """
            from tpkg.app.models import Item
            Item.objects.get()
        """
        )

        result = django_pytester.runpytest_subprocess("-v")
        result.stdout.fnmatch_lines(
            [
                '*RuntimeError: Database access not allowed, use the "django_db" mark, '
                'or the "db" or "transactional_db" fixtures to enable it.'
            ]
        )


'''
Em Python tudo é um objeto: incluindo classes
Metaclasses são as "classes" que criam classes.
type é uma metaclasse
'''

class Pai:
    nome = 'Ola'

A = type(
    'A',
    (Pai,),
    {
        'attr': 'Olá Mundo'
    }
)

a = A()
print(a.nome)
print(a.attr)


from rest_framework.routers import DefaultRouter
from .views import TransacaoPorPedidoListView, AfiliadoDetailViewAlteracaoPagamento, ModelFinanceiroViewSet, ClienteDetailViewAlteracaoPagamento, TransacaoAfiliadoAdministradorViewSet
from django.urls import path

app_name = 'financeiro'

router = DefaultRouter(trailing_slash=False) #False para nao precisar colocar / no final
router.register(r'financeiro', ModelFinanceiroViewSet)
router.register(r'financeiro-afiliado', TransacaoAfiliadoAdministradorViewSet)

urlpatterns = [
    # ... adicione suas URLs personalizadas aqui
    path('alterar-status-pg/<int:pedido__id>/', ClienteDetailViewAlteracaoPagamento.as_view(), name='alterar-status'),
    path('alterar-status-afiliado/<int:pedido__id>/', AfiliadoDetailViewAlteracaoPagamento.as_view(), name='alterar-status-afiliado'),
    path('transacoes/pedido/<int:id_pedido>/', TransacaoPorPedidoListView.as_view(), name='transacao-por-pedido'),
]

urlpatterns += router.urls


""" Tests for core_raster.py """
# pylint: disable=missing-function-docstring, bare-except

# Standard library
import os
import sys; sys.path.append("../")

# External
from osgeo import ogr

# Internal
from utils_tests import create_sample_vector
from buteo.vector.reproject import vector_reproject

tmpdir = "./tests/tmp/"

sample_vector_wgs84 = create_sample_vector(geom_type="point", num_features=10, epsg_code=4326)
sample_vector_mercator = create_sample_vector(geom_type="point", num_features=10, epsg_code=3857)

def test_vector_reproject_basic():
    reprojected = vector_reproject(
        sample_vector_wgs84,
        sample_vector_mercator,
        out_path="./tests/tmp/reprojected.gpkg",
        overwrite=True,
    )

    assert reprojected is not None, "Reprojected vector is None"

    # Check if the reprojected vector has the same feature count as the input vector
    assert (
        ogr.Open(reprojected).GetLayer().GetFeatureCount()
        == ogr.Open(sample_vector_mercator).GetLayer().GetFeatureCount()
    ), "Reprojected vector has different feature count than input vector"

    # Check if the reprojected vector has the same geometry type as the input vector
    assert (
        ogr.Open(reprojected).GetLayer().GetGeomType()
        == ogr.Open(sample_vector_mercator).GetLayer().GetGeomType()
    ), "Reprojected vector has different geometry type than input vector"

    # Check if the reprojected vector has the same spatial reference as the input vector
    assert (
        ogr.Open(reprojected).GetLayer().GetSpatialRef().ExportToWkt()
        == ogr.Open(sample_vector_mercator).GetLayer().GetSpatialRef().ExportToWkt()
    ), "Reprojected vector has different spatial reference than input vector"

    os.remove(reprojected)


from django.urls import path
from .views import files, fileConverion, download_file, download_zip_files, view_file, Profile

urlpatterns = [
    # path('', files),

    # path('admin/', files, name='admin'),

    path('conversion/', files, name='files'),
    path('fileconverter/',fileConverion, name='fileconverter'),
    path('profile/', Profile, name='home'),

]


# Find the Sum of Numbers in a given Range in Python
# Method 1: Using Brute Force
# In this method we’ll use loops like for, while and do while to sum all the numbers that lay in the intervals of the given input integers.
def sum_of_natural(x,y):
    sum=0
    for i in range(x,y+1):
        sum+=i
    return sum
x=int(input('enter the starting number: '))
y=int(input('enter the ending number: '))
print(sum_of_natural(x,y))

# Method 2: Using the Formula
# In this method we’ll use formula mentioned below to find the sum of all the numbers that lay in the interval given by the input variable.
def sum_of_range(x,y):
    a=(((y*(y+1))//2)-(x*(x+1)//2)+x)
    print(a)

x=int(input('enter the starting number: '))
y=int(input('enter the ending number: '))
sum_of_range(x,y)

# Method 3: Using Recursion
# In this method we’ll use recursion to find the sum of all the numbers that lay in the interval given by the input variable. To know more about recursion, refer to Recursion in Python.
def sum_of_range(sum,x,y):
    if x>y:
        return sum
    return x+sum_of_range(sum,x+1,y)

sum=0
x=int(input('enter the starting number: '))
y=int(input('enter the ending number: '))
print(sum_of_range(sum,x,y))


# preliminary implementation for variants of slice samplers

import numpy as np

from . import sphere

# some nice colors
colors = [
    (0.85, 0.3, 0.1),
    (0.15, 0.35, 0.6),
    (0.95, 0.7, 0.1),
    (0.0, 0.0, 0.0),
    (0.8, 0.8, 0.8),
]

def sample_slice(log_prob, current, bounds, return_n_reject=False):
    """
    Bracketing procedure as presented in the paper.
    """
    threshold = log_prob(current) + np.log(np.random.rand())
    L, R = bounds
    x = np.random.uniform(0, 2 * np.pi)
    L, R = x - 2 * np.pi, x
    n_reject = 0

    while True:
        x = np.random.uniform(L, R)
        if log_prob(x) > threshold:
            if return_n_reject:
                return x, n_reject
            else:
                return x
        elif x < current:
            L = x
        else:
            R = x
        n_reject += 1

def sample_slice2(log_prob, current, bounds):
    """
    Alternative version in which the brackets are first shifted.
    """
    threshold = log_prob(current) + np.log(np.random.rand())
    x = np.random.uniform(*bounds)
    L, R = x + bounds[0], x + bounds[1]

    while True:
        if log_prob(x) > threshold:
            return x
        elif x < current:
            L = x
        else:
            R = x
        x = np.random.uniform(L, R)

def metropolis_hastings(
    pdf, n_samples, stepsize=0.5, adapt_stepsize=False, reproject=True
):
    """
    Sample hyperspherical distribution with Metropolis Hastings.
    """
    samples = []
    x = sphere.sample_sphere(pdf.d - 1)
    n_acc = 0

    while len(samples) < n_samples:
        # propose
        r = np.sqrt(np.random.gamma(0.5 * len(x)) / 0.5) if reproject else 1.0
        y = sphere.radial_projection(r * x + stepsize * np.random.randn(pdf.d))

        # accept / reject
        accept = np.log(np.random.rand()) < pdf.log_prob(y) - pdf.log_prob(x)
        x = y if accept else x

        # adapt stepsize
        if adapt_stepsize:
            stepsize *= 1.02 if accept else 0.98

        samples.append(np.copy(x))
        n_acc += int(accept)

    print(f"stepsize: {stepsize}, acceptance rate: {(n_acc/n_samples):.1%}")

    return np.array(samples)

def slice_sampling(pdf, n_samples=1e3):
    """
    Slice sampling on the sphere using first bracketing procedure.
    """
    bounds = (-np.pi, np.pi)

    # initialization
    v = sphere.sample_sphere(pdf.d - 1)
    samples = [v]
    n_reject = []

    while len(samples) < n_samples:
        # draw uniformly from subsphere
        u = sphere.sample_subsphere(v)

        # define probability on slice
        def log_prob(theta, pdf=pdf, v=v, u=u):
            return pdf.log_prob(np.cos(theta) * v + np.sin(theta) * u)

        # slice sampling using first bracketing procedure starting at current
        # sample (corresponding to theta=0)
        theta, n = sample_slice(log_prob, 0.0, bounds, return_n_reject=True)

        v = np.cos(theta) * v + np.sin(theta) * u

        samples.append(v)
        n_reject.append(n)

    print(f"average number of rejections: {np.mean(n_reject)}")

    return np.array(samples)

def slice_sampling2(pdf, n_samples=1e3):
    """
    Slice sampling on the sphere using second bracketing procedure.
    """
    bounds = (-np.pi, np.pi)

    # initialization
    v = sphere.sample_sphere(pdf.d - 1)
    samples = [v]
    n_reject = []

    while len(samples) < n_samples:
        # draw uniformly from subsphere
        u = sphere.sample_subsphere(v)

        # define probability on slice
        def log_prob(theta, pdf=pdf, v=v, u=u):
            return pdf.log_prob(np.cos(theta) * v + np.sin(theta) * u)

        # slice sampling using second bracketing procedure starting at current
        # sample (corresponding to theta=0)
        theta, n = sample_slice2(log_prob, 0.0, bounds, return_n_reject=True)

        v = np.cos(theta) * v + np.sin(theta) * u

        samples.append(v)
        n_reject.append(n)

    print(f"average number of rejections: {np.mean(n_reject)}")

    return np.array(samples)

def slice_sampling3(pdf, n_samples=1e3):
    """
    Slice sampling on the sphere using slerp and bracketing.
    """
    # initialization
    v = sphere.sample_sphere(pdf.d - 1)

    samples = [v]
    n_reject = []

    while len(samples) < n_samples:
        # draw uniformly from sphere
        u = sphere.sample_sphere(pdf.d - 1)

        # slerp
        slerp = sphere.slerp(u, v)
        theta = np.arccos(u @ v)  # - 0.5 * np.pi

        bounds = (theta - np.pi, theta + np.pi)

        # define probability on slice
        def log_prob(theta, pdf=pdf, slerp=slerp):
            return pdf.log_prob(slerp(theta))

        # slice sampling using first bracketing procedure starting at current
        # sample (corresponding to theta=0)
        theta, n = sample_slice(log_prob, theta, bounds, return_n_reject=True)

        v = slerp(theta)

        samples.append(v)
        n_reject.append(n)

    print(f"average number of rejections: {np.mean(n_reject)}")

    return np.array(samples)

def slice_sampling4(pdf, n_samples=1e3):
    """
    Slice sampling on the sphere using random Givens rotations and bracketing.
    """
    bounds = (-np.pi, np.pi)

    # initialization
    x = sphere.sample_sphere(pdf.d - 1)

    samples = [x]
    n_reject = []

    while len(samples) < n_samples:
        # draw uniformly from sphere
        u = sphere.sample_sphere(pdf.d - 1)
        v = sphere.sample_sphere(pdf.d - 1)  # generates a small circle?

        # how to construct a great circle?
        v = x  # also generates a small circle
        # unless
        u = sphere.spherical_projection(u, x)

        # Givens rotation
        givens = sphere.givens(u, v, x)

        # define probability on slice
        def log_prob(theta, pdf=pdf, givens=givens):
            return pdf.log_prob(givens(theta))

        assert np.isclose(log_prob(0.0), pdf.log_prob(x))

        # slice sampling using first bracketing procedure starting at current
        # sample (corresponding to theta=0)
        theta, n = sample_slice(log_prob, 0.0, bounds, return_n_reject=True)

        x = givens(theta)

        samples.append(x)
        n_reject.append(n)

    print(f"average number of rejections: {np.mean(n_reject)}")

    return np.array(samples)

def spherical_rejection_sampling(pdf, n_samples=1e3):
    """
    Use rejection sampling to sample from slice.
    """
    bounds = (-np.pi, np.pi)
    bounds = (0, 2 * np.pi)

    # initialization
    v = sphere.sample_sphere(pdf.d - 1)
    samples = [v]

    n_reject = []
    while len(samples) < n_samples:
        # draw uniformly from subsphere
        u = sphere.sample_subsphere(v)

        # define probability on slice
        def log_prob(theta, pdf=pdf, v=v, u=u):
            return pdf.log_prob(np.cos(theta) * v + np.sin(theta) * u)

        # rejection sampling where current sample defines threshold
        threshold = log_prob(0.0) + np.log(np.random.rand())
        n = 0
        while True:
            theta = np.random.uniform(*bounds)
            if log_prob(theta) > threshold:
                n_reject.append(n)
                break
            n += 1

        v = np.cos(theta) * v + np.sin(theta) * u

        samples.append(v)

    print(f"average number of rejections: {np.mean(n_reject)}")

    return np.array(samples)


import boto3

from . import settings

s3 = boto3.client("s3", endpoint_url=settings.AWS_ENDPOINT_URL)

s3_resource = boto3.resource("s3", endpoint_url=settings.AWS_ENDPOINT_URL)

def get_s3_object(path, version=None):
    params = dict(Bucket=settings.AWS_STORAGE_BUCKET_NAME, Key=path)
    if version:
        params["VersionId"] = version
    return s3.get_object(**params)


from exporters.backends.prometheus import PrometheusExporterBackend

def get_exporter_backend(uri, type="prometheus", logger=None):
    """
    A factory method pattern to decide which storage implementation to use

    @param: type - string (s3, filesystem)

    @return: Storage Class Implementation

    """
    if type == "prometheus":
        return PrometheusExporterBackend(uri, logger)
    raise NotImplementedError(
        f"No storage backend implementation for type {type}")


import numpy as np
import cv2
import random
import argparse
from pathlib import Path

def overlay_obj_on_canvas(source_img, output_img, source_img_class_id):
    # Randomly geneate Y and X coordinate values where the source_image needs to be pasted
    height = output_img.shape[0]
    width = output_img.shape[1]

    # extract source image height and width
    source_img_height = source_img.shape[0]
    source_img_width = source_img.shape[1]

    #generate random coordinates
    rnd_y_coord = random.randint(0, height-source_img_height)
    rnd_x_coord = random.randint(0, width-source_img_width)

    # Paste the source image on a random coordinate
    start_pos = (rnd_y_coord,  rnd_x_coord)
    end_pos = (rnd_y_coord + source_img_height,  rnd_x_coord + source_img_width)
    output_img[start_pos[0]:end_pos[0], start_pos[1]:end_pos[1], :] = source_img

    # Store the coordinates of the bbox (class_id, xmin, ymin, xmax, ymax)
    bbox_coordinate = np.array([[source_img_class_id, start_pos[1], start_pos[0], end_pos[1], end_pos[0]]], dtype=np.int32) # (1,5) shape

    return bbox_coordinate , output_img

if __name__ == "__main__":
    # Dictionary of source image path
    source_imgs = {
        0: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/car_small.png",  # car small
        1: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/car_small_g.png",  # car small green
        2: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/car_big.png", # car big
        3: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/car_big_g.png",  # car big green
        4: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/car_big_r.png",  # car big red
        5: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/one_dash.png" ,#one dash
        6: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/two_dash.png",  # two dash
        7: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/three_dash.png" , #three dash
        8: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/four_dash.png" , #four dash
        9: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/five_dash.png",  # five dash
        10: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/Dotted_lines_LR.png", # dotted lanes white
        11: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/dotted_lanes_g.png" , # dotted lanes green
        12: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/dotted_lanes_LR_r.png" , # dotted lanes red
        13: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/brackets_LR.png",  # brackets LR
        14: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/brackets_LR_g.png",  # brackets LR green
        15: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/triangles_LR.png",  # triangles LR
        16: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/triangles_LR_g.png",  # triangles LR green
        17: "/Users/samiksha/master_thesis/images_from_drive_nippon/my_dataset/triangles_LR_r.png",  # triangles LR red
    }

    # accept values of number of images to generate and directory in which the images need to be stored
    parser = argparse.ArgumentParser()
    parser.add_argument("--dir_output", type=Path, default="output",
                        help="Directory to store generated img and txt file")
    parser.add_argument("--num_imgs", type=Path, default=2000,
                        help="Number of images to generate")
    args = parser.parse_args()

    dir_output = args.dir_output
    # create directory output
    dir_output.mkdir(parents=True, exist_ok=True)
    dir_images = dir_output / "images"
    dir_annotations = dir_output / "annotations"
    dir_images.mkdir(parents=True, exist_ok=True)
    dir_annotations.mkdir(parents=True, exist_ok=True)

    num_of_output_imgs = args.num_imgs
    for output_img_idx in range(num_of_output_imgs):

        # decide how many source image to pick
        max_source_images = min(len(source_imgs), 4)
        number_of_source_images_to_use = random.randint(1, max_source_images)

        # Create a black image canvas of given dimension
        output_img = np.zeros((256, 256, 3), dtype=np.uint8)

        bbox_coordinates = []
        for image_idx in range(number_of_source_images_to_use):

            # randomly select 1 source image from the dictionary
            source_img_dict_list = list(source_imgs.items())
            random_source_img = random.choice(source_img_dict_list) #randomly chose 1 source image from the list of items from dict
            random_source_img_path = random_source_img[1]
            random_source_img_class_id = random_source_img[0]

            # Read the image
            source_img = cv2.imread(random_source_img_path)
            #print("source_img", source_img.shape)

            # Create bbox coordinate list
            source_img_coordinates , output_img = overlay_obj_on_canvas(source_img, output_img, random_source_img_class_id)
            bbox_coordinates.append(source_img_coordinates)

        # Convert the list of bbox coordinates into numpy array to save it into a text
        bbox_numpy = np.concatenate(bbox_coordinates, axis=0)
        f_annotation = dir_annotations / f'{output_img_idx:04d}.txt'
        np.savetxt(str(f_annotation), bbox_numpy, delimiter=',', fmt='%d')

        # Save the output image in a file
        f_images = dir_images / f'{output_img_idx:04d}.png'
        cv2.imwrite(str(f_images), output_img)

        # Visualize the bboxes
        dir_debug = dir_output / "debug"
        dir_debug.mkdir(parents=True, exist_ok=True)
        f_debug_img = dir_debug / f"{output_img_idx:04d}.png"
        output_img_debug = output_img.copy()
        for bbox in bbox_numpy:
            start_point = (bbox[1], bbox[2])
            end_point = (bbox[3], bbox[4])
            color = (255, 0, 0)
            thickness = 2
            output_img_debug = cv2.rectangle(output_img_debug, start_point, end_point, color, thickness)
        cv2.imwrite(str(f_debug_img), output_img_debug)


import argparse
import os
#os.environ["CUDA_VISIBLE_DEVICES"]="1"
import json
import time
import math
import torch
import torch.nn as nn
from torch.autograd import Variable

import data_ptb as data
from model_torch import RNNModel

###############################################################################
# Load configuration
###############################################################################
parser = argparse.ArgumentParser(description='PyTorch PennTreeBank RNN Language Model')
parser.add_argument('--hps-file', type=str, required=True,
                    help='location of hyper parameter json file.')
parser.add_argument('--model', type=str, default='UNI', help='rnn model')
args = parser.parse_args()

hps = json.load(open(args.hps_file))
hps['model'] = args.model

# Set the random seed manually for reproducibility.
torch.manual_seed(hps['seed'])
if torch.cuda.is_available():
    if not hps['cuda']:
        print("WARNING: You have a CUDA device, "
              "so you should probably run with --cuda")
    else:
        print("You run with --cuda")
        torch.cuda.manual_seed(hps['seed'])

###############################################################################
# Load data
###############################################################################
def batchify(data, bsz, cuda=False):
    # Work out how cleanly we can divide the dataset into bsz parts.
    nbatch = data.size(0) // bsz
    # Trim off any extra elements that wouldn't cleanly fit (remainders).
    data = data.narrow(0, 0, nbatch * bsz)
    # Evenly divide the data across the bsz batches.
    data = data.view(bsz, -1).t().contiguous()
    if cuda:
        data = data.cuda()
    return data

corpus = data.Corpus(hps['data'])
###############################################################################
# Build the model
###############################################################################

ntokens = len(corpus.dictionary)
model = RNNModel(hps['model'], ntokens, hps['emsize'], hps['nhid'],
                 hps['nlayers'], hps['dropout'], hps['tied'])
if hps['cuda']:
    model.cuda()

criterion = nn.CrossEntropyLoss()
#optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=0)
###############################################################################
# Training code
###############################################################################

def repackage_hidden(h):
    """Wraps hidden states in new Variables,
        to detach them from their history."""
    if isinstance(h, Variable):
        return Variable(h.data)
    else:
        return tuple(repackage_hidden(v) for v in h)

def get_batch(source, i, evaluation=False):
    seq_len = min(hps['bptt'], len(source) - 1 - i)
    data = Variable(source[i:i+seq_len], requires_grad=False)#, volatile=evaluation)
    target = Variable(source[i+1:i+1+seq_len].view(-1), requires_grad=False)
    return data, target

def evaluate(data_source):
    with torch.no_grad():
        # Turn on evaluation mode which disables dropout.
        model.eval()
        total_loss = 0
        ntokens = len(corpus.dictionary)
        hidden = model.init_hidden(eval_batch_size)
        for i in range(0, data_source.size(0) - 1, hps['bptt']):
            data, targets = get_batch(data_source, i, evaluation=True)
            output, hidden = model(data, hidden)
            output_flat = output.view(-1, ntokens)
            total_loss += len(data) * criterion(output_flat, targets).data
            hidden = repackage_hidden(hidden)
        return total_loss.item() / len(data_source)

def train():
    # Turn on training mode which enables dropout.
    model.train()
    total_loss = 0
    start_time = time.time()
    ntokens = len(corpus.dictionary)
    hidden = model.init_hidden(hps['batch_size'])
    for batch, i in enumerate(range(0, train_data.size(0) - 1, hps['bptt'])):
        data, targets = get_batch(train_data, i)
        # Starting each batch, we detach the hidden state from how it
        # was previously produced. If we didn't, the model would try
        # backpropagating all the way to start of the dataset.
        hidden = repackage_hidden(hidden)
        model.zero_grad()
        output, hidden = model(data, hidden)
        loss = criterion(output.view(-1, ntokens), targets)
        loss.backward()

        # `clip_grad_norm` helps prevent the exploding gradient problem
        # in RNNs / LSTMs.
        nn.utils.clip_grad_norm_(model.parameters(), hps['clip'])
        #for p in model.parameters():
        #    p.data.add_(-lr, p.grad.data)
        optimizer.step()

        total_loss += loss.data

        if batch % hps['log_interval'] == 0 :# and batch > 0:
            cur_loss = total_loss.item() / hps['log_interval']
            elapsed = time.time() - start_time
            print(
                '| epoch {:3d} | {:5d}/{:5d} batches | lr {:02.2f} | '
                'ms/batch {:5.2f} | loss {:5.2f} | ppl {:8.2f}'.format(
                    epoch, batch, len(train_data) // hps['bptt'], lr,
                    elapsed * 1000 / hps['log_interval'],
                    cur_loss, math.exp(cur_loss)))
            total_loss = 0
            start_time = time.time()

# Loop over epochs.
lr = hps['lr']
best_val_loss = None

eval_batch_size = 10
train_data = batchify(corpus.train, hps['batch_size'], hps['cuda'])
val_data = batchify(corpus.valid, eval_batch_size, hps['cuda'])
# At any point you can hit Ctrl + C to break out of training early.
try:
    for epoch in range(1, hps['epochs']+1):
        epoch_start_time = time.time()
        train()
        val_loss = evaluate(val_data)
        print('-' * 89)
        print(
            '| end of epoch {:3d} | time: {:5.2f}s | valid loss {:5.2f} | '
            'valid ppl {:8.2f}'.format(
                epoch, (time.time() - epoch_start_time),
                val_loss, math.exp(val_loss)))
        print('-' * 89)
        # Save the model if the validation loss is the best we've seen so far.
        if not best_val_loss or val_loss < best_val_loss:
            os.makedirs(os.path.dirname(hps['save']), exist_ok=True)
            if hps['cuda']:
                torch.save(model.state_dict(), hps['save'] + '_' + hps['model'] + '.gpu')
                model.cpu()
                torch.save(model.state_dict(), hps['save'] + '_' + hps['model'] + '.cpu')
                model.cuda()
            else:
                torch.save(model.state_dict(), hps['save'] + '_' + hps['model'] + '.cpu')
            best_val_loss = val_loss
        else:
            # Anneal the learning rate if no improvement has been seen
            # in the validation dataset.
            lr *=0.95
except KeyboardInterrupt:
    print('-' * 89)
    print('Exiting from training early')

model = RNNModel(hps['model'], ntokens, hps['emsize'], hps['nhid'],
                 hps['nlayers'], hps['dropout'], hps['tied'])
# Load the best saved model params.
if hps['cuda']:
    model.cuda()
    model.load_state_dict(torch.load(hps['save'] + '_' + hps['model'] + '.gpu'))
else:
    model.load_state_dict(torch.load(hps['save'] + '_' + hps['model'] + '.cpu'))

# Run on test data.
test_data = batchify(corpus.test, eval_batch_size, hps['cuda'])
test_loss = evaluate(test_data)
print('=' * 89)
print('| End of training | test loss {:5.2f} | test ppl {:8.2f}'.format(
    test_loss, math.exp(test_loss)))
print('=' * 89)


class Graph:
    def __init__(self):
        self.adj_list = {}

    def add_node(self, node):
        if node not in self.adj_list:
            self.adj_list[node] = []

    def add_edge(self, node1, node2, weight=1):
        self.add_node(node1)
        self.add_node(node2)
        self.adj_list[node1].append((node2, weight))
        self.adj_list[node2].append((node1, weight))

    def remove_edge(self, node1, node2):
        for i, (node, weight) in enumerate(self.adj_list[node1]):
            if node == node2:
                del self.adj_list[node1][i]
                break
        for i, (node, weight) in enumerate(self.adj_list[node2]):
            if node == node1:
                del self.adj_list[node2][i]
                break

    def remove_node(self, node):
        del self.adj_list[node]
        for other_node in self.adj_list:
            for i, (n, w) in enumerate(self.adj_list[other_node]):
                if n == node:
                    del self.adj_list[other_node][i]
                    break

    def is_path(self, node1, node2):
        visited = set()
        stack = [node1]
        while stack:
            node = stack.pop()
            if node == node2:
                return True
            if node not in visited:
                visited.add(node)
                stack.extend(neighbour for neighbour, weight in self.adj_list[node])
        return False

# example usage
g = Graph()
g.add_edge('A', 'B')  # add an edge between nodes 'A' and 'B'
g.add_edge('B', 'C')  # add an edge between nodes 'B' and 'C'
print(g.adj_list)  # print the adjacency list
# Output: {'A': [('B', 1)], 'B': [('A', 1), ('C', 1)], 'C': [('B', 1)]}

g.add_edge('A', 'D')  # add an edge between nodes 'A' and 'D'
print(g.adj_list)  # print the adjacency list
# Output: {'A': [('B', 1), ('D', 1)], 'B': [('A', 1), ('C', 1)], 'C': [('B', 1)], 'D': [('A', 1)]}

g.remove_edge('A', 'D')  # remove the edge between nodes 'A' and 'D'
g.remove_node('B')  # remove node 'B' from the graph
print(g.adj_list)  # print the adjacency list
# Output: {'A': [], 'C': []}

print(g.is_path('A', 'C'))  # check if a path exists between nodes 'A' and 'C'
# Output: False
print(g.is_path('A', 'D'))  # check if a path exists between nodes 'A' and 'D'
# Output: False
print(g.is_path('D', 'A'))  # check if a path exists between nodes 'D' and 'A'
# Output: True

2023-1/Lecture Notes/LaTeX Source/Lectuture Notes (Graphs)/graph_adj_list.py


from random import randrange, randint
from time import sleep
import textwrap
import signal
import sys

small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31] # etc.
do_sleep = False

def test_prime(n, k):
    """Return True if n passes k rounds of the Miller-Rabin primality
    test (and is probably prime). Return False if n is proved to be
    composite.

    """
    if n < 2: return False
    for p in small_primes:
        if n < p * p: return True
        if n % p == 0: return False
    r, s = 0, n - 1
    while s % 2 == 0:
        r += 1
        s //= 2 # Floor
    for _ in range(k):
        a = randrange(2, n - 1)
        x = pow(a, s, n)
        if x == 1 or x == n - 1:
            continue
        for _ in range(r - 1):
            x = pow(x, 2, n)
            if x == n - 1:
                break
        else:
            return False
    return True

def find_mmi(e,phi):
    for i in range(0,phi-1):
        if (e*i) % phi == 1:
            return i
    return False

def find_prime(min, max):
    tested = []
    while True:
        i = randint(min,max)
        if i in tested:
            continue
        prime = test_prime(i, 1000)
        if prime:
            return i

def find_e(phi):
    prime = False
    while not prime:
        rand = randint(0, phi)
        prime = test_prime(rand,10000)
        if prime and phi % rand != 0:
            return rand

def calc_phi(p,q):
    return p*q - p - q + 1

def encrypt(m, pub):
    return m**pub['e'] % pub['mod']

def decrypt(c, d, mod):
    return c**d % mod

def interrupted(signum, frame):
    raise NameError("Stop waiting")

def prompt(timeleft):
    try:
        input("[Press Enter to continue] (" + timeleft + ")")
        return True
    except NameError:
        return False

def blankline():
    print()

def pause(seconds):
    blankline()
    signal.signal(signal.SIGALRM, interrupted)
    for i in range(0, seconds):
        timeleft = str(seconds - i)
        signal.alarm(1)
        if prompt(timeleft):
            signal.alarm(0)
            print("\033[A\r", end="") #Up one line and back to column 0
            break;
        signal.alarm(0)
        print("\r" + " "*80 + "\r", end="", flush=True) # Back to col 0, space out line and back to col 0 again

    signal.alarm(0)
    print("\r" + " "*80 + "\033[A\r", end="", flush=True) # Back to col0, space out line, move up one line and back to col0

def output(text):
    print (textwrap.fill(text, width=80))

def start():
    print("#######################################")
    print("### Welcome to Viktor RSA Lesson ####")
    print("#######################################")
    output("To begin, you need to know the basic concepts of private-public key cryptography. I have a blog post where I explain these concepts in greater detail, which you can find at https://viha.se/blog/tags/internet_cryptography?order=reverse")
    blankline()
    output("But the short version is that there are 2 keys: a private one and a public one. Stuff that is encrypted with the private key can only be decrypted with the public key, and vice verse. This means that Bob can generate a keypair, and put the public key on his website, then anyone who wants to send a message they only want Bob to be able to read, they enrypt the message with Bobs public key")
    blankline()
    pause(10)

    output("But lets just get into the gritty details.")
    blankline()
    output("To generate the keypair, we need two prime numbers. For the purpose of demonstration we'll use very small numbers.")
    output("Would you like me to generate these? (Answer no if you want to supply them yourself)")
    answered = False
    p = -1
    q = -1
    while not answered:
        tmp = input("[yes/no]: ")
        if tmp == "yes":
            answered = True
            p = find_prime(10,90)
            q = find_prime(10,90)
        elif tmp == "no":
            answered = True
            while p == -1:
                tmp = input("p: ")
                tmp = int(tmp)
                if not test_prime(tmp, 1000):
                    print(str(tmp) + " is not a prime number, try again..")
                else:
                    p = tmp
            while q == -1:
                tmp = input("q: ")
                tmp = int(tmp)
                if not test_prime(tmp, 1000):
                    print(str(tmp) + " is not a prime number, try again..")
                else:
                    q= tmp

        else:
            print("Answer yes or no:")

    mod = p*q
    blankline()
    output("So, what we have now are two prime numbers, lets call them p and q")
    blankline()
    output("  p = " + str(p))
    output("  q = " + str(q))
    blankline()
    pause(5)
    output("Next up, we'll compute the 'modulus' which is:")
    blankline()
    pause(5)
    output("  p * q = modulus")
    pause(5)
    output("  " + str(p) + " * " + str(q) + " = " + str(mod))
    pause(5)
    blankline()
    output("The next number we need is phi(modulus)")
    output("This is called the 'totient' of the product")
    output("The formula for this is this:")
    blankline()
    output("  (p -1)(q-1) = p*q - p - q + 1 = phi( modulus ) ")
    pause(5)
    output("or, using our numbers:")
    blankline()
    pause(5)
    phi = calc_phi(p,q)
    print("  " + str(p) + " * " + str(q) + " - "  + str(p) + " - " + str(q) + " + 1 = " + str(phi))
    blankline()
    pause(5)
    output("The next number we need we'll call e. This is a bit harder to calculate. The requirements for e is that it should be 1 < e < phi(modulus) and that it should be a 'coprime' of phi(modulus). Now I don't now what 'coprime' is, but according to wikipedia, if we choose e as a prime number, we only have to check that e is not a 'divisor' of phi(modulus).")
    pause(5)
    output("The fastest way to do this when dealing with numbers of this magnitude is to just brute force it.")
    blankline()
    pause(5)
    output("So what we do is that we pick a random number in the allowed range, and then using the Miller-Rabin primality test. If we find a prime number we check if phi(modulus) % x == 0. If this is true, then we try again until we find a number that is not a divisor.")
    blankline()
    pause(5)
    output("So back to our numbers, lets try to find a prime between 1 and " + str(phi))
    pause(5)
    e = find_e(phi)
    output("hmmm, lets see... " + str(e) + " will probably do...")
    pause(5)
    output("Is it in the range 1 < " + str(e) + " < " + str(phi) + "... yes that is correct")
    rem = phi % e
    pause(5)
    output("Is " + str(e) + " a divisor of " + str(phi) + "? Well... " + str(phi) + " % " + str(e) + " = " + str(rem) + ". So no, its not a divisor.")
    blankline()
    pause(5)
    output("The final number we must derive is called 'd'. This is the private key, and also the most difficult one to calculate. This one is also bruteforced, since the math is too hard for me to do.")
    blankline()
    pause(5)
    output("Here we need to get the 'modular multiplicative inverse'. This is the formula to find that:")
    blankline()
    pause(5)
    output("  (d * e) % phi(modulus) = 1")
    blankline()
    pause(5)
    output("How we do this is simple test all numbers d between 0 and phi(modulus) and check if they make that equation equal to 1.")
    d = find_mmi(e,phi)
    pause(5)
    output("In this case this number is : " + str(d))
    blankline()
    pause(5)
    output("So to summarize:")
    pause(1)
    output("We have the following numbers:")
    pause(1)
    output("  p = " + str(p))
    pause(1)
    output("  q = " + str(q))
    pause(1)
    output("  modulus = " + str(mod))
    pause(1)
    output("  phi(modulus) = " + str(phi))
    pause(1)
    output("  e = " + str(e))
    pause(1)
    output("  d = " + str(d))
    blankline()
    pause(5)
    output("The public key consists of both modulus and e, these are commonly refered to as the modulus and the exponent. And the private key is simply the number e")
    blankline()
    pause(5)
    output("The function to encrypt an integer m with the public key is this:")
    blankline()
    output("  m^e % modulus = c")
    blankline()
    pause(5)
    output("And the function to decrypt c with the private key is:")
    blankline()
    output("  c ^ d % modulus = m")
    blankline()
    pause(5)
    output("Although a limit of this is that the integer can only be as large as the modulus")
    blankline()
    pause(5)
    output("So lets put this to the test. What integer would you like to encrypt?")
    m = input("[0 - " + str(mod) + "]: ")
    m = int(m)
    pub = {'e': e, 'mod':mod}
    c = encrypt(m, pub)
    newm = decrypt(c, d, mod)
    blankline()
    output("  " + str(m) + "^" + str(e) + " % " + str(mod) + " = "  + str(c))
    blankline()
    output("So if we encrypt your number " + str(m) + " it becomes " + str(c) + ". This new integer can then be sent to Bob. He can then decrypt it using his private key like so:")
    blankline()
    pause(5)
    output("  " + str(c) + "^" + str(d) + " % " + str(mod) + " = " + str(newm))
    blankline()

if __name__ == "__main__":
    start()

def test():
    p = 23
    q = 19
    m = 64

    mod = p * q
    phi = calc_phi(p,q)
    e = find_e(phi)
    d = find_mmi(e, phi)
    print("mod: " + str(mod))
    print("phi: " + str(phi))
    print("e: " + str(e))
    print("d: " + str(d))

    pub = {'e': e, 'mod':mod}
    c = encrypt(m, pub)
    print("Message: " + str(m) + " encrypted: " + str(c))
    md = decrypt(c, d, mod)
    print("Decrypted: " + str(md))


# -*- coding:utf-8 -*-
"""
ウィンドウ（画面）の表示
"""
__author__  = "kudo"
__version__ = "1.00"
__date__    = "2018/01/14"

import pygame
from pygame.locals import *
import sys

# 画面縦
SCREEN_LENGTH = 400

# 画面横
SCREEN_WIDTH = 300

# 画面名
SCREEN_NAME = "Test"

# 画面色:赤
RGB_R = 0

# 画面色:緑
RGB_G = 0

# 画面色:青
RGB_B = 0

def resize_screen(length,width):
    """
    指定の画面サイズに変更する
    :param  length  画面縦サイズ
    :param  width   画面横サイズ
    :return:
    """
    return pygame.display.set_mode((length, width))

def main():
    """
    ウィンドウを表示する関数
    :return:
    """
    pygame.init()                                         # 初期化
    screen = resize_screen(SCREEN_LENGTH, SCREEN_WIDTH)   # 大きさ400*300の画面を生成
    pygame.display.set_caption(SCREEN_NAME)               # タイトルバーに表示する文字

    while (1):
        screen.fill((RGB_R, RGB_G, RGB_B))  # 画面を黒色(#000000)に塗りつぶし
        pygame.display.update()             # 画面を更新
        # イベント処理
        for event in pygame.event.get():
            if event.type == QUIT:  # 閉じるボタンが押されたら終了
                pygame.quit()       # 終了(画面閉じられる)
                sys.exit()

if __name__ == "__main__":
    main()


#!/usr/bin/env python
'''Usage:
    In [] !python  log.py  log_192-20171220-0826_prune.txt  step
    In [] !python  log.py  log_192-20171220-0826_acc.txt    acc
    In [] !python  log.py  log_192-20171220-0826_prune.txt  conv2rank
    In [] !python  log.py  log_192-20171220-0826_prune.txt  conv2hrank

    # Ipython alias
    In [] step       log_192-20171220-0826_prune.txt
    In [] acc        log_192-20171220-0826_prune.txt
    In [] conv2rank  log_192-20171220-0826_prune.txt
'''
import os
import sys
assert (len(sys.argv) == 3)

if sys.argv[2] in ('step', 'Step'):
    if os.path.isdir(sys.argv[1]):
        prune_txts = [os.path.join(sys.argv[1], i) for i in os.listdir(sys.argv[1]) if i.endswith("prune.txt")]
        if len(prune_txts) != 1:
            print("There are not 1 `prune.txt` in your provided directory, please check.")
            print (prune_txts)
            exit(1)
        inFile = prune_txts[0]
    else:
        inFile = sys.argv[1]
        assert("prune" in inFile)
    os.system('cat %s | grep "Step" > %s' % (inFile, inFile.replace('_prune.txt', '_Step.log')))

elif sys.argv[2] in ('acc'):
    os.system('cat %s | grep "accuracy = "' % sys.argv[1])

elif 'hrank' in sys.argv[2]:
    os.system('cat %s | grep "%s" > %s' % (sys.argv[1], sys.argv[2], sys.argv[1].replace('_prune.txt', '_' + sys.argv[2] + '.txt')))

elif 'rank' in sys.argv[2]:
    os.system('cat %s | grep "%s" > %s' % (sys.argv[1], sys.argv[2], sys.argv[1].replace('_prune.txt', '_' + sys.argv[2] + '.txt')))