import json
from knack.log import get_logger
from azure.cli.core.azclierror import ForbiddenError, RequiredArgumentMissingError, InvalidArgumentValueError
from azext_iot.common.utility import process_json_arg, handle_service_exception, scantree
from azext_iot.digitaltwins.common import ADTModelCreateFailurePolicy
from azext_iot.digitaltwins.providers.base import DigitalTwinsProvider
from azext_iot.sdk.digitaltwins.dataplane.models import ErrorResponseException
from tqdm import tqdm

logger = get_logger(__name__)
MAX_MODELS_API_LIMIT = 250

def get_model_dependencies(model, model_id_to_model_map=None):
    """Return a list of dependency DTMIs for a given model"""
    dependencies = []

    # Add everything that would have dependency DTMIs, worry about flattening later
    if "contents" in model:
        components = [item["schema"] for item in model["contents"] if item["@type"] == "Component"]
        dependencies.extend(components)

    if "extends" in model:
        dependencies.append(model['extends'])

    # Go through gathered items, get the DTMI references, and flatten if needed
    no_dup = set()
    for item in dependencies:
        # Models defined in a DTDL can implement extensions of up to two interfaces.
        # These interfaces can be in the form of a DTMI reference, or a nested model.
        if isinstance(item, str):
            # If its just a string, thats a single DTMI reference, so just add that to our set
            no_dup.add(item)
            # Calculate recursive dependencies if model id to model map is passed
            if model_id_to_model_map is not None:
                dep_model = model_id_to_model_map[item]
                no_dup.update(set(get_model_dependencies(dep_model, model_id_to_model_map)))
        elif isinstance(item, dict):
            # If its a single nested model, get its dtmi reference, dependencies and add them
            no_dup.update(set(get_model_dependencies(item, model_id_to_model_map)))
        elif isinstance(item, list):
            # If its a list, could have DTMIs or nested models
            for sub_item in item:
                if isinstance(sub_item, str):
                    # If there are strings in the list, that's a DTMI reference, so add it
                    no_dup.add(sub_item)
                    # Calculate recursive dependencies if model id to model map is passed
                    if model_id_to_model_map is not None:
                        sub_dep_model = model_id_to_model_map[sub_item]
                        no_dup.update(set(get_model_dependencies(sub_dep_model, model_id_to_model_map)))
                elif isinstance(sub_item, dict):
                    # This is a nested model. Now go get its dependencies and add them
                    no_dup.update(set(get_model_dependencies(sub_item, model_id_to_model_map)))

    return list(no_dup)

class ModelProvider(DigitalTwinsProvider):
    def __init__(self, cmd, name, rg=None):
        super(ModelProvider, self).__init__(
            cmd=cmd, name=name, rg=rg,
        )
        self.model_sdk = self.get_sdk().digital_twin_models

    def add(self,
            max_models_per_batch: int,
            models=None,
            from_directory=None,
            failure_policy=ADTModelCreateFailurePolicy.ROLLBACK.value):
        if not any([models, from_directory]):
            raise RequiredArgumentMissingError("Provide either --models or --from-directory.")

        # If both arguments are provided. --models wins.
        payload = []
        models_per_batch = max_models_per_batch
        if models:
            models_result = process_json_arg(content=models, argument_name="models")

            if isinstance(models_result, list):
                payload.extend(models_result)
            elif isinstance(models_result, dict):
                payload.append(models_result)

        elif from_directory:
            payload = self._process_directory(from_directory=from_directory)

        logger.info("Models payload %s", json.dumps(payload))

        models_created = []
        try:
            # Process models in batches if models to process exceed the API limit
            if len(payload) > MAX_MODELS_API_LIMIT:

                model_id_to_model_map = {}
                for model_def in payload:
                    model_id_to_model_map[model_def['@id']] = model_def

                # Create a dictionary to categorize models by their number of dependencies
                dep_count_to_models_map = {}
                for model in payload:
                    num_dependencies = len(get_model_dependencies(model, model_id_to_model_map))
                    if num_dependencies not in dep_count_to_models_map:
                        dep_count_to_models_map[num_dependencies] = []
                    dep_count_to_models_map[num_dependencies].append(model)

                # Sort by dependency count
                dep_count_to_models_tuples = sorted(dep_count_to_models_map.items())
                models_batch = []
                response = []
                pbar = tqdm(total=len(payload), desc='Creating models...', ascii=' #')
                # The tuples being iterated are sorted by dependency count, hence models with 0 dependencies go first,
                # followed by models with 1 dependency, then 2 dependencies and so on... This ensures that all dependencies
                # of each model being added were either already added in a previous iteration or are in the current payload.
                for _, models_list in dep_count_to_models_tuples:
                    while len(models_batch) + len(models_list) > models_per_batch:
                        num_models_to_add = models_per_batch - len(models_batch)
                        models_batch.extend(models_list[0:num_models_to_add])
                        response.extend(self.model_sdk.add(models_batch, raw=True).response.json())
                        models_created.extend([model['@id'] for model in models_batch])
                        pbar.update(len(models_batch))
                        # Remove the model ids which have been processed
                        models_list = models_list[num_models_to_add:]
                        models_batch = []
                    models_batch.extend(models_list)
                # Process the last set of model ids
                if len(models_batch) > 0:
                    pbar.update(len(models_batch))
                    response.extend(self.model_sdk.add(models_batch, raw=True).response.json())
                pbar.close()
                return response
            return self.model_sdk.add(payload, raw=True).response.json()
        except ErrorResponseException as e:
            if len(models_created) > 0:
                pbar.close()
                # Delete all models created by this operation when the failure policy is set to 'Rollback'
                if failure_policy == ADTModelCreateFailurePolicy.ROLLBACK.value:
                    logger.error(
                        "Error creating models. Deleting {} models created by this operation...".format(len(models_created))
                    )
                    # Models will be deleted in the reverse order they were created.
                    # Hence, ensuring each model's dependencies are deleted after deleting the model.
                    models_created.reverse()
                    for model_id in models_created:
                        self.delete(model_id)
                # Models created by this operation are not deleted when the failure policy is set to 'None'
                elif failure_policy == ADTModelCreateFailurePolicy.NONE.value:
                    logger.error(
                        "Error creating current model batch. Successfully created {} models.".format(len(models_created))
                    )
                else:
                    raise InvalidArgumentValueError(
                        "Invalid failure policy: {}. Supported values are: '{}' and '{}'".format(
                            failure_policy, ADTModelCreateFailurePolicy.ROLLBACK.value, ADTModelCreateFailurePolicy.NONE.value
                        )
                    )
            # @vilit - hack to customize 403's to have more specific error messages
            if e.response.status_code == 403:
                error_text = "Current principal access is forbidden. Please validate rbac role assignments."
                raise ForbiddenError(error_text)
            handle_service_exception(e)

    def _process_directory(self, from_directory):
        logger.debug(
            "Documents contained in directory: {}, processing...".format(from_directory)
        )
        payload = []
        for entry in scantree(from_directory):
            if all(
                [not entry.name.endswith(".json"), not entry.name.endswith(".dtdl")]
            ):
                logger.debug(
                    "Skipping {} - model file must end with .json or .dtdl".format(
                        entry.path
                    )
                )
                continue
            entry_json = process_json_arg(content=entry.path, argument_name=entry.name)
            payload.append(entry_json)

        return payload

    def get(self, id, get_definition=False):
        try:
            return self.model_sdk.get_by_id(
                id=id, include_model_definition=get_definition, raw=True
            ).response.json()
        except ErrorResponseException as e:
            handle_service_exception(e)

    def list(
        self, get_definition=False, dependencies_for=None, top=None
    ):  # top is guarded for int() in arg def
        from azext_iot.sdk.digitaltwins.dataplane.models import DigitalTwinModelsListOptions

        list_options = DigitalTwinModelsListOptions(max_items_per_page=top)

        return self.model_sdk.list(
            dependencies_for=dependencies_for,
            include_model_definition=get_definition,
            digital_twin_models_list_options=list_options,
        )

    def update(self, id, decommission: bool):
        patched_model = [
            {"op": "replace", "path": "/decommissioned", "value": decommission}
        ]

        # Does not return model object upon updating
        try:
            self.model_sdk.update(id=id, update_model=patched_model)
        except ErrorResponseException as e:
            handle_service_exception(e)

        return self.get(id=id)

    def delete(self, id: str):
        try:
            self.model_sdk.delete(id=id)
        except ErrorResponseException as e:
            handle_service_exception(e)

    def delete_all(self):
        # Get all models
        incoming_pager = self.list(get_definition=True)
        incoming_result = []
        try:
            while True:
                incoming_result.extend(incoming_pager.advance_page())
        except StopIteration:
            pass
        except ErrorResponseException as e:
            handle_service_exception(e)

        # Build dict of model_id : set of parent_ids
        parsed_models = {model.id: set() for model in incoming_result}
        for model in incoming_result:
            # Parse dependents, add current model as parent of dependents
            dependencies = get_model_dependencies(model.model)
            for d_id in dependencies:
                parsed_models[d_id].add(model.id)

        def delete_parents(model_id, model_dict):
            # Check if current model has been deleted already
            if model_id not in model_dict:
                return

            # Delete parents first
            for parent_id in model_dict[model_id]:
                if parent_id in model_dict:
                    delete_parents(parent_id, model_dict)

            # Delete current model and remove references
            del model_dict[model_id]
            try:
                self.delete(model_id)
            except Exception as e:
                logger.warning(f"Could not delete model {model_id}; error is {e}")

        while len(parsed_models) > 0:
            model_id = next(iter(parsed_models))
            delete_parents(model_id, parsed_models)


import requests, json, sys
from flask import Flask, render_template, flash, redirect, url_for
from flask.ext.script import Manager
from flask.ext.bootstrap import Bootstrap
from flask.ext.wtf import Form
from wtforms import StringField, TextAreaField, SelectField, SubmitField
from flask.ext.wtf.html5 import EmailField
from wtforms.validators import Required, Length, Email

# import from 21 Bitcoin Developer Library
from two1.commands.config import Config
from two1.lib.wallet import Wallet
from two1.lib.bitrequests import BitTransferRequests

app = Flask(__name__, template_folder="../templates")
manager = Manager(app)
bootstrap = Bootstrap(app)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'a_very-long_password-here'

wallet = Wallet()
username = Config().username

class GreetingForm(Form):
    message = TextAreaField(
        validators=[Required(message='A greeting is required..'), Length(min=1, max=1024)])
    email = EmailField(
        validators=[Required(message='An email is required..'), Email(message='A valid e-mail is required.')])
    submit = SubmitField('Happy Birthday!')

@app.route('/', methods=['GET', 'POST'])
def index():
    form = GreetingForm()
    if form.validate_on_submit():
        bit_transfer_request = BitTransferRequests(wallet, username)
        json = {
            'message': form.message.data,
            'email': form.email.data
        }
        headers = {
            'Content-Type': 'application/json'
        }
        response = bit_transfer_request.post(url='http://localhost:8080/greeting/', headers=headers, json=json)
        if response.status_code != 201:
            flash('An error occured: {}, statuscode: {}'.format(response, response.status_code))
            return redirect(url_for('.index'))
        else:
            flash('Your Birthday message was sent to: {}'.format(form.email.data))
            return redirect(url_for('.index'))
    else:
        for field, errors in form.errors.items():
            flash('Error in the {} field: {}'.format(getattr(form, field).label.text, errors))
    return render_template('base.html', form=form)

# request the bitcoin-enabled endpoint you're hosting on the 21 Bitcoin Computer
@manager.option('-m', '--message', dest='message', help='Enter your message')
@manager.option('-e', '--email', dest='email', help='Recipient of greeting card')
def send(message, email):
    bit_transfer_requests = BitTransferRequests(wallet, username)
    json = {
        'message': message,
        'email': email
    }
    headers = {
        'Content-Type': 'application/json'
    }
    response = bit_transfer_requests.post(url='http://localhost:8080/greeting/', headers=headers, json=json)
    if response.status_code != 201:
        print(response.text)
        sys.exit()
    print(response.text)

if __name__ == '__main__':
    manager.run()


import os
"""
This is for processing the .csv file into .txt file, which is imported to the dataloader.
"""

with open('SHGD13_labels.csv') as f:
    lines = f.readlines()
categories = []
for line in lines:
    line = line.rstrip()
    categories.append(line)
categories = sorted(categories)
with open('SHGD13_category.txt','w') as f:
    f.write('\n'.join(categories))

dict_categories = {}
for i, category in enumerate(categories):
    dict_categories[category] = i

files_input = 'Tuples.txt'
files_output = 'test_list.txt'
cnt = 0
labels = []
with open(files_input) as f:
    lines = f.readlines()

for line in lines:
    label_one = []
    line = line.rstrip()
    items = line.split(',')
    label_one.append(dict_categories[items[0]])
    label_one.append(dict_categories[items[1]])
    label_one.append(dict_categories[items[2]])
    labels.append(label_one)
output = []
for i in range(len(labels)):

    # counting the number of frames in each video folders
    dir_files_grayscale = os.listdir(os.path.join('../Images/Tuples/set1/Grayscale', str(i)))
    dir_files_depth = os.listdir(os.path.join('../Images/Tuples/set1/Depth', str(i)))
    if (len(dir_files_grayscale) == len(dir_files_depth)):
        output.append('%s %d %d %d %d'%(i, len(dir_files_depth), int(labels[i][0]), int(labels[i][1]), int(labels[i][2])))
    else:
        print(i + 'Wrong!')
        break
    print('%d/%d'%(i, len(labels)))
    with open(files_output,'w') as f:
        f.write('\n'.join(output))


from django.shortcuts import render, reverse, HttpResponseRedirect, HttpResponse, Http404
from django.contrib.auth.decorators import login_required
from django.contrib.auth import get_user_model
from django.contrib import messages
from django.conf import settings
from .models import GameRoom, Player, id_generator
from .helper import GameServer
from user_profile.models import UserProfile

from channels.layers import get_channel_layer
import json
from asgiref.sync import async_to_sync

ERROR = "error"
SUCCESS = "success"
MAX_JOINED_PLAYER_COUNT = 10
MINIMUM_ONLINE_PLAYER_REQUIRED = 3

channel_layer = get_channel_layer()

User = get_user_model()

def broadcast_notification(group_name, message):
    """
        Helper Function to Broadcast Notifications in Game Room.
    :param group_name: Name of Group in which event should be broadcast.
    :param message: Notification Message.
    :return:
    """
    text = {
        "status": "broadcast_notification",
        "message": message,
    }
    group_name = f"game_room_{group_name}"
    async_to_sync(channel_layer.group_send)(
        group_name,
        {
            "type": "broadcast.notification",
            "text": json.dumps(text)
        }
    )

@login_required
def play_now(request):
    player = request.user
    if not player.is_authenticated:
        message = f"You need to login first!"
        return render(request, '404.html', {"message": message})

    player_profile = UserProfile.objects.get(user=player)
    if not player_profile.is_email_verified:
        messages.info(request, f"Your email is not verified.")
        return HttpResponseRedirect(reverse('user_profile', kwargs={"username": player.username}))

    # Show animation in case player's league upgraded/degraded.
    if player_profile.is_league_changed != UserProfile.LEAGUE_STABLE:
        league_change_context = {
            "player": player,
            "profile": player_profile,
            "is_league_changed": player_profile.is_league_changed,
        }
        player_profile.is_league_changed = UserProfile.LEAGUE_STABLE
        player_profile.save()
        return render(request, 'game/league_changed.html', league_change_context)

    # Fetching top 10 player's
    top_ratings = UserProfile.objects.order_by('-current_rating').filter(total_public_games_count__gt=0).values_list('current_rating', flat=True).distinct()
    top_players = UserProfile.objects.order_by('-current_rating').filter(total_public_games_count__gt=0).filter(current_rating__in=top_ratings[:10])
    context = {
        "top_players": top_players,
    }
    return render(request, 'game/play_now.html', context=context)

# TODO: Play Anonymously option for authenticated users as well.
def enter_public_play(request):
    """
    View to enter Public Game Room
    :param request:
    :return:
    """
    player = request.user
    if player.is_authenticated:
        player_profile = UserProfile.objects.get(user=player)
        if not player_profile.is_email_verified:
            messages.info(request, f"Your email is not verified.")
            return HttpResponseRedirect(reverse('user_profile', kwargs={"username": player.username}))
        current_player_league = player_profile.current_league
        if GameServer.AVAILABLE_PUBLIC_GAMES:
            for public_game in GameServer.AVAILABLE_PUBLIC_GAMES:
                if public_game.get_count_of_players() < MAX_JOINED_PLAYER_COUNT:
                    if not public_game.is_game_running:
                        if public_game.league == current_player_league:
                            active_unique_id = public_game.unique_id
                            return HttpResponseRedirect(
                                reverse('proceed_to_game',
                                        kwargs={'game_type': GameServer.PUBLIC, 'unique_id': active_unique_id}))
        # If no Public Game Room Available, create new.
        active_unique_id = id_generator(10)
        return HttpResponseRedirect(
            reverse('proceed_to_game', kwargs={'game_type': GameServer.PUBLIC, 'unique_id': active_unique_id}))
    else:
        message = f"You need to Login/Signup first."
        return render(request, '404.html', {"message": message})

def enter_friend_play(request):
    """
    View to enter Friendly Game Room.
    :param request:
    :return:
    """
    player = request.user
    player_profile = UserProfile.objects.get(user=player)
    if not player_profile.is_email_verified:
        messages.info(request, f"Your email is not verified.")
        return HttpResponseRedirect(reverse('user_profile', kwargs={"username": player.username}))

    if request.method == "POST":  # Enter Existing Game
        unique_id = request.POST['friend_unique_id']
        if GameServer.AVAILABLE_FRIEND_GAMES:
            for friend_game in GameServer.AVAILABLE_FRIEND_GAMES:
                if friend_game.unique_id == unique_id:
                    if friend_game.get_count_of_players() == MAX_JOINED_PLAYER_COUNT:
                        message = f"Custom Game Room with ID {unique_id} is full."
                        return render(request, '404.html', {"message": message})
                    if friend_game.is_game_running:
                        message = f"Game is already running in Custom Game Room with ID {unique_id}."
                        return render(request, '404.html', {"message": message})
                    return HttpResponseRedirect(
                        reverse('proceed_to_game',
                                kwargs={"game_type": GameServer.CUSTOM, "unique_id": unique_id}))
        message = f"Custom Game Room with ID {unique_id} does'nt exist."
        return render(request, '404.html', {"message": message})
    elif request.method == "GET":  # Creating New Game and Entering
        unique_id = id_generator(10)
        return HttpResponseRedirect(
            reverse('proceed_to_game', kwargs={"game_type": GameServer.CUSTOM, "unique_id": unique_id}))

def proceed_to_game(request, game_type, unique_id):
    """
    View to show game room tutorial.
    :param request:
    :param game_type:
    :param unique_id:
    :return:
    """
    context = {
        "game_type": game_type,
        "unique_id": unique_id,
    }
    return render(request, 'game/info.html', context)

@login_required
def enter_game_room(request, game_type, unique_id):
    """
        View to Enter the Game Room. This can be called only after
        a player has Joined the Game Room.
    :param request:
    :param game_type: Type of Game: PUBLIC or CUSTOM.
    :param unique_id:
    :return:
    """

    player = request.user
    player_profile = UserProfile.objects.get(user=player)
    if not player_profile.is_email_verified:
        messages.info(request, f"Your email is not verified.")
        return HttpResponseRedirect(reverse('user_profile', kwargs={"username": player.username}))

    if not player.is_authenticated:
        error_message = f"Login / Signup to enter a Game Room."
        return render(request, '404.html', {"message": error_message})

    context = {
        'unique_id': unique_id,
        'peer_js_host_name': settings.PEER_JS_HOST_NAME,
        'peer_js_port_number': settings.PEER_JS_PORT_NUMBER,
    }
    return render(request, 'game/enter_game_room.html', context)


import argparse
import os
from git.repo import Repo
from app import get_save_path, load_config
from asker import Prompt, do_ask_for_large_file_cmd
from common import open_file, write_file

PROG_NAME = 'code_reviewer'
DESC = '''A code reviewer used to generate code review

* Generate the latest (or unsubmitted) review based on the git repository where the incoming file is located
* Generate the submission information of this review
'''

def create_prompt(lan: str) -> Prompt:
    first = f'''The content I sent you is a part of a code patch.
please help me do a brief code review. If any bug risk and improvement suggestion are welcome.
Reply in {lan}:'''

    next = f'''Please continue to do code view.
If any bug risk and improvement suggestion are welcome. Reply in {lan}:'''

    sumarize_multi = f'''The following content is code reviews of different parts of the same code patch.
First, please summarize them with the most unique and helpful points, into a list of key points and takeaways.
Then, please provide a commit message 30 words or less. Please reply in {lan}:'''

    sumarize_single = f'''Bellow is the code patch, First, please help me do a brief code review,
If any bug risk and improvement suggestion are welcome.
Then, please provide a commit message 30 words or less.
Please reply in {lan}:'''

    return Prompt(first, next, sumarize_multi, sumarize_single)

def create_args_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(description=DESC)
    parser.add_argument('-t', '--test', action='store_true', help='whether it is in test mode')
    parser.add_argument('-f', '--file', help='file path, the git repository root directory will be taken as this file directory')
    parser.add_argument('-cfg', '--config', help='path of the config file')

    return parser

def gen_patch(repo: Repo, file) -> str:
    if not repo:
        raise Exception(f'The directory where the file [{file}] is located is not a git repository')

    repo_name = os.path.basename(repo.working_dir)
    patch_path = os.path.join(get_save_path(), f'{repo_name}.patch')
    if repo.is_dirty():
        repo.git.add(A=True)
        repo.index.commit('Automatically submitted by code_reviewer')
        os.system(f'cd {os.path.dirname(file)} && git format-patch -1 --stdout > {patch_path}')
        repo.git.reset('HEAD~1')
    else:
        os.system(f'cd {os.path.dirname(file)} && git format-patch -1 --stdout > {patch_path}')

    if not os.path.exists(patch_path):
        raise Exception(f'Failed to generate patch file. Please check whether the directory where the file [{file}] is located is a git repository')
    return patch_path

def gen_review_header(repo: Repo) -> str:
    commit_message = repo.head.commit.message.strip()
    return f'''# Code review

Repository: {os.path.basename(repo.working_dir)}
Branch: {repo.active_branch.name}
Commit information: {"(unsubmitted)" if repo.is_dirty() else commit_message}
Commit author: {"(unknown)" if repo.is_dirty() else repo.head.commit.author}
'''

def test() -> None:
    repo = Repo(os.path.dirname(__file__), search_parent_directories=True)
    print(gen_review_header(repo))

if __name__ == '__main__':
    parser = create_args_parser()
    args = parser.parse_args()

    if args.test:
        test()
        exit(0)

    file = args.file
    if not file:
        print(parser.format_help())
        exit(0)

    repo = Repo(os.path.dirname(file), search_parent_directories=True)
    patch_path = gen_patch(repo, file)
    print(f'Generated patch file [{patch_path}]')

    config = load_config(args.config)
    prompt = create_prompt(config['language'])
    result = do_ask_for_large_file_cmd(patch_path, prompt, config)

    review_header = gen_review_header(repo)
    repo_name = os.path.basename(repo.working_dir)
    result_path = os.path.normpath(os.path.join(get_save_path(), f'code_reviewer/{repo_name}.md'))
    write_file(result_path, review_header + '\n' + result + '\n')
    print(f'Results saved in: {result_path}')
    open_file(result_path)


"""
File:   ddpg.py
Author: Nathaniel Hamilton

Description:    This class implements the Deep Deterministic Policy Gradient algorithm written about in
                https://arxiv.org/abs/1509.02971

"""

import time
import gc
import os
import numpy as np
import torch
import torch.optim as optim
from torch.autograd import Variable
import torch.nn.functional as F
# from algorithms.abstract_algorithm import Algorithm
from utils.replay_buffer import *
from utils.ornstein_uhlenbeck_noise import *
from algorithms.ddpg.core import *

class DDPG():
    def __init__(self, runner, num_training_steps, time_per_step, rollout_length=1000, evaluation_length=1000,
                 evaluation_iter=10, num_evaluations=5, random_seed=8, replay_capacity=500, batch_size=100,
                 architecture='standard',
                 actor_learning_rate=1e-4, critic_learning_rate=1e-3, weight_decay=1e-2, gamma=0.99, tau=0.001,
                 noise_sigma=0.2, noise_theta=0.15, log_path='.', save_path='.', load_path=None, render_eval=True):
        """
        This class implements the Deep Deterministic Policy Gradient algorithm written about in
        https://arxiv.org/abs/1509.02971

        The input names are descriptive of variable's meaning, but within the class, the variable names from the paper
        are used.

        :param runner:               (Runner) The interface between the learning agent and the environment.
        :param num_training_steps:   (int)    The total number of steps taken during training. The agent will execute at
                                                least this many steps.
        :param rollout_length:       (int)    The maximum number of steps the agent should take during a rollout.
                                                i.e. how far the agent explores in any given direction.
        :param evaluation_length:    (int)    The maximum number of steps the agent should take when evaluating the
                                                policy.
        :param evaluation_iter:      (int)    The number of exploration iterations completed between policy evaluations.
                                                This is also the point at which the policy is saved.
        :param num_evaluations:      (int)    The number of evaluations that over at an evaluation point. It is best to
                                                complete at lease 3 evaluation traces to account for the variance in
                                                transition probabilities.
        :param random_seed:          (int)    The random seed value to use for the whole training process.
        :param replay_capacity:      (int)    The capacity of the replay buffer. It will never hold more than this many
                                                memories.
        :param batch_size:           (int)    Number of memories to sample for each update.
        TODO: NN architecture info
        :param actor_learning_rate:  (float)  The learning rate for the Adam optimizer updating the actor.
        :param critic_learning_rate: (float)  The learning rate for the Adam optimizer updating the critic.
        :param weight_decay:         (float)  Weight decay for Adam optimizer updating the critic.
        :param gamma:                (float)  Discount factor for computing returns.
        :param tau:                  (float)  Soft update factor.
        :param noise_sigma:          (float)  Standard deviation of exploration noise.
        :param noise_theta:          (float)  Theta parameter for Ornstein-Uhlenbeck exploration noise.
        :param log_path:             (str)    File path to directory where episode_performance.csv will be saved.
        :param save_path:            (str)    File path to directory where all models will be saved.
        :param load_path:            (str)    File path to initial model to be loaded.
        :param render_eval           (bool)   Boolean selection for rendering the environment during evaluation.
        """

        # Save all parameters
        self.runner = runner
        self.is_discrete = runner.is_discrete
        self.H = rollout_length
        self.eval_len = evaluation_length
        self.eval_iter = evaluation_iter
        self.num_evals = num_evaluations
        self.num_training_steps = num_training_steps
        self.save_path = save_path
        self.capacity = replay_capacity
        self.batch_size = batch_size
        self.actor_lr = actor_learning_rate
        self.critic_lr = critic_learning_rate
        self.weight_decay = weight_decay
        self.gamma = gamma
        self.tau = tau
        self.render = render_eval

        # Initialize Cuda variables
        use_cuda = torch.cuda.is_available()
        self.device = torch.device("cuda" if use_cuda else "cpu")

        # Set the random seed
        np.random.seed(random_seed)
        torch.manual_seed(random_seed)
        torch.cuda.manual_seed_all(random_seed)

        # Create the actor neural network and its target
        if architecture == 'verivital':
            self.actor = VerivitalActor(num_inputs=runner.obs_shape[0], hidden_size1=64, hidden_size2=64,
                                        num_actions=runner.action_shape[0], final_bias=3e-3).to(self.device)
            self.actor_target = VerivitalActor(num_inputs=runner.obs_shape[0], hidden_size1=64, hidden_size2=64,
                                               num_actions=runner.action_shape[0], final_bias=3e-3).to(self.device)
        else:
            self.actor = DDPGActor(num_inputs=runner.obs_shape[0], hidden_size1=64, hidden_size2=64,
                                   num_actions=runner.action_shape[0], final_bias=3e-3).to(self.device)
            self.actor_target = DDPGActor(num_inputs=runner.obs_shape[0], hidden_size1=64, hidden_size2=64,
                                          num_actions=runner.action_shape[0], final_bias=3e-3).to(self.device)

        # Create the critic neural network and its target
        self.critic = DDPGCritic(num_inputs=runner.obs_shape[0], hidden_size1=64, hidden_size2=64,
                                 num_actions=runner.action_shape[0], final_bias=3e-3).to(self.device)
        self.critic_target = DDPGCritic(num_inputs=runner.obs_shape[0], hidden_size1=64, hidden_size2=64,
                                        num_actions=runner.action_shape[0], final_bias=3e-3).to(self.device)

        # Create the optimizers for the actor and critic neural networks
        self.actor_optimizer = optim.Adam(self.actor.parameters(), lr=self.actor_lr)
        self.critic_optimizer = optim.Adam(self.critic.parameters(), lr=self.critic_lr,
                                           weight_decay=self.weight_decay)

        # Initialize the target NNs or load models
        if (load_path is None) or (load_path == 'None'):
            # Targets are copied with a hard update
            hard_update(target=self.actor_target, source=self.actor)
            hard_update(target=self.critic_target, source=self.critic)

        else:
            self.load_model(load_path)

        # Create the log files
        if not os.path.isdir(log_path):
            os.makedirs(log_path)
        self.log_save_name = log_path + '/episode_performance.csv'
        f = open(self.log_save_name, "w+")
        f.write("training steps, time, steps in evaluation, accumulated reward, done, exit condition \n")
        f.close()

        # Make sure the save path exists
        if not os.path.isdir(save_path):
            os.mkdir(save_path)

        # Initialize variables used by the learner
        self.replay_buffer = ReplayBuffer(self.capacity)
        self.noise = OrnsteinUhlenbeckActionNoise(mu=np.zeros(runner.action_shape),
                                                  sigma=(noise_sigma * np.ones(runner.action_shape)),
                                                  theta=noise_theta, dt=time_per_step)
        # self.old_params = list(self.actor.parameters())[0].clone()

    def evaluate_model(self, evaluation_length=-1):
        """
        This method performs an evaluation of the model. The evaluation lasts for the specified number of executed
        steps. Multiple evaluations should be used to account for variations in performance.

        :input:
            :param evaluation_length:   (int)   The maximum number of steps to execute during the evaluation run. If -1
                                                    is used, the method will ignore an upper bound for number of steps
                                                    to execute.
        :outputs:
            :return reward_sum:         (float) The cummulative reward collected during the run.
            :return step:               (int)   The number of steps executed during the run.
            :return done:               (int)   A signal indicating if the agent reached a final state.
            :return exit_cond:          (int)   A signal indicating if the agent reached a fatal state.
        """

        # Initialize
        step = 0
        reward_sum = 0

        # Start the evaluation from a safe starting point
        self.runner.reset(evaluate=True)
        state = self.runner.get_state()
        done = 0
        exit_cond = 0

        while self.runner.is_available():
            # Stop the controller if there is a collision or time-out
            if done or exit_cond or (step >= evaluation_length != -1):
                # stop
                self.runner.stop()
                break

            # Determine the next action
            action = self.get_action(state)  # No noise injected during evaluation

            # Execute determined action
            next_state, reward, done, exit_cond = self.runner.step(action, render=self.render)

            # Update for next step
            reward_sum += reward
            state = next_state
            step += 1

        return reward_sum, step, done, exit_cond

    def __explore(self, num_steps):
        """
        Execute random actions exploring the environment updating after each step.

        :param num_steps:   (int)   The number of steps to perform during the exploration.
        """

        # Initialize variables
        steps_taken = 0

        # Get the initial state information and reset the Ornstein-Uhlenbeck noise
        self.noise.reset()
        state = self.runner.get_state()

        # during exploration, update after every step
        while steps_taken < num_steps:

            # Determine the action to take
            action = self.get_action(state, self.noise.noise())

            # Take the action
            next_state, reward, done, exit_cond = self.runner.step(action)

            # Record the information in the replay buffer
            self.replay_buffer.add_memory(state, action, reward, done, exit_cond, next_state)

            # Only update if the replay buffer is full
            if len(self.replay_buffer.rewards) >= self.batch_size:
                # Update the neural networks using a random sampling of the replay buffer
                mb_states, mb_actions, mb_rewards, mb_dones, mb_exits, mb_next_states = self.replay_buffer.sample_batch(
                    self.batch_size)
                self.update_model(mb_states, mb_actions, mb_rewards, mb_dones, mb_exits, mb_next_states)

            # Only reset the environment if a terminal state has been reached
            if done == 1 or exit_cond == 1:
                self.runner.reset()
                self.noise.reset()
                state = self.runner.get_state()
            else:
                state = next_state

            steps_taken += 1
        print('episode completed')
        return

    def get_action(self, state, noise=None):
        """
        This function calculates the desired output using the NN and the exploration noise.

        :input:
            :param state:       (ndarray)   Input state to determine which action to take
            :param noise:       (ndarray)   The exploration noise. Default=[0, 0] (no noise)
        :output:
            :return action:     (ndarray)   The chosen action to take
        """
        # Forward pass the network
        state = torch.FloatTensor(state).to(self.device)
        self.actor.eval()  # Must be in eval mode to execute a forward pass
        action = self.actor.forward(state)
        self.actor.train()  # Must be in train mode to record gradients
        action = action.cpu()

        # Add the process noise to the action
        if noise is not None:
            action = action + torch.FloatTensor(noise).cpu()
            # print(action)
        action = action.clamp(-1.0, 1.0)  # Make sure action cannot exceed limits

        # Convert to numpy array
        np_action = action.detach().numpy()

        return np_action

    def load_model(self, load_path=None):
        """
        This function loads the neural network models and optimizers for both the actor and the critic from one file.
        If a load_path is not provided, the function will not execute. For more examples on how to save/load models,
        visit https://pytorch.org/tutorials/beginner/saving_loading_models.html

        :param load_path:  (string) The file name where the models will be loaded from. default=None
        """

        # Load the saved file as a dictionary
        if load_path is not None:
            checkpoint = torch.load(load_path)

            # Store the saved models
            self.actor.load_state_dict(checkpoint['actor'])
            self.critic.load_state_dict(checkpoint['critic'])
            self.actor_target.load_state_dict(checkpoint['actor_target'])
            self.critic_target.load_state_dict(checkpoint['critic_target'])
            self.actor_optimizer.load_state_dict(checkpoint['actor_optimizer'])
            self.critic_optimizer.load_state_dict(checkpoint['critic_optimizer'])
            self.replay_buffer = ReplayBuffer(self.capacity, checkpoint['replay_buffer'])

            # Evaluate the neural networks to ensure the weights were properly loaded
            self.actor.eval()
            self.critic.eval()
            self.actor_target.eval()
            self.critic_target.eval()

        # Clean up any garbage that's accrued
        gc.collect()

        return

    def save_model(self, save_path='.'):
        """
        This method saves the neural network models and optimizers for both the actor and the critic in one file. For
        more examples on how to save/load models, visit
        https://pytorch.org/tutorials/beginner/saving_loading_models.html

        :input:
            :param save_path: (string) The file name the model will be saved to. Default='model.pth'
        """

        # Save everything necessary to start up from this point
        torch.save({
            'actor': self.actor.state_dict(),
            'critic': self.critic.state_dict(),
            'actor_target': self.actor_target.state_dict(),
            'critic_target': self.critic_target.state_dict(),
            'actor_optimizer': self.actor_optimizer.state_dict(),
            'critic_optimizer': self.critic_optimizer.state_dict(),
            'replay_buffer': self.replay_buffer,
        }, save_path)

        # Clean up any garbage that's accrued
        gc.collect()

        return

    def train_model(self):
        """
        This method trains the agent to learn an optimal model according to the DDPG algorithm.

        :outputs:
            :return final_policy_reward_sum: (float) The accumulated reward collected by the agent evaluated using the
                                                        latest update of the learned policy.
            :return execution_time:          (float) The amount of time (in seconds) it took to run the full
                                                        train_model() method.
            :return training_time:           (float) The amount of time (in seconds) it took to complete the training
                                                        process.
        """

        # Initialize iterative values
        t_start = time.time()
        step = 0
        eval_count = 0
        evaluation_time = 0.0

        # Evaluate once before training
        t_eval_start = time.time()
        log_time = t_eval_start - t_start - evaluation_time
        avg_steps = 0.0
        avg_reward = 0.0
        for j in range(self.num_evals):
            reward, eval_steps, done, exit_cond = self.evaluate_model(self.eval_len)

            # Log the evaluation run
            with open(self.log_save_name, "a") as myfile:
                myfile.write(str(step) + ', ' + str(log_time) + ', ' + str(eval_steps) + ', ' + str(reward) +
                             ', ' + str(done) + ', ' + str(exit_cond) + '\n')

            avg_steps += eval_steps
            avg_reward += reward

        # Print the average results for the user to debugging
        print('Training Steps: ' + str(step) + ', Avg Steps in Episode: ' + str(avg_steps / self.num_evals) +
              ', Avg Acc Reward: ' + str(avg_reward / self.num_evals))

        # Save the model that achieved this performance
        print('saving...')
        save_path = self.save_path + '/step_' + str(step) + '_model.pth'
        self.save_model(save_path=save_path)

        # Do not count the time taken to evaluate and save the model as training time
        t_eval_end = time.time()
        evaluation_time += t_eval_end - t_eval_start
        self.runner.reset()

        # Iterate through a sufficient number of steps broken into horizons
        while step < self.num_training_steps:

            # Train through exploration
            ep_length = min(self.H, (self.num_training_steps - step))
            self.__explore(ep_length)
            step += ep_length

            # Evaluate the model
            eval_count += 1
            if eval_count % self.eval_iter == 0:
                t_eval_start = time.time()
                log_time = t_eval_start - t_start - evaluation_time
                avg_steps = 0.0
                avg_reward = 0.0
                for j in range(self.num_evals):
                    reward, eval_steps, done, exit_cond = self.evaluate_model(self.eval_len)

                    # Log the evaluation run
                    with open(self.log_save_name, "a") as myfile:
                        myfile.write(str(step) + ', ' + str(log_time) + ', ' + str(eval_steps) + ', ' + str(reward) +
                                     ', ' + str(done) + ', ' + str(exit_cond) + '\n')

                    avg_steps += eval_steps
                    avg_reward += reward

                # Print the average results for the user to debugging
                print('Training Steps: ' + str(step) + ', Avg Steps in Episode: ' + str(avg_steps / self.num_evals) +
                      ', Avg Acc Reward: ' + str(avg_reward / self.num_evals))

                # Save the model that achieved this performance
                print('saving...')
                save_path = self.save_path + '/step_' + str(step) + '_model.pth'
                self.save_model(save_path=save_path)

                # Do not count the time taken to evaluate and save the model as training time
                t_eval_end = time.time()
                evaluation_time += t_eval_end - t_eval_start

        t_train = time.time()
        training_time = t_train - t_start - evaluation_time

        # Evaluate and save the final learned model
        final_policy_reward_sum, _, _, _ = self.evaluate_model(self.eval_len)
        print('saving...')
        save_path = self.save_path + '/final_model.pth'
        self.save_model(save_path=save_path)

        t_final = time.time()
        execution_time = t_final - t_start

        return final_policy_reward_sum, execution_time, training_time

    def update_model(self, states, actions, rewards, dones, exits, next_states):
        """
        This function updates neural networks for the actor and critic using back-propogation. More information about
        this process can be found in the DDPG paper.

        :inputs:
            :param states:       (list)  The batch of states from the replay buffer
            :param actions:      (list)  The batch of actions from the replay buffer
            :param rewards:      (list)  The batch of rewards from the replay buffer
            :param dones:        (list)  The batch of done values (1 indicates done, 0 indicates not done) from the
                                           replay buffer
            :param exits:        (list)  The batch of exit conditions (1 indicates exited early, 0 indicates normal)
                                           from the replay buffer
            :param next_states:  (list)  The batch of states reached after executing the actions from the replay buffer
        :outputs:
            :return actor_loss:  (float) The loss value calculated for the actor
            :return critic_loss: (float) The loss value calculated for the critic
        """
        # Convert the inputs into tensors to speed up computations
        batch_states = Variable(torch.FloatTensor(states).to(self.device), requires_grad=True)
        batch_actions = Variable(torch.FloatTensor(actions).to(self.device), requires_grad=True)
        batch_rewards = torch.FloatTensor(rewards).to(self.device).unsqueeze(1)
        batch_dones = torch.FloatTensor(dones).to(self.device).unsqueeze(1)
        batch_exits = torch.FloatTensor(exits).to(self.device).unsqueeze(1)
        batch_next_states = torch.FloatTensor(next_states).to(self.device)

        # Compute the critics estimated Q values
        # print(batch_actions)
        batch_qs = self.critic.forward(batch_states, batch_actions)

        # Compute what the actions would have been without noise
        actions_without_noise = self.actor.forward(batch_states)

        # Compute the target's next state and next Q-value estimates used for computing loss
        target_next_action_batch = (self.actor_target.forward(batch_next_states)).detach()
        target_next_q_batch = (self.critic_target.forward(batch_next_states, target_next_action_batch)).detach()

        # Compute y (a metric for computing the critic loss)
        y = (batch_rewards + ((1 - batch_dones) * (1 - batch_exits) * self.gamma * target_next_q_batch)).detach()

        # Compute critic loss and update using the optimizer
        self.critic_optimizer.zero_grad()
        critic_loss = F.mse_loss(y, batch_qs)
        critic_loss.backward()
        self.critic_optimizer.step()

        # Compute the actor loss and update using the optimizer
        self.actor_optimizer.zero_grad()
        actor_loss = -self.critic(batch_states, actions_without_noise)
        actor_loss = actor_loss.mean()
        actor_loss.backward()
        self.actor_optimizer.step()

        # Update the target networks
        soft_update(target=self.actor_target, source=self.actor, tau=self.tau)
        soft_update(target=self.critic_target, source=self.critic, tau=self.tau)

        # new_params = list(self.actor.parameters())[0].clone()
        # print(torch.equal(new_params.data, self.old_params.data))
        #
        # self.old_params = new_params

        # Output the loss values for logging purposes
        return actor_loss.cpu(), critic_loss.cpu()


import asyncio
import discord
import json
import random
import math
import time
import datetime
import os
import shutil
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from discord.ext import commands
from discord.ext import tasks

class Stock(commands.Cog):

    def __init__(self, client):
        self.client = client
        print(f'{__name__} 로드 완료!')

    @commands.command(aliases=["차트", "매수", "매도", "그래프", "주식정보", "주식구매", "주식판매"])
    async def 주식(self, ctx):
        await ctx.send("현재 점검중인 기능입니다.")

    @commands.command()
    async def 계정생성(self, ctx):
        user_id = str(ctx.author.id)
        with open("stock/usr_data.json", 'r') as f:
            user_data = json.load(f)  # 유저 데이터 불러오는 코드
        try:
            a = user_data[user_id]
            await ctx.send('이미 등록된 계정입니다.')
            return
        except KeyError:
            pass
        user_data[user_id] = {}
        user_data[user_id]["money"] = 1000
        user_data[user_id]['alba'] = None
        with open("stock/usr_data.json", 'w') as f:
            json.dump(user_data, f, indent=4)
        await ctx.send('계정을 생성했습니다!')

    @commands.command()
    async def 지갑(self, ctx, member: discord.Member = None):
        if member is None:
            member = ctx.author
        user_id = str(member.id)
        with open("stock/data.json", 'r') as f:
            stock_data = json.load(f)  # 주식 데이터 불러오는 코드
        with open("stock/usr_data.json", 'r') as f:
            user_data = json.load(f)  # 유저 데이터 불러오는 코드
        try:
            embed = discord.Embed(title='지갑', description=str(member.mention), colour=discord.Color.red())
            embed.add_field(name='돈', value=f'{str(user_data[user_id]["money"])}원', inline=False)
            await ctx.send(embed=embed)
        except KeyError:
            await ctx.send('계정을 먼저 생성해주세요.')

    @commands.command(aliases=["알바"])
    async def 알바하자(self, ctx):
        author_id = str(ctx.author.id)
        currenttime = time.strftime('%Y%m%d')
        with open(f'stock/usr_data.json', 'r') as f:
            money = json.load(f)
        try:
            if money[author_id]['alba'] is None:
                pass
            elif int(currenttime) == int(money[author_id]['alba']):
                await ctx.send("알바는 하루에 1번만 가능합니다.")
                return
            money_choices = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8590]
            got_money = random.choice(money_choices)
            await ctx.send(f'돈이다. ({got_money}원)')
            money[author_id]['money'] += got_money
            money[author_id]['alba'] = currenttime
            with open(f'stock/usr_data.json', 'w') as s:
                json.dump(money, s, indent=4)
        except KeyError:
            await ctx.send('계정을 먼저 생성해주세요.')
            return

    @commands.command()
    async def 가즈아(self, ctx, amount):
        amount = int(amount)
        author_id = str(ctx.author.id)
        if amount <= 0:
            await ctx.send('1원 이상으로 입력해주세요.')
            return
        with open(f'stock/usr_data.json', 'r') as f:
            money = json.load(f)
        try:
            if amount > money[author_id]['money']:
                await ctx.send('돈이 부족합니다.')
                return
            money[author_id]['money'] -= amount
            amolang = ['yes', 'no', 'no']
            result = random.choice(amolang)
            if result == 'yes':
                await ctx.send('도박에 성공했습니다. 3배의 돈을 벌었습니다.')
                money[author_id]['money'] += amount * 4
            else:
                await ctx.send('도박에 실패했습니다. 돈을 잃었습니다.')
            with open(f'stock/usr_data.json', 'w') as s:
                json.dump(money, s, indent=4)
        except KeyError:
            await ctx.send('계정을 먼저 생성해주세요.')
            return

    @commands.command()
    async def 한강가즈아(self, ctx):
        author_id = str(ctx.author.id)
        try:
            with open(f'stock/usr_data.json', 'r') as f:
                money = json.load(f)
            del money[author_id]
            with open(f'stock/usr_data.json', 'w') as f:
                json.dump(money, f, indent=4)
        except KeyError:
            await ctx.send('계정을 먼저 생성해주세요.')
            return
        await ctx.send('당신은 한강에서 사망하셨습니다. 계정이 삭제되었습니다.')

    @commands.command()
    async def 가위바위보(self, ctx):
        user_id = str(ctx.author.id)
        with open("stock/usr_data.json", 'r') as f:
            user_data = json.load(f)  # 유저 데이터 불러오는 코드
        await ctx.send("`가위, 바위, 보` 중에서 하나를 5초 안에 말해주세요!")
        try:
            a = user_data[user_id]
        except KeyError:
            await ctx.send('계정을 먼저 생성해주세요.')
            return

        rpc = ['가위', '바위', '보']

        def check(m):
            return m.content == "가위" or m.content == "바위" or m.content == "보"

        def game(A, B):
            if A not in rpc:
                return
            if A == rpc[0] and B == rpc[2] or A == rpc[1] and B == rpc[0] or A == rpc[2] and B == rpc[1]:
                return 1
            elif A == B:
                return 2
            elif A == rpc[0] and B == rpc[1] or A == rpc[1] and B == rpc[2] or A == rpc[2] and B == rpc[0]:
                return 3

        try:
            answer = await self.client.wait_for("message", timeout=5, check=check)
        except asyncio.TimeoutError:
            await ctx.send("시간이 초과됬어요...")
            return

        choice = random.choice(rpc)
        result = game(answer.content, choice)
        if result == 1:
            await ctx.send(f"{ctx.author.mention}님이 이겼어요... ({answer.content}, {choice})\n`+100원`")
            user_data[user_id]["money"] += 100
        elif result == 3:
            await ctx.send(f"제가 이겼어요! ({answer.content}, {choice})")
        elif result == 2:
            await ctx.send(f"비겼네요. ({answer.content}, {choice})\n`+50원`")
            user_data[user_id]["money"] += 50
        with open("stock/usr_data.json", 'w') as f:
            json.dump(user_data, f, indent=4)

def setup(client):
    client.add_cog(Stock(client))


import holoviews as hv
import panel as pn
import datetime as dt
import matplotlib as plt
hv.extension("bokeh")

import pytest
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import geopandas
import geoviews as gv
from cartopy import crs
import panel as pn
import datetime as dt
import holoviews as hv
import jupyter_bokeh
gv.extension('bokeh')

def stacked_plot_damages(df):
    """
    Prepares dataframe to be used as a stacked bar plot for damages incurred over time.

    **:df: pd.DataFrame**
        The natural disaster dataframe

    **Returns: pd.DataFrame**
        Prepared dataframe to be used for stacked bar plot.
    """
    assert isinstance(df, pd.DataFrame) #df should be a pandas dataframe

    df = df.loc[:,['Year','Disaster Type','Total Damages (\'000 US$)']]
    #selecting all rows but only columns containing Year, Disaster Type and Total Damages

    df = df.fillna(0)
    new_df=df.pivot_table(index=['Year'],
                          columns='Disaster Type',
                          values='Total Damages (\'000 US$)',
                          aggfunc='sum').reset_index().rename_axis(None, axis=1)
    #pivoting the table and accumulating the sum of the total damages incurred for each disaster.
    #also resetting the index to be the year

    new_df = new_df.fillna(0)
    new_df = new_df[new_df["Year"] >= 1970]

    return new_df

def stacked_plot_occurences(df):
    """
    Prepares dataframe to be used as a stacked bar plot for disaster occurances over time.

    **:df: pd.DataFrame**
        The natural disaster dataframe

    **Returns: pd.DataFrame**
        Prepared dataframe to be used for stacked bar plot.
    """
    assert isinstance(df, pd.DataFrame)
    #df should be a pandas dataframe

    new_df = df[(df['Year'] >= 1970) & (df['Year'] <= 2020)]
    new_df = new_df.groupby(['Disaster Type','Year']).size().reset_index(name="Count")

    new_df['id'] = np.divmod(np.arange(len(new_df)), 10)[0] + 1

    new_df = new_df.set_index(['id', 'Disaster Type', 'Year']).unstack('Disaster Type') # similar to pivot
    new_df.columns = [x[1] for x in new_df.columns] # replace the MultiIndex column names if you don't need them

    new_df.reset_index(inplace=True)
    # Now you're back in the format you needed originally, with `Class` as a column and each row as a point in space

    new_df = new_df.fillna(0)
    new_df=new_df.drop('id', axis=1)
    new_df=new_df.groupby('Year', as_index=False).agg(lambda x: x.sum())

    new_df = new_df[new_df["Year"] >= 1970]
    return new_df

def stacked_plot_deaths(df):
    """
    Prepares dataframe to be used as a stacked bar plot for deaths ocurred over time.

    **:df: pd.DataFrame**
        The natural disaster dataframe

    **Returns: pd.DataFrame**
        Prepared dataframe to be used for stacked bar plot.
    """
    assert isinstance(df, pd.DataFrame)
    #df should be a pandas dataframe

    df = df.loc[:,['Year','Disaster Type','Total Deaths']]
    df = df.fillna(0)

    df['Total'] = df.groupby(['Year', 'Disaster Type'])['Total Deaths'].transform('sum')
    #making a column Total which adds the total deaths for each disaster type

    new_df = df.drop_duplicates(subset=['Year', 'Disaster Type'])

    new_df=new_df.pivot_table(index=['Year'],
                      columns='Disaster Type',
                      values='Total',
                      aggfunc='sum').reset_index().rename_axis(None, axis=1)
    #pivoting the table to have columns as disaster type name

    new_df = new_df[new_df["Year"] >= 1970]
    return new_df

def dis_analysis(df,voila=True):
    """
    Does natural disaster trends analysis using Holoviews Dynamic Map.

    **:df: pd.DataFrame**
        The natural disaster dataframe.

    **:voila: bool**
        Use to return plot that is visible in a notebook

    **Returns: ipywidget.widget**
        a widget incorporating panel controlling parameters and a holoviews dynamic map

    """
    assert isinstance(df, pd.DataFrame)

    colors = plt.cm.Spectral(np.linspace(0, 1, 9))[::-1]

    def make_bar_stacked(barType,):
        """
        barType: list
        Constructs holoviews bar natural for disaster trends analysis using Holoviews
        """

        values=list(set(df['Disaster Type'].value_counts().index)-set(['Animal accident', 'Insect infestation', 'Mass movement (dry)', 'Fog','Glacial lake outburst']))
        if barType=="Total Deaths":
            df_stacked_bar_melt=stacked_plot_deaths(df).melt(id_vars=['Year'], value_vars=values)
            bar_stacked= hv.Bars(df_stacked_bar_melt, kdims=["Year", "variable"], vdims=["value"])
            bar_stacked.opts(width=700, xlabel="year", title="Stacked chart for analysis", color="species", cmap="Category20", legend_position='right',stacked=True)
            return bar_stacked
        elif barType=="Total Damages ('000 US$)":
            values=list(set(df['Disaster Type'].value_counts().index)-set(['Animal accident', 'Insect infestation', 'Mass movement (dry)', 'Fog','Glacial lake outburst']))
            df_stacked_bar_melt=stacked_plot_damages(df).melt(id_vars=['Year'], value_vars=values)
            bar_stacked= hv.Bars(df_stacked_bar_melt, kdims=["Year", "variable"], vdims=["value"])
            bar_stacked.opts(width=700, xlabel="year", title="Stacked chart for analysis", color="species", cmap="Category20", legend_position='right',stacked=True)
            return bar_stacked
        elif barType=="Disaster Occurence":
            values=list(set(df['Disaster Type'].value_counts().index)-set(['Animal accident', 'Insect infestation', 'Mass movement (dry)', 'Fog', 'Glacial lake outburst']))
            df_stacked_bar_melt=stacked_plot_occurences(df).melt(id_vars=['Year'], value_vars=values)
            bar_stacked= hv.Bars(df_stacked_bar_melt, kdims=["Year", "variable"], vdims=["value"])
            bar_stacked.opts(width=700, xlabel="year", title="Stacked chart for analysis", color="species", cmap="Category20", legend_position='right',stacked=True)
            return bar_stacked
    scale = 3/2
    width=int(300*scale)*2
    height=int(250*scale)

    barTypes=['Disaster Occurence','Total Deaths', "Total Damages ('000 US$)"]
    select_damage = pn.widgets.Select(options=barTypes, name='Damage Type')
    dmap = hv.DynamicMap(pn.bind(make_bar_stacked,barType=select_damage.param.value))
    dmap = dmap.redim.values(Bar_Type = barTypes)

    dmap.opts(framewise=True)
    dmap.opts(height=height, width=width, line_width=1.0, tools=['hover'], xrotation=70)
    description = pn.pane.Markdown('''
    ## What type of disasters are most common?

    We can also take a closer look at how often different types of disasters occur over a certain time period. Knowing the historical distribution of disaster
    data can help us prepare in the long-term; as the frequency of natural disasters increase year after year, we rely on donators now more than ever to assist
    us in helping tragedy-stricken communities rebuild after disaster strikes. Try filtering the data by the number of disaster occurrences, deaths, or
    economic damage incurred. Steadily, the monetary damage to communities increases over time - your donations help rebuild these areas faster.
    ''')
    final_module = pn.Column(description,pn.Row(select_damage),dmap)
    if voila:
        return pn.ipywidget(final_module)
    else:
        return final_module


from conans import ConanFile, CMake, tools, python_requires
import os
import os.path as osp
import glob

tc = python_requires("tc/0.3.0@tc/stable")
opts = tc.OptCreator().add_bool("shared", True).add_bool("fPIC", True)

class CppServerConan(ConanFile, tc.SourceHelper, tc.CmakeHelper, tc.ComponentHelper):
    name = "cppserver"
    license = "MIT"
    exports_sources = ["CMakeLists.txt"]
    generators = tc.CmakeHelper.generators
    settings = tc.CmakeHelper.settings
    options, default_options = opts.options, opts.default

    scm = {
        "type": "git",
        "subfolder": "source_subfolder",
        "url": "https://github.com/rozkalibrowany/CppServer.git",
        "revision": "master",
    }

    def build(self):
        os.chdir(self._source_subfolder)
        self.run("gil update")
        return self.do_build()

    def package(self):
        inc_dir = osp.join(self._source_subfolder, "include")
        common_dir = osp.join(self._source_subfolder, "modules", "CppCommon", "include")
        self.copy("*.h*", dst="include", src=inc_dir)
        self.copy("*.h*", dst="include", src=common_dir)
        self.copy("*.inl", dst="include", src=common_dir)
        self.copy("*.inl", dst="include", src=inc_dir)
        self.copy("*.so", dst="lib", src=osp.join(self._build_subfolder, "lib"))

    def package_info(self):
        self.add_components(
            [
                {
                    "target": "lib",
                    "libs": ["fmt"],
                },
                {
                    "target": "lib",
                    "libs": ["cppserver"],
                },

            ]
        )
        #libdir_c = os.path.join(os.path.join(self.package_folder, "lib"), "cmake")
        #self.output.info("Appending PATH environment variable: {}".format(libdir_c))
        #self.env_info.PATH.append(libdir_c)


from django.urls import path, include
from rest_framework.routers import DefaultRouter

from client import views

router = DefaultRouter()
router.register('company', views.CompanyViewSet)        # Company API URL - /api/client/company/
router.register('logs', views.LogViewSet)                # Log API URL     - /api/client/logs/
router.register('clients', views.ClientViewSet)          # Client API URL  - /api/client/clients/

app_name = 'client'

urlpatterns = [
    path('', include(router.urls))
]


#! /usr/bin/env python3

import os, hashlib, time, datetime

def timestamp():
    now = datetime.datetime.now()
    timestamp = now.strftime("%m-%d-%y %H:%M:%S:%f")
    return str(timestamp)

def hash_it(datapath):
    md5_hash = hashlib.md5()
    with open(datapath,"rb") as f:
        # Read and update hash in chunks of 4K
        for byte_block in iter(lambda: f.read(4096),b""):
            md5_hash.update(byte_block)
        print(md5_hash.hexdigest())

def linux():
    filepath = input("Input absolute directory path: \n")
    for root, dirs, files in os.walk(filepath):
    # For each hit, concatenate the current directory pathing to left of result
        for name in files:
            datapath = (os.path.join(root, name))
            time = timestamp()
            print(time)
            hash = hash_it(datapath)
            apikey = os.getenv('API_KEY_VIRUSTOTAL') # Set your environment variable before proceeding. You'll need a free API key from virustotal.com so get signed up there first.

            query = 'python3 virustotal-search.py -k ' + apikey + ' -m ' + hash

os.system(query)

linux()


from pyspark.sql.functions import col
import pyspark.sql.functions as F
from pyspark.sql.types import *
from pyspark.sql.functions import udf
spark.sparkContext.setLogLevel("WARN")

Logger= spark._jvm.org.apache.log4j.Logger
mylogger = Logger.getLogger("DAG")

def check(path, table):
    df = spark.read.parquet(path).filter("i94_dt = '{}'".format(month_year))
    if len(df.columns) > 0 and df.count() > 0:
        mylogger.warn("{} SUCCESS".format(table))
    else:
        mylogger.warn("{} FAIL".format(table))

check("s3a://de-capstone/lake/immigrant/", "immigrant")
check("s3a://de-capstone/lake/immigration/", "immigration")
check("s3a://de-capstone/lake/immigration_demographic/", "immigration_demographic")


from enum import Enum

class LabelType(Enum):
    """Тип элемента в области видимости."""
    FUNC = "function"
    VAR = "variable"

class Label:
    """Класс, описывающий элемент области видимости."""
    def __init__(self, label_type: LabelType, name, val):
        self.label_type = label_type
        self.name = name
        self.val = val

class Scope:
    """Класс, описывающий область видимости."""
    def __init__(self, prev_scope):
        self._labels = []
        self.children_scopes = []
        self.prev_scope = prev_scope

    def add_label(self, label: Label, loc):
        """Этот метод добавляет функцию или переменную."""
        label_names = [lbl.name for lbl in self._labels]
        # Если эл-т не существует в области видимости, мы его добавляем в неё
        if label.name not in label_names:
            self._labels.append(label)
            return True
        else:
            # В противном случае мы проверяем, не существует ли функции с таким же именем.
            index = label_names.index(label)
            if label.label_type is LabelType.FUNC or self._labels[index].label_type is LabelType.FUNC:
                # Если она существует, выводим ошибку.
                raise SemanticException("Объект с именем {} уже существует.".format(label.name), loc[0], loc[1])
            else:
                # Если существует переменная с таким же именем, мы переопределяем её значение.
                self._labels[index] = label

    def get_label(self, name, loc):
        """Метод, возвращающий переменную из текущей области видимости или из её родительской области видимости."""
        result = [lbl for lbl in self._labels if lbl.name == name]
        if len(result) > 0:
            # Если переменная или функция с таким именем существует, возвращаем её.
            return result[0]
        else:
            if self.prev_scope is not None:
                # Если она не существует в текущей области видимости, ищем её в родительской области видимости.
                return self.prev_scope.get_label(name, loc)
            else:
                # Если такой переменной или функции нет, то выводим ошибку.
                raise SemanticException("Объекта с именем {} не существует. ".format(name), loc[0], loc[1])

class SemanticException(Exception):
    """Исключения в семантическом анализе."""
    def __init__(self, message, row: int = None, col: int = None) -> None:
        if row or col:
            message += " ("
            if row:
                message += "строка: {}".format(row)
                if col:
                    message += ", "
            if row:
                message += "символ: {}".format(col)
            message += ")"
        self.message = message


"""
    Excercise 3: Prime numbers

    Additional exercise: Primzahlensatz
"""

import numpy as np
import matplotlib.pyplot as plt
from woche3 import eratosthenes, loop_invariant

if __name__ == '__main__':
    number_of_primes = 10000

    print("\nCalculate primes using Eratosthenes...")
    primes = np.array(eratosthenes(number_of_primes))

    # print("\nCalculate primes using loop invariants...")
    # primes = np.array(loop_invariant(number_of_primes))

    print("Highest prime found: {prime}".format(prime=primes[-1]))

    # Calculate log of primes
    log_p = np.log(primes)

    # Calculate ratio between primes and their log
    ratio = primes / log_p

    # Normalize ratio by k
    prime_range_k = np.array(range(1, number_of_primes + 2))
    ratio_normalized = ratio / prime_range_k

    # Plot ratio
    plt.title("Primzahlensatz")
    plt.xlabel("k")
    plt.ylabel("P_k/(k*log(P_k))")
    plt.plot(prime_range_k, ratio_normalized, '-')
    plt.ylim([.75, 1.25])
    plt.savefig('primzahlensatz.pdf')
    plt.show()


from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))

actions = ActionChains(driver)

driver.get("https://jqueryui.com/resources/demos/slider/default.html")
driver.maximize_window()
driver.implicitly_wait(1)

slider = driver.find_element(By.XPATH, "//*[@id=\"slider\"]/span")

MainSlider = driver.find_element(By.ID, "slider")

location = MainSlider.location
size = MainSlider.size

w,h = size['width'], size['height']
print(location)
print(size)
print(w,h)

ActionChains(driver).drag_and_drop_by_offset(slider, w/2, 0).perform()

time.sleep(50)

driver.quit()


import json

from django.contrib.staticfiles import finders
from django.http import HttpResponse, HttpResponseNotFound

import weasyprint

from .models import Event, ObjectBiographyPage, SourcePage

def bio_timeline(request, bio_id):
    """Returns the timeline data for the ObjectBiography with `bio_id` in
    JSON format."""
    events = Event.objects.filter(biographies__biography__id=bio_id)
    return timeline(events)

def biography_pdf(request, bio_id):
    try:
        bio = ObjectBiographyPage.objects.live().get(pk=bio_id)
    except ObjectBiographyPage.DoesNotExist:
        return HttpResponseNotFound()
    html = weasyprint.HTML(url=bio.full_url)
    return _generate_pdf(html, bio.slug)

def full_timeline(request):
    biographies = ObjectBiographyPage.objects.live()
    events = Event.objects.filter(biographies__biography__id__in=biographies)
    return timeline(events)

def _generate_pdf(html, filename):
    css = weasyprint.CSS(filename=finders.find('scss/pdf.css'))
    doc = html.render(stylesheets=[css])
    response = HttpResponse(doc.write_pdf(), content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="{}.pdf"'.format(
        filename)
    return response

def source_pdf(request, source_id):
    try:
        source = SourcePage.objects.live().get(pk=source_id)
    except SourcePage.DoesNotExist:
        return HttpResponseNotFound()
    html = weasyprint.HTML(url=source.full_url)
    return _generate_pdf(html, source.slug)

def timeline(events):
    data = {'events': []}
    for event in events:
        data['events'].append(event.get_event_data())
    return HttpResponse(json.dumps(data), content_type='application/json')


# -*- encoding: utf-8 -*-
from ..component_utils import dateformat
from datetime import datetime, timedelta

class TableInvoices:
    def __init__(self):
        pass

    def get_origen_lectura(self, cursor, uid, lectura):
        """Busquem l'origen de la lectura cercant-la a les lectures de facturació"""
        res = {lectura.data_actual: '',
            lectura.data_anterior: ''}

        lectura_obj = lectura.pool.get('giscedata.lectures.lectura')
        tarifa_obj = lectura.pool.get('giscedata.polissa.tarifa')
        origen_obj = lectura.pool.get('giscedata.lectures.origen')
        origen_comer_obj = lectura.pool.get('giscedata.lectures.origen_comer')

        estimada_id = origen_obj.search(cursor, uid, [('codi', '=', '40')])[0]
        sin_lectura_id = origen_obj.search(cursor, uid, [('codi', '=', '99')])[0]
        estimada_som_id = origen_comer_obj.search(cursor, uid, [('codi', '=', 'ES')])[0]
        calculada_som_id = origen_obj.search(cursor, uid, [('codi', '=', 'LC')])
        calculada_som_id = calculada_som_id[0] if calculada_som_id else None

        #Busquem la tarifa
        tarifa_id = tarifa_obj.search(cursor, uid, [('name', '=', lectura.name[:-5])])
        if tarifa_id:
            tipus = lectura.tipus == 'activa' and 'A' or 'R'

            search_vals = [('comptador', '=', lectura.comptador),
                        ('periode.name', '=', lectura.name[-3:-1]),
                        ('periode.tarifa', '=', tarifa_id[0]),
                        ('tipus', '=', tipus),
                        ('name', 'in', [lectura.data_actual,
                                        lectura.data_anterior])]
            lect_ids = lectura_obj.search(cursor, uid, search_vals)
            lect_vals = lectura_obj.read(cursor, uid, lect_ids,
                                        ['name', 'origen_comer_id', 'origen_id'])
            for lect in lect_vals:
                # En funció dels origens, escrivim el text
                # Si Estimada (40) o Sin Lectura (99) i Estimada (ES): Estimada Somenergia
                # Si Estimada (40) o Sin Lectura (99) i F1/Q1/etc...(!ES): Estimada distribuïdora
                # La resta: Real
                origen_txt = "real"
                if lect['origen_id'][0] in [ estimada_id, sin_lectura_id ]:
                    if lect['origen_comer_id'][0] == estimada_som_id:
                        origen_txt = "calculada per Som Energia"
                    else:
                        origen_txt = "estimada distribuïdora"
                if lect['origen_id'][0] == calculada_som_id:
                    origen_txt = "calculada segons CCH"
                res[lect['name']] = "%s" % (origen_txt)

        return res

    def get_data(self, cursor, uid, wiz, invoice_ids, context={}):
        result = {}
        result['type'] = 'TableInvoices'
        result['taula'] = []
        result['date_from'] = False
        result['date_to'] = False
        fact_obj = wiz.pool.get('giscedata.facturacio.factura')
        for invoice_id in invoice_ids:
            invoice = fact_obj.browse(cursor, uid, invoice_id)
            if invoice.type in ('out_invoice', 'out_refund') and invoice.state in ('paid', 'open'):
                linia_taula = {}
                linia_taula['invoice_number'] = invoice.number
                linia_taula['date'] = dateformat(invoice.date_invoice)
                linia_taula['date_from'] = dateformat(invoice.data_inici)
                if invoice.data_inici:
                    if not result['date_from'] or datetime.strptime(invoice.data_inici,'%Y-%m-%d') < datetime.strptime(result['date_from'],'%d-%m-%Y'):
                        result['date_from'] = dateformat(invoice.data_inici)
                linia_taula['date_to'] = dateformat(invoice.data_final)
                if invoice.data_final:
                    if not result['date_to'] or  datetime.strptime(invoice.data_final,'%Y-%m-%d') > datetime.strptime(result['date_to'],'%d-%m-%Y'):
                        result['date_to'] = dateformat(invoice.data_final)
                linia_taula['max_power'] = invoice.potencia_max or 0
                linia_taula['invoiced_energy'] = invoice.energia_kwh or 0
                linia_taula['exported_energy'] = invoice.generacio_kwh or 0
                linia_taula['origin'] = self.get_invoice_origin(cursor, uid, invoice)
                linia_taula['invoiced_days'] = invoice.dies or 0
                linia_taula['total'] = invoice.signed_amount_total
                result['taula'].append(linia_taula)
        return result

    def get_invoice_origin(self, cursor, uid, invoice):
        readings = {}
        lectures = invoice.lectures_energia_ids
        if lectures != None:
            for lectura in lectures:
                origens = self.get_origen_lectura(cursor, uid,lectura)
                if '(P1)' in lectura.name:
                    data = str(datetime.strptime(lectura.data_anterior, '%Y-%m-%d').date() + timedelta(days=1))
                    origin = (u'estimada')
                    if origens[lectura.data_anterior] == 'real' and origens[lectura.data_actual] =='real':
                        origin = (u'real')
                    elif (origens[lectura.data_anterior] == 'estimada distribuïdora' or origens[lectura.data_anterior] == 'real') and origens[lectura.data_actual] == 'calculada segons CCH':
                        origin = (u'calculada')
                    elif origens[lectura.data_anterior] == 'calculada segons CCH' and (origens[lectura.data_actual] =='calculada segons CCH' or origens[lectura.data_actual] == 'real'):
                        origin = (u'calculada')

                    readings[data] = origin

            return readings[invoice.data_inici] if invoice.data_inici in readings else (u'sense lectura')


#!/usr/bin/env python

import argparse
import logging
import os
import shutil
import sys
import numpy as np
import time

import torch
import torch.nn as nn
import torch.optim as optim
from torch.distributions import MultivariateNormal
from torch.utils import tensorboard
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision.utils import save_image
from torchvision.transform import to_tensor
from torchvision.datasets import MNIST

################################################################################
# Utils
################################################################################
def setup_logger(name, save_dir, distributed_rank=0):
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    # don't log results for the non-master process
    if distributed_rank > 0:
        return logger
    ch = logging.StreamHandler(stream=sys.stdout)
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s")
    ch.setFormatter(formatter)
    logger.addHandler(ch)

    if save_dir:
        fh = logging.FileHandler(os.path.join(save_dir, "log.txt"))
        fh.setLevel(logging.DEBUG)
        fh.setFormatter(formatter)
        logger.addHandler(fh)

    return logger

def setup_exp(save_dir, exp_name, clean_run='False'):
    if not os.path.exists(save_dir):
        os.mkdir(save_dir)
    runs_dir = os.path.join(save_dir, 'runs', exp_name)
    chkpt_dir = os.path.join(save_dir, exp_name, 'chkpt')
    log_dir = os.path.join(save_dir, exp_name, 'logs')

    def mkdir(dir_name):
        print(dir_name)
        if not os.path.exists(dir_name):
            os.makedirs(dir_name)

    if clean_run:
        if os.path.exists(log_dir) or os.path.exists(chkpt_dir):
            shutil.rmtree(os.path.join(save_dir, exp_name))
        if os.path.exists(runs_dir):
            shutil.rmtree(runs_dir)
        time.sleep(5)
    mkdir(log_dir)
    mkdir(runs_dir)
    mkdir(chkpt_dir)

    return log_dir, runs_dir, chkpt_dir

################################################################################
# Model
################################################################################
class Model(nn.Module):
    def __init__(self, args):
        super(Model, self).__init__()
        self.enc_hid_sz = args.enc_hid_sz
        self.embed_sz = args.latent_sz

        self.enc_layer1 = nn.Linear(args.input_sz, 256)
        self.enc_layer2 = nn.Linear(256, 128)
        self.enc_layer3 = nn.Linear(128, 64)
        self.enc_layer_mu = nn.Linear(64, 20)
        self.enc_layer_var = nn.Linear(64, self.embed_sz)

        self.dec_layer1 = nn.Linear(self.embed_sz, 28)
        self.dec_layer2 = nn.Linear(28, 64)
        self.dec_layer3 = nn.Linear(64, 128)
        self.dec_layer4 = nn.Linear(128, 256)
        self.dec_layer_out = nn.Linear(256, args.input_sz)

    def enc_forward(self, x):
        x = nn.functional.relu(self.enc_layer1(x))
        x = nn.functional.relu(self.enc_layer2(x))
        x = nn.functional.relu(self.enc_layer3(x))
        mu = self.enc_layer_mu(x)
        logvar = self.enc_layer_var(x)
        return mu, logvar

    def sample(self, mu, logvar):
        eps = torch.randn(logvar.shape).to(logvar.device)
        return mu + eps * logvar

    def dec_forward(self, z):
        z = nn.functional.relu(self.dec_layer1(z))
        z = nn.functional.relu(self.dec_layer2(z))
        z = nn.functional.relu(self.dec_layer3(z))
        z = nn.functional.relu(self.dec_layer4(z))
        return nn.functional.sigmoid(self.dec_layer_out(z))

    def forward(self, x):
        mu, logvar = self.enc_forward(x)
        z = self.sample(mu, logvar)
        x_prime = self.dec_forward(z)
        return mu, logvar, z, x_prime

################################################################################
# Dataloader
################################################################################
def get_loader(args, train):
    # transform_fnc = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
    transform_fnc = transforms.Compose([transforms.ToTensor()])
    if train:
        loader = DataLoader(MNIST('./.torch/data', train=True, download=True, transform=transform_fnc),
                            batch_size=args.batch_size, shuffle=True)
    else:
        loader = DataLoader(MNIST('./.torch/data', train=False, download=True, transform=transform_fnc),
                            batch_size=args.batch_size, shuffle=True)

    return loader

################################################################################
# Trainer
################################################################################
def kl_criterion(mu, logvar, reduce=None):
    kl_loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp(), 1)
    return torch.mean(kl_loss)

def visualize(x, writer, writer_idx, args):
    img = x.view((-1,) + args.img_shape)
    img = torch.unsqueeze(img[:, :], 1)
    writer.add_images('Recon Output', img, writer_idx, dataformats='NCHW')

def latent_visualize(model, writer, writer_ix, args):
    a = torch.arange(0, 1, 10)
    b = torch.arange(0, 1, 10)
    res = torch.zeros(100, 28, 28)
    for i in range(0, 10):
        for j in range(0, 10):
            z = [i, j]
            res[i*10 + j] = model.dec_forward((z))

def train(args, model, loader, logger, writer, device):
    model.train()
    model = model.to(device)
    batch_size = args.batch_size
    num_batches = args.num_samples // batch_size
    optimizer = optim.Adam(params=model.parameters(), lr=args.lr)
    num_epochs = args.num_epochs
    # cls_criterion = nn.functional.binary_cross_entropy (reduction='mean')
    kl_factor = 1.0
    train_loader, test_loader = loader
    writer_idx = 0
    for eid in range(num_epochs):
        for bid, data in enumerate(train_loader):
            x, y = data
            x = x.view(min(x.shape[0], args.batch_size), -1).to(device)
            y = y.to(device)
            mu, logvar , z, x_prime = model.forward(x)
            kl_loss = kl_criterion(mu, logvar)
            # Important See the defination of bce loss at https://pytorch.org/docs/stable/nn.html#loss-functions
            cls_loss = torch.mean(torch.sum(nn.functional.binary_cross_entropy(x_prime.view(x.shape[0], -1), x.view(x.shape[0], -1), reduction='none'), 1))
            loss = cls_loss + kl_factor * kl_loss
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            if bid % args.log_freq == 0:
                writer_idx += 1
                logger.info(f'Writer Idx:{writer_idx%args.log_freq}, Epoch Idx:{eid}, cls_loss: {cls_loss}, kl_loss: {kl_loss}, Loss: {kl_factor * kl_loss + cls_loss}')
                writer.add_scalar('kl_loss', kl_loss, writer_idx)
                writer.add_scalar('cls_loss', cls_loss, writer_idx)
                writer.add_scalar('kl_factor', kl_factor, writer_idx)
                visualize(x_prime, writer, writer_idx, args)
        test(args, model, test_loader, logger, writer, device, eid, kl_factor)
        sample = torch.randn(64, args.latent_sz).to(device)
        res = model.dec_forward(sample)
        img = res.view((-1,) + args.img_shape)
        img = torch.unsqueeze(img[:, :], 1)
        save_image(img, 'final_ouput.png')
        writer.add_images('Final Output', img, eid, dataformats='NCHW')
        kl_factor = 1.0 / (1+np.exp(-eid+3))

def test(args, model, test_loader, logger, writer, device, eid, kl_factor):
    model.eval()
    model = model.to(device)
    batch_size = args.batch_size
    num_batches = args.test_num_samples // batch_size
    cls_criterion = nn.BCEWithLogitsLoss()
    for bid, data in enumerate(test_loader):
        writer_idx = bid * batch_size + (eid * num_batches * batch_size)
        x, y = data
        x = x.view(min(args.batch_size, x.shape[0]), -1).to(device)
        y = y.to(device)
        mu, logvar, z, x_prime = model.forward(x)
        kl_loss = kl_criterion(mu, logvar, reduce='mean')
        cls_loss = cls_criterion(x_prime, x)
        loss = cls_loss + kl_factor * kl_loss

    logger.info(f'Epoch: {eid}, Test Loss: {loss}')
    writer.add_scalar('test_kl_loss', kl_loss, writer_idx)
    writer.add_scalar('test_cls_loss', cls_loss, writer_idx)

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--save_dir', help='Save Directory', default='./variational', type=str)
    parser.add_argument('--clean_run', help='Start From scratch', default=True, type=bool)
    parser.add_argument('--exp_name', help='Exp Name', default='default', type=str)
    parser.add_argument('--batch_size', help='Batch Size', default=64, type=int)
    parser.add_argument('--num_epochs', help='Number of Epochs', default=100, type=int)
    parser.add_argument('--num_samples', help='Number of samples to use', default=-1, type=int)
    parser.add_argument('--lr', help='learning rate', default=1e-4, type=float)
    parser.add_argument('--device_id', help='Device number', default=-1, type=int)
    parser.add_argument('--enc_hid_sz', help='Encoder Hidden Size', default=100, type=int)
    parser.add_argument('--latent_sz', help='Latent Embedding Size', default=20, type=int)
    parser.add_argument('--log_freq', help='Logging Frequency', default=100, type=int)
    parser.add_argument('--img_shape', help='Image Shape', default=(28, 28), type=tuple)
    parser.add_argument('--input_sz', help='Input Size', default=784, type=int)

    args = parser.parse_args()
    device = 'cuda:1' if torch.cuda.is_available() else 'cpu'
    log_dir, runs_dir, chkpt_dir = setup_exp(args.save_dir, args.exp_name, args.clean_run)
    writer = tensorboard.SummaryWriter(runs_dir)
    logger = setup_logger(args.exp_name, log_dir)
    model = Model(args)
    train_loader = get_loader(args, train=True)
    test_loader = get_loader(args, train=False)
    if args.num_samples == -1:
        args.num_samples = len(train_loader.dataset)
        args.test_num_samples = len(test_loader.dataset)
    train(args, model, [train_loader, test_loader], logger, writer, device)

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from flask import Flask, request, jsonify
from flask_basicauth import BasicAuth
import os
import pickle

#criar app
app = Flask(__name__)

app.config['BASIC_AUTH_USERNAME'] = os.environ.get('BASIC_AUTH_USERNAME')
app.config['BASIC_AUTH_PASSWORD'] = os.environ.get('BASIC_AUTH_PASSWORD')

basic_auth = BasicAuth(app)

#movies
movies = pd.read_csv("movies.csv")
#coluna de dados
colunas = ['filmeId', 'nota_media', 'Drama', 'Documentary', 'Romance', 'Action',
       'Adventure', 'IMAX', 'Horror', 'War', 'Musical', 'Sci-Fi', 'Fantasy',
       'Animation', 'Film-Noir', 'Crime', 'Mystery', 'Children', 'Comedy',
       'Western', 'Thriller']

#colunas = ['id','filmeId']

def load_model( file_name = 'decision_tree.pkl'):
    return pickle.load(open(file_name, "rb"))

modelo = load_model('decision_tree.pkl')

@app.route('/reco/<id>')
def show_id(id):
    return f'Recebendo dados \n ID: {id}'

@app.route('/reco/', methods=['POST'])
@basic_auth.required
def get_recomendations():

    dados = request.get_json()
    playload = np.array([dados[col] for col in colunas])

    playload = playload.reshape(1, -1)
    score = np.float(modelo.predict(playload))
    score = int(score)
    if(score):
        return f'O filme que recomendamos para você é {movies.iloc[score][1]}'

    else:
        return 'nada aqui'

@app.route('/')
def home():
    return 'API de predição de filmes'

app.run(debug=True)


# printing data summary
OUTPUT = """  Financial Analysis
  ----------------------------
  Total Months: %i
  Total: $%i
  Average  Change: $%i
  Greatest Increase in Profits: %s ($%i)
  Greatest Decrease in Profits: %s ($%i)
"""
#print(OUTPUT)
import os
import csv

def return_average_change(list):
  length = len(list)
  total_months_sum = 0
  for i in list:
    total_months_sum += i
  average_change = total_months_sum/length
  average_change = round(average_change,2)
  return average_change

# The total number of months included in the dataset
total_months = 0

# The total net amount of "Profit/Losses" over the entire period
total_profit_loss = 0

# The average change in "Profit/Losses" between months over the entire period
# sum of months_changes/total month = avg change
average_change = 0

change_list = []
last = 0
#Create a loop to find the diff b/t each months
# The greatest increase in profits (date and amount) over the entire period
greatest_increase = 0

# The greatest decrease in losses (date and amount) over the entire period
greatest_decrease = 0

file_path = os.path.join('budget_data.csv')

with open(file_path, 'r') as file_object:
  budget_data = csv.reader(file_object)

  for row in budget_data:
    num = int(row[1])
    total_months = total_months + 1
    total_profit_loss = total_profit_loss + num
    # find the diff b/t each months

    if (last == 0):
      last = num
    else:
      current = num
      months_change = current - last
      change_list.append(months_change)
      last = current

  total_months_change = sum(change_list)
  average_change = return_average_change(change_list)
  greatest_increase = max(change_list)
  greatest_decrease = min(change_list)

  print(file_object)
  print(f"Total Months: {total_months}")
  print(f"Total: ${total_profit_loss}")
  print(f"Average Change: ${average_change}")
  print(f"Greatest Increase in Profits:  ${greatest_increase}")
  print(f"Greatest Decrease in Profits:  ${greatest_decrease}")
  # print(f"total_months_change:${total_months_change}")
  # print(change_list)

output = (
  "Financial Analysis\n"
  "---------------------------"
  f"Total Months: {total_months}\n"
  f"Total: ${total_profit_loss}\n"
  f"Average Change: ${average_change}\n"
  f"Greatest Increase in Profits: ${greatest_increase}\n"
  f"Greatest Decrease in Profits: ${greatest_decrease}\n"
  # f"total_months_change:${total_months_change}\n"
)

output_file = "sample.txt"

with open(output_file, 'w') as txt_file:
  txt_file.write(output)

# for x in range(0,51):
#   if x % 10 == 0:
#     print(x)

# list = [2, 4, 6 , 8, 11, 22, 34, 56, 78]
# list2 = [x+3 for x in list]
# print(list2)

# create empty list: lsit = []

# dict = {"name": "Bob",
#         "age": 50,
#        }

# dict = {}
# dict['name'] = "Bob"
# dict['age'] = 50

# for key, value in dict.items():
#   print(f"key: {key}, value: {value}")

''' total_profit_loss = 0
  greatest_increase = {'month': '', 'amount': 0}
  greatest_decrease = {'month': '', 'amount': 0}
  total_months = 0
  average_change = 0

  for line in f.readlines():
    date = line.split(',')[0]
    pl = int(line.split(',')[1])
    total_profit_loss = total_profit_loss + pl
    if pl > 0:
      if greatest_increase['amount'] < pl:
        greatest_increase = {'month': date, 'amount': pl}
    else:
      if greatest_decrease['amount'] > pl:
        greatest_decrease = {'month': date, 'amount': pl}
    total_months += 1

  print(f"{total_months}, {total_profit_loss}")

# putting data summary as a .txt file output
f = open('bank_data.txt','w')
f.write(OUTPUT)
f.close()

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