import time
import os

from selenium import webdriver
from selenium.common.exceptions import (
    NoSuchElementException,
    ElementClickInterceptedException,
)

from dotenv import load_dotenv

load_dotenv()

chrome_driver = "/usr/bin/chromedriver"

url = "https://tinder.com/"

driver = webdriver.Chrome(chrome_driver)

driver.get(url)

time.sleep(1)
# xpath for acccept cookies link
xpath = '//*[@id="t-1801132545"]/div/div[2]/div/div/div[1]/button/span'
# if the accept cookie link exists, click it
try:
    driver.find_element_by_xpath(xpath).click()
except NoSuchElementException:
    print("Cookie popup not found")

time.sleep(1)
# xpath for Log in button in top right of screen
xpath = (
    '//*[@id="t-1801132545"]/div/div[1]/div/main/div[1]/div/div/div/div/'
    "header/div/div[2]/div[2]/button/span"
)
driver.find_element_by_xpath(xpath).click()

time.sleep(1)
# xpath Log In with Facebook button
xpath = (
    '//*[@id="t--239073259"]/div/div/div[1]/div/div[3]/span/div[2]/'
    "button/span[2]"
)
driver.find_element_by_xpath(xpath).click()

time.sleep(1)
# switch to facebook login pop up and login with facebook details
driver.switch_to.window(driver.window_handles[1])
driver.find_element_by_id("email").send_keys(os.getenv("FB_USERNAME"))
driver.find_element_by_id("pass").send_keys(os.getenv("FB_PASSWORD"))
driver.find_element_by_id("loginbutton").click()

time.sleep(3)
# switch back to main tinder window
driver.switch_to.window(driver.window_handles[0])
# Allow tinder to use my location
xpath = '//*[@id="t--239073259"]/div/div/div/div/div[3]/button[1]/span'
try:
    driver.find_element_by_xpath(xpath).click()
except NoSuchElementException:
    print("location popup not found")

# Not Interested in Notifcations
time.sleep(2)
xpath = '//*[@id="t--239073259"]/div/div/div/div/div[3]/button[2]/span'
try:
    driver.find_element_by_xpath(xpath).click()
except NoSuchElementException:
    print("notification popup not found")

time.sleep(2)
# xpath for dislike button
xpath = (
    '//*[@id="t-1801132545"]/div/div[1]/div/main/div[1]/div/div/div[1]'
    "/div/div[2]/div[2]/button"
)
# try and click disklike in loop with pause between, print an error to
# console if dislike button not found
for _ in range(10):
    try:
        driver.find_element_by_xpath(xpath).click()
    except NoSuchElementException:
        print("dislike button not found")
    except ElementClickInterceptedException:
        print("click intercepted")
    time.sleep(2)

driver.quit()


import numpy as np
import matplotlib.pyplot as plt

if __name__ == '__main__':

    x_axis = np.array([2, 6, 10, 14])
    Schuler_vor = [10, 14, 1, 15]
    Schuler_nach = [16, 14, 2, 8]
    Schulerinnen_vor = [10, 14, 0, 16]
    Schulerinnen_nach = [13, 15, 0, 12]

    with plt.style.context('seaborn'):
        plt.bar(x_axis-.5,
                height=Schulerinnen_vor,
                #color='#1b4f72',
                label='Strategie vorher'
                )  # Limit for View is at bins=10^4!

        plt.bar(x_axis+.5,
                height=Schulerinnen_nach,
                #color='#1b4f72',
                label='Strategie nachher'
                )  # Limit for View is at bins=10^4!

        plt.legend(loc='upper right',
                   prop={'weight': 'bold', 'size': 20},
                   frameon=True,
                   fancybox=True,
                   shadow=True,
                   facecolor='white')  # location of legend upper right (best option)

        plt.tick_params(labelsize=25)
        plt.xticks(x_axis, ['Punkte', 'Anzahl', 'Kombination', 'Spontan'])
        plt.yticks(range(0, 22, 5))

        plt.xlabel('Strategien der Schülerinnen', fontsize=25, fontweight='bold')
        plt.ylabel('Häufigkeit', fontsize=25, fontweight='bold')

plt.grid(True)
plt.show()


from helper import get_participant_folders, get_sorted_bds_files
import csv
from datetime import datetime, time, timedelta

def main():
    participants = get_participant_folders()
    for part in participants:
        create_bds_stamps(part)

BDS_HEADER = ["phase", "trial_num", "bds_count", "listen_start", "listen_end", "answer_stamp", "correct"]

def create_bds_stamps(participant):
    bds_files = get_sorted_bds_files(participant)

    with open(participant / "BDS_STAMPS.csv", "w") as of:
        csvw =  csv.DictWriter(of, fieldnames=BDS_HEADER)
        csvw.writeheader()
        phase = 0
        for bdsf in bds_files:
            phase += 1
            data = extract_bds_stamps(bdsf)
            for row in data:
                row[BDS_HEADER[0]] = phase
                csvw.writerow(row)

def extract_bds_stamps(filepath):
    startstamp = filepath.name.split("_")[2][:10]
    startstamp = datetime.fromtimestamp(float(startstamp))
    rows = []
    with open(filepath, "r") as infile:
        csvr = csv.DictReader(infile)
        outrow = None
        for row in csvr:
            if row["key_press"] == "13":
                # answer transmitted, save this row and prepare next start
                outrow["answer_stamp"] = get_timestamp(startstamp, row)
                outrow["bds_count"] = len(row["correct"].split(","))
                outrow["correct"] = row["was_correct"]
                rows.append(outrow)
                outrow = None
            elif type(outrow) is dict:
                stamp = get_timestamp(startstamp, row)
                if "listen_start" not in outrow:
                    outrow["listen_start"] = stamp
                else:
                    outrow["listen_end"] = stamp
            elif row["stimulus"].startswith("<p>Test"):
                # next rows will be numbers and timestamps, prepare dict
                outrow = { "trial_num" : len(rows) + 1 }
    return rows

def get_timestamp(startstamp, row):
    secs = float(row["time_elapsed"]) / 1000
    offset = timedelta(seconds=secs)
    return (startstamp + offset).timestamp()

main()


from flask import Flask, render_template, request
import sqlite3

app = Flask(__name__)

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

# Helper function to get the total number of tracks in the database
def get_total_tracks():
    conn = sqlite3.connect('kTunes.sqlite')
    cursor = conn.cursor()
    cursor.execute('SELECT COUNT(*) FROM tracks')
    total_tracks = cursor.fetchone()[0]
    conn.close()
    return total_tracks

# Helper function to get a page of tracks from the database
def get_tracks(start, limit):
    conn = sqlite3.connect('kTunes.sqlite')
    cursor = conn.cursor()
    cursor.execute('SELECT artist, song, category, album, play_cnt, last_play_dt, date_added FROM tracks ORDER BY artist LIMIT ?, ?', (start, limit))
    tracks = cursor.fetchall()
    conn.close()
    return tracks

# Route for the tracks page
@app.route('/tracks')
def tracks():
    # Get the page number from the request args, default to 1 if not present
    page = request.args.get('page', 1, type=int)
    # Set the number of tracks per page
    per_page = 20
    # Calculate the starting index of the tracks for the current page
    start = (page - 1) * per_page
    # Get the total number of tracks in the database
    total_tracks = get_total_tracks()
    # Get the tracks for the current page
    tracks = get_tracks(start, per_page)
    # Calculate the total number of pages based on the number of tracks per page
    total_pages = (total_tracks + per_page - 1) // per_page
    # Render the template with the tracks and pagination information
    print("before render_template, tracks=",tracks)
    return render_template('scroll.html', tracks=tracks, total_pages=total_pages)

if __name__ == '__main__':
    app.run(debug=True)


import codecs
import json

def read_file(path_to_file, year='2014', legislature='Senado'):
    f_ = codecs.open(path_to_file, 'r', 'utf-8')
    dimensions_number = 0
    congresistas = dict()
    lista_de_votaciones = list()
    vectors = dict()
    for line in f_:
        votacion = json.loads(line.strip())
        if 'detailed' in votacion and votacion['ano'] == year and votacion['camaras'] == legislature:
            id_votacion = votacion['id']
            lista_de_votaciones.append(id_votacion)

            for congresista, detalles in votacion['detailed'].items():
                if not congresista in congresistas:
                    congresistas[congresista] = dict()
                    congresistas[congresista]['partido'] = detalles['party']
                    congresistas[congresista]['votos'] = dict()
                if detalles['vote']=="Aprobado":
                    congresistas[congresista]['votos'][id_votacion] =  100
                else:
                    congresistas[congresista]['votos'][id_votacion] =  -100

    all_votaciones = set(lista_de_votaciones)

    for name_congresista, congresista in congresistas.items():
        vector =list()
        for votacion in all_votaciones:
            if votacion in congresista['votos']:
                vector.append(congresista['votos'][votacion])
            else:
                vector.append(0)
        dimensions_number = len(vector)
        vectors[name_congresista + " " + congresista['partido']] = { 'vector': vector,
                                                                     'partido':congresista['partido']
                                                                   }

    output_file_name = 'vectors_%s_%s_%s.json' %(legislature, year, dimensions_number)
    out = codecs.open(output_file_name, 'w', 'utf-8')
    out.write(json.dumps(vectors, ensure_ascii=False))
    out.close()

read_file('../../dumps/5-11-2014.json')


import random
import pygame
pygame.init()
loop=1

window = pygame.display.set_mode((1600,900))
background = pygame.Surface(window.get_size())
background.fill((255,255,255))
background = background.convert()

background = pygame.image.load("menu_background.png")

window.blit(background,(0,0))

pygame.display.flip()

while loop == 1:
    for event in pygame.event.get():
        if event.type==pygame.KEYDOWN:
            if event.key==pygame.K_ESCAPE:
                pygame.quit()
                quit()


import re

from bs4 import BeautifulSoup
from requests import get

from pyrogram import filters
from pyrogram.errors import MessageIdInvalid, MessageNotModified
from pyrogram.types import CallbackQuery, InlineQuery, InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardButton, InlineKeyboardMarkup

from userge import Message, userge, config as Config
from ...builtin import sudo

COMPILE = re.compile(r"(.*)[*]*\-arm")

@userge.on_cmd(
    "gapps", about={
        'header': "get latest google apps"
    }
)
async def latest_gapps(message: Message):
    """ get gapps """
    reply_markup = InlineKeyboardMarkup(
        [
            [
                InlineKeyboardButton(
                    text="11", callback_data="gapps_v|11.0"),
                InlineKeyboardButton(
                    text="12", callback_data="gapps_v|12.0"),
                InlineKeyboardButton(
                    text="12L", callback_data="gapps_v|12.1"),
            ]
        ]
    )
    if message.client.is_bot:
        await userge.bot.send_message(message.chat.id, "**Select gapps version**", reply_markup=reply_markup)
    else:
        await message.delete()
        username = (await userge.bot.get_me()).username
        x = await userge.get_inline_bot_results(username, "gapps")
        await userge.send_inline_bot_result(chat_id=message.chat.id, query_id=x.query_id, result_id=x.results[0].id)

if userge.has_bot:
    def check_owner(func):
        async def wrapper(_, c_q: CallbackQuery):
            if c_q.from_user and c_q.from_user.id in (list(Config.OWNER_ID) + list(sudo.USERS)):
                try:
                    await func(c_q)
                except MessageNotModified:
                    await c_q.answer("Nothing Found to Refresh 🤷♂", show_alert=True)
                except MessageIdInvalid:
                    await c_q.answer("Sorry, I Don't Have Permissions to edit this 😔",
                                     show_alert=True)
            else:
                user_dict = await userge.bot.get_user_dict(Config.OWNER_ID[0])
                await c_q.answer(
                    f"Only {user_dict['flname']} Can Access this...! Build Your Own @fnixsup 🤘",
                    show_alert=True)
        return wrapper

    @userge.bot.on_inline_query(
        filters.create(
            lambda _, __, inline_query: (
                inline_query.query
                and inline_query.query.startswith("gapps")
                and inline_query.from_user
                and inline_query.from_user.id in Config.OWNER_ID
            ),
            name="InlineGapps"
        ),
        group=-2
    )
    async def inline_gap(_, inline_query: InlineQuery):
        results = [
            InlineQueryResultArticle(
                title="Gapps",
                input_message_content=InputTextMessageContent(
                    "**Select gapps version**"
                ),
                url="https://github.com/fnixdev/Hilzu",
                description="Get latest gapps",
                thumb_url="https://telegra.ph/file/aa2776cc8f104120d2e4a.jpg",
                reply_markup=InlineKeyboardMarkup(
                    [
                        [
                            InlineKeyboardButton(
                                text="11", callback_data="gapps_v|11.0"),
                            InlineKeyboardButton(
                                text="12", callback_data="gapps_v|12.0"),
                            InlineKeyboardButton(
                                text="12L", callback_data="gapps_v|12.1"),
                        ]
                    ]
                )
            )
        ]
        await inline_query.answer(results=results, cache_time=3)

    # ==  Sector select gapps version

    @userge.bot.on_callback_query(filters=filters.regex(pattern=r"gapps_v\|(.*)"))
    @check_owner
    async def gapps_filter_cq(cq: CallbackQuery):
        cb = cq.data.split("|")
        version = cb[1]
        buttons = InlineKeyboardMarkup([
            [
                InlineKeyboardButton(
                    text="Flame Gapps", callback_data=f"gapps_flame|{version}"),
                InlineKeyboardButton(
                    text="Nik Gapps", callback_data=f"gapps_nik|{version}"),
            ],
            [
                InlineKeyboardButton(
                    text="Back", callback_data="gapps_main"),
            ]
        ])
        await cq.edit_message_text(text=f"**Select your preferred gapps for {version}**", reply_markup=buttons)

    # ==  Sector select gapps variant

    @userge.bot.on_callback_query(filters=filters.regex(pattern=r"gapps_(flame|nik)\|(.*)"))
    @check_owner
    async def gapps_filter_cq(cq: CallbackQuery):
        cb = cq.data.split("|")
        version = cb[1]
        if cb[0] == "gapps_flame":
            if version == "11.0":
                link = "https://sourceforge.net/projects/flamegapps/files/arm64/android-11/"
            elif version == "12.0":
                link = "https://sourceforge.net/projects/flamegapps/files/arm64/android-12/"
            elif version == "12.1":
                link = "https://sourceforge.net/projects/flamegapps/files/arm64/android-12.1/"

        elif cb[0] == "gapps_nik":
            if version == "11.0":
                link = "https://sourceforge.net/projects/nikgapps/files/Releases/NikGapps-R/"
            if version == "12.0":
                link = "https://sourceforge.net/projects/nikgapps/files/Releases/NikGapps-S/"
            if version == "12.1":
                link = "https://sourceforge.net/projects/nikgapps/files/Releases/NikGapps-SL/"
        url = get(link)
        page = BeautifulSoup(url.content, "lxml")
        content = page.tbody.tr
        date = content["title"]
        url2 = get(f"{link}{date}")
        page2 = BeautifulSoup(url2.content, "lxml")
        name = page2.tbody.find_all("th", {'headers': 'files_name_h'})
        btn_sub = []
        buttons = []
        for item in name:
            nam = item.find("a")
            string = nam.span.text
            match = re.search(COMPILE, string)
            btn_sub.append(InlineKeyboardButton(
                text=match.group(1), url=nam['href'])
            )
            if len(btn_sub) == 2:
                buttons.append(btn_sub)
                btn_sub = []
        buttons.append([InlineKeyboardButton(text="Back", callback_data=f"gapps_v|{version}")])
        await cq.edit_message_text(text=f"**Select your preferred gapps version**", reply_markup=InlineKeyboardMarkup(buttons))

    # ==  Main menu

    @userge.bot.on_callback_query(filters=filters.regex(pattern=r"gapps_main"))
    @check_owner
    async def gapps_filter_cq(cq: CallbackQuery):
        reply_markup = InlineKeyboardMarkup(
            [
                [
                    InlineKeyboardButton(
                        text="11", callback_data="gapps_v|11.0"),
                    InlineKeyboardButton(
                        text="12", callback_data="gapps_v|12.0"),
                    InlineKeyboardButton(
                        text="12L", callback_data="gapps_v|12.1"),
                ]
            ]
        )
        await cq.edit_message_text(text="**Select gapps version**", reply_markup=reply_markup)


#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import collections
import random

import torch
import numpy as np
import scipy.misc as misc
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms

class vggfaceInfo:
    def __init__(self, id_name, uid, image_url, left_boundingbox, top_boundingbox, right_boundingbox, bottom_boundingbox, score, curation):
        self.id_name = id_name
        self.uid = uid
        self.image_url = image_url
        self.left_boundingbox = left_boundingbox
        self.top_boundingbox = top_boundingbox
        self.right_boundingbox = right_boundingbox
        self.bottom_boundingbox = bottom_boundingbox
        self.score = score
        self.curation = curation
        pass

class vggfaceLoader(Dataset):
    def __init__(self, root, split="train"):
        file_list = os.listdir(root)
        self.m_vggfaceInfos = []
        for filename in file_list:
            file = open(os.path.join(root, filename))
            for line in file.readlines():
                line_split = line.split(' ')
                uid = line_split[0]
                image_url = line_split[1]
                left_boundingbox = line_split[2]
                top_boundingbox = line_split[3]
                right_boundingbox = line_split[4]
                bottom_boundingbox = line_split[5]
                score = line_split[6]
                curation = line_split[7]
                # print('uid:', uid)
                # print('image_url:', image_url)
                # print('left_boundingbox:', left_boundingbox)
                # print('top_boundingbox:', top_boundingbox)
                # print('right_boundingbox:', right_boundingbox)
                # print('bottom_boundingbox:', bottom_boundingbox)
                # print('score:', score)
                # print('curation:', curation)
                id_name = filename[:filename.rfind('.')]
                l_vggfaceInfo = vggfaceInfo(id_name=id_name, uid=uid, image_url=image_url, left_boundingbox=left_boundingbox, top_boundingbox=top_boundingbox, right_boundingbox=right_boundingbox, bottom_boundingbox=bottom_boundingbox, score=score, curation=curation)
                self.m_vggfaceInfos.append(l_vggfaceInfo)

    def __getitem__(self, index):
        l_vggfaceInfo = self.m_vggfaceInfos[index]
        return l_vggfaceInfo.id_name, l_vggfaceInfo.uid, l_vggfaceInfo.image_url, l_vggfaceInfo.left_boundingbox, l_vggfaceInfo.top_boundingbox, l_vggfaceInfo.right_boundingbox, l_vggfaceInfo.bottom_boundingbox, l_vggfaceInfo.score, l_vggfaceInfo.curation

    def __len__(self):
        return len(self.m_vggfaceInfos)

if __name__ == '__main__':
    local_path = os.path.expanduser('~/Data/face/vgg_face_dataset/files')
    local_image_path = os.path.expanduser('~/Data/face/vgg_face_dataset/images')
    batch_size = 1
    dst = vggfaceLoader(local_path)
    trainloader = DataLoader(dst, batch_size=batch_size)
    for i, (id_names, uids, image_urls, left_boundingboxs, top_boundingboxs, right_boundingboxs, bottom_boundingboxs, scores, curations) in enumerate(trainloader):
        print(i)
        if i == 100000:
            exit()
        # print(uids)
        id_names_0 = id_names[0]
        uids_0 = uids[0]
        image_urls_0 = image_urls[0]
        left_boundingboxs_0 = left_boundingboxs[0]
        top_boundingboxs_0 = top_boundingboxs[0]
        right_boundingboxs_0 = right_boundingboxs[0]
        bottom_boundingboxs_0 = bottom_boundingboxs[0]
        # print(image_urls_0)
        unique_image_urls_path_0 = os.path.join(local_image_path, id_names_0, uids_0+'.jpg')

        # x_0 = float(left_boundingboxs_0)
        # y_0 = float(top_boundingboxs_0)
        # width_0 = abs(float(left_boundingboxs_0)-float(right_boundingboxs_0))
        # height_0 = abs(float(top_boundingboxs_0)-float(bottom_boundingboxs_0))
        # if os.path.exists(unique_image_urls_path_0):
        #     imgs_0 = misc.imread(unique_image_urls_path_0)
        #     ax = plt.subplot(111)
        #     ax.imshow(imgs_0)
        #     ax.add_patch(patches.Rectangle((x_0, y_0), width_0, height_0, fill=False))
        #     plt.show()
        print(unique_image_urls_path_0)
        image_path = os.path.join(local_image_path, id_names_0)
        print(image_path)
        if not os.path.exists(image_path):
            os.mkdir(image_path)
        # if not os.path.exists(unique_image_urls_path_0):
        os.system("proxychains4 wget -c {} -O {} -t 1".format(image_urls_0, unique_image_urls_path_0))
        # exit()


from torchvision import transforms
import matplotlib.pyplot as plt

"""CODE BLOCK: 3"""
def data_transforms():

    # Train data transformations
    train_transforms = transforms.Compose([
        transforms.RandomApply([transforms.CenterCrop(22), ], p=0.1),
        transforms.Resize((28, 28)),
        transforms.RandomRotation((-15., 15.), fill=0),
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,)),
        ])

    # Test data transformations
    test_transforms = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1407,), (0.4081,))
        ])

    return train_transforms, test_transforms

"""CODE BLOCK: 6"""
def plot_data(batch_data, batch_label, num_plots, row, col):

# batch_data, batch_label = next(iter(train_loader))

    fig = plt.figure()

    for i in range(num_plots):
        plt.subplot(row,col,i+1)
        plt.tight_layout()
        plt.imshow(batch_data[i].squeeze(0), cmap='gray')
        plt.title(batch_label[i].item())
        plt.xticks([])
        plt.yticks([])

"""CODE BLOCK: 11"""
def plot_loss_accuracy(train_losses, test_losses, train_acc, test_acc):
    fig, axs = plt.subplots(2,2,figsize=(15,10))
    axs[0, 0].plot(train_losses)
    axs[0, 0].set_title("Training Loss")
    axs[1, 0].plot(train_acc)
    axs[1, 0].set_title("Training Accuracy")
    axs[0, 1].plot(test_losses)
    axs[0, 1].set_title("Test Loss")
    axs[1, 1].plot(test_acc)
    axs[1, 1].set_title("Test Accuracy")


"""
Functions in here provide "prefixes" for the tests (see pytest prefixes)
"""
import pytest
import numpy as np
import xarray as xr

import eurec4a_environment.source_data
from eurec4a_environment.constants import cp_d, g
from eurec4a_environment import nomenclature as nom

@pytest.fixture
def ds_joanne():
    return eurec4a_environment.source_data.open_joanne_dataset()

@pytest.fixture
def ds_isentropic_test_profiles():
    z = np.arange(0.0, 3000.0, 10.0)
    da_timesteps = xr.DataArray(np.arange(0, 3), dims=("timestep"))
    da_altitude = xr.DataArray(
        z,
        dims=(nom.ALTITUDE),
        attrs=dict(standard_name=nom.CF_STANDARD_NAMES[nom.ALTITUDE], units="m"),
    )
    ds = xr.Dataset(coords={nom.ALTITUDE: da_altitude, "timestep": da_timesteps})

    # isentropic atmosphere with surface temperature at 300K
    # (multiplying by ds.timesteps is just a quick hack to get ds.T have shape
    # of (alt, timestep)
    ds[nom.TEMPERATURE] = 300.0 - g / cp_d * ds[nom.ALTITUDE] + 0.2 * ds.timestep
    ds[nom.TEMPERATURE].attrs["units"] = "K"
    ds[nom.TEMPERATURE].attrs["long_name"] = "absolute temperature"
    ds[nom.TEMPERATURE].attrs["standard_name"] = nom.CF_STANDARD_NAMES[nom.TEMPERATURE]

    ds[nom.RELATIVE_HUMIDITY] = 0.95 * xr.ones_like(ds[nom.TEMPERATURE])
    ds[nom.RELATIVE_HUMIDITY].attrs["units"] = ""
    ds[nom.RELATIVE_HUMIDITY].attrs["long_name"] = "relative humidity"
    ds[nom.RELATIVE_HUMIDITY].attrs["standard_name"] = nom.CF_STANDARD_NAMES[
        nom.RELATIVE_HUMIDITY
    ]

    return ds


import pdb

from modeling.detectors.deconv_rcnn import DeformConvRCNN
from modeling.detectors.predictor import Predictor
from engine.inference import inference
from data.build import make_data_loader
from solver.build import make_optimizer_DeConv as make_optimizer
from PIL import Image
from torchvision.transforms import functional as F

import datetime
def get_time():
    return (str(datetime.datetime.now())[:-10]).replace(' ','-').replace(':','-')
from utils.logger import setup_logger
from utils.collect_env import collect_env_info
import time
import os
from tensorboardX import SummaryWriter
import torch
import torch.distributed as dist
from utils.comm import get_world_size
from utils.metric_logger import MetricLogger
from utils.miscellaneous import mkdir
from tqdm import tqdm
from pathlib import Path
import cv2

class Learner(object):
    def __init__(self, cfg):
        self.cfg = cfg.clone()
        num_gpus = int(os.environ["WORLD_SIZE"]) if "WORLD_SIZE" in os.environ else 1
        self.logger = setup_logger("deformconv RCNN", 'workspace/logger', 0)
        self.logger.info("Using {} GPUs".format(num_gpus))
        self.logger.info("Collecting env info (might take some time)")
        self.logger.info("\n" + collect_env_info())
        self.logger.info("Running with config:\n{}".format(cfg))
        self.device = torch.device(cfg.MODEL.DEVICE)
        self.model = DeformConvRCNN(cfg).to(self.device)
        [*self.model.backbone.modules()][1].stem.load_state_dict(torch.load(cfg.MODEL.BACKBONE.PRETRAINED_STEM_WEIGHTS))
        [*self.model.backbone.modules()][1].layer1.load_state_dict(torch.load(cfg.MODEL.BACKBONE.PRETRAINED_LAYER1_WEIGHTS))
        self.train_loader = make_data_loader(cfg, is_train=True)
        self.val_loader = make_data_loader(cfg, is_train=False)[0]
        remove_empty_target(self.val_loader.dataset)
        self.optimizer = make_optimizer(cfg, self.model)
        self.writer = SummaryWriter(cfg.WRITER_DIR)
        self.predictor = Predictor(cfg, self.model,
                                   confidence_threshold=cfg.SOLVER.CONF_THRES,
                                   min_image_size=cfg.TEST.MIN_IMG_SIZE)
        self.predictor.model.roi_heads.box.post_processor.detections_per_img = 20
        self.step = 0
        self.milestones = cfg.SOLVER.STEPS
        self.workspace = Path(cfg.WORKSPACE)
        self.board_loss_every = len(self.train_loader.dataset) // cfg.SOLVER.IMS_PER_BATCH // cfg.SOLVER.BOARD_LOSS_INTERVAL
        self.evaluate_every = len(self.train_loader.dataset) // cfg.SOLVER.IMS_PER_BATCH // cfg.SOLVER.EVALUATE_INTERVAL
        self.save_every = len(self.train_loader.dataset) // cfg.SOLVER.IMS_PER_BATCH // cfg.SOLVER.SAVE_INTERVAL
        self.board_pred_image_every = len(self.train_loader.dataset) // cfg.SOLVER.IMS_PER_BATCH // cfg.SOLVER.BOARD_IMAGE_INTERVAL
        self.inference_every = len(self.train_loader.dataset) // cfg.SOLVER.IMS_PER_BATCH // cfg.SOLVER.INFERENCE_INTERVAL

        # test only
#         self.board_loss_every = 10
#         self.evaluate_every = 10
#         self.save_every = 10
#         self.board_pred_image_every = 10
#         self.inference_every = 10
        # test only

    def schedule_lr(self):
        if self.step in self.milestones:
            print('lr scheduled when meeting {} steps'.format(self.step))
            for params in self.optimizer.param_groups:
                params['lr'] /= 10
            print(self.optimizer)

    def evaluate(self, num=None):
        self.val_loader = make_data_loader(self.cfg, is_train=False)[0]
        remove_empty_target(self.val_loader.dataset)
        running_loss = 0.
        running_loss_classifier = 0.
        running_loss_box_reg = 0.
        running_loss_mask = 0.
        running_loss_objectness = 0.
        running_loss_rpn_box_reg = 0.
        running_loss_mimicking_cls = 0.
        running_loss_mimicking_cos_sim = 0.
        if num == None:
            total_num = len(self.val_loader)
        else:
            assert num <= len(self.val_loader), 'validation batches should be less than total'
            total_num = num
        with torch.no_grad():
            counts = 0
            for images, targets, _ in tqdm(iter(self.val_loader), total=total_num):
                images = images.to(self.device)
                targets = [target.to(self.device) for target in targets]
                loss_dict = self.model(images, targets)
                loss_dict = self.weight_loss(loss_dict)
                losses = sum(loss for loss in loss_dict.values())
                running_loss += losses.item()
                running_loss_classifier += loss_dict['loss_classifier']
                running_loss_box_reg += loss_dict['loss_box_reg']
                running_loss_mask += loss_dict['loss_mask']
                running_loss_objectness += loss_dict['loss_objectness']
                running_loss_rpn_box_reg += loss_dict['loss_rpn_box_reg']
                running_loss_mimicking_cls += loss_dict['loss_mimicking_cls']
                running_loss_mimicking_cos_sim += loss_dict['loss_mimicking_cos_sim']
                counts += 1
                if counts > total_num:
                    break
        return running_loss / total_num, \
            running_loss_classifier / total_num, \
            running_loss_box_reg / total_num, \
            running_loss_mask / total_num, \
            running_loss_objectness / total_num,\
            running_loss_rpn_box_reg / total_num, \
            running_loss_mimicking_cls / total_num, \
            running_loss_mimicking_cos_sim / total_num

    def save_state(self, val_loss, box_mmap, seg_mmap, to_save_folder=False, model_only=False):
        if to_save_folder:
            save_path = self.workspace/'save'
        else:
            save_path = self.workspace/'model'
        time = get_time()
        torch.save(
            self.model.state_dict(), save_path /
            ('model_{}_val_loss:{}_boxmmap:{}_segmmap:{}_step:{}.pth'.format(time,
                                                                val_loss,
                                                                box_mmap,
                                                                seg_mmap,
                                                                self.step)))
        if not model_only:
            torch.save(
                self.optimizer.state_dict(), save_path /
                ('optimizer_{}_val_loss:{}_boxmmap:{}_segmmap:{}_step:{}.pth'.format(time,
                                                                val_loss,
                                                                box_mmap,
                                                                seg_mmap,
                                                                self.step)))

    def load_state(self, fixed_str, from_save_folder=False, model_only=False):
        if from_save_folder:
            save_path = self.workspace/'save'
        else:
            save_path = self.workspace/'model'
        self.model.load_state_dict(torch.load(save_path/'model_{}'.format(fixed_str)))
        print('load model_{}'.format(fixed_str))
        if not model_only:
            self.optimizer.load_state_dict(torch.load(save_path/'optimizer_{}'.format(fixed_str)))
            print('load optimizer_{}'.format(fixed_str))

    def resume_training_load(self, from_save_folder=False):
        if from_save_folder:
            save_path = self.workspace/'save'
        else:
            save_path = self.workspace/'model'
        sorted_files = sorted([*save_path.iterdir()],  key=lambda x: os.path.getmtime(x), reverse=True)
        seeking_flag = True
        index = 0
        while seeking_flag:
            if index > len(sorted_files) - 2:
                break
            file_a = sorted_files[index]
            file_b = sorted_files[index + 1]
            if file_a.name.startswith('model'):
                fix_str = file_a.name[6:]
                self.step = int(fix_str.split(':')[-1].split('.')[0]) + 1
                if file_b.name == ''.join(['optimizer', '_', fix_str]):
                    self.model.load_state(fix_str, from_save_folder)
                    return
                else:
                    index += 1
                    continue
            elif file_a.name.startswith('optimizer'):
                fix_str = file_a.name[10:]
                self.step = int(fix_str.split(':')[-1].split('.')[0]) + 1
                if file_b.name == ''.join(['model', '_', fix_str]):
                    self.load_state(fix_str, from_save_folder)
                    return
                else:
                    index += 1
                    continue
            else:
                index += 1
                continue
        print('no available files founded')
        return

    def board_scalars(self,
                      key,
                      loss_total,
                      loss_classifier,
                      loss_box_reg,
                      loss_mask,
                      loss_objectness,
                      loss_rpn_box_reg,
                      loss_mimicking_cls,
                      loss_mimicking_cos_sim):
        self.writer.add_scalar('{}_loss_total'.format(key), loss_total, self.step)
        self.writer.add_scalar('{}_loss_classifier'.format(key), loss_classifier, self.step)
        self.writer.add_scalar('{}_loss_box_reg'.format(key), loss_box_reg, self.step)
        self.writer.add_scalar('{}_loss_mask'.format(key), loss_mask, self.step)
        self.writer.add_scalar('{}_loss_objectness'.format(key), loss_objectness, self.step)
        self.writer.add_scalar('{}_loss_rpn_box_reg'.format(key), loss_rpn_box_reg, self.step)
        self.writer.add_scalar('{}_loss_mimicking_cls'.format(key), loss_mimicking_cls, self.step)
        self.writer.add_scalar('{}_loss_mimicking_cos_sim'.format(key), loss_mimicking_cos_sim, self.step)

    def weight_loss(self, loss_dict):
        loss_dict['loss_classifier'] *= self.cfg.SOLVER.BOXCLS_WEIGHT
        loss_dict['loss_box_reg'] *= self.cfg.SOLVER.BOXREG_WEIGHT
        loss_dict['loss_mask'] *= self.cfg.SOLVER.MASK_WEIGHT
        loss_dict['loss_objectness'] *= self.cfg.SOLVER.RPNOBJ_WEIGHT
        loss_dict['loss_rpn_box_reg'] *= self.cfg.SOLVER.RPNREG_WEIGHT
        loss_dict['loss_mimicking_cls'] *= self.cfg.SOLVER.MIKCLS_WEIGHT
        loss_dict['loss_mimicking_cos_sim'] *= self.cfg.SOLVER.MIKCOS_WEIGHT
        return loss_dict

    def train(self, resume = False, from_save_folder = False):
        if resume:
            self.resume_training_load(from_save_folder)
        self.logger.info("Start training")
        meters = MetricLogger(delimiter="  ")
        max_iter = len(self.train_loader)

        self.model.train()

        end = time.time()

        running_loss = 0.
        running_loss_classifier = 0.
        running_loss_box_reg = 0.
        running_loss_mask = 0.
        running_loss_objectness = 0.
        running_loss_rpn_box_reg = 0.
        running_loss_mimicking_cls = 0.
        running_loss_mimicking_cos_sim = 0.

        val_loss = None
        bbox_mmap = None
        segm_mmap = None

        start_step = self.step
        for _, (images, targets, _) in tqdm(enumerate(self.train_loader, start_step)):
            data_time = time.time() - end
            self.step += 1
            self.schedule_lr()

            self.optimizer.zero_grad()

            images = images.to(self.device)
            targets = [target.to(self.device) for target in targets]

            loss_dict = self.model(images, targets)
            loss_dict = self.weight_loss(loss_dict)

            losses = sum(loss for loss in loss_dict.values())

            losses.backward()
            self.optimizer.step()

            torch.cuda.empty_cache()

            meters.update(loss=losses, **loss_dict)
            running_loss += losses.item()
            running_loss_classifier += loss_dict['loss_classifier']
            running_loss_box_reg += loss_dict['loss_box_reg']
            running_loss_mask += loss_dict['loss_mask']
            running_loss_objectness += loss_dict['loss_objectness']
            running_loss_rpn_box_reg += loss_dict['loss_rpn_box_reg']
            running_loss_mimicking_cls += loss_dict['loss_mimicking_cls']
            running_loss_mimicking_cos_sim += loss_dict['loss_mimicking_cos_sim']

            if self.step != 0:
                if self.step % self.board_loss_every == 0:
                    self.board_scalars('train',
                                        running_loss / self.board_loss_every,
                                        running_loss_classifier / self.board_loss_every,
                                        running_loss_box_reg / self.board_loss_every,
                                        running_loss_mask / self.board_loss_every,
                                        running_loss_objectness / self.board_loss_every,
                                        running_loss_rpn_box_reg / self.board_loss_every,
                                        running_loss_mimicking_cls / self.board_loss_every,
                                        running_loss_mimicking_cos_sim / self.board_loss_every)
                    running_loss = 0.
                    running_loss_classifier = 0.
                    running_loss_box_reg = 0.
                    running_loss_mask = 0.
                    running_loss_objectness = 0.
                    running_loss_rpn_box_reg = 0.
                    running_loss_mimicking_cls = 0.
                    running_loss_mimicking_cos_sim = 0.

                if self.step % self.evaluate_every == 0:
                    self.model.train()
                    val_loss, val_loss_classifier, \
                    val_loss_box_reg, \
                    val_loss_mask, \
                    val_loss_objectness, \
                    val_loss_rpn_box_reg, \
                    val_loss_mimicking_cls, \
                    val_loss_mimicking_cos_sim= self.evaluate(num = self.cfg.SOLVER.EVAL_NUM)
                    self.board_scalars('val',
                                        val_loss,
                                        val_loss_classifier.item(),
                                        val_loss_box_reg.item(),
                                        val_loss_mask.item(),
                                        val_loss_objectness.item(),
                                        val_loss_rpn_box_reg.item(),
                                        val_loss_mimicking_cls.item(),
                                        val_loss_mimicking_cos_sim.item())

                if self.step % self.board_pred_image_every == 0:
                    self.model.eval()
                    for i in range(20):
                        img_path = Path(self.val_loader.dataset.root)/self.val_loader.dataset.get_img_info(i)['file_name']
                        cv_img = cv2.imread(str(img_path))
                        predicted_img = self.predictor.run_on_opencv_image(cv_img)
                        self.writer.add_image('pred_image_{}'.format(i), F.to_tensor(Image.fromarray(predicted_img)), global_step=self.step)
                    self.model.train()

                if self.step % self.inference_every == 0:
                    self.model.eval()
                    try:
                        with torch.no_grad():
                            cocoEval = inference(self.model, self.val_loader, 'coco2014', iou_types=['bbox', 'segm'])[0]
                            bbox_map05 = cocoEval.results['bbox']['AP50']
                            bbox_mmap = cocoEval.results['bbox']['AP']
                            segm_map05 = cocoEval.results['segm']['AP50']
                            segm_mmap = cocoEval.results['segm']['AP']
                    except:
                        print('eval on coco failed')
                        bbox_map05 = -1
                        bbox_mmap = -1
                        segm_map05 = -1
                        segm_mmap = -1
                    self.model.train()
                    self.writer.add_scalar('bbox_map05', bbox_map05, self.step)
                    self.writer.add_scalar('bbox_mmap', bbox_mmap, self.step)
                    self.writer.add_scalar('segm_map05', segm_map05, self.step)
                    self.writer.add_scalar('segm_mmap', segm_mmap, self.step)

                if self.step % self.save_every == 0:
                    try:
                        self.save_state(val_loss, bbox_mmap, segm_mmap)
                    except:
                        print('save state failed')
                        self.step += 1
                        continue
                    if self.step % (10 * self.save_every) == 0:
                        try:
                            self.save_state(val_loss, bbox_mmap, segm_mmap, to_save_folder=True)
                        except:
                            print('save state failed')
                            self.step += 1
                            continue

            batch_time = time.time() - end
            end = time.time()
            meters.update(time=batch_time, data=data_time)

            eta_seconds = meters.time.global_avg * (max_iter - self.step)
            eta_string = str(datetime.timedelta(seconds=int(eta_seconds)))

            if self.step % 20 == 0 or self.step == max_iter:
                self.logger.info(
                    meters.delimiter.join(
                        [
                            "eta: {eta}",
                            "iter: {iter}",
                            "{meters}",
                            "lr: {lr:.6f}",
                            "max mem: {memory:.0f}",
                        ]
                    ).format(
                        eta=eta_string,
                        iter=self.step,
                        meters=str(meters),
                        lr=self.optimizer.param_groups[0]["lr"],
                        memory=torch.cuda.max_memory_allocated() / 1024.0 / 1024.0,
                    )
                )
            if self.step >= max_iter:
                self.save_state(val_loss, bbox_mmap, segm_mmap, to_save_folder=True)
                return

def remove_empty_target(dataset):
    dataset.ids = [
        img_id
        for img_id in dataset.ids
            if len(dataset.coco.getAnnIds(imgIds=img_id, iscrowd=None)) > 0
        ]

    dataset.json_category_id_to_contiguous_id = {
        v: i + 1 for i, v in enumerate(dataset.coco.getCatIds())
    }
    dataset.contiguous_category_id_to_json_id = {
        v: k for k, v in dataset.json_category_id_to_contiguous_id.items()
    }
    dataset.id_to_img_map = {k: v for k, v in enumerate(dataset.ids)}


# 연산자 계산
# https://school.programmers.co.kr/learn/courses/30/lessons/67257

from collections import deque

def solution(expression):

    answer = 0

    operands = []
    operators = []

    def calc(prio):
        operandsQ = deque(operands)
        operatorsQ = deque(operators)

        for p in prio:
            tmpOperands = deque()
            tmpOperators = deque()
            for o in operatorsQ:
                if p == o:
                    o1 = operandsQ.popleft()
                    o2 = operandsQ.popleft()
                    if p == "*":
                        operandsQ.appendleft(o1*o2)
                    elif p == "+":
                        operandsQ.appendleft(o1+o2)
                    elif p == "-":
                        operandsQ.appendleft(o1-o2)
                else:
                    tmpOperands.append(operandsQ.popleft())
                    tmpOperators.append(o)
            tmpOperands.append(operandsQ.popleft())
            operandsQ = tmpOperands
            operatorsQ = tmpOperators
        return operandsQ.popleft()

    tmp = ""
    for e in expression:
        if e == "*":
            operators.append("*")
            operands.append(int(tmp))
            tmp = ""
        elif e == "+":
            operators.append("+")
            operands.append(int(tmp))
            tmp = ""
        elif e == "-":
            operators.append("-")
            operands.append(int(tmp))
            tmp = ""
        else:
            tmp += e
    operands.append(int(tmp))

    answer = 0
    priority = [('*', '+', '-'), ('*', '-', '+'), ('+', '*', '-'), ('+', '-', '*'), ('-', '*', '+'), ('-', '+', '*')]

    for prio in priority:
        res = abs(calc(prio))
        if res > answer:
            answer = res

    print(answer)
    return answer


"""
"""
import numpy as np
from scipy.stats import norm

__all__ = ('gaussian_kernel_selection', 'bt_pdf_fixed_sm', 'bt_pdf_fixed_sm_ssfr',
        'sfr_sequence_bulge_disk_fractions_vs_sm', 'bulge_disk_fractions_vs_sm')

def gaussian_kernel_selection(x, mu, sigma):
    """ Probability that a point ``x`` should be selected according to
    a Gaussian kernel with input mean ``mu`` and width ``sigma``.

    Parameters
    ----------
    x : float or ndarray
        Float or ndarray of shape (ngals, ) storing
        the attribute of the data determining the probability of selection

    mu : float
        Center of the selection function

    sigma : float
        Gaussian spread of the selection function

    Returns
    -------
    mask : float or ndarray
        Boolean array of shape (ngals, ) that can be used as a mask to select
        values of the input ``x`` passing the kernel selection

    Examples
    ---------
    >>> ngals = int(1e4)
    >>> stellar_mass = np.random.uniform(9.5, 11.75, ngals)
    >>> mu, sigma = 10.3, 0.1
    >>> selection_prob = gaussian_kernel_selection(stellar_mass, mu, sigma)
    >>> selection_mask = np.random.rand(ngals) < selection_prob
    """
    prob = 1 - 2*np.abs(0.5 - norm.cdf(x, loc=mu, scale=sigma))
    return np.random.rand(len(x)) < prob

def bt_pdf_fixed_sm(bt, sm, fixed_sm, bt_bins, sigma=0.1):
    """
    """
    sample_mask = gaussian_kernel_selection(sm, fixed_sm, sigma=sigma)
    assert np.count_nonzero(sample_mask) > 100, "Must have at least 100 galaxies in bin to estimate PDF"
    return np.histogram(bt[sample_mask], bt_bins, density=True)[0]

def bt_pdf_fixed_sm_ssfr(bt, sm, ssfr, fixed_sm, fixed_ssfr, bt_bins,
            sigma_sm=0.1, sigma_ssfr=0.25):
    """
    """
    sm_sample_mask = gaussian_kernel_selection(sm, fixed_sm, sigma=sigma_sm)
    ssfr_mask = gaussian_kernel_selection(ssfr[sm_sample_mask], fixed_ssfr, sigma=sigma_ssfr)
    assert np.count_nonzero(ssfr_mask) > 100, "Must have at least 100 galaxies in bin to estimate PDF"
    return np.histogram(bt[sm_sample_mask][ssfr_mask], bt_bins, density=True)[0]

def bulge_disk_fractions_vs_sm(bt, sm, sm_abscissa, domination_vals, sigma_sm):
    """
    """
    frac_disk_dom = np.zeros_like(sm_abscissa)
    frac_bulge_dom = np.zeros_like(sm_abscissa)

    for i, sm_mid in enumerate(sm_abscissa):
        sm_mask = gaussian_kernel_selection(sm, sm_mid, sigma_sm)
        nbin_total = np.count_nonzero(sm_mask)
        msg = "Bin #{0} with M*~{1:.2f} has {2} galaxies"
        assert nbin_total > 25, msg.format(i, sm_mid, nbin_total)
        nbin_disk_dom = np.count_nonzero(bt[sm_mask] < domination_vals[0])
        nbin_bulge_dom = np.count_nonzero(bt[sm_mask] > domination_vals[1])

        frac_disk_dom[i] = nbin_disk_dom/float(nbin_total)
        frac_bulge_dom[i] = nbin_bulge_dom/float(nbin_total)

    return frac_disk_dom, frac_bulge_dom

def sfr_sequence_bulge_disk_fractions_vs_sm(bt, sm, ssfr,
            sm_abscissa=np.arange(9.75, 11.35, 0.1), domination_vals=(0.25, 0.75),
            sigma_sm=0.1, gv_range=(-11.25, -10.75), return_data_vector=False):
    """
    """
    sfs_range = (gv_range[1], np.inf)
    q_range = (-np.inf, gv_range[0])

    sfs_mask = (ssfr >= sfs_range[0]) & (ssfr < sfs_range[1])
    gv_mask = (ssfr >= gv_range[0]) & (ssfr < gv_range[1])
    q_mask = (ssfr >= q_range[0]) & (ssfr < q_range[1])

    sfs_bt = bt[sfs_mask]
    gv_bt = bt[gv_mask]
    q_bt = bt[q_mask]
    sfs_sm = sm[sfs_mask]
    gv_sm = sm[gv_mask]
    q_sm = sm[q_mask]

    frac_disk_dom_all, frac_bulge_dom_all = bulge_disk_fractions_vs_sm(
            bt, sm, sm_abscissa, domination_vals, sigma_sm)

    frac_disk_dom_sfs, frac_bulge_dom_sfs = bulge_disk_fractions_vs_sm(
            sfs_bt, sfs_sm, sm_abscissa, domination_vals, sigma_sm)

    frac_disk_dom_gv, frac_bulge_dom_gv = bulge_disk_fractions_vs_sm(
            gv_bt, gv_sm, sm_abscissa, domination_vals, sigma_sm)

    frac_disk_dom_q, frac_bulge_dom_q = bulge_disk_fractions_vs_sm(
            q_bt, q_sm, sm_abscissa, domination_vals, sigma_sm)

    result = (sm_abscissa, frac_disk_dom_all, frac_bulge_dom_all,
            frac_disk_dom_sfs, frac_bulge_dom_sfs,
            frac_disk_dom_gv, frac_bulge_dom_gv,
            frac_disk_dom_q, frac_bulge_dom_q)

    if return_data_vector:
        num_sm_bins = len(sm_abscissa)
        num_distributions = 6
        assert num_distributions == len(result) - 3, "inconsistency in handling data vector bundling"
        num_bins_total = num_sm_bins*num_distributions
        data_vector = np.zeros(num_bins_total)
        for i in range(num_distributions):
            ifirst, ilast = i*num_sm_bins, (i+1)*num_sm_bins
            data_vector[ifirst:ilast] = result[i+3]
        return data_vector
    else:
        return result


import jackal_envs
import gym
from jackal_sim_wrapper import *

import numpy

import argparse
import os
import json

parser = argparse.ArgumentParser(description = 'Jackal navigation simulation')
parser.add_argument('--record', dest='record', action='store_true')
parser.add_argument('--gui', dest='gui', action='store_true')
parser.add_argument('--seed', dest='seed', type = int, default = 43)
parser.add_argument('--avg', dest='avg', type = int, default = 20)

args = parser.parse_args()
record = args.record
gui = 'true' if args.gui else 'false'
seed = args.seed
avg = args.avg

config = {
  "section": "ACKTR_random_start_goal",
  "world_name": "sequential_applr_testbed.world",
  "VLP16": "false",
  "gui": "false",
  "camera": "false",
  "wrapper": "reward_shaping",
  "wrapper_args": {
    "start_range": [[-1.5, -0.5], [-1.5, 1.5]],
    "goal_range": [[0.5, 1.5], [-1.5, 1.5]],
    "seed": 43,

    "reduction": 10,
    "polar_goal": "true",
    "centered_bin": "",
    "reward_shaping": "false",

    "goal_distance_reward": "true",
    "stuck_punishment": 0.5
  },
  "max_step": 300,
  "time_step": 1,
  "init_position": [-8, 0, 0],
  "goal_position": [54, 0, 0],
  "param_delta": [0.2, 0.3, 1, 2, 0.2, 0.2],
  "param_init": [1.5-0.2, 3.14-0.3, 6-1, 20-2, 0.75-0.2, 1-0.2],
  "param_list": ["max_vel_x", "max_vel_theta", "vx_samples", "vtheta_samples", "path_distance_bias", "goal_distance_bias"],
  "total_steps": 50000,
  "policy_network": "MlpPolicy",
  "algorithm": "ACKTR",
  "lr_schedule": "constant",
  "learning_rate": 0.1,
  "gamma": 0.95
}

if record:
    config['world_name'] = config['world_name'].split('.')[0] + '_camera' + '.world'

if config['wrapper']:
    config['wrapper_args']['seed'] = seed
    env = wrapper_dict[config['wrapper']](gym.make('jackal_navigation-v0',
                                        gui = gui,
                                        VLP16 = config['VLP16'],
                                        world_name = config['world_name'],
                                        init_position = config['init_position'],
                                        goal_position = config['goal_position'],
                                        max_step = config['max_step'],
                                        time_step = config['time_step'],
                                        param_delta = config['param_delta'],
                                        param_init = config['param_init'],
                                        param_list = config['param_list']
                                        ), config['wrapper_args'])
else:
    env = gym.make('jackal_navigation-v0',
                    gui = gui,
                    VLP16 = config['VLP16'],
                    world_name = config['world_name'],
                    init_position = config['init_position'],
                    goal_position = config['goal_position'],
                    max_step = config['max_step'],
                    time_step = config['time_step'],
                    param_delta = config['param_delta'],
                    param_init = config['param_init'],
                    param_list = config['param_list']
                    )

rs = []
cs = []
succeed = 0
for i in range(avg):
    print("Running: %d/%d" %(i+1, avg), end="\r")
    r = 0
    obs = env.reset()
    done = False
    count = 0
    while not done:
        count += 1
        obs, reward, done, info = env.step(63)
        for init, pn in zip(env.param_init, env.param_list):
            env.navi_stack.set_navi_param(pn, init)
        r += reward
        print(reward, count)
    if count != config['max_step'] and reward != -1000:
        succeed += 1
        rs.append(r)
        cs.append(count)
print("succeed: %d/%d \t episode reward: %.2f \t steps: %d" %(succeed, avg, sum(rs)/float((len(rs))), sum(cs)/float((len(cs)))))

env.close()

######## About recording ###########
# Add the camera model to the world you used to train
# Check onetwofive_meter_split_camera.world
# The frames will be save to folder /tmp/camera_save_tutorial
# run
# ffmpeg -r 30 -pattern_type glob -i '/tmp/camera_save_tutorial/default_camera_link_my_camera*.jpg' -c:v libx264 my_camera.mp4
# to generate the video


import matplotlib
import pretty_errors
import matplotlib.pyplot as plt
import matplotlib.tri as tri
from matplotlib.cm import ScalarMappable as sm
import numpy as np

# x_shift = 0

# X_train_range_low = -3. + x_shift
# X_train_range_high = 3. + x_shift
# X_test_range_low = -3. + x_shift
# X_test_range_high = 3. + x_shift

# X_train_range_low = -10. + x_shift
# X_train_range_high = 10. + x_shift
# X_test_range_low = -10. + x_shift
# X_test_range_high = 10.+ x_shift

def plot_1d(X_train, X_test, f_train, Y_train, f_test, Y_test, Y_test_pred, Y_test_var, A,
group_centers, group_test, group_test_pred, group_test_var,
model_name = 'gprg', num_group = None, grouping_method = 'random', X_train_range_low = -3., X_train_range_high = 3., shift = 0):

    num_train = X_train.shape[0]

    sorted_train_idx = np.argsort(X_train, axis = 0).reshape(X_train.shape[0],)
    sorted_test_idx = np.argsort(X_test, axis = 0).reshape(X_test.shape[0],)

    # print('test label: ', Y_test[sorted_test_idx])
    # print('test pred: ', Y_test_pred[sorted_test_idx])
    # print('test std: ', np.sqrt(Y_test_var[sorted_test_idx]))

    # if A is None:
    if A is None:
        plt.plot(X_train[sorted_train_idx,:], Y_train[sorted_train_idx,:], '.', color = 'tab:green', label = 'train')
    else:
        # plt.plot(X_train[sorted_train_idx,:], Y_train[sorted_train_idx,:], '.', color = 'tab:green', label = 'train')
        A_sorted = A[:,sorted_train_idx]
        for i in range(A.shape[0]):
            plt.plot(X_train[sorted_train_idx,:][A_sorted[i,:] == 1,:], Y_train[sorted_train_idx,:][A_sorted[i,:] == 1,:], '.')
    # if A_ast.shape[0] == Y_test.shape[0]:
    plt.plot(X_test[sorted_test_idx,:], f_test[sorted_test_idx,:], color = 'tab:orange', label = 'f_test')
    plt.plot(X_test[sorted_test_idx,:], Y_test_pred[sorted_test_idx,:], color = 'tab:blue', label = 'pred')
    plt.fill_between(X_test[sorted_test_idx,:].reshape(X_test.shape[0],),
                (Y_test_pred[sorted_test_idx,:] - 2 * np.sqrt(Y_test_var[sorted_test_idx,:])).reshape(X_test.shape[0],),
                (Y_test_pred[sorted_test_idx,:] + 2 * np.sqrt(Y_test_var[sorted_test_idx,:])).reshape(X_test.shape[0],), alpha = 0.3)
    # else:
    sorted_group_idx = np.argsort(group_centers, axis = 0).reshape(group_centers.shape[0],)
    plt.plot(group_centers[sorted_group_idx,:], group_test[sorted_group_idx,:], color = 'tab:orange', marker = 'o', label = 'group_test')
    plt.plot(group_centers[sorted_group_idx,:], group_test_pred[sorted_group_idx,:], color = 'tab:blue', marker = 'o', label = 'group pred')
    for c in group_centers:
        plt.axvline(x=c, linestyle = '--', color = 'black',alpha = 0.3)
        # plt.fill_between(X_test[sorted_test_idx,:].reshape(X_test.shape[0],),
        #             (Y_test_pred[sorted_test_idx,:] - 2 * np.sqrt(Y_test_var[sorted_test_idx,:])).reshape(X_test.shape[0],),
        #             (Y_test_pred[sorted_test_idx,:] + 2 * np.sqrt(Y_test_var[sorted_test_idx,:])).reshape(X_test.shape[0],), alpha = 0.3)
    plt.legend()
    if model_name == 'gprg':
        info = model_name + '_train_' + str(num_train) + '_group_' + str(num_group) + '_' + str(grouping_method)
    elif model_name == 'gpr':
        info = model_name + '_train_' + str(num_train)
    else:
        print('unknown model name!')
        info = 'None'
    # plt.ylim(-1.7, 1.2)
    plt.title(info)
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.savefig(info + '_1d' + '.png')

def plot_2d(X_train, X_test, f_train, Y_train, f_test, Y_test, Y_test_pred, Y_test_var, A,
group_centers, group_test, group_test_pred, group_test_var,
model_name = 'gprg', num_group = None, grouping_method = 'random',
X_train_range_low = -3., X_train_range_high = 3., shift = 0):
    # counter plot, only for mean
    # refer https://matplotlib.org/3.1.1/gallery/images_contours_and_fields/irregulardatagrid.html#sphx-glr-gallery-images-contours-and-fields-irregulardatagrid-py

    num_train = X_train.shape[0]

    fig, axes = plt.subplots(figsize = (30,10), nrows = 2, ncols=3)

    if model_name == 'gprg':
        info = model_name + '_train_' + str(num_train) + '_group_' + str(num_group) + '_' + str(grouping_method)
    elif model_name == 'gpr':
        info = model_name + '_train_' + str(num_train)
    else:
        print('unknown model name!')
        info = 'None'

    # sorted_train_idx = np.argsort(X_train, axis = 0).reshape(X_train.shape[0],)
    # sorted_test_idx = np.argsort(X_test, axis = 0).reshape(X_test.shape[0],)

    # npts = 200
    ngridx = 100
    ngridy = 100
    # x = np.random.uniform(-3.5, 3.5, npts)
    # y = np.random.uniform(-3.5, 3.5, npts)
    # z = np.sin(x) * np.sin(y)
    x = X_test[:,0]
    y = X_test[:,1]
    z_test = np.sin(x) * np.sin(y)
    z_test_pred = Y_test_pred.reshape(len(z_test),)
    z_test_pred_var = Y_test_var.reshape(len(z_test),)
    z_test_pred_ucb = z_test_pred + 2 * np.sqrt(z_test_pred_var)
    z_test_pred_lcb = z_test_pred - 2 * np.sqrt(z_test_pred_var)

    # Create grid values first.
    X_test_range_low = X_train_range_low
    X_test_range_high = X_train_range_high
    xi = np.linspace(X_test_range_low, X_test_range_high, ngridx)
    yi = np.linspace(X_test_range_low, X_test_range_high, ngridy)
    Xi, Yi = np.meshgrid(xi, yi)

    # Perform linear interpolation of the data (x,y)
    # on a grid defined by (xi,yi)
    triang = tri.Triangulation(x, y)

    # ------------------------------------------------------------
    # subplot 1: |z_test - z_test_pred|
    z_diff_mean = np.abs(z_test - z_test_pred)
    # print(z_test)
    # print(z_diff)
    interpolator1 = tri.LinearTriInterpolator(triang, z_diff_mean)
    zi1 = interpolator1(Xi, Yi)

    # Note that scipy.interpolate provides means to interpolate data on a grid
    # as well. The following would be an alternative to the four lines above:
    #from scipy.interpolate import griddata
    #zi = griddata((x, y), z, (xi[None,:], yi[:,None]), method='linear')

    # vmin = 0.
    # vmax = -0.5
    # levels = np.linspace(vmin, vmax, 14)
    levels = 14

    axes[0,0].contour(xi, yi, zi1, levels=levels, linewidths=0.5, colors='k')
    cntr1 = axes[0,0].contourf(xi, yi, zi1, levels=levels, cmap="RdBu_r")
    if A is None:
        axes[0,0].plot(X_train[:,0], X_train[:,1],'ko',ms = 3)
    else:
        for i in range(A.shape[0]):
            axes[0,0].plot(X_train[A[i,:] == 1,0], X_train[A[i,:] == 1,1], 'o', ms = 3)
    # if A is None:
    #     axes[0,0].plot(X_train[:,0], X_train[:,1],'ko',ms = 3)
    # else:
    #     for i in range(A.shape[0]):
    #         axes[0,0].plot(X_train[A[i,:] == 1,0], X_train[A[i,:] == 1,1],'.',ms = 3)
    axes[0,0].set_xlabel('X[:,0]')
    axes[0,0].set_ylabel('X[:,1]')
    axes[0,0].set_title(info + ' (pred mean - true mean)')
    plt.colorbar(cntr1, ax=axes[0,0])

    # ------------------------------------------------------------
    # subplot 2: pred ucb - true mean

    z_diff_ucb = np.abs(z_test_pred_ucb - z_test)
    # print(z_test)
    # print(z_diff)
    interpolator2 = tri.LinearTriInterpolator(triang, z_diff_ucb)
    zi2 = interpolator2(Xi, Yi)

    # vmin = -1.
    # vmax = 1.
    # levels = np.linspace(vmin, vmax, 14)

    axes[0,1].contour(xi, yi, zi2, levels=levels, linewidths=0.5, colors='k')
    cntr2 = axes[0,1].contourf(xi, yi, zi2, levels=levels, cmap="RdBu_r")
    if A is None:
        axes[0,1].plot(X_train[:,0], X_train[:,1],'ko',ms = 3)
    else:
        for i in range(A.shape[0]):
            axes[0,1].plot(X_train[A[i,:] == 1,0], X_train[A[i,:] == 1,1], 'o', ms = 3)
    axes[0,1].set_xlabel('X[:,0]')
    axes[0,1].set_ylabel('X[:,1]')
    axes[0,1].set_title(info + ' (pred ucb - true mean)')
    plt.colorbar(cntr2, ax=axes[0,1])

    # ------------------------------------------------------------
    # subplot 3: true mean - pred lcb

    z_diff_lcb = np.abs(z_test - z_test_pred_lcb)
    # print(z_test)
    # print(z_diff)
    interpolator3= tri.LinearTriInterpolator(triang, z_diff_lcb)
    zi3 = interpolator3(Xi, Yi)

    axes[0,2].contour(xi, yi, zi3, levels=levels, linewidths=0.5, colors='k')
    cntr3 = axes[0,2].contourf(xi, yi, zi3, levels=levels, cmap="RdBu_r")
    if A is None:
        axes[0,2].plot(X_train[:,0], X_train[:,1],'ko',ms = 3)
    else:
        for i in range(A.shape[0]):
            axes[0,2].plot(X_train[A[i,:] == 1,0], X_train[A[i,:] == 1,1], 'o', ms = 3)
    axes[0,2].set_xlabel('X[:,0]')
    axes[0,2].set_ylabel('X[:,1]')
    axes[0,2].set_title(info + ' (true mean - pred lcb)')
    plt.colorbar(cntr3, ax=axes[0,2])

    # --------------------------------------------------------------
    # subplot 4: true mean

    interpolator4= tri.LinearTriInterpolator(triang, z_test)
    zi4 = interpolator4(Xi, Yi)

    axes[1,0].contour(xi, yi, zi4, levels=levels, linewidths=0.5, colors='k')
    cntr4 = axes[1,0].contourf(xi, yi, zi4, levels=levels, cmap="RdBu_r")
    if A is None:
        axes[1,0].plot(X_train[:,0], X_train[:,1],'ko',ms = 3)
    else:
        for i in range(A.shape[0]):
            axes[1,0].plot(X_train[A[i,:] == 1,0], X_train[A[i,:] == 1,1], 'o', ms = 3)
    axes[1,0].set_xlabel('X[:,0]')
    axes[1,0].set_ylabel('X[:,1]')
    axes[1,0].set_title(info + ' true mean')
    plt.colorbar(cntr4, ax=axes[1,0])

    # --------------------------------------------------------------
    # subplot 5: pred mean

    interpolator5= tri.LinearTriInterpolator(triang, z_test_pred)
    zi5 = interpolator5(Xi, Yi)

    axes[1,1].contour(xi, yi, zi5, levels=levels, linewidths=0.5, colors='k')
    cntr5 = axes[1,1].contourf(xi, yi, zi5, levels=levels, cmap="RdBu_r")
    if A is None:
        axes[1,1].plot(X_train[:,0], X_train[:,1],'ko',ms = 3)
    else:
        for i in range(A.shape[0]):
            axes[1,1].plot(X_train[A[i,:] == 1,0], X_train[A[i,:] == 1,1], 'o', ms = 3)
    axes[1,1].set_xlabel('X[:,0]')
    axes[1,1].set_ylabel('X[:,1]')
    axes[1,1].set_title(info + ' pred mean')
    plt.colorbar(cntr5, ax=axes[1,1])

    # --------------------------------------------------------------
    # subplot 6: pred var

    interpolator6= tri.LinearTriInterpolator(triang, z_test_pred_var)
    zi6 = interpolator6(Xi, Yi)

    axes[1,2].contour(xi, yi, zi6, levels=levels, linewidths=0.5, colors='k')
    cntr6 = axes[1,2].contourf(xi, yi, zi6, levels=levels, cmap="RdBu_r")
    if A is None:
        axes[1,2].plot(X_train[:,0], X_train[:,1],'ko',ms = 3)
    else:
        for i in range(A.shape[0]):
            axes[1,2].plot(X_train[A[i,:] == 1,0], X_train[A[i,:] == 1,1], 'o', ms = 3)
    axes[1,2].set_xlabel('X[:,0]')
    axes[1,2].set_ylabel('X[:,1]')
    axes[1,2].set_title(info + ' pred var')
    plt.colorbar(cntr6, ax=axes[1,2])

    # plt.contour(X_train[:,0], X_train[:,1], Y_train,label = 'train')
    # plt.plot(X_test[sorted_test_idx,:], f_test[sorted_test_idx,:], label = 'test')
    # plt.plot(X_test[sorted_test_idx,:], Y_test_pred[sorted_test_idx,:], label = 'pred')
    # plt.fill_between(X_test[sorted_test_idx,:].reshape(X_test.shape[0],),
    #             (Y_test_pred[sorted_test_idx,:] - 2 * np.sqrt(Y_test_var[sorted_test_idx,:])).reshape(X_test.shape[0],),
    #             (Y_test_pred[sorted_test_idx,:] + 2 * np.sqrt(Y_test_var[sorted_test_idx,:])).reshape(X_test.shape[0],), alpha = 0.5)
    # plt.legend()

    # plt.xlabel('X')
    # plt.ylabel('Y')
    plt.savefig(info + '_2d' + '.png')
    # plt.show()


import math
import string
import random
from flask import Flask, jsonify, make_response, redirect, render_template, request, url_for, send_file
from pony import orm
from datetime import datetime
from decimal import Decimal

DB = orm.Database()

app = Flask(__name__)

class Item(DB.Entity):
    name = orm.Required(str, unique=True)
    category = orm.Required(str)
    price = orm.Required(Decimal)
    amount = orm.Required(int)

class Receipt(DB.Entity):
    time = orm.Required(str, unique=True)
    items = orm.Required(orm.StrArray)
    amounts = orm.Required(orm.IntArray)
    total_price = orm.Required(Decimal)

class ReceiptFile(DB.Entity):
    receiptNumber = orm.PrimaryKey(int, auto=True)
    receiptId = orm.Required(str)
    file = orm.Required(str)

class DailyTraffic(DB.Entity):
    date = orm.Required(str)
    total_traffic = orm.Required(Decimal)

class DetailedDailyTraffic(DB.Entity):
    date = orm.Required(str)
    items = orm.Required(orm.StrArray)
    amounts = orm.Required(orm.IntArray)
    prices = orm.Required(orm.FloatArray)

DB.bind(provider="sqlite", filename="database.sqlite", create_db=True)
DB.generate_mapping(create_tables=True)

def add_item(json_request):
    try:
        name = json_request["name"]
        category = json_request["category"]
        price = json_request["price"]
        amount = json_request["amount"]
        with orm.db_session:
            Item(name=name, category=category, price=price, amount=amount)
            db_querry = orm.select(x for x in Item)[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            response = {"response": "Success", "data": results_list}
            return response
    except Exception as e:
        return {"response": "Fail", "error": e}

def get_all_items():
    try:
        with orm.db_session:
            db_querry = orm.select(x for x in Item)[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            response = {"response": "Success", "data": results_list}
            return response
    except Exception as e:
        return {"response": "Fail", "error": e}

def update_item(json_request):
    try:
        name = json_request["name"]
        new_name = json_request["new name"]
        category = json_request["category"]
        price = json_request["price"]
        amount = json_request["amount"]
        with orm.db_session:
            item = Item.get(name=name)
            if (new_name):
                item.name = new_name
            if (price):
                item.price = price
            if (category):
                item.category = category
            if (amount):
                item.amount = amount
            db_querry = orm.select(x for x in Item)[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            response = {"response": "Success", "data": results_list}
            return response
    except Exception as e:
        return {"response": "Fail", "error": e}

def sell_items(json_request):
    try:
        with orm.db_session:
            items_in_cart = 0
            sold_items = []
            total_cost = 0
            amount_sold = []
            current_time = datetime.now()
            for item_name, sold_amount in json_request.items():
                if not sold_amount == "Choose amount":
                    item = Item.get(name=item_name)
                    item.amount -= int(sold_amount)
                    sold_items.append(item.name)
                    amount_sold.append(int(sold_amount))
                    total_cost += int(sold_amount) * item.price
                    items_in_cart += 1
            if (not items_in_cart):
                raise Exception("No items in cart")
            Receipt(time=str(current_time),
                    items=sold_items,
                    amounts=amount_sold,
                    total_price=total_cost)
            generate_receipt(str(current_time))
            item_prices = []
            for sold_item in sold_items:
                item_prices.append(float(Item.get(name=sold_item).price))
            existing_day = DetailedDailyTraffic.get(
                date=str(current_time.date()))
            if (not existing_day):
                DetailedDailyTraffic(date=str(current_time.date()),
                                     items=sold_items,
                                     amounts=amount_sold,
                                     prices=item_prices)
            else:
                items_already_sold = existing_day.items
                for sold_item in sold_items:
                    if sold_item in items_already_sold:
                        index_of_existing_item = items_already_sold.index(
                            sold_item)
                        existing_day.amounts[index_of_existing_item] += amount_sold[sold_items.index(
                            sold_item)]
                    else:
                        items_already_sold.append(sold_item)
                        existing_day.amounts.append(
                            amount_sold[sold_items.index(sold_item)])
                        existing_day.prices.append(
                            item_prices[sold_items.index(sold_item)])
            existing_traffic = DailyTraffic.get(date=str(current_time.date()))
            if (existing_traffic):
                existing_traffic.total_traffic += total_cost
            else:
                DailyTraffic(date=str(current_time.date()),
                             total_traffic=total_cost)
            db_querry = orm.select(x for x in Item)[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            response = {"response": "Success", "data": results_list}
            return response
    except Exception as e:
        print("erradadada " + str(e))
        return {"response": "Fail", "error": str(e)}

def generate_receipt(receipt_time):
    try:
        def round_up(n, decimals=0):
            multiplier = 10 ** decimals
            return Decimal(math.ceil(n * multiplier) / multiplier)

        zki = generate_zki()
        jir = generate_jir()

        this_receipt = Receipt.get(time=receipt_time)
        item_names = this_receipt.items
        item_amounts = this_receipt.amounts
        item_prices = []
        item_tax = []
        categories_for_B = ["newspaper", "agriculture"]
        categories_for_D = ["bread", "milk",
                            "children", "book", "magazine", "medicine"]
        with orm.db_session:
            for item in item_names:
                item_prices.append(Item.get(name=item).price)
                try:
                    item_category = Item.get(name=item).category
                    if item_category in categories_for_D:
                        item_tax.append("D")
                    elif item_category in categories_for_B:
                        item_tax.append("B")
                    else:
                        item_tax.append("A")
                except Exception as e:
                    print(e)
            # TODO: find out why this makes ids available
            db_querry = orm.select(
                x for x in Receipt if x.time == receipt_time)[:]
            print(db_querry)
        total = 0
        total_for_A = 0
        total_for_B = 0
        total_for_D = 0
        for amount, price, tax in zip(item_amounts, item_prices, item_tax):
            added_amount = amount * price
            total += added_amount
            if tax == "D":
                total_for_D += added_amount
            elif tax == "B":
                total_for_B += added_amount
            else:
                total_for_A += added_amount

        with open('receipt.txt', 'w', encoding="utf-8") as f:
            f.write('                  SPAR HRVATSKA d.o.o.')
            f.write('\n          Slavonska avenija 50, 10000 Zagreb')
            f.write('\n            MB: 1527100 OIB: 46108893754')
            f.write('\n               SPAR SUPERMARKET Labin')
            f.write('\n               Pulska 2C, 52220 Labin')
            f.write('\n')
            f.write('\n')
            f.write('\n*****************************************************')
            f.write('\n                      OTVORENO')
            f.write('\n                PON-SUB  7:00 - 21:00')
            f.write('\n                NEDJELJA 8:00 - 21:00')
            f.write('\n')
            f.write('\n           SPAR - supermarket za svaki dan')
            f.write('\n=====================================================')
            f.write('\nNaziv artikla')
            f.write('\nKoličina          Cijena              Iznos         P')
            f.write('\n-----------------------------------------------------')
            for item, amount, price, tax in zip(item_names,
                                                item_amounts,
                                                item_prices,
                                                item_tax):
                f.write('\n')
                f.write(item)
                f.write('\n')
                for _ in range(7 - len(str(amount))):
                    f.write(' ')
                f.write(str(amount))
                f.write(' x')
                for _ in range(14 - len(str(price))):
                    f.write(' ')
                f.write(str(price))
                f.write(' =')
                for _ in range(18 - len(str(amount*price))):
                    f.write(' ')
                f.write(str(amount*price))
                f.write('         ')
                f.write(tax)
            f.write('\n-----------------------------------------------------')
            f.write('\nUkupno kn')
            for _ in range(34 - len(str(total))):
                f.write(' ')
            f.write(str(total))
            f.write('\n=====================================================')
            f.write('\nPRIMLJENO   Gotovina')
            for _ in range(23 - len(str((round_up(total))) + ".00")):
                f.write(' ')
            f.write(str(round_up(total)) + ".00")
            f.write('\nVRAĆENO     kn')
            for _ in range(29 - len(str(round_up(total) - total))):
                f.write(' ')
            f.write(str(round_up(total) - total))
            f.write('\n')
            f.write('\nP  PDV(%)    Osnovica      Iznos')
            f.write('\n-----------------------------------------------------')
            if "A" in item_tax:
                f.write('\nA   25.00')
                for _ in range(12 - len(str(round(total_for_A * Decimal(0.75), 2)))):
                    f.write(' ')
                f.write(str(round(total_for_A * Decimal(0.75), 2)))
                for _ in range(11 - len(str(round(total_for_A * Decimal(0.25), 2)))):
                    f.write(' ')
                f.write(str(round(total_for_A * Decimal(0.25), 2)))
            if "B" in item_tax:
                f.write('\nB   13.00')
                for _ in range(12 - len(str(round(total_for_B * Decimal(0.87), 2)))):
                    f.write(' ')
                f.write(str(round(total_for_B * Decimal(0.87), 2)))
                for _ in range(11 - len(str(round(total_for_B * Decimal(0.13), 2)))):
                    f.write(' ')
                f.write(str(round(total_for_B * Decimal(0.13), 2)))
            if "D" in item_tax:
                f.write('\nD    5.00')
                for _ in range(12 - len(str(round(total_for_D * Decimal(0.95), 2)))):
                    f.write(' ')
                f.write(str(round(total_for_D * Decimal(0.95), 2)))
                for _ in range(11 - len(str(round(total_for_D * Decimal(0.05), 2)))):
                    f.write(' ')
                f.write(str(round(total_for_D * Decimal(0.05), 2)))
            f.write('\n-----------------------------------------------------')
            f.write('\nBroj računa:')
            f.write(' ')
            f.write(str(this_receipt.get_pk()))
            f.write("/870272/102")
            f.write('\nZKI:')
            f.write(zki)
            f.write('\n')
            f.write('\nJIR:')
            f.write(jir)
            f.write('\n')
            f.write('\n')
            f.write('\n')
            f.write('\nLabin                                ')
            f.write(datetime.strptime(this_receipt.time,
                    "%Y-%m-%d %H:%M:%S.%f").strftime("%d.%m.%Y %H:%M"))
            f.write('\nBlagajna 102 Trans 8388 Blagajnik 10231')
            f.write('\n')
            f.write('\n*****************************************************')
            f.write('\n                   NAJLJEPŠE HVALA')
            f.write('\n                    NA POVJERENJU')
            f.write('\n*********************www.spar.hr*********************')
            f.write('\n')
            f.write('\n')
        with open('receipt.txt', encoding="utf-8") as f:
            with orm.db_session:
                ReceiptFile(receiptId=receipt_time, file=f.read())
    except Exception as e:
        print(str(e))
        return {"response": "Fail", "error": str(e)}

def generate_zki():
    return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits) for _ in range(36))

def generate_jir():
    chars = string.ascii_lowercase + string.digits
    first_row = ''.join(random.SystemRandom().choice(chars) for _ in range(8))
    second_row = ''.join(random.SystemRandom().choice(chars) for _ in range(4))
    third_row = ''.join(random.SystemRandom().choice(chars) for _ in range(4))
    fourth_row = ''.join(random.SystemRandom().choice(chars) for _ in range(4))
    fifth_row = ''.join(random.SystemRandom().choice(chars) for _ in range(12))
    return first_row + "-" + second_row + "-" + third_row + "-" + fourth_row + "-" + fifth_row

def delete_item(item_to_delete):
    try:
        with orm.db_session:
            item = Item.get(name=item_to_delete)
            item.delete()
            db_querry = orm.select(x for x in Item)[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            response = {"response": "Success", "data": results_list}
            return response
    except Exception as e:
        return {"response": "Fail", "error": e}

def get_all_receipts():
    try:
        with orm.db_session:
            db_querry = orm.select(x for x in Receipt)[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            response = {"response": "Success", "data": results_list}
            return response
    except Exception as e:
        return {"response": "Fail", "error": e}

def get_all_daily_traffic():
    try:
        with orm.db_session:
            db_querry = orm.select(x for x in DailyTraffic)[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            response = {"response": "Success", "data": results_list}
            return response
    except Exception as e:
        return {"response": "Fail", "error": e}

def get_detailed_daily_traffic():
    try:
        with orm.db_session:
            db_querry = orm.select(
                x for x in DetailedDailyTraffic if x.date == str(datetime.now().date()))[:]
            results_list = []
            for r in db_querry:
                results_list.append(r.to_dict())
            if results_list:
                todays_traffic = results_list[0]
                items = todays_traffic["items"]
                amounts = todays_traffic["amounts"]
                amounts, items = (list(t)
                                  for t in zip(*sorted(zip(amounts, items))))
                todays_traffic["items"] = items
                todays_traffic["amounts"] = amounts
                response = {"response": "Success", "data": todays_traffic}
            else:
                response = {"response": "Success", "data": {}}
            return response
    except Exception as e:
        return {"response": "Fail", "error": str(e)}

@app.route('/')
def home():
    return render_template('home.html')

@app.route('/register', methods=["GET", "POST"])
def register():
    if request.method == "POST":
        try:
            json_request = {}
            for key, value in request.form.items():
                if value == "":
                    json_request[key] = None
                else:
                    json_request[key] = value
        except Exception as e:
            response = {"response": str(e)}
            return make_response(jsonify(response), 400)

        response = sell_items(json_request)
        response2 = get_all_receipts()

        if response["response"] == "Success" and response2["response"] == "Success":
            return make_response(render_template("register.html",
                                                 items=response["data"],
                                                 receipts=response2["data"][-5:],
                                                 zip=zip), 200)
        elif response["error"] == "No items in cart" and response2["response"] == "Success":
            response = get_all_items()
            return make_response(render_template("register.html",
                                                 items=response["data"],
                                                 receipts=response2["data"][-5:],
                                                 zip=zip,
                                                 sentEmptyOrder=True), 200)
        else:
            return make_response(render_template("register.html",
                                                 zip=zip,
                                                 sentEmptyOrder=True), 200)
    else:
        response = get_all_items()
        response2 = get_all_receipts()
        if response["response"] == "Success" and response2["response"] == "Success":
            return make_response(render_template("register.html", items=response["data"], receipts=response2["data"][-5:], zip=zip), 200)
        else:
            return make_response(render_template("register.html", zip=zip), 200)

@app.route('/manager', methods=["POST", "GET", "PATCH", "DELETE"])
def manager():
    if request.form.get("_method") == "PATCH":
        try:
            json_request = {}
            for key, value in request.form.items():
                if value == "":
                    json_request[key] = None
                else:
                    json_request[key] = value
        except Exception as e:
            response = {"response": str(e)}
            return make_response(jsonify(response), 400)

        response = update_item(json_request)

        response1 = get_all_items()
        response2 = get_all_receipts()
        response3 = get_all_daily_traffic()
        response4 = get_detailed_daily_traffic()
        if response1["response"] == "Success" and \
           response2["response"] == "Success" and \
           response3["response"] == "Success" and \
           response4["response"] == "Success":
            items_data = response1["data"]
            receipts_data = response2["data"]
            daily_traffic = response3["data"]
            detailed_daily_traffic = response4["data"]
            days = []
            traffic = []
            for day in daily_traffic[-5:]:
                days.append(day["date"])
                traffic.append(float(day["total_traffic"]))
            return make_response(render_template("manager.html",
                                                 items=items_data,
                                                 receipts=receipts_data,
                                                 days=days,
                                                 traffic=traffic,
                                                 detailed_daily_traffic=detailed_daily_traffic,
                                                 zip=zip), 200)
        else:
            return make_response(jsonify(response1), 400)

    elif request.form.get("_method") == "DELETE":
        try:
            item_to_delete = request.form.get("name")
        except Exception as e:
            response = {"response": str(e)}
            return make_response(jsonify(response), 400)
        response = delete_item(item_to_delete)
        response1 = get_all_items()
        response2 = get_all_receipts()
        response3 = get_all_daily_traffic()
        response4 = get_detailed_daily_traffic()
        if response1["response"] == "Success" and \
           response2["response"] == "Success" and \
           response3["response"] == "Success" and \
           response4["response"] == "Success":
            items_data = response1["data"]
            receipts_data = response2["data"]
            daily_traffic = response3["data"]
            detailed_daily_traffic = response4["data"]
            days = []
            traffic = []
            for day in daily_traffic[-5:]:
                days.append(day["date"])
                traffic.append(float(day["total_traffic"]))
            return make_response(render_template("manager.html",
                                                 items=items_data,
                                                 receipts=receipts_data,
                                                 days=days,
                                                 traffic=traffic,
                                                 detailed_daily_traffic=detailed_daily_traffic,
                                                 zip=zip), 200)
        else:
            return make_response(jsonify(response1), 400)

    elif request.method == "POST" and request.form.get("mission") == "redirect":
        try:
            receiptId = request.form.get("receipt")
            return redirect(url_for('manager_receipt', receiptId=receiptId))
        except Exception as e:
            print(e)

    elif request.method == "POST" and request.form.get("mission") == "download":
        try:
            receiptId = request.form.get("receipt")
            with orm.db_session:
                if (not ReceiptFile.get(receiptId=receiptId)):
                    generate_receipt(receiptId)
                receipt = ReceiptFile.get(receiptId=receiptId).file
                with open('new_receipt.txt', 'w', encoding="utf-8") as f:
                    receipt = "                 " + receipt
                    f.write(receipt)
                path = "./new_receipt.txt"
                return send_file(path, as_attachment=True)
        except Exception as e:
            print(e)

    elif request.method == "POST":
        try:
            json_request = {}
            for key, value in request.form.items():
                if value == "":
                    json_request[key] = None
                else:
                    json_request[key] = value
        except Exception as e:
            response = {"response": str(e)}
            return make_response(jsonify(response), 400)

        response = add_item(json_request)
        response1 = get_all_items()
        response2 = get_all_receipts()
        response3 = get_all_daily_traffic()
        response4 = get_detailed_daily_traffic()
        if response1["response"] == "Success" and \
           response2["response"] == "Success" and \
           response3["response"] == "Success" and \
           response4["response"] == "Success":
            items_data = response1["data"]
            receipts_data = response2["data"]
            daily_traffic = response3["data"]
            detailed_daily_traffic = response4["data"]
            days = []
            traffic = []
            for day in daily_traffic[-5:]:
                days.append(day["date"])
                traffic.append(float(day["total_traffic"]))
            return make_response(render_template("manager.html",
                                                 items=items_data,
                                                 receipts=receipts_data,
                                                 days=days,
                                                 traffic=traffic,
                                                 detailed_daily_traffic=detailed_daily_traffic,
                                                 zip=zip), 200)
        else:
            return make_response(render_template("manager.html",
                                                 detailed_daily_traffic={},
                                                 zip=zip), 200)

    else:
        response1 = get_all_items()
        response2 = get_all_receipts()
        response3 = get_all_daily_traffic()
        response4 = get_detailed_daily_traffic()
        if response1["response"] == "Success" and \
           response2["response"] == "Success" and \
           response3["response"] == "Success" and \
           response4["response"] == "Success":
            items_data = response1["data"]
            receipts_data = response2["data"]
            daily_traffic = response3["data"]
            detailed_daily_traffic = response4["data"]
            days = []
            traffic = []
            for day in daily_traffic[-5:]:
                days.append(day["date"])
                traffic.append(float(day["total_traffic"]))
            return make_response(render_template("manager.html",
                                                 items=items_data,
                                                 receipts=receipts_data,
                                                 days=days,
                                                 traffic=traffic,
                                                 detailed_daily_traffic=detailed_daily_traffic,
                                                 zip=zip), 200)
        else:
            DB.create_tables()
            return make_response(render_template("manager.html",
                                                 detailed_daily_traffic={},
                                                 zip=zip), 200)

@app.route('/manager/receipt', methods=["GET"])
def manager_receipt():
    receiptId = request.args["receiptId"]
    with orm.db_session:
        if (not ReceiptFile.get(receiptId=receiptId)):
            generate_receipt(receiptId)
        receipt = ReceiptFile.get(receiptId=receiptId).file
        with open('new_receipt.txt', 'w', encoding="utf-8") as f:
            receipt = "                 " + receipt
            f.write(receipt)
            return render_template("receipt.html", receiptId=receipt)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)


import sqlite3
from sqlite3 import Error
from random import randint

def create_conn(db_file):
     try:
         conn = sqlite3.connect(db_file)
     except Error as e:
         print(e)
     finally:
         conn.close()

conn = sqlite3.connect('db\\sqlite\\db\\pythonsqlite.db')

c = conn.cursor()
c.execute("PRAGMA foreign_keys = ON")

def create_tables(c):
    try:

        c.execute('CREATE TABLE IF NOT EXISTS LOGIN'
                  '(id integer PRIMARY KEY NOT NULL, '
                  'email text, '
                  'pswd text)');

        c.execute('CREATE TABLE IF NOT EXISTS STUD_INFO'
                  '(id integer PRIMARY KEY NOT NULL, '
                  'fname text, '
                  'lname text, '
                  'sem_id integer, '
                  'FOREIGN KEY(id) REFERENCES LOGIN(id) ON DELETE CASCADE)');

        c.execute('CREATE TABLE IF NOT EXISTS GPA_DETAILS'
                  '(id integer, '
                  'sem1 real, '
                  'sem2 real, '
                  'sem3 real, '
                  'sem4 real, '
                  'sem5 real, '
                  'sem6 real, '
                  'sem7 real, '
                  'sem8 real, '
                  'FOREIGN KEY(id) REFERENCES STUD_INFO(id) ON DELETE CASCADE)');

    except Error as e:
        print(e)

create_tables(c)
conn.commit()

def populate(c):
    try:
        # id, email, pswd

        LOGIN_INFO = [(1, 'bisensd@rknec.edu', 'bisensd'),
                       (2, 'kankariyas@rknec.edu', 'kankariyas'),
                       (3, 'tiwariy@rknec.edu', 'tiwariy'),
                       (4, 'pala@rknec.edu', 'pala'),
                      (5, 'lalwanit@rknec.edu', 'lalwanit'),
                      (6, 'bhalotias@rknec.edu', 'bhalotias'),
                      (7, 'budhrajank@rknec.edu', 'budhrajank'),
                      (8, 'rathir@rknec.edu', 'rathir'),
                      (9, 'kulkarnir@rknec.edu', 'kulkarnir'),
                      (10, 'agrawals@rknec.edu', 'agrawals'),
                      (11, 'rathorea@rknec.edu', 'rathorea'),
                      (12, 'lahotir@rknec.edu', 'lahotir')]

        c.executemany('INSERT INTO LOGIN VALUES (?,?,?)', LOGIN_INFO)

        # id, fname, lname, sem_id

        STUD_DETAILS = [(1, 'Shreya', 'Bisen', 6),
                         (2, 'Surabhi', 'Kankariya', 7),
                         (3, 'Yashi', 'Tiwari', 8),
                         (4, 'Ashish', 'Pal', 6),
                        (5, 'Tarun', 'Lalwani', 7),
                        (6, 'Shashank', 'Bhalotia', 8),
                        (7, 'Nidhi', 'Budhraja', 8),
                        (8, 'Rohit', 'Rathi', 3),
                        (9, 'Ram', 'Kulkarni', 2),
                        (10, 'Shantanu', 'Agrawal', 3),
                        (11, 'Aman', 'Rathore', 5),
                        (12, 'Radhika', 'Lahoti', 6)]

        c.executemany('INSERT INTO STUD_INFO VALUES (?,?,?,?)', STUD_DETAILS)

        # id, sem(1 to 8)

        GPA_DETAILS = [(1, 8.9 , 8.3 , 8.6 , 8.5 , 8.4 , 0.0 , 0.0 , 0.0),
                       (2, 8.9 , 8.3 , 8.6 , 8.5 , 8.4 , 8.9 , 0.0 , 0.0),
                       (3, 8.9 , 8.3 , 8.6 , 8.5 , 8.4 , 8.5 , 9.2 , 0.0),
                       (4, 8.9, 8.3, 8.6, 8.5, 8.4, 0.0, 0.0, 0.0),
                       (5, 8.6, 8.3, 9.0, 8.5, 8.4, 8.9, 0.0, 0.0),
                       (6, 8.4, 8.3, 9.4, 8.9, 8.8, 9.5, 9.2, 0.0),
                       (7, 8.4, 8.3, 7.9, 8.5, 8.4, 8.9, 9.0, 0.0),
                       (8, 8.0, 8.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
                       (9, 8.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
                       (10, 8.1, 8.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
                       (11, 8.7, 8.7, 8.6, 8.5, 0.0, 0.0, 0.0, 0.0),
                       (12, 8.9, 8.7, 8.6, 8.5, 8.1, 0.0, 0.0, 0.0)
                       ]

        c.executemany('INSERT INTO GPA_DETAILS VALUES (?,?,?,?,?,?,?,?,?)', GPA_DETAILS);

    except Error as e:
        print(e)

populate(c)
conn.commit()

def bulkDataIns():
#    print("DATA INSERTED")
#     for num in range(13,150):
#         if (num%2)==0:
#             c.execute( "INSERT INTO LOGIN VALUES(?,?,?)",(num,'abc'+str(num)+'@rknec.edu','abc'+str(num)) )
##             c.execute( "INSERT INTO STUD_INFO VALUES(?,?,?,?)", () )
#         else:
#             c.execute("INSERT INTO LOGIN VALUES(?,?,?)",(num,'xyz'+str(num)+'@rknec.edu','xyz'+str(num)) )

     for num in range(13, 201):
         if (num % 2) == 0:

              c.execute("INSERT INTO LOGIN VALUES(?,?,?)", (num, 'abc' + str(num) + '@rknec.edu', 'abc' + str(num)))
              c.execute( "INSERT INTO STUD_INFO VALUES(?,?,?,?)", (num, 'ABC' , 'DEF' , 8) )
              c.execute("INSERT INTO GPA_DETAILS VALUES(?,?,?,?,?,?,?,?,?)", (num, 8.4, 8.3, 9.4, 8.9, 8.8, 9.5, 9.2, 0.0))
         else:
              c.execute("INSERT INTO LOGIN VALUES(?,?,?)", (num, 'xyz' + str(num) + '@rknec.edu', 'xyz' + str(num)))
              c.execute("INSERT INTO STUD_INFO VALUES(?,?,?,?)", (num, 'PQR', 'XYZ', 7))

              c.execute("INSERT INTO GPA_DETAILS VALUES(?,?,?,?,?,?,?,?,?)", (num, 8.6, 8.3, 9.0, 8.5, 8.4, 8.9, 0.0, 0.0))

bulkDataIns()
conn.commit()

for num in range(13,15):
         print(num,'abc'+str(num)+'@rknec.edu','abc'+str(num))


from setuptools import setup, find_packages
from pathlib import Path

here = Path(__file__).parent.resolve()

long_description = (here / "README.md").read_text(encoding="utf-8")

setup(
    name='os-monitoring-tool',
    version='1.0.dev1',
    packages=find_packages(where="src", exclude=["db.ReturnResultsThread.py", "db.page.txt", ]),
    url='https://github.com/jalnor/os_monitoring_tool.git',
    license='MIT',
    author='jalnor',
    author_email='',
    description='A process monitoring tool',
    python_requires=">=3.8"
)