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

import pyvirtualdisplay.smartdisplay as smartdisplay
import selenium.webdriver
import contextlib
import time
import csv
import bs4
import psycopg2

import settings

def download_html(site_url, output_file):
    with smartdisplay.SmartDisplay(visible=0, bgcolor='black'):
        with contextlib.closing(selenium.webdriver.Chrome()) as browser:
            browser.get(site_url)

            time.sleep(settings.BROWSER_JS_EXEC_PAUSE)

            browser.execute_script("window.scrollTo "
                                   "(0, document.body.scrollHeight);")

            with open(output_file, "w") as fp:
                fp.write(browser.page_source.encode(settings.DEFAULT_ENCODING))

def extract_into_csv(input_html, output_csv):
    with open(input_html, "r") as fp:
        soup = bs4.BeautifulSoup(fp, "lxml")

    with open(output_csv, "w") as fp:
        csv_writer = csv.writer(fp)

        csv_writer.writerow(settings.CSV_HEADER)

        for row in soup.find_all('tr'):
            row_to_write = tuple(
                (r.encode(settings.DEFAULT_ENCODING)
                    for r in row.stripped_strings)
            )
            csv_writer.writerow(row_to_write)

def download_to_bd(input_csv):
    try:
        with psycopg2.connect(**(settings.DATABASE_SETTINGS)) as db:
            cur = db.cursor()

            query = """INSERT into snap_jobs."Jobs"
                    (job_title, category, status, location)
                    VALUES ('{}', '{}', '{}', '{}')"""

            with open(input_csv) as fp:
                csv_reader = csv.reader(fp)

                csv_reader.next()

                for row in csv_reader:
                    cur.execute(query.format(*row))

            db.commit()

    except psycopg2.IntegrityError as error:
        print(error)


import os
import pandas as pd
import numpy as np

from shutil import move, copy2
from PIL import Image

from utils import create_nested_folders
import data.models.yolov5.yolov5_git.train as yolo_train
import data.models.yolov5.yolov5_git.val as yolo_val

class YoloV5:

    def __init__(self):
        self.__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))

    def train(self, dataset, batch_size, weights, img_size, num_epochs, device=0):
        yml = f"{dataset.dataset_id.lower()}.yaml"
        yolo_train.run(data=yml, imgsz=img_size, weights=weights, device=device, batch_size=batch_size,
                       epochs=num_epochs)

    def val(self, dataset, batch_size, weights, img_size, device=0, task='val'):
        yml = f"{self.__location__}/yolov5_git/data/{dataset.dataset_id.lower()}.yaml"
        res = yolo_val.run(data=yml, batch_size=batch_size, imgsz=img_size, device=device, weights=weights, task=task)
        print(res)

    def prepare_dataset(self, dataset, is_data_augmentation=False, data_augmentation_path=None, task='val'):
        dataset_funcs = {
            "GTSRB": self._prepare_gtsrb,
            "GTSDB": self._prepare_gtsdb,
        }
        dataset_funcs.get(dataset.dataset_id)(dataset)
        if is_data_augmentation:
            self.copy_augmented_data(dataset, data_augmentation_path, task)

    def copy_augmented_data(self, dataset, data_augmentation_path, task):
        yolo_folder = f"{dataset.path}/yolo/{task}/images"
        for image in os.listdir(yolo_folder):
            os.remove(f"{yolo_folder}/{image}")

        for image in os.listdir(data_augmentation_path):
            copy2(f"{data_augmentation_path}/{image}", yolo_folder)

    def _prepare_gtsrb(self, dataset):
        # collect gtsrb file paths in txt file, so that yolo can read the dataset
        gtsrb_root = dataset.path
        gtsrb_train = gtsrb_root + "/Train/"
        gtsrb_test = gtsrb_root + "/Test/"

        create_nested_folders(f"{gtsrb_train}yolo/images/")
        for folder in os.listdir(gtsrb_train):
            if folder == "yolo":
                continue
            for image in os.listdir(f"{gtsrb_train}{folder}/"):
                copy2(f"{gtsrb_train}{folder}/{image}", f"{gtsrb_train}yolo/images/")

        create_nested_folders(f"{gtsrb_test}/yolo/images/")
        for image in os.listdir(gtsrb_test):
            if image == "yolo":
                continue
            copy2(f"{gtsrb_test}{image}", f"{gtsrb_test}yolo/images/")

        # convert gtsrb csv Labels to YoloFileFormat
        # YOLO format:
        # one *.txt file per image; The *.txt file specifications are:
        # - one row per object
        # - each row is [class x_center y_center width height] format
        # - Box coordinates must be in normalized xywh format (from 0 - 1). If your boxes are in pixels, divide x_center and width
        #   by image width, and y_center and height by image height
        # - Class numbers are zero-indexed (start from 0)

        create_nested_folders(f"{gtsrb_train}yolo/labels/")
        create_nested_folders(f"{gtsrb_test}yolo/labels/")

        # [train_df, test_df]
        dfs = [pd.read_csv(f"{gtsrb_root}/Train.csv"), pd.read_csv(f"{gtsrb_root}/Test.csv")]
        for subset_df in dfs:
            # Normalize Coordinates
            subset_df["Roi.X1"] /= subset_df["Width"]
            subset_df["Roi.X2"] /= subset_df["Width"]
            subset_df["Roi.Y1"] /= subset_df["Height"]
            subset_df["Roi.Y2"] /= subset_df["Height"]

            for index, row in subset_df.iterrows():
                try:
                    current_subset_id, _, current_image = row.loc["Path"].split("/")
                except ValueError:
                    current_subset_id, current_image = row.loc["Path"].split("/")

                # convert to YoloFormat
                converted = np.array([
                    row.loc["ClassId"],
                    (row.loc["Roi.X1"] + row.loc["Roi.X2"]) / 2.0,
                    (row.loc["Roi.Y1"] + row.loc["Roi.Y2"]) / 2.0,
                    row.loc["Roi.X2"] - row.loc["Roi.X1"] if row.loc["Roi.X2"] - row.loc["Roi.X1"] < 1.0 else 1.0,
                    row.loc["Roi.Y2"] - row.loc["Roi.Y1"] if row.loc["Roi.Y2"] - row.loc["Roi.Y1"] < 1.0 else 1.0
                ])

                # write to label file
                with open(f"{gtsrb_root}/{current_subset_id}/yolo/labels/{current_image[:-4]}.txt", "w+") as f:
                    f.write(f"{int(converted[0])} {' '.join(map(str, converted[1:]))}")

    def _prepare_gtsdb(self, dataset):
        gtsdb_root = dataset.path

        gt_df = pd.read_csv(f"{gtsdb_root}/{dataset.train_ground_truth}",
                            sep=";",
                            names=["Filename", "X1.ROI", "Y1.ROI", "X2.ROI", "Y2.ROI", "classID"]
                            )

        image_size = (1360, 800)  # (width, height)

        # Normalize Coordinates
        gt_df["X1.ROI"] /= image_size[0]
        gt_df["X2.ROI"] /= image_size[0]
        gt_df["Y1.ROI"] /= image_size[1]
        gt_df["Y2.ROI"] /= image_size[1]

        train = dataset.load_train_subset()
        val = dataset.load_validation_subset()
        test = dataset.load_test_subset()

        print("prepared subset: ", val)

        print(len(train))
        print(len(val))
        print(len(test))

        self._prepare_gtsdb_split(train, "train", gt_df, dataset)
        self._prepare_gtsdb_split(val, "val", gt_df, dataset)
        self._prepare_gtsdb_split(test, "test", gt_df, dataset)

    def _prepare_gtsdb_split(self, split_df, split_name, gt_df, dataset):
        gtsdb_root = dataset.path

        create_nested_folders(
            f"{gtsdb_root}/yolo/{split_name}/images",
            f"{gtsdb_root}/yolo/{split_name}/labels",
        )

        # convert gtsdb csv Labels to YoloFileFormat
        # YOLO format:
        # one *.txt file per image; The *.txt file specifications are:
        # - one row per object
        # - each row is [class x_center y_center width height] format
        # - Box coordinates must be in normalized xywh format (from 0 - 1). If your boxes are in pixels, divide x_center and width
        #   by image width, and y_center and height by image height
        # - Class numbers are zero-indexed (start from 0)

        for image in split_df[0]:
            with Image.open(image) as im:  # Yolo can't read images in ppm format
                image_file_name = image.split("/")[-1]
                im.save(
                    f"{gtsdb_root}/yolo/{split_name}/images/{image_file_name[:-4]}.png")  # Therefore instead of moving the image, the image is copied and converted simultaneously
            with open(f"{gtsdb_root}/yolo/{split_name}/labels/{image_file_name[:-4]}.txt", "w+") as f:
                image_df = gt_df.loc[gt_df["Filename"] == image_file_name]
                gt_converted = np.array([
                    [
                        row.loc['classID'],
                        (row.loc["X1.ROI"] + row.loc["X2.ROI"]) / 2.0,
                        (row.loc["Y1.ROI"] + row.loc["Y2.ROI"]) / 2.0,
                        row.loc["X2.ROI"] - row.loc["X1.ROI"],
                        row.loc["Y2.ROI"] - row.loc["Y1.ROI"]
                    ] for index, row in image_df.iterrows()])
                lines = [f"{int(entry[0])} {' '.join(map(str, entry[1:]))}" for entry in gt_converted]
                f.write('\n'.join(lines))
                f.close()


from tkinter import *
from tkinter import messagebox
from configparser import ConfigParser
import requests

# basic url and code I learnt from: https://www.youtube.com/watch?v=7JoMTQgdxg0&ab_channel=teachmesome
# urlfr has "&lang=fr" to change to API to collect the information in french
url = 'http://api.openweathermap.org/data/2.5/weather?q={}&appid={}&lang=en'
urlfr = 'http://api.openweathermap.org/data/2.5/weather?q={}&appid={}&lang=fr' #mycode

# a file to retrieve the API and code I learnt from: https://www.youtube.com/watch?v=7JoMTQgdxg0&ab_channel=teachmesome
# the weather API is from: https://openweathermap.org/api
config_file = 'config.ini'
config = ConfigParser()
config.read(config_file)
api_key = config['api_key']['key']

# this definition of get_weather(city) allows me to pick up the information from the api which I learnt from:
# I learnt from: https://www.youtube.com/watch?v=7JoMTQgdxg0&ab_channel=teachmesome
# the additional functions and information that I retrieved from what I learnt in the video
# were description, timezone, adjusted_timezone to add my own new found knowledge

def get_weather(city):
    result = requests.get(url.format(city, api_key))
    if result:
        json = result.json()
        # (City, Country, temp_celsius, temp_fahrenheit, icon, weather, description, adjusted_timezone)
        city = json['name']
        country = json['sys']['country']
        temp_kelvin = json['main']['temp']
        temp_celsius = temp_kelvin - 273.15
        temp_fahrenheit = (temp_kelvin - 273.15) * 9 / 5 + 32
        weather = json['weather'][0]['main']
        description = json['weather'][0]['description'] #mycode
        timezone = json['timezone'] #mycode
        adjusted_timezone = timezone / 3600 #mycode
        final = (city, country, temp_celsius, temp_fahrenheit, weather, description, adjusted_timezone)
        return final
    else:
        return None

# picks up the information from the api in french
# only change is in line 50 from line 29
def get_weather_fr(city):
    result = requests.get(urlfr.format(city, api_key))
    if result:
        json = result.json()
        # (City, Country, temp_celsius, temp_fahrenheit, icon, weather, description, adjusted_timezone)
        city = json['name']
        country = json['sys']['country']
        temp_kelvin = json['main']['temp']
        temp_celsius = temp_kelvin - 273.15
        temp_fahrenheit = (temp_kelvin - 273.15) * 9 / 5 + 32
        weather = json['weather'][0]['main']
        description = json['weather'][0]['description'] #mycode
        timezone = json['timezone'] #mycode
        adjusted_timezone = timezone / 3600 #mycode
        final = (city, country, temp_celsius, temp_fahrenheit, weather, description, adjusted_timezone)
        return final
    else:
        return None

# this search function allows to use the definition from get_weather(city) and retrieve the api information
# to display on the gui
# the extra spaces allows in location_lbl and description_lbl replace the background with white background
# example: if you were to look up "Vancouver" then "Hanoi", Hanoi will just overlap Vancouver and you would be able
# example: to see part of Vancouver behind Hanoi without the spaces "Va-Hanoi-er"
# therefore the spaces fixes this issue
# \u2103 is for degree celsius and \u2109 is for degree fahrenheit, which are universal codes that I found on
# https://en.wikipedia.org/wiki/Degree_symbol
# if the city cannot be found, it will pop up a error message
# example: if you were to type "asdf32452gad" it will not be able to find this city or town or country as it is
# not a valid option
# most of the code is from: https://www.youtube.com/watch?v=7JoMTQgdxg0&ab_channel=teachmesome
# the code unique (my code) from below is the added space to solve issue described above and
# timezone_lbl to display the timezone in UTC with the offset in hours
# the code is repeated in line 94 except it is search_fr and the function get_weather_fr picks up the urlfr instead of url

def search():
    city = city_text.get()
    weather = get_weather(city)
    if weather:
        location_lbl['text'] = '               {}, {}               '.format(weather[0], weather[1])
        temp_lbl['text'] = '{:.2f}\u2103, {:.2f}\u2109'.format(weather[2], weather[3])
        weather_lbl['text'] = weather[4]
        description_lbl['text'] = '     Description: {}        '.format(weather[5])
        timezone_lbl['text'] = 'Universal time zone offset by {} hours'.format(weather[6], weather [6])
    else:
        messagebox.showerror('Error', 'Cannot find city {}'.format(city))

def search_fr():
    city = city_text.get()
    weather = get_weather_fr(city)
    if weather:
        location_lbl['text'] = '               {}, {}               '.format(weather[0], weather[1])
        temp_lbl['text'] = '{:.2f}\u2103, {:.2f}\u2109'.format(weather[2], weather[3])
        weather_lbl['text'] = weather[4]
        description_lbl['text'] = '     Descriptif: {}        '.format(weather[5])
        timezone_lbl['text'] = 'Décalage du fuseau horaire universel de {} heures'.format(weather[6])
    else:
        messagebox.showerror('Error', 'Cannot find city {}'.format(city))

#this code is from: https://www.youtube.com/watch?v=7JoMTQgdxg0&ab_channel=teachmesome
# I learnt this from a previous group project, Rock Paper Scissors as well
#This is designed to make a GUI from tkinter
# app = Tk() allows to create a window
# app.title allows you to name the window
# app.geometry allows you to customize the window size where the first number '450' is the width,
# and the number '200' is the height and the 'x' is required to separate the numbers and is conventional
# app.configure(bg='white') allows you to customize the colour of the background otherwise its this dull grey colour

app = Tk()
app.title("Weather")
app.geometry('450x200')
app.configure(bg='white')

#this allows you to type a string in the search function which is define above in def Search():
city_text = StringVar()
city_entry = Entry(app, textvariable=city_text)
# to place it on the window screen *insert name*.pack()
# where name is the defined string
city_entry.pack()

# search button which allows you to enter the string for the lines 96-101 above
search_btn = Button(app, text='Search', width=12, command=search, bg='white')
search_btn.pack()

# the search button but in french
search_btn_fr = Button(app, text=' Cherche', width=12, command=search_fr, bg='white')
search_btn_fr.pack()

# location and country
location_lbl = Label(app, text='', font=('bold', 20), bg='white')
location_lbl.pack()

# temperature
temp_lbl = Label(app, text='', bg='white')
temp_lbl.pack()

# weather in general
weather_lbl = Label(app, text='', bg='white')
weather_lbl.pack()

# weather description
description_lbl = Label(app, text='', bg='white')
description_lbl.pack()

# timezone
timezone_lbl = Label(app, text='', bg='white')
timezone_lbl.pack()

#this allows the window to loop in this certain window and close it off
#this is essential for the GUI
app.mainloop()


import datetime as dt
from typing import Optional, List
import uuid

from fastapi import APIRouter, Depends
from pydantic import BaseModel
from sqlalchemy import func
from sqlalchemy.orm import Session
from app.db.deps import get_db
from app.db.utils import NOT_FOUND_EXCEPTION, save_model
from app.dependencies.auth import TokenUser, credential_check
# from app.db.utils import save_model

from app.models.task import Task, TaskOut
from app.models.task_activity import TaskActivity, TaskActivityOut
from app.models.task_completion import TaskCompletion, TaskCompletionOut
from app.models.user import User

router = APIRouter()

@router.get("/", response_model=List[TaskOut])
async def get_tasks(
    limit: Optional[int] = 100,
    skip: Optional[int] = 0,
    db: Session = Depends(get_db),
):
    return db.query(Task).limit(limit).offset(skip).all()

@router.get("/active", response_model=List[TaskActivityOut])
async def get_active_tasks(
    limit: Optional[int] = 100,
    skip: Optional[int] = 0,
    db: Session = Depends(get_db),
    user: TokenUser = Depends(credential_check)
):
    query = (
        db.query(TaskActivity).
        filter(
            TaskActivity.id.not_in(
                db.query(TaskCompletion.task_activity_id)
                    .filter(TaskCompletion.user_id == user.id)
            ),
            func.date(TaskActivity.ends_at) >= dt.date.today()
        ).
        order_by(TaskActivity.ends_at)
    )

    return (
        query.limit(limit).offset(skip).all()
    )

@router.post("/complete/{task_activity_id}", response_model=TaskCompletionOut)
async def post_complete_task(
    task_activity_id : uuid.UUID,
    db : Session = Depends(get_db),
    user : TokenUser = Depends(credential_check)
):
    # TODO TEST
    task_activity = db.query(TaskActivity).filter(TaskActivity.id == task_activity_id).one_or_none()
    if task_activity == None:
        raise NOT_FOUND_EXCEPTION

    tc = TaskCompletion(
        task_activity_id = task_activity_id,
        task_id = task_activity.task.id,
        user_id = user.id
    )
    usr = db.query(User).filter(User.id == user.id).one_or_none()

    if user == None:
        raise NOT_FOUND_EXCEPTION

    usr.emissions_saved += task_activity.emissions_saved
    usr.money_saved += task_activity.money_saved
    db.add(usr)

    usr = db.query(User).filter(User.id == user.id).one_or_none()

    if user == None:
        raise NOT_FOUND_EXCEPTION

    usr.emissions_saved += task_activity.emissions_saved
    usr.money_saved += task_activity.money_saved
    db.add(usr)

    return save_model(db,tc)

@router.get("/user/completed", response_model=List[TaskActivityOut])
async def get_active_tasks(
    limit: Optional[int] = 100,
    skip: Optional[int] = 0,
    db: Session = Depends(get_db),
    user: TokenUser = Depends(credential_check)
):
    return (
        db.query(TaskCompletion).
        filter(TaskCompletion.user_id == user.id).
        limit(limit).offset(skip).all()
    )

class EmissionAnalytics(BaseModel):
    emissions_saved: float
    date: dt.datetime

class MoneyAnalytics(BaseModel):
    money_saved: float
    date: dt.datetime

@router.get("/emission/analytics", response_model=List[EmissionAnalytics])
async def get_active_tasks(
    days: Optional[int] = 6,
    db: Session = Depends(get_db),
    user: TokenUser = Depends(credential_check)
):
    query = (
        db.query(
            func.sum(TaskActivity.emissions_saved).label(
                "emissions_saved"
            ),
            func.date_trunc('day', TaskCompletion.completed_at).label("date")
        ).
        outerjoin(TaskActivity, TaskActivity.id == TaskCompletion.task_activity_id).
        filter(
            TaskCompletion.user_id == user.id,
            func.date(TaskCompletion.completed_at) >= dt.date.today() - dt.timedelta(days=days)
        ).group_by(
            func.date_trunc('day', TaskCompletion.completed_at)
        )
    )

    return query.all()

@router.get("/money/analytics", response_model=List[MoneyAnalytics])
async def get_active_tasks(
    days: Optional[int] = 6,
    db: Session = Depends(get_db),
    user: TokenUser = Depends(credential_check)
):
    query = (
        db.query(
            func.sum(TaskActivity.money_saved).label(
                "money_saved"
            ),
            func.date_trunc('day', TaskCompletion.completed_at).label("date")
        ).
        outerjoin(TaskActivity, TaskActivity.id == TaskCompletion.task_activity_id).
        filter(
            TaskCompletion.user_id == user.id,
            func.date(TaskCompletion.completed_at) >= dt.date.today() - dt.timedelta(days=days)
        ).group_by(
            func.date_trunc('day', TaskCompletion.completed_at)
        )
    )

    return query.all()


from django import forms
from .models import Calculator
from prices.models import SolarModulePreise, WallBoxPreise
from django.core.exceptions import ValidationError
import decimal

def validate_two_decimal_places(value):
    decimal_value = decimal.Decimal(value)
    if decimal_value.as_tuple().exponent < -2:  # type: ignore
        raise ValidationError(
            "Achten Sie darauf, dass dieser Wert nicht mehr als zwei Dezimalstellen hat."
        )

def validate_floats(value):
    if not isinstance(value, float) or value < 0:
        raise ValidationError(
            (
                "Ungültige Eingabe: %(value)s. Eine gültige Gleitkommazahl größer oder gleich Null ist erforderlich."
            ),
            params={"value": value},
        )

def validate_integers(value):
    if not isinstance(value, int) or value < 0:
        raise ValidationError(
            (
                "Ungültige Eingabe: %(value)s. Eine gültige ganze Zahl größer oder gleich Null ist erforderlich."
            ),
            params={"value": value},
        )

def validate_integers_ticket(value):
    if not isinstance(value, int):
        raise ValidationError(
            ("Ungültige Eingabe: %(value)s. Die Menge muss ganzzahlig sein."),
            params={"value": value},
        )

def validate_solar_module_anzahl(value):
    if value < 6 and value != 0:
        raise ValidationError(
            (
                "Ungültige Eingabe: %(value)s. Die Anzahl der Solarmodule sollte 6 oder mehr betragen."
            ),
            params={"value": value},
        )

def validate_solar_module_ticket_anzahl(value):
    if value > 4:
        raise ValidationError(
            (
                "Ungültige Eingabe: %(value)s. Die Anzahl der Solarmodule sollte 4 oder weniger betragen."
            ),
            params={"value": value},
        )

def validate_optimizer_ticket_anzahl(value):
    if value > 4:
        raise ValidationError(
            (
                "Ungültige Eingabe: %(value)s. Die Anzahl der Optimierer sollte 4 oder weniger betragen."
            ),
            params={"value": value},
        )

def validate_range(value):
    if not isinstance(value, int):
        if value < 0 or value > 6:
            raise ValidationError(
                ("Ungültige Eingabe: %(value)s. Der gültige Bereich ist 0-6."),
                params={"value": value},
            )

def validate_empty(value):
    if value is None or value == "":
        raise ValidationError(
            ("Ungültige Eingabe: %(value)s. Etwas hinzufügen"),
            params={"value": value},
        )

class CalculatorForm(forms.ModelForm):
    solar_module = forms.ChoiceField(
        label="Solar Module",
        widget=forms.Select(attrs={"class": "form-select", "id": "solar_module"}),
    )

    modulanzahl = forms.IntegerField(
        label="Module Anzahl",
        initial=0,
        validators=[validate_solar_module_anzahl],
        widget=forms.NumberInput(
            attrs={
                "class": "form-control",
                "id": "id_modulanzahl",
            }
        ),
    )
    wallboxtyp = forms.ChoiceField(
        required=False,
        widget=forms.Select(
            attrs={
                "class": "form-select",
                "id": "wallboxtyp",
            }
        ),
    )
    wallbox_anzahl = forms.IntegerField(
        initial=0,
        label="Anzahl",
        required=False,
        widget=forms.NumberInput(
            attrs={
                "class": "form-control",
                "id": "id_wallbox_anzahl",
            }
        ),
    )
    optimizer = forms.BooleanField(
        label="Optimizer",
        required=False,
        widget=forms.CheckboxInput(
            attrs={"class": "form-check-input form-check-input mb-3", "id": "optimizer"}
        ),
    )
    notstrom = forms.BooleanField(
        label="Notstrom",
        required=False,
        widget=forms.CheckboxInput(
            attrs={"class": "form-check-input form-check-input mb-3", "id": "notstrom"}
        ),
    )
    elwa = forms.BooleanField(
        label="AC-ELWA 2",
        required=False,
        widget=forms.CheckboxInput(
            attrs={
                "class": "form-check-input",
                "id": "elwa",
                "style": "max-width: 70px",
            }
        ),
    )
    thor = forms.BooleanField(
        label="AC-THOR",
        required=False,
        widget=forms.CheckboxInput(attrs={"class": "form-check-input", "id": "thor"}),
    )
    heizstab = forms.BooleanField(
        label="Heizstab inklusive",
        required=False,
        widget=forms.CheckboxInput(
            attrs={
                "class": "form-check-input",
                "id": "heizstab-checkbox",
                "style": "max-width: 300px",
            }
        ),
    )
    anzOptimizer = forms.IntegerField(
        label="Optimizer",
        required=True,
        validators=[validate_integers],
        widget=forms.NumberInput(
            attrs={"class": "form-control form-control mb-3", "id": "id_anzOptimizer"}
        ),
    )
    anz_speicher = forms.IntegerField(
        label="Anzahl Speichermodule (kann sein 0)",
        required=False,
        initial=0,
        validators=[validate_range],
        widget=forms.NumberInput(
            attrs={
                "class": "form-control form-control mb-3",
                "id": "id_anz_speicher",
            }
        ),
    )
    speicher = forms.BooleanField(
        label="Speichermodule",
        required=False,
        widget=forms.CheckboxInput(
            attrs={
                "class": "form-check-input form-check-input mb-3",
                "id": "speicher",
            }
        ),
    )
    angebotsumme = forms.FloatField(
        label="Angebotsumme: ",
        required=False,
        widget=forms.NumberInput(
            attrs={"class": "badge badge-info-lighten", "id": "id_angebotsumme"}
        ),
    )

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

        self.fields["solar_module"].choices = [
            (module.name, module.name)
            for module in SolarModulePreise.objects.filter(in_stock=True)
        ]
        self.fields["wallboxtyp"].choices = [
            (module.name, module.name)
            for module in WallBoxPreise.objects.filter(in_stock=True)
        ]
        self.fields["wallbox_anzahl"].widget.attrs.update({"id": "wallbox_anzahl"})
        self.fields["modulanzahl"].widget.attrs.update({"id": "modulanzahl"})
        self.fields["anzOptimizer"].widget.attrs.update({"id": "anzOptimizer"})
        self.fields["anz_speicher"].widget.attrs.update({"id": "anz_speicher"})
        self.fields["angebotsumme"].widget.attrs.update({"id": "angebotsumme"})

        for field in self.fields:
            if self.initial.get(field):
                self.fields[field].widget.attrs.update(
                    {"placeholder": self.initial[field]}
                )

    def save(self, commit=True):
        calculator_form = super(CalculatorForm, self).save(commit=False)

        if commit:
            calculator_form.save()

        return calculator_form

    class Meta:
        model = Calculator
        fields = [
            "solar_module",
            "modulanzahl",
            "notstrom",
            "elwa",
            "thor",
            "heizstab",
            "optimizer",
            "anzOptimizer",
            "wallboxtyp",
            "wallbox_anzahl",
            "speicher",
            "anz_speicher",
            "angebotsumme",
        ]


import plotly.express as px
from die import Die

# Create the d6
die_1 = Die()
die_2 = Die()

# Make rolls and store results
results = [die_1.roll() + die_2.roll() for roll_num in range(1000)]

# Analyze results.
frequencies = []
max_result = die_1.num_sides + die_2.num_sides
poss_results = range(2, max_result + 1)
frequencies = [results.count(value) for value in poss_results]

# Visualize results.
title = 'Results of Rolling 2d6 1000 Times'
labels = {'x': 'Results', 'y': 'Frequency of Result'}
fig = px.bar(x=poss_results, y=frequencies, title=title, labels=labels)

# Further customize chart.
fig.update_layout(xaxis_dtick=1)

fig.show()
# fig.write_html('dice_visual.html')

Python Crash Course/data_visualization/Generating Data/dice_visual.py


import sys
import curses
import argparse
from string import ascii_letters, punctuation
from random import shuffle
from collections import deque

SCREEN = None
ARGS = None

DIGRAPHS = {('a', ':'): 'ä',
            ('o', ':'): 'ö',
            ('u', ':'): 'ü',
            ('s', 's'): 'ß'}
USER_CHARS = ascii_letters+punctuation+' '

def line_from_center(d=0):
    return (curses.LINES//2)+d

class Deck:
    """
    A Deck of flash cards.
    """
    def __init__(self, title):
        self.title = title
        self.cards = []

    def __repr__(self):
        rep = ["\t{}".format(card) for card in self.cards]
        return "\n".join(["==> {}".format(self.title)]+rep)

class Card:
    """
    A flash card.
    """
    def __init__(self, sideA, sideB):
        self.sideA = sideA
        self.sideB = sideB

    def __repr__(self):
        return "{x.sideA} <==> {x.sideB}".format(x=self)

def parse_decks():
    with open(ARGS.flashyfile) as f:
        decks = []
        for line in f.readlines():
            line = line.split("#")[0].strip()
            if not line:
                continue
            if line[0] == "$":
                decks.append(Deck(line[1:]))
            else:
                sideA, sideB = (lang.strip() for lang in line.split("::"))
                decks[-1].cards.append(Card(sideA, sideB))
                if ARGS.all:
                    decks[-1].cards.append(Card(sideB, sideA))
    return decks

def display_question(question):
    left_bound = (curses.COLS-len(question)-1)//2
    SCREEN.addstr(line_from_center(-1), left_bound, question)

def display_answer(answer):
    left_bound = (curses.COLS-len(answer)-1)//2
    SCREEN.addstr(line_from_center(0), left_bound, answer)

def display_opts(opts):
    left_bound = (curses.COLS-len(opts)-1)//2
    SCREEN.addstr(curses.LINES-2, left_bound, opts)

def display_stats(remain, total):
    s = "({}/{})".format(remain, total)
    left_bound = curses.COLS-len(s)-1
    SCREEN.addstr(0, left_bound, s)

def display_title(title):
    s = "Deck: {}".format(title)
    left_bound = (curses.COLS-len(s)-1)//2
    SCREEN.addstr(0, left_bound, s)

def display_guess(s):
    s = "=>"+s
    left_bound = (curses.COLS-1)//2 - 5
    row = line_from_center(2)
    SCREEN.move(row, 0)
    SCREEN.clrtoeol()
    SCREEN.addstr(row, left_bound, s)

def display_correct(correct):
    s = "Correct!" if correct else "Not Correct"
    left_bound = (curses.COLS-len(s)-1)//2
    SCREEN.addstr(line_from_center(3), left_bound, s)

def select_deck(decks):
    SCREEN.clear()
    if len(decks) > 1:
        SCREEN.addstr(0, 0, "Please Select a Deck to Use")
        for i, deck in enumerate(decks):
            SCREEN.addstr(i+1, 0, "{:2d}: {}".format(i+1, deck.title))
        SCREEN.addstr(i+2, 0, " q: Quit")
        SCREEN.move(i+3, 0)
        curses.echo()
        curses.curs_set(2)
        while True:
            selection = SCREEN.getstr().strip().lower()
            if selection == b"q":
                sys.exit(0)
            try:
                selection = int(selection)
                deck = decks[selection-1]
                curses.noecho()
                curses.curs_set(0)
                return deck
            except Exception:
                continue
    else:
        return decks[0]

def get_guess(mimick=None):
    s = ""
    while True:
        display_guess(s)
        key = curses.keyname(SCREEN.getch()).decode()
        if key == '^?':  # BACKSPACE
            s = s[:-1]
        elif key == '^J' and not mimick:  # ENTER
            return s
        elif key == '^W':  # CTRL-W(quit deck)
            return False
        ch = ''
        if key == '^K':  # CTRL-K(Enter digraph)
            dig1 = SCREEN.getkey()
            dig2 = SCREEN.getkey()
            dig = (dig1, dig2)
            if dig in DIGRAPHS:
                ch = DIGRAPHS[dig]
        elif key in USER_CHARS:
            ch = key
        if mimick and not mimick.startswith(s+ch):
            continue
        else:
            s += ch
        if s == mimick:
            return s

def run_deck(deck):
    cards = deque(deck.cards)
    shuffle(cards)
    N = len(cards)
    while cards:
        card = cards.popleft()
        if ARGS.reverse:
            show1, show2 = card.sideA, card.sideB
        else:
            show1, show2 = card.sideB, card.sideA
        SCREEN.clear()
        display_stats(len(cards)+1, N)
        display_title(deck.title)
        display_question(show1)
        if ARGS.spelling:  # Spelling mode
            display_opts('ctrl-W <quit>')
            guess = get_guess()
            if guess is False:
                return
            display_answer(show2)
            if guess.strip() != show2:
                cards.append(card)
                display_correct(False)
                guess = get_guess(show2)
                if guess is False:
                    return
            else:
                display_correct(True)
                SCREEN.getkey()

        else:  # Flash card mode
            SCREEN.getkey()
            display_answer(show2)
            display_opts("r <replace>  d <discard>  q <quit>")

            while True:
                c = SCREEN.getkey().lower()
                if c == 'r':
                    cards.append(card)
                    break
                elif c == 'd':
                    break
                elif c == 'q':
                    return

def main(stdscr):
    global SCREEN
    SCREEN = stdscr

    SCREEN.immedok(True)
    curses.noecho()
    curses.curs_set(0)
    decks = parse_decks()

    while True:
        deck = select_deck(decks)
        run_deck(deck)

if __name__ == "__main__":
    PARSER = argparse.ArgumentParser()
    PARSER.add_argument("flashyfile", help="The card file to use")
    PARSER.add_argument("-r", "--reverse",
                        help="Reverses which side is shown",
                        action="store_true")
    PARSER.add_argument("-a", "--all",
                        help="Creates deck with cards both \
                              flipped and unflipped",
                        action="store_true")
    PARSER.add_argument("-s", "--spelling",
                        help="Enable spelling mode",
                        action="store_true")
    ARGS = PARSER.parse_args()

    curses.wrapper(main)


import argparse

def SolveEqt(eqt:str, verbose: bool=False) -> float:
	""" The main controller, it takes the eqation string
	    and returns the outcome.

	Args:
		eqt(str): The equation string. It is a string
			  containing an equation (ex:
			  1 + 2 / (2 * 4) )
		verbose(bool): Whether or not an output should be
				generated.
	Returns:
		The outcome of the passed equation
	"""

	eqt = equationify(eqt)  #: Get back a list of each valid element for the equation
	outcome = bedmasify(eqt, verbose)  #: Get the outcome of the equation
	return outcome  #: Return the outcome.

def bedmasify(eqt: list, verbose:bool, nested_level: int=0) -> list:
	""" Evaluates the equation based on bedmas/pedmas rules.

	Args:
		eqt(list): A list containing all of the operations and numbers of
			   the equation. (ex ['1', '+', '1', '*', '2'])
		vebose(bool): Whether or not an output should be generated.
	Returns:
		The outcome of the passed equation list.
	"""

	#: Evaluate all equations within curly braces as if they are their
	#: own seperate equations.
	while '{' in eqt:
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print_eqt(eqt)

		#: Get the indices of the first opening and closing curl braces.
		open_cur = eqt.index('{')
		close_cur = eqt.index('}')
		if verbose:
			print()
			for i in range(nested_level):
				print("\t", end='')
			print('{')

		#: If nested parenthesis exist, find the outermost closing curly brace..
		i = 0
		while '(' in eqt[open_par + 1: close_par] and ')' not in eqt[open_par + 1: close_par]:
			i += 1
			close_par = eqt.index(')', i)

		#: Black magic of recursion.
		#: Replace the chunk of the list containing the bracketed section
		#: With the outcome of the chunk within brackets by recursively
		#: Evaluating the inside of the brackets.
		#: Example:
		#:	['1', '+', '{', '3', '*', '2', '}']
		#: 	the inside of the brackets (3 * 2) are evaluated recursively
		#:	 so the list becomes:
		#:		['3', '*', '2']
		#:	which is evaluated to [6] by upcoming devices, and then the
		#:	original list becomes:
		#:	['1', '+', '6']
		#: 	which is finally resolved to [7]
		eqt[open_cur: close_cur + 1] = [bedmasify(eqt[open_cur + 1: close_cur], verbose, nested_level + 1)]

		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print('}\n')

	#: Evalulate all equations within square braces as if they are their own
	#: Seperate equations.
	while '[' in eqt:
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print_eqt(eqt)

		#: Get the indices of the first appearing set of opening and
		#: Square Braces.
		open_sq = eqt.index('[')
		close_sq = eqt.index(']')

		if verbose:
			print()
			for i in range(nested_level):
				print("\t", end='')
			print('[')

		#: If nested square brackets exist, find the outermost closing square bracket.
		i = 0
		while '[' in eqt[open_sq + 1: close_sq] and ']' not in eqt[open_sq + 1: close_sq]:
			i += 1
			close_sq = eqt.index(']', i)

		#: Black magic of recursion. PLEASE NOTE, THIS USES THE SAME
		#: FUNCTIONALTY AS THE CURLY BRACES SECTION
		#: Replace the chunk of the list containing the bracketed section
		#: With the outcome of the chunk within brackets by recursively
		#: Evaluating the inside of the brackets.
		#: Example:
		#:	['1', '+', '[', '3', '*', '2', ']']
		#: 	the inside of the brackets (3 * 2) are evaluated recursively
		#:	 so the list becomes:
		#:		['3', '*', '2']
		#:	which is evaluated to [6] by upcoming devices, and then the
		#:	original list becomes:
		#:	['1', '+', '6']
		#: 	which is finally resolved to [7]
		eqt[open_sq: close_sq + 1] = [bedmasify(eqt[open_sq + 1: close_sq], verbose, nested_level + 1)]
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print(']\n')

	#: Evaluate all equations within paranthesis as if they are their
	#: own seperate equations.
	while '(' in eqt:
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print_eqt(eqt)

		#: Find the first appearance of an opening and closing parenthesis.
		open_par = eqt.index('(')
		close_par = eqt.index(')')

		if verbose:
			print()
			for i in range(nested_level):
				print("\t", end='')
			print('(')

		#: If nested parenthesis exist, find the outermost closing parenthesis.
		i = 0
		while '(' in eqt[open_par + 1: close_par] and ')' not in eqt[open_par + 1: close_par]:
			i += 1
			close_par = eqt.index(')', i)

		#: Black magic of recursion. PLEASE NOTE, THIS USES THE SAME
		#: FUNCTIONALTY AS THE CURLY BRACES SECTION
		#: Replace the chunk of the list containing the bracketed section
		#: With the outcome of the chunk within brackets by recursively
		#: Evaluating the inside of the brackets.
		#: Example:
		#:	['1', '+', '[', '3', '*', '2', ']']
		#: 	the inside of the brackets (3 * 2) are evaluated recursively
		#:	 so the list becomes:
		#:		['3', '*', '2']
		#:	which is evaluated to [6] by upcoming devices, and then the
		#:	original list becomes:
		#:	['1', '+', '6']
		#: 	which is finally resolved to [7]
		eqt[open_par: close_par + 1] = [bedmasify(eqt[open_par + 1: close_par], verbose, nested_level + 1)]
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print(")\n")

	#: Evaluate all powers as this comes after brackets/parenthesis in bedmas/pedmas.
	while '^' in eqt:
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print_eqt(eqt)

		#: Find the index of the first appearance of the power symbol.
		hat = eqt.index('^')

		base_pos = hat - 1  #: Get the index for the base of the found symbol.
		exp_pos = hat + 1  #: Get the index for the exponent of the found symbol.
		base = float(eqt[base_pos])  #: Gets the value of the base.
		exponent = float(eqt[exp_pos])  #: Gets the value of the exponent.
		eval = float(base) ** float(exponent)  #: Evaluates the exponential expression.

		#: Replace the 'X', '^', 'Y' portion of the list with the
		#: outcome of the exponential expression.
		eqt[base_pos: exp_pos + 1] = [eval]

	#: Evaluate all multiplication and division expressions from left to right
	#: as this comes after exponentials in bedmas/pedmas.
	while '*' in eqt or '/' in eqt:
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print_eqt(eqt)
		#: Try to find an index for the multiplication symbol. If it isnt found
		#: Set its position to 1 + the length of the list so that it will be ignored.
		#: PLEASE NOTE:
		#: 	this block of code will never be reached unless either the division
		#: 	or multiplication symbols exist, so setting one of the symbols to
		#:	1 + the length of the list is NOT an issue
		try:
			mul = eqt.index('*')
		except ValueError:
			mul = len(eqt) + 1

		#: Try to find an index  for the division symbol. If it isnt found
		#: set its position to 1 + the length of the list so that it will be ignored.
		#: PLEASE NOTE:
		#: 	this block of code will never be reached unless either the division
		#: 	or multiplication symbols exist, so setting one of the symbols to
		#:	1 + the length of the list is NOT an issue
		try:
			div = eqt.index('/')
		except ValueError:
			div = len(eqt) + 1

		#: Multiply the two values if a multiplication symbol is found before a
		#: Division symbol, otherwise divide.
		multiply = False  #: Default
		if mul < div:  #: If the multiply index is lower than the division index,
			multiply = True  #: Set multiply to true.

		#: Find the index of the first type of appearing symbol.
		sym_position = min([mul, div])

		first_pos = sym_position - 1  #: Get the operator's index
		second_pos = sym_position + 1  #: Get the operand's index

		first = float(eqt[first_pos])  #: Get the value for the operator
		second = float(eqt[second_pos])  #: Get the value for the operand

		#: If multply is true, then set eval equal to the operator times the operand.
		#: Otherwise, set eval to the operator divided by the operand.
		if multiply:
			eval = first * second
		else:
			eval = first / second

		#: Replace the 'X', '*', 'Y' or 'X', '/', 'Y'  portion of the list with the
		#: outcome of the multiplication/division expression.
		eqt[first_pos:second_pos + 1] = [eval]

	#: Evaluate all addition and subtractions expressions from left to right
	#: as this comes after division and multiplication in bedmas/pedmas.
	while '+' in eqt or '-' in eqt:
		if verbose:
			for i in range(nested_level):
				print("\t", end='')
			print_eqt(eqt)

		#: Try to find an index for the addition symbol. If it isnt found
		#: Set its position to 1 + the length of the list so that it will be ignored.
		#: PLEASE NOTE:
		#: 	this block of code will never be reached unless either the subtraction
		#: 	or addtion symbols exist, so setting one of the symbols to
		#:	1 + the length of the list is NOT an issue
		try:
			add = eqt.index('+')
		except ValueError:
			add = len(eqt) + 1

		#: Try to find an index for the subtraction symbol. If it isnt found
		#: Set its position to 1 + the length of the list so that it will be ignored.
		#: PLEASE NOTE:
		#: 	this block of code will never be reached unless either the subtraction
		#: 	or addtion symbols exist, so setting one of the symbols to
		#:	1 + the length of the list is NOT an issue
		try:
			sub = eqt.index('-')
		except ValueError:
			sub = len(eqt) + 1

		#: add the two values if an addition symbol is found before a
		#: subtraction symbol, otherwise subtract.
		add = False
		if add < sub:
			add = True

		#: Find the index of the first type of appearing symbol.
		sym_position = min([add, sub])
		first_pos = sym_position - 1  #: The index of the operatior.
		second_pos = sym_position + 1  #: The index of the operand.

		first = float(eqt[first_pos])  #: Get the value of the operator
		second = float(eqt[second_pos])  #: Get the value of the operand.

		#: If addition is true, then set eval equal to the operator plus the operand.
		#: Otherwise, set eval to the operator subtract by the operand.
		if add:
			eval = first + second
		else:
			eval = first - second
		#: Replace the 'X', '+', 'Y' or 'X', '-', 'Y'  portion of the list with the
		#: outcome of the addition/subtraction expression.
		eqt[first_pos:second_pos + 1] = [eval]

	if verbose:
		for i in range(nested_level):
			print('\t', end='')
		print(eqt[0])
	return eqt[0]  #: Return the outcome of the equation.

def equationify(eqt: str):
	""" Takes in a string (preferably without garbage characters, though it
	    does handle those) and converts it into a list of operators, operands and
	    operations.

	    PLEASE NOTE:
			All comments marked with (GR) are used to remove garbage from the
			equation string.

	Args:
		eqt(str): The equation string to convert.
	Returns:
		A list with the operators operands, and operations
		of the passed strings.
	"""

	proper = ''  #: Initialize the "proper" string.
	symbol = True  #: Used to determine whether the last encountered item was a symbol (GR)
	eqt = "".join(eqt.split())  #: Removes all whitespace from the string (GR)
	brackets = ['(', ')', '[', ']', '{', '}']  #: A list of the types of brackes that may be used.
	operations = ['+', '-', '*', 'x', 'X', '/', '^']  #: A list of valid operators.

	#: Append each bracket type to the operators list.
	for type in brackets:
		operations.append(type)

	#: Sanatize the string so that it only contains valid operands and operators.
	#: This will remove any doubled up operators (excluding a symbol followed by a -
	#: for negative numbers, and a symbol following a brackets or a bracket following
	#: a symbol.
	#: Example sanitized string:
	#:		"1asjdfie+dlfdk2*kkkkkkkkkkkk3"
	#:		becomes: "1+2*3"
	#: 		---- OR ----
	#:		"1 ++* 2 /@R #3"
	#:		becomes: "1+2/3"
	#:
	for index, character in enumerate(eqt):

		if character.isdigit() or character == '.':  #: If this character is a digit or a decimal point for a number.
			if symbol:  #: then, if the previous character was a symbol
				symbol = False #: then set symbol to false.
			proper += character  #: And finally append the character to proper.

		elif character in operations:  #: Otherwise, if the character is an operation (GR)
			if not symbol:  #: If the previous character wasn't a symbol

				#: Then if the character is not a closing bracket, set
				#: symbol to true, and...
				if character != ')' and character != ']' and character != '}':
					symbol = True

				#: If the character is an x or X, append a multiplication symbol.
				if 'x' == character.lower():
					proper += "*"

				#: Otherwise, append the operation's character to the proper string.
				else:
					proper += character

			#: If the last character WAS a symbol
			#: Then check the special cases, and append
			#: characters if this is a special case.

			elif character == '-':  #: Special case: Number is negative
				proper += ':' #: ':' is being used to signify a negative value.

			elif character in brackets:  #: Special case: This is a bracket
				proper += character  #: Append the characer.

	eqt = []  #: Initialize a list to hold the equation.
	builder = ""  #: Initialize a string to build numbers with.

	#: For each chatacter in the string that has been sanitized,
	#: Add each character to the builder string until an operator
	#: is reached, then append the builder string (which will be a number)
	#: then append the symbol.
	for character in proper:
		if  character in operations:  #: If the character is in operations,
			if builder != "":  #: If the builder string is not empty
				eqt.append(builder)  #: Append the string
			eqt.append(character)  #: Then append the operator.
			builder = ""  #: And finally reset the builder string for a new number.

		#: If the character is a colon, then this is leftovers from sanitation, and
		#: the colon means that this number is negative.
		elif character == ':':
			builder += '-'

		#: After all special cases are accounted for, append the character to the builder
		#: string as the character is guarenteed to be a number.
		else:
			builder += character

	#: Catch the last number.
	if builder != "":  #: If the builder string is not empty
		eqt.append(builder)  #: Append that string to the equation list.

	return eqt #: Return the equation list.

def print_eqt(eqt: list):
	""" Used to print out the equation lists without
	    the square brackets, commas, or quotes that come
	    with printing a list.
	    For example, printing the list ['5', '5'] you would get:
		"['5', '5']"
	    When using this function, you would get:
	    "5 5"

	Args:
		eqt(list): The equation to be printed

	"""

	#: Print each item of the list seperately followed by a space.
	for item in eqt:
		print(item, end=' ')

	print()  #: Print a newline after for readablity.

if __name__ == "__main__":  #: Allow this code to be used outside of just the command line.

	#: Create an arugment parser to be used when this is called from the command line.
	parser = argparse.ArgumentParser(description="Command line equation solver")

	#: Create the equation argument.
	parser.add_argument("Equation", type=str, help="The equation that should be solved. Type = str")

	#: Create the verbose argument.
	parser.add_argument('-v', "--verbose", action="store_true",
			    help="Output each step of the equation solver.")

	#: Parse the arguments.
	args = parser.parse_args()

	#: Print the result of the passed equation. If the verbose argument was given,
	#: output each step of the computing process.
	if args.verbose:
		SolveEqt(args.Equation, args.verbose)
	else:
		print(SolveEqt(args.Equation))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on May 11 22:42:06 2021
@author: krzysztof_skos
"""

import matplotlib.pyplot as plt
import numpy as np

def data_for_cylinder_along_z(center_x, center_y, radius, height_z):
    """
    Method for creating grid for cylinder drawing. Cylinder will be created along Z axis
    :param center_x: Euclidean 3 dimensional center of drawing on X axis
    :param center_y: Euclidean 3 dimensional center of drawing on Y axis
    :param radius: cylinder radius
    :param height_z: cylinder height
    :return: Three lists with grid coordinates for z, y, x sequentially
    """
    z = np.linspace(0, height_z, 50)
    theta = np.linspace(0, 2 * np.pi, 50)
    theta_grid, z_grid = np.meshgrid(theta, z)
    x_grid = radius * np.cos(theta_grid) + center_x
    y_grid = radius * np.sin(theta_grid) + center_y
    return z_grid, y_grid, x_grid

def drawPlot(rad, ax, nodeList, length):
    """
    Method for drawing plot during simulation
    :param rad: vein radius
    :param ax: instance of figure() with subplot
    :param nodeList: list of nodes to draw
    :param length: cylinder length
    :return:
    """
    ax.clear()
    ax.scatter(length-2, 0, rad, marker="o")  # router
    ax.text(length - 1.9, 0, rad, "router")
    for node in nodeList:
        if node.x <= length:
            if node.inRouterRange:
                if node.isSendingMessage:
                    ax.scatter(node.x, node.coordinateY, node.coordinateZ, marker="d", c="#00ff02")
                else:
                    ax.scatter(node.x, node.coordinateY, node.coordinateZ, marker="x", c="#00ff02")
            else:
                if node.isSendingMessage:
                    ax.scatter(node.x, node.coordinateY, node.coordinateZ, marker="d", c="Red")
                else:
                    ax.scatter(node.x, node.coordinateY, node.coordinateZ, marker="x", c="Red")

    xc, yc, zc = data_for_cylinder_along_z(0, 0, rad, length)
    ax.plot_surface(xc, yc, zc, alpha=0.5)

    ax.set_xlabel("X")
    ax.set_ylabel("Y")
    ax.set_zlabel("Z")
    plt.show()


import glob
import io
from pathlib import Path

import pandas as pd
import pytest
from hamcrest import *
from typer.testing import CliRunner

from ilids.commands.sztr.extract_video_metadata_sztr import typer_app

runner = CliRunner()

def test_no_input(tmp_path):
    result = runner.invoke(
        typer_app,
        ["ffprobe", Path(tmp_path) / "input.txt"],
    )
    assert result.exit_code == 1

@pytest.mark.sztr_files(("video", "video_folder"))
def test_invoke(video_folder: Path):
    result = runner.invoke(typer_app, ["ffprobe", str(video_folder)])
    assert result.exit_code == 0, result.stderr

    df = pd.read_csv(io.StringIO(result.stdout))
    assert_that(len(df), is_(len(glob.glob(str(video_folder / "*.mov")))))
    assert_that(len(df.columns), greater_than_or_equal_to(5))

def test_invoke_meta():
    result = runner.invoke(typer_app, ["meta"])
    assert result.exit_code == 0, result.stderr

    assert_that(
        len(result.stdout.splitlines()), greater_than_or_equal_to(2)
    )  # 2 being the number of "fields"


from __future__ import unicode_literals, print_function, division
import torch.nn as nn
from torch.nn import ModuleList
import torch.nn.functional as F
from torch_geometric.nn import BatchNorm
from torch_geometric.nn import GeneralConv
from model.datautil import (flat_gather)
from model.gnn_datatransform import GNNDataTransform, DependencyIndexer

class SubwordNet(nn.Module):
    def __init__(self, options):
        super().__init__()
        self.subword_edge_feature_emb = nn.Embedding(options["depth_size"],
                                                    options["depth_dim"],
                                                    padding_idx=options["depth_emb_pad"])
        self.convs = ModuleList()
        self.batch_norms = ModuleList()
        for _ in range(options["n_layers"]):
            conv = GeneralConv(in_channels=options["dims"][0],
                                    out_channels=options["dims"][1],
                                    in_edge_channels=options["depth_dim"],
                                    aggr=options["aggregation"],
                                    skip_linear=options["linearity"],
                                    directed_msg=True,
                                    attention=False,
                                    l2_normalize=False,
                                    bias=True,
                                    flow="target_to_source")
            self.convs.append(conv)
            self.batch_norms.append(BatchNorm(options["dims"][1]))

        self.transform = GNNDataTransform()
        self.dep_indexer = DependencyIndexer()

    def forward(self, inputs):
        '''
            Compute graph representation of sequence dependency structure.

            transform:              Data transformation object.
            dep_indexer:            Dependency data indexing object.
            data:                   Latent data.
            token_arc_head:         Sparsified dependency head of syntactic arc.
            token_arc_type:         Sparsified dependency type of syntactic arc.
            attention_mask:         Inlucde special tokens such as BOS and EOS.
                                    It is created by a tokenizer.
            token_dense_mask:       Mask out the special tokens from attention_mask.
            token_sparse_mask:      Sparse mask that mask the first token of word segmentation.
                                    It may include the special tokens.
        '''
        data = inputs["data"]
        attention_mask = inputs["attention_mask"]
        token_head = inputs["token_head"]
        token_depth = inputs["token_depth"]
        token_dense_mask = inputs["token_dense_mask"]
        token_sparse_mask = inputs["token_sparse_mask"]

        sparse_mask = token_sparse_mask*token_dense_mask
        results = self.dep_indexer(mask=attention_mask,
                                sparse_mask=sparse_mask)
        indexer = results["indexer"]
        cumsum = results["cumsum"]
        edges = self.transform.make_edges(token_head, indexer, cumsum)
        edge_features = self.subword_edge_feature_emb(token_depth)
        edge_features = flat_gather(edge_features, sparse_mask)
        data_g = self.transform.debatch(data, indexer=None)
        repr = self.subword_net(x=data_g,
                                edge_index=edges,
                                edge_attr=edge_features)

        repr = repr.reshape(data.shape)
        return repr

    def subword_net(self, x, edge_index, edge_attr):
        for conv, batch_norm in zip(self.convs, self.batch_norms):
            x = F.relu(batch_norm(conv(x, edge_index, edge_attr)))
        return x


#importing some Python libraries
from sklearn import svm
import csv

dbTest = []
X_training = []
Y_training = []
c = [1, 5, 10, 100]
degree = [1, 2, 3]
kernel = ["linear", "poly", "rbf"]
decision_function_shape = ["ovo", "ovr"]
highestAccuracy = 0

#reading the data in a csv file
with open('SVM/input_data/heartTraining_V2.csv', 'r') as trainingFile:
  reader = csv.reader(trainingFile)
  for i, row in enumerate(reader):
      X_training.append(row[:-1])
      Y_training.append(row[-1])

#reading the data in a csv file
with open('SVM/input_data/heartTesting_V2.csv', 'r') as testingFile:
  reader = csv.reader(testingFile)
  for i, row in enumerate(reader):
      dbTest.append(row)

#created 4 nested for loops that will iterate through the values of c, degree, kernel, and decision_function_shape
#--> add your Python code here

for i in c: #iterates over c
    for j in degree: #iterates over degree
        for k in kernel: #iterates kernel
           for l in decision_function_shape: #iterates over decision_function_shape

                #Create an SVM classifier that will test all combinations of c, degree, kernel, and decision_function_shape as hyperparameters. For instance svm.SVC(c=1)
                clf = svm.SVC(C=i,degree=j,kernel=k,decision_function_shape=l)

                #Fit SVM to the training data
                clf.fit(X_training, Y_training)

                #make the classifier prediction for each test sample and start computing its accuracy
                #--> add your Python code here
                counter=0

                for m in range(len(dbTest)):
                    class_predicted = clf.predict([dbTest[m][0:11]])
                    if class_predicted==dbTest[m][11]:
                        counter = counter +1

                acc = counter/len(dbTest) #temporary value of accuracy

                #check if the calculated accuracy is higher than the previously one calculated. If so, update update the highest accuracy and print it together with the SVM hyperparameters
                #Example: "Highest SVM accuracy so far: 0.92, Parameters: a=1, degree=2, kernel= poly, decision_function_shape = 'ovo'"
                #--> add your Python code here

                if counter==0:
                    highestAccuracy = acc
                    print("Highest SVM accuracy so far:" + str(highestAccuracy) + ", Parameters: c = " + str(i) + ", degree = " + str(j) + ", kernel = " + str(k) + ", decision_function_shape = " + str(l))
                else:
                    if acc >highestAccuracy:
                        highestAccuracy = acc
                        print("Highest SVM accuracy so far:" + str(highestAccuracy) + ", Parameters: c = " + str(i) + ", degree = " + str(j) + ", kernel = " + str(k) + ", decision_function_shape = " + str(l))


from BikeShop.models import Companies, Cities, BikeShops, Products, BikeShops_Products
import random
from django.core.exceptions import ObjectDoesNotExist
companies ={
    'Giro': "123 Main st",
    'Bell': "456 West St",
    'FOX': "789 Tree St",
    'CamelBak': "147 Far St",
    'Dakine': "258 North St"
}
cityid=1

def makeProducts(fileName):
    city = Cities.objects.get(id= cityid)
    with open(fileName) as f:
        lines = f.read().splitlines()
    company = None
    for line in lines:
        split_line = line.split('  ')
        if (split_line[0] == 'company'):

            addr = companies[split_line[1]]
            company = Companies.objects.get_or_create(address= addr, name=split_line[1], city_id= city)
        else:
            split_line = line.split(', ')
            starting_bikeShop_id = 1
            ending_bikeshop_id = starting_bikeShop_id + 9
            num_to_Make = random.randint(1, 7)
            for insert in range(num_to_Make):

                bs_pk = random.randint(starting_bikeShop_id, ending_bikeshop_id)

                # this will be none unless it finds, in which case an exception should be caugh
                # and the function should return
                shop = None
                try:
                    shop = BikeShops.objects.get(id=bs_pk)
                except ObjectDoesNotExist:
                    print("Bike Shop was not found. Please take a look at line 35")

                product = Products.objects.get_or_create(name= split_line[0], price= split_line[1], thumbnail= split_line[2], company_code=company[0])

                BikeShops_Products.objects.update_or_create(bikeshop_id= shop, product_id= product[0])


# график потерь Англии и Франции в войнаХ XVII-XX в.в.
#
import matplotlib.pyplot as plt
import numpy as np

def view_chart():

    # подготовка данных
    century = ['XVII в.', 'XVIII в.', 'XIX в.', 'XX в.']
    england = np.array([226, 314, 273, 807])
    france = np.array([673, 1783, 2522, 1427])
    x = np.arange(len(century))

    # ширина колонки
    width = 0.4

    # создать фигуру
    fg, ax = plt.subplots()

    # нарисовать столбцы
    rects1 = ax.bar(x, france, width, label='Франция')
    rects2 = ax.bar(x + width, england, width, label='Англия')

    # вывести значения на столбцы
    ax.bar_label(rects1, padding=-16, color='w')
    ax.bar_label(rects2, padding=-16)

    # дооформить график
    ax.set_title('Потери Англии и Франции в войнах')
    ax.set_xticks(x + width - (width/2), century)
    ax.set_ylabel('Потери (тыс.чел.)')
    ax.tick_params(bottom=False)
    ax.legend(loc='upper left', ncols=2, frameon=False)

    wm = plt.get_current_fig_manager()
    # развернуть с заголовком
    wm.window.state('zoomed')
    # развернуть без заголовка
    #wm.full_screen_toggle()

    # показать окно
    plt.show()

if __name__ == '__main__':
    view_chart()


# -*- coding: utf-8 -*-
"""
Created on Tue Dec 22 17:34:54 2020

@author: SENJU
"""

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog , QMessageBox
from PyQt5.QtGui import QImage
import cv2
import numpy as np

from fonctions import otsu , griser , egalisationHisto , lisse , etale , luminosite , translation  ,rotation90 , floutter
from fonctions import inversionCouleur , binarisation , erosion , dilatation , conserver, getLigne , getColonne

class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(1242, 698)
            self.size1 = 1200
            self.size2 = 700
            sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
            MainWindow.setSizePolicy(sizePolicy)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.label = QtWidgets.QLabel(self.centralwidget)
            self.label.setGeometry(QtCore.QRect(9, 9, 1189, 630))
            self.label.setMaximumSize(QtCore.QSize(1250, 720))
            self.label.setText("")
            self.label.setPixmap(QtGui.QPixmap("../../AIVOPr/images/01972_hsbccelebrationoflight_1920x1080.jpg"))
            self.label.setScaledContents(True)
            self.label.setObjectName("label")
            self.horizontalSlider = QtWidgets.QSlider(self.centralwidget)
            self.horizontalSlider.setGeometry(QtCore.QRect(1199, 40, 151, 22))
            self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
            self.horizontalSlider.setObjectName("horizontalSlider")
            self.horizontalSlider_2 = QtWidgets.QSlider(self.centralwidget)
            self.horizontalSlider_2.setGeometry(QtCore.QRect(1200, 90, 160, 22))
            self.horizontalSlider_2.setOrientation(QtCore.Qt.Horizontal)
            self.horizontalSlider_2.setObjectName("horizontalSlider_2")
            self.label_2 = QtWidgets.QLabel(self.centralwidget)
            self.label_2.setGeometry(QtCore.QRect(1200, 20, 61, 16))
            self.label_2.setObjectName("label_2")
            self.label_3 = QtWidgets.QLabel(self.centralwidget)
            self.label_3.setGeometry(QtCore.QRect(1200, 70, 61, 16))
            self.label_3.setObjectName("label_3")
            MainWindow.setCentralWidget(self.centralwidget)
            self.menubar = QtWidgets.QMenuBar(MainWindow)
            self.menubar.setEnabled(True)
            self.menubar.setGeometry(QtCore.QRect(0, 0, 1290, 22))
            self.menubar.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
            self.menubar.setDefaultUp(False)
            self.menubar.setNativeMenuBar(True)
            self.menubar.setObjectName("menubar")
            self.menuOuvrir = QtWidgets.QMenu(self.menubar)
            icon = QtGui.QIcon()
            icon.addPixmap(QtGui.QPixmap("icons/16x16/Open_16px_1.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.menuOuvrir.setIcon(icon)
            self.menuOuvrir.setObjectName("menuOuvrir")
            self.menuAmelioration = QtWidgets.QMenu(self.menubar)
            self.menuAmelioration.setObjectName("menuAmelioration")
            self.menuFiltrage = QtWidgets.QMenu(self.menubar)
            self.menuFiltrage.setObjectName("menuFiltrage")
            self.menuBinarisation = QtWidgets.QMenu(self.menubar)
            self.menuBinarisation.setObjectName("menuBinarisation")
            self.menuTransformation = QtWidgets.QMenu(self.menubar)
            self.menuTransformation.setObjectName("menuTransformation")
            self.menuRotation = QtWidgets.QMenu(self.menubar)
            self.menuRotation.setObjectName("menuRotation")
            self.menuTranslation = QtWidgets.QMenu(self.menubar)
            self.menuTranslation.setObjectName("menuTranslation")
            MainWindow.setMenuBar(self.menubar)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
            self.toolBar = QtWidgets.QToolBar(MainWindow)
            self.toolBar.setObjectName("toolBar")
            MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
            self.toolBar_2 = QtWidgets.QToolBar(MainWindow)
            self.toolBar_2.setObjectName("toolBar_2")
            MainWindow.addToolBar(QtCore.Qt.RightToolBarArea, self.toolBar_2)
            self.actionOuvrir = QtWidgets.QAction(MainWindow)
            icon1 = QtGui.QIcon()
            icon1.addPixmap(QtGui.QPixmap("icons/16x16/Add Image_16px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionOuvrir.setIcon(icon1)
            self.actionOuvrir.setIconVisibleInMenu(False)
            self.actionOuvrir.setObjectName("actionOuvrir")
            self.actionEnregister = QtWidgets.QAction(MainWindow)
            icon2 = QtGui.QIcon()
            icon2.addPixmap(QtGui.QPixmap("icons/16x16/Save_16px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionEnregister.setIcon(icon2)
            self.actionEnregister.setObjectName("actionEnregister")
            self.actionExit = QtWidgets.QAction(MainWindow)
            icon3 = QtGui.QIcon()
            icon3.addPixmap(QtGui.QPixmap("icons/16x16/Exit_16px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionExit.setIcon(icon3)
            self.actionExit.setObjectName("actionExit")
            self.actionEgalisation = QtWidgets.QAction(MainWindow)
            self.actionEgalisation.setObjectName("actionEgalisation")
            self.actionMedian = QtWidgets.QAction(MainWindow)
            self.actionMedian.setObjectName("actionMedian")
            self.actionGaussien = QtWidgets.QAction(MainWindow)
            self.actionGaussien.setObjectName("actionGaussien")
            self.actionMoyenne = QtWidgets.QAction(MainWindow)
            self.actionMoyenne.setObjectName("actionMoyenne")
            self.actionLissage = QtWidgets.QAction(MainWindow)
            self.actionLissage.setObjectName("actionLissage")
            self.actionSeuil = QtWidgets.QAction(MainWindow)
            self.actionSeuil.setObjectName("actionSeuil")
            self.actionErosion = QtWidgets.QAction(MainWindow)
            self.actionErosion.setObjectName("actionErosion")
            self.actionDilatation = QtWidgets.QAction(MainWindow)
            self.actionDilatation.setObjectName("actionDilatation")
            self.actionNiveau_de_gris = QtWidgets.QAction(MainWindow)
            self.actionNiveau_de_gris.setObjectName("actionNiveau_de_gris")
            self.actionNiveau_de_gris_2 = QtWidgets.QAction(MainWindow)
            self.actionNiveau_de_gris_2.setObjectName("actionNiveau_de_gris_2")
            self.actionNiveau_de_Gris = QtWidgets.QAction(MainWindow)
            self.actionNiveau_de_Gris.setIcon(icon)
            self.actionNiveau_de_Gris.setObjectName("actionNiveau_de_Gris")
            self.actionOpen = QtWidgets.QAction(MainWindow)
            self.actionOpen.setIcon(icon1)
            self.actionOpen.setObjectName("actionOpen")
            self.actionInversion = QtWidgets.QAction(MainWindow)
            icon4 = QtGui.QIcon()
            icon4.addPixmap(QtGui.QPixmap("icons/16x16/Sorting Arrows_16px_1.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.actionInversion.setIcon(icon4)
            self.actionInversion.setObjectName("actionInversion")
            self.actionRotation_90 = QtWidgets.QAction(MainWindow)
            self.actionRotation_90.setObjectName("actionRotation_90")
            self.actionRotation_45 = QtWidgets.QAction(MainWindow)
            self.actionRotation_45.setObjectName("actionRotation_45")
            self.actionConservation = QtWidgets.QAction(MainWindow)
            self.actionConservation.setObjectName("actionConservation")
            self.actionSymetrie = QtWidgets.QAction(MainWindow)
            self.actionSymetrie.setObjectName("actionSymetrie")
            self.actionContours = QtWidgets.QAction(MainWindow)
            self.actionContours.setObjectName("actionContours")
            self.actionTranslation_1_0_100_0_1_50 = QtWidgets.QAction(MainWindow)
            self.actionTranslation_1_0_100_0_1_50.setObjectName("actionTranslation_1_0_100_0_1_50")
            self.menuOuvrir.addAction(self.actionOpen)
            self.menuOuvrir.addAction(self.actionEnregister)
            self.menuOuvrir.addAction(self.actionExit)
            self.menuAmelioration.addAction(self.actionEgalisation)
            self.menuAmelioration.addAction(self.actionConservation)
            self.menuFiltrage.addAction(self.actionMoyenne)
            self.menuFiltrage.addAction(self.actionLissage)
            self.menuBinarisation.addAction(self.actionSeuil)
            self.menuBinarisation.addAction(self.actionErosion)
            self.menuBinarisation.addAction(self.actionDilatation)
            self.menuBinarisation.addAction(self.actionContours)
            self.menuTransformation.addAction(self.actionNiveau_de_Gris)
            self.menuTransformation.addAction(self.actionInversion)
            self.menuTransformation.addAction(self.actionSymetrie)
            self.menuRotation.addAction(self.actionRotation_90)
            self.menuTranslation.addAction(self.actionTranslation_1_0_100_0_1_50)
            self.menubar.addAction(self.menuOuvrir.menuAction())
            self.menubar.addAction(self.menuTransformation.menuAction())
            self.menubar.addAction(self.menuAmelioration.menuAction())
            self.menubar.addAction(self.menuFiltrage.menuAction())
            self.menubar.addAction(self.menuBinarisation.menuAction())
            self.menubar.addAction(self.menuRotation.menuAction())
            self.menubar.addAction(self.menuTranslation.menuAction())

            self.retranslateUi(MainWindow)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
            self.actionOpen.triggered.connect(self.recuperer)
            self.actionEgalisation.triggered.connect(self.egalisationHistogrammeCouleur)
            self.actionNiveau_de_Gris.triggered.connect(self.grise)
            self.actionSeuil.triggered.connect(self.seuil)
            self.actionInversion.triggered.connect(self.inversion)
            self.actionErosion.triggered.connect(self.erosion)
            self.actionDilatation.triggered.connect(self.dilatation)
            self.actionLissage.triggered.connect(self.lissage)
            self.actionMoyenne.triggered.connect(self.etalage)
            self.actionEnregister.triggered.connect(self.enregister)
            self.actionSymetrie.triggered.connect(self.symetrie)
            self.horizontalSlider.valueChanged['int'].connect(self.valueLuminosite)
            self.horizontalSlider_2.valueChanged['int'].connect(self.valueBlur)
            self.actionRotation_90.triggered.connect(self.rotation)
            self.actionTranslation_1_0_100_0_1_50.triggered.connect(self.translation)

            self.filename = None #retenir adresse de l'image

            self.temp = None #affichage temporaire de l'image pour affichage

        def recuperer(self):
            self.filename = QtWidgets.QFileDialog.getOpenFileName(filter="Image (*.*)")[0]
            self.image = cv2.imread(self.filename)
            self.affichage(self.image)

        def enregister(self):
            cv2.imwrite("Image.png",self.temp)
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)
            msg.setText("Enregistrement")
            msg.setInformativeText("Image enregister")
            msg.setWindowTitle("Enregister")
            msg.exec()

        def affichage(self,image):
            self.temp = image
            self.resize()
            frame = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            image = QImage(frame , frame.shape[1], frame.shape[0] , frame.strides[0],QImage.Format_RGB888)
            window = MainWindow.height()
            self.size1 = getLigne(window)
            self.size2 = getColonne(self.image,window)
            self.label.setMaximumSize(QtCore.QSize(self.size1, self.size2))
            self.label.setPixmap(QtGui.QPixmap.fromImage(image))

        def grise(self):
            image_grise = griser(self.filename)
            self.affichage(image_grise)

        def egalisationHistogramme(self):

            self.image = self.griser()
            equ = cv2.equalizeHist(self.image)
            self.affichage(equ)

        def egalisationHistogrammeCouleur(self):

            image = cv2.imread(self.filename)
            #on divise l'image en 3 bandes R V B
            b,v,r = cv2.split(image)
            #on egalise l'histogramme de chaque bande
            #on fusionne les 3 bandes pour avoir une seule image couleur
            y = cv2.merge((egalisationHisto(b),egalisationHisto(v),egalisationHisto(r)))
            self.affichage(y)

        def seuil(self):
            image_grise = griser(self.filename)
            seuil = otsu(image_grise)
            newimage = image_grise.copy()
            image_binaire = binarisation(image_grise,seuil,newimage)

            self.affichage(image_binaire)

        def resize(self):
            image = cv2.imread(self.filename)
            window = MainWindow.height()
            self.size1 = MainWindow.height() - 100
            self.size2 = ((MainWindow.height() - 100 ) * image.shape[0]) / image.shape[1]
            self.size1 = getLigne(window)
            self.size2 = getColonne(image,window)
            self.label.setMaximumSize(QtCore.QSize(self.size1, self.size2))

        def inversion(self):
            image = cv2.imread(self.filename)
            #on divise l'image en 3 bandes R V B
            b,v,r = cv2.split(image)

            new_imageInverser = cv2.merge((inversionCouleur(r) , inversionCouleur(v) , inversionCouleur(b)))
            self.affichage(new_imageInverser )

        def erosion(self):
            image_grise = griser(self.filename)
            image_erode = image_grise.copy()
            new_imageErode = erosion(image_grise,image_erode)
            self.affichage(new_imageErode)

        def dilatation(self):
            image_grise = griser(self.filename)
            image_dilate = image_grise.copy()
            ligne = image_grise.shape[0]
            colonne = image_grise.shape[1]
            new_imageDilate = dilatation(image_grise,ligne,colonne,image_dilate)

            self.affichage(new_imageDilate)

        def conservateur(self):
            #image_grise = griser(self.filename)
            #image_conserver = image_grise.copy()
            #new_imageConserver = conserver(image_grise,image_conserver)
            image = cv2.imread(self.filename)
            image_conserver = image.copy()
            #on divise l'image en 3 bandes R V B
            b,v,r = cv2.split(image)

            new_imageConserver = cv2.merge((conserver(b,image_conserver),conserver(v,image_conserver),conserver(r,image_conserver)))
            self.affichage(new_imageConserver)

        def lissage(self):
            image = cv2.imread(self.filename)
            image_lisse = image.copy()
            #on divise l'image en 3 bandes R V B
            b,v,r = cv2.split(image)
            image_lisseRVB = cv2.merge((lisse(v,image_lisse),lisse(b,image_lisse),lisse(r,image_lisse)))
            self.affichage(image_lisseRVB)

        def valueLuminosite(self,value):
            image = cv2.imread(self.filename)
            self.luminosite_value_now = value
            new_imageChanger = luminosite(image,value)
            self.affichage(new_imageChanger)

        def valueBlur(self,value):
            image = cv2.imread(self.filename)
            self.blur_value_now = value
            blur_image =  floutter(image,value)
            self.affichage(blur_image)

        def etalage(self):
            image = cv2.imread(self.filename)
            #on divise l'image en 3 bandes R V B et on l'etale un par un puis le mettre en une seule image
            b,v,r = cv2.split(image)
            image_etale = cv2.merge((etale(b),etale(v),etale(r)))
            self.affichage(image_etale)

        def symetrie(self):
            image = cv2.imread(self.filename)
            image_sym = image.copy()
            for i in range(0,image.shape[0]):
                for j in range(0,image.shape[1]):
                  image_sym[i][j] = image[image.shape[0] - 1 - i][j]

            self.affichage(image_sym)

        def rotation(self):
            image = self.temp
            image_rot = rotation90(image)
            self.affichage(image_rot)

        def translation(self):
            image = cv2.imread(self.filename)
            image_translation = translation(image)

            self.affichage(image_translation)

        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.label_2.setText(_translate("MainWindow", "Lumonisite"))
            self.label_3.setText(_translate("MainWindow", "Floutter"))
            self.menuOuvrir.setTitle(_translate("MainWindow", "Ouvrir"))
            self.menuAmelioration.setTitle(_translate("MainWindow", "Amelioration"))
            self.menuFiltrage.setTitle(_translate("MainWindow", "Filtrage"))
            self.menuBinarisation.setTitle(_translate("MainWindow", "Binarisation"))
            self.menuTransformation.setTitle(_translate("MainWindow", "Transformation"))
            self.menuRotation.setTitle(_translate("MainWindow", "Rotation"))
            self.menuTranslation.setTitle(_translate("MainWindow", "Translation"))
            self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
            self.toolBar_2.setWindowTitle(_translate("MainWindow", "toolBar_2"))
            self.actionOuvrir.setText(_translate("MainWindow", "Ouvrir"))
            self.actionEnregister.setText(_translate("MainWindow", "Enregister"))
            self.actionExit.setText(_translate("MainWindow", "Quitter"))
            self.actionEgalisation.setText(_translate("MainWindow", "Egalisation Histogramme"))
            self.actionMedian.setText(_translate("MainWindow", "Median"))
            self.actionGaussien.setText(_translate("MainWindow", "Gaussien"))
            self.actionMoyenne.setText(_translate("MainWindow", "Etalage"))
            self.actionLissage.setText(_translate("MainWindow", "Lissage"))
            self.actionSeuil.setText(_translate("MainWindow", "Seuillage Otsu"))
            self.actionErosion.setText(_translate("MainWindow", "Erosion"))
            self.actionDilatation.setText(_translate("MainWindow", "Dilatation"))
            self.actionNiveau_de_gris.setText(_translate("MainWindow", "Niveau de gris"))
            self.actionNiveau_de_gris_2.setText(_translate("MainWindow", "Niveau de gris"))
            self.actionNiveau_de_Gris.setText(_translate("MainWindow", "Niveau de Gris"))
            self.actionOpen.setText(_translate("MainWindow", "Ouvrir"))
            self.actionInversion.setText(_translate("MainWindow", "Inversion Couleur"))
            self.actionRotation_90.setText(_translate("MainWindow", "Rotation 90 "))
            self.actionRotation_45.setText(_translate("MainWindow", "Rotation 45"))
            self.actionSymetrie.setText(_translate("MainWindow", "Symetrie"))
            self.actionContours.setText(_translate("MainWindow", "Contours"))
            self.actionTranslation_1_0_100_0_1_50.setText(_translate("MainWindow", "Translation [[1,0,100],[0,1,50]]"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())


## remaining tasks:
    ## 1- initial values
    ## 2- quantization for forward

import torch
import torch.nn.functional as F
import math
import time
import torch.optim as optim
from .binarized_modules import Binarize

class Maj3(torch.nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=3, bias=True):
        super(Maj3, self).__init__()

        self.k_w = kernel_size
        self.k_h = kernel_size
        self.k_w_pad = math.floor(self.k_w/2)
        self.k_h_pad = math.floor(self.k_h/2)

        self.c_in = in_channels
        self.c_out = out_channels

        self.weights = torch.nn.Parameter(torch.empty(self.c_out, self.k_w * self.k_h * self.c_in))
        self.bias = torch.nn.Parameter(torch.empty(self.c_out)) if bias else None

        self.reset_parameters()

    def reset_parameters(self):
        #stdv = 1.0 / math.sqrt(self.state_size)
        for weight in self.parameters():
            #weight.data.uniform_(-stdv, +stdv)
            weight.data = torch.randint(0, 2 , weight.data.shape,
                dtype=torch.float).mul_(2.0).add_(-1)

    def forward(self, input):
        # it sems that quantization should be applied on both weights and inputs here
        if input.size(1) != 3: #dont binarise input
            input.data = Binarize(input.data)
        if not hasattr(self.weights,'org'):
            self.weights.org=self.weights.data.clone()
        self.weights.data=Binarize(self.weights.org)

        # compute majority
        input_shape = input.shape
        w_in = input_shape[2]
        h_in = input_shape[3]

        input_paded = F.pad(input, (0,0,self.k_h_pad,self.k_h_pad,self.k_w_pad,self.k_w_pad),
            mode='constant', value=-1)

        input_unfolded = input_paded.unfold(1,self.k_w,1).unfold(2,self.k_h,1).reshape(
            [-1,self.k_w*self.k_h*self.c_in])

        inter_maj3 = torch.sum(torch.einsum('bj,aj->baj', input_unfolded, self.weights).reshape(
            [-1,self.k_w,self.k_h*self.c_in]), 1)
        output = torch.sum(torch.clamp(inter_maj3, min=-1.0, max=1.0).mul_(3.0), 1).reshape(
            [-1, w_in, h_in, self.c_out])

        # add bias if required
        if not self.bias is None:
            self.bias.org=self.bias.data.clone()
            output += self.bias.view(1, 1, 1, -1).expand_as(output)

        output = output.transpose(2,3).transpose(1,2)
        return output

"""
def mse_loss(input, target):
    return ((input - target) ** 2).sum() / input.data.nelement()
##############################
assert torch.cuda.is_available()
cuda_device = torch.device('cuda:0')  # device object representing GPU

B = 50
Win = 32
Hin = 32
Cin = 4

Cout = 8
Kh = 3
Kw = 3
Khpad = math.floor(Kh/2)
Kwpad = math.floor(Kw/2)

X = torch.randint(0, 2 , (B, Win, Hin, Cin),
    device=cuda_device, dtype=torch.float).mul_(2.0).add_(-1)

maj3 = Maj3(Cout, Kw, Kh, Cin).to(device=cuda_device)

optimizer = optim.SGD(maj3.parameters(), lr=0.01, momentum=0.9)

forward = 0
backward = 0
iter_counter = 10
for _ in range(iter_counter):
    start = time.time()
    output = maj3(X)
    #print(output[0,0,0,:])

    torch.cuda.synchronize()
    forward += time.time() - start

    start = time.time()

    optimizer.zero_grad()
    loss = mse_loss(output, torch.zeros_like(output))
    print (loss)
    loss.backward()
    optimizer.step()

    torch.cuda.synchronize()
    backward += time.time() - start

print('Forward: {:.3f} us | Backward {:.3f} us'.format(
    forward * 1e6/iter_counter, backward * 1e6/iter_counter))
"""


from typing import Tuple

import tensorflow as tf
from tensorflow.keras.layers import Conv3D, Dense, Flatten, MaxPooling3D
from tensorflow.keras.models import Sequential

from src import logging
from src.data import dataloader, preprocessing
from src.data.train import default_config
from src.model import base

logger = logging.create_logger(__name__)

NAME = "Conv3D"

class CNN3D(base.Model):
    """Create Conv3D model."""

    def __init__(self, num_images=8):
        """Initialize the architecture."""
        super().__init__(NAME)
        self.num_images = num_images

        self.scaling_image = preprocessing.min_max_scaling_images()
        self.scaling_ghi = preprocessing.min_max_scaling_ghi()

        self.conv1 = self._convolution_step((1, 5, 5), 64)
        self.conv2 = self._convolution_step((1, 3, 3), 128)
        self.conv3 = self._convolution_step((1, 3, 3), 256)

        self.flatten = Flatten()

        self.d1 = Dense(1048, activation="relu")
        self.d2 = Dense(512, activation="relu")
        self.d3 = Dense(256, activation="relu")
        self.d4 = Dense(4)

    def call(self, data: Tuple[tf.Tensor], training=False):
        """Performs the forward pass in the neural network.

        Can use a different pass with the optional training boolean if
        some operations need to be skipped at evaluation(e.g. Dropout)
        """
        x = data[0]

        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)

        x = self.flatten(x)

        x = self.d1(x)
        x = self.d2(x)
        x = self.d3(x)
        x = self.d4(x)

        return x

    def _convolution_step(self, kernel_size, channels):
        conv3d_1 = Conv3D(channels, kernel_size=kernel_size, activation="relu")
        conv3d_2 = Conv3D(channels, kernel_size=kernel_size, activation="relu")
        conv3d_3 = Conv3D(channels, kernel_size=kernel_size, activation="relu")
        max_pool = MaxPooling3D(pool_size=(1, 2, 2))

        return Sequential([conv3d_1, conv3d_2, conv3d_3, max_pool])

    def config(self) -> dataloader.DataloaderConfig:
        """Configuration."""
        config = default_config()
        config.num_images = self.num_images
        config.ratio = 0.1
        config.time_interval_min = 30
        config.features = [dataloader.Feature.image, dataloader.Feature.target_ghi]

        return config

    def preprocess(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
        """Applies the preprocessing to the inputs and the targets."""

        def preprocess(images, target_ghi):
            images = self.scaling_image.normalize(images)
            target_ghi = self.scaling_ghi.normalize(target_ghi)
            return images, target_ghi

        return dataset.map(preprocess)


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from tqdm import tqdm
from SVM import OVO_test, OVO_train
import kernels
import argparse
from hog import hog
from utils import decision

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-c", "--combine", default=False, help="Wether to combine both methods or not")
args = parser.parse_args()
config = vars(args)

from kmeans import kmeans_centroids
from utils import extract_patches, whiten_patches, compute_features, post_processing

Xtr = pd.read_csv('data/Xtr.csv',header=None,sep=',',usecols=range(3072))
Xte = pd.read_csv('data/Xte.csv',header=None,sep=',',usecols=range(3072))
Ytr_ = pd.read_csv('data/Ytr.csv')#, index_col = None, header = None)

Xtr = np.array(Xtr).reshape(5000, 3,32, 32).swapaxes(1,2).swapaxes(2,3)
Xte = np.array(Xte).reshape(2000, 3,32, 32).swapaxes(1,2).swapaxes(2,3)
Ytr = np.array(Ytr_['Prediction'])
X_tot = np.vstack([Xtr, Xte]) #Entire dataset used for feature extraction

##Extract
patches = extract_patches(X_tot, 200000, 6)

##Whiten
print("whitening patches...")
patches, M, P = whiten_patches(patches)

##Cluster
print("computing centroids...")
centroids = kmeans_centroids(patches, num_centroids = 400, n_iter = 50)

##Compute features
print("Computing train features...")
X_train = compute_features(Xtr, centroids, stride=10, patch_size = 6, M = M, P = P)
print("Computing test features...")
X_test = compute_features(Xte, centroids, stride=10, patch_size = 6, M = M, P = P)

##Scale
X_train = post_processing(X_train)
X_test = post_processing(X_test)

print("Fitting SVM...")
dic = OVO_train(X_train, Ytr, sigma = 60, C = 10, ker = kernels.RBF)
_, pred = OVO_test(X_test, dic)

if config["combine"]:
    print("training the hog model!")
    print("computing hog features...")
    Xtr_hog = np.array([hog(image) for image in Xtr])
    Xte_hog = np.array([hog(image) for image in Xte])
    print("Fitting SVM...")
    dic2 = OVO_train(Xtr_hog, Ytr, sigma = 3, C = 1, ker=kernels.LaplacianRBFKernel) #Laplacian kernel
    allvotes,_ = OVO_test(Xte_hog, dic2)
    pred = np.array([decision(pred[i],allvotes[i]) for i in range(len(pred))])

print("done!")
aux = pd.DataFrame(pred).reset_index()
aux['index']+=1
aux.rename(columns={'index':'Id', 0:"Prediction"}, inplace=True)
pd.DataFrame(aux).to_csv("Yte.csv", index=False)


import unittest
import json
from tweetybird import is_retweeted_text

class RetweetedTextTestCase(unittest.TestCase):
    def test_is_retweeted(self):
        with open("tweet_2020.js") as f1:
            self.assertTrue(is_retweeted_text(json.load(f1)))

    def test_is_not_retweeted(self):
        with open("tweet_2021.js") as f1:
            self.assertFalse(is_retweeted_text(json.load(f1)))

if __name__ == '__main__':
    unittest.main()


import tqdm
import random
import numpy as np
import tensorflow as tf

import utils
import data_loader
from model import NLR_model
from hyper_params import HyperParams

def test():
    hparams = HyperParams()

    parser = hparams.parser
    hp = parser.parse_args()

    test_users, test_hist_items, test_scores, test_labels = data_loader.load_test_datas(
        hp.test_datas, hp.is_with_feedback)

    user_2_id, item_2_id, train_hypers = utils.load_training_info(hp.checkpoint_dir)
    id_2_item = {id: item for item, id in item_2_id.items()}

    model = NLR_model(user_embedding_dim=train_hypers.get('user_embedding_dim'),
                      item_embedding_dim=train_hypers.get('item_embedding_dim'),
                      hidden1_dim=train_hypers.get('hidden1_dim'),
                      hidden2_dim=train_hypers.get('hidden2_dim'),
                      num_users=train_hypers.get('num_users'),
                      num_items=train_hypers.get('num_items'),
                      interact_type=train_hypers.get('interact_type'))

    saver = tf.train.Saver()
    with tf.Session() as sess:
        # restore
        saver.restore(sess, hp.ckpt)

        items_embedding_matrix = sess.run(model.item_embedding_layer)
        items_embedding_matrix = items_embedding_matrix[:, np.newaxis, :]

        topk = hp.topk
        count = 0
        hr_total = 0
        ndcg_total = 0
        for user, hist, feedback, label in tqdm.tqdm(zip(test_users, test_hist_items, test_scores,
                                                         test_labels)):
            # if random.random() > 0.02:
            #     continue
            user_data, items_data, feedback_data = data_loader.test_batch(user, hist, feedback,
                                                                          user_2_id, item_2_id)

            prob_pos = sess.run(model.probability_pos,
                                feed_dict={model.input_user: user_data,
                                           model.input_items: items_data,
                                           model.input_feedback_score: feedback_data,
                                           model.target_emb_vec: items_embedding_matrix})

            prob_pos = np.squeeze(prob_pos, axis=1)
            pred_item_ids = np.argsort(prob_pos, axis=0)[::-1][:topk]
            label_ids = [item_2_id.get(label, item_2_id[data_loader.UNKNOWN_TAG])]

            ndcg_score = utils.calNDCG(pred_item_ids, label_ids)
            ndcg_total += ndcg_score

            hr_score = len(set(pred_item_ids).intersection(set(label_ids))) / len(label_ids)
            hr_total += hr_score

            count += 1

        print('HR@{}: {:.6f}'.format(topk, hr_total / count))
        print('NDCG@{}: {:.6f}'.format(topk, ndcg_total / count))

if __name__ == '__main__':
    test()


import random

import requests

def get_quotes(url, anzahl=5):
    # Make a GET request and get response data
    response = requests.get(url)

    # parse json and get the quote list back
    data = response.json()

    quotes = [dictionary['text'] for dictionary in data]
    return quotes[:anzahl]

def get_hidden_quote(some_quote):
    # 'We can only' => '__ ___ ____'

    # create empty string (hidden_quote)
    hidden_quote = ''
    # for each letter in quote
    for letter in some_quote:
        # if a letter => add '_' to string
        if letter.isalpha():
            hidden_quote += '_'

        # else add the symbol
        else:
            hidden_quote += letter
    # return the hidden quote
    return hidden_quote

def reveal_letter_in_quote(some_letter: str, some_quote: str, some_hidden_quote: str) -> str:
    # some_quote = 'We can only'
    # some_hidden_quote = '__ ___ ____'
    # some_letter = 'a'

    new_hidden_quote = ''
    # for each letter from the quote
    for letter, letter_hidden in zip(some_quote, some_hidden_quote):

        # if the letter is not _ => copy it to new_hidden_quote
        if letter_hidden != '_' or letter.lower() == some_letter.lower():
            new_hidden_quote += letter
        else:
            # else add _
            new_hidden_quote += '_'

    return new_hidden_quote

if __name__ == '__main__':
    api_url = 'https://type.fit/api/quotes'

    quote_list = get_quotes(api_url, 20)

    # Ein Satz wälen
    quote = random.sample(quote_list, 1)[0]
    quote_hidden = get_hidden_quote(quote)
    # print(quote, '\n', quote_hidden, sep='')

    # Anzahl Leben
    leben = 10

    while leben != 0 and quote != quote_hidden:

        print(quote_hidden)

        # Sage ein Buchstabe
        buchstabe = input('Sage einen Buchstaben!')

        # Testen ob diesen Buchstaben gibt
        if buchstabe in quote:
            quote_hidden = reveal_letter_in_quote(buchstabe, quote, quote_hidden)

        else:
            leben -= 1
            print(f'Buchstaben nicht vorhanden! Du hast noch {leben}')

    if leben > 0:
        print(f'Du hast gewonnen mit {leben}!')
    else:
        print(f'Du hast verloren. \n Der Satz lautet {quote}!')