import discord
import time
import datetime
from discord import app_commands
import asyncio
from discord.ext import commands
from discord import Webhook
import requests
import pyshorteners as ps
import aiohttp
from dotenv import dotenv_values

# load the environment variables
env = dotenv_values()

# Will need to move this somewhere other than a source file in the future
TOKEN = env['DISCORD_TOKEN']
# may want to limit the intents in the future
intents = discord.Intents.all()
intents.members = True

# bot (subclass of the discord client class)
bot = commands.Bot(
    command_prefix='!',
    case_insensitive=True,
    intents=intents
)

client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)

# ensures the bot is working/connected
@bot.event
async def on_ready():
    print("Logged in as {0.user}".format(bot))
    try:
        synced = await bot.tree.sync()
        print(f"Synced {len(synced)} command(s)")
    except Exception as e:
        print(e)

@bot.event
async def on_member_join(member):
    # This function will be called when a new member joins the server
    # Sends the member a welcome message that mentions the server name and the member
    # Get the "get-verified" channel from the server and sends a reference to user DM
    get_verified_channel = discord.utils.get(member.guild.channels, name="get-verified")
    server_name = member.guild.name
    await member.send(f"""Hey, {member.mention}! Welcome to {server_name}! We are thrilled to have you here. To get started, please head to the server and click on the {get_verified_channel.mention} channel. Then type '/verify' to invoke this bot to help complete the verification process.\nAfter that, you'll be all set to embark on your Discord journey. If you have any questions or need assistance, don't hesitate to reach out to humanID at discord@human-id.org. Replies to this message do not reach humanID. Enjoy your time here!
""")

# /help command that gives a list of commands
@bot.tree.command(name="help")
async def hello(interaction: discord.Interaction):
    member = interaction.user
    get_verified_channel = discord.utils.get(member.guild.channels, name="get-verified")
    await interaction.response.send_message(f"""To get started, {member.mention}, please head to the server and click on the {get_verified_channel.mention} channel. Then type '/verify' to invoke this bot to help complete the verification process.\nAfter that, you'll be all set to embark on your Discord journey. If you have any questions or need assistance, don't hesitate to reach out to humanID at discord@human-id.org. Replies to this message do not reach humanID. Enjoy your time here!
""")

# When joining a server
# 1. automatically create the humanID-Verified role, get-verified channel, and logs channel
# 2. set the permissions for the humanID-Verified role
# 3. set the permissions for the get-verified channel
@bot.event
async def on_guild_join(guild):
    channels = discord.utils.get(guild.channels, name='get-verified')
    # Only create the channel if it does not exist
    if not channels:
        await guild.create_text_channel('get-verified')
    verification_channel = discord.utils.get(guild.channels, name='get-verified')
    log_channel = discord.utils.get(guild.channels, name='logs')
    if not log_channel:
        log_channel = await guild.create_text_channel('logs')
    await setupVerifiedRole(guild)
    # everyone_channels = []
    # for channel in guild.channels:
    #     # Check if the @everyone role has the "View Channel" permission
    #     if channel.permissions_for(guild.default_role).view_channel:
    #         everyone_channels.append(channel.name)
    # if everyone_channels:
    #     await verification_channel.send(f"Channels viewable by @everyone prior to installing humanID Discor Bot: {', '.join(everyone_channels)}")
    #     await verification_channel.send(f"These channels are now viewable by users with @humanID-Verified role through completing the /verify command.")
    # else:
    #     await verification_channel.send("There are no channels viewable by @everyone in this server.")
    # verified_role = discord.utils.get(guild.roles, name='humanID-Verified')
    # for channel_name in everyone_channels:
    #     if channel_name != 'get-verified':
    #         channel = discord.utils.get(guild.channels, name=channel_name)
    #         await channel.set_permissions(everyone, read_messages=False, send_messages=False)
    #         await channel.set_permissions(verified_role, read_messages=True, send_messages=True)

    overwrites = {
        guild.default_role: discord.PermissionOverwrite(
            view_channel=True,
            use_application_commands=True,
            change_nickname=True,
            send_messages=True
        )
    }
    await verification_channel.edit(overwrites=overwrites)

async def setupVerifiedRole(guild):
    # Getting the Verified Role
    verification_channel = discord.utils.get(guild.channels, name='get-verified')
    verified_role = discord.utils.get(guild.roles, name='humanID-Verified')
    if verified_role:
        await verification_channel.send('Pre-existing humanID-Verified Role Detected: Please make sure the humanID-Verified role is ranked under the humanID Verification bot Role.')
    else:
        await guild.create_role(name='humanID-Verified')
    verified_role = discord.utils.get(guild.roles, name='humanID-Verified')
    verified_role_permissions = verified_role.permissions
    verified_role_permissions.update(
        view_channel=True,
        change_nickname = True,
        send_messages=True,
        send_messages_in_threads=True,
        create_public_threads=True,
        embed_links=True,
        attach_files=True,
        add_reactions=True,
        use_external_emojis=True,
        read_message_history=True,
        use_application_commands=True
    )
    try:
    # Update the permissions for the @humanID-Verified role
        await verified_role.edit(permissions=verified_role_permissions)
    except discord.Forbidden:
    # If the bot lacks the "Manage Roles" permission or other issues occur, send a message in the channel.
        error_message = (
            f"Failed to update @Verfied role permissions. "
            f"Please ensure the @humanID-Verified role has appropriate permissions within the server."
        )
        await verification_channel.send(error_message)
    await verification_channel.send("""To gain full access to this Discord server, please enter '/verify' in the chat box to initiate the verification process. Rest assured, we do not retain any of your private information during this process. If you encounter any issue, please contact humanID at discord@human-id.org. Replies to this message do not reach humanID.
                                    """)

# test simple slash commandac
@bot.tree.command(name="hello")
async def hello(interaction: discord.Interaction):
    await interaction.response.send_message(f"Hey {interaction.user.mention}! This is a slash command!")

# Catches the /verify slash command
@bot.tree.command(name='verify')
async def verify(interaction: discord.Interaction):
    channels = discord.utils.get(interaction.guild.channels, name='logs')
    if not channels:
        channel = await interaction.guild.create_text_channel('logs')

    author = interaction.user
    serverId = str(interaction.guild.id)
    userId = str(author.id)

    if interaction.channel.name != 'get-verified':
        # message was not sent in the allowed channel
        channels = discord.utils.get(interaction.guild.channels, name='get-verified').id
        await interaction.response.send_message(
            'This command can only be used in the <#{}> channel.'.format(str(channels)),
            ephemeral=True
        )
        return

    BACKEND_URL = env["DISCORD_BACKEND_URL"]
    FRONTEND_URL = env["DISCORD_FRONTEND_URL"]
    response = requests.get(
        BACKEND_URL + '/api?serverId=' + serverId
    )
    if response.status_code == 400:
        await interaction.response.send_message(
            'This server does not have associated credentials. Please ask an admin to add this server from the humanID developer console.',
            ephemeral=True
        )
        return
    elif response.status_code == 403:
        await interaction.response.send_message(
            'Invalid credentials associated with this server.',
            ephemeral=True
        )
        return
    resJson = response.json()
    requestId = resJson['requestId']
    url = resJson['url']
    # Creates a db entry for the user to keep track of the link timeout
    requests.put(
        BACKEND_URL + '/api/start/?requestId={}&userId={}&serverId={}'.format(requestId, userId, serverId)
    )

    # hash id here TODO
    hashedId = userId;

    # Send the humanID link that is unique to the current discord server
    await interaction.response.send_message(
        'Please use this link to verify: {}'.format(
            # TODO hash id
            FRONTEND_URL + '?server={}&url={}'.format(interaction.guild.id, url)
        ),
        ephemeral=True
    )
    success = False
    outcome = 'Failed to verify your identity. Please try again.'
    # 5 minute of pinging
    for timeout in range(100):
        # Trying the await clause
        response = requests.get(
            BACKEND_URL + '/api/confirm/?requestId={}'.format(requestId),
        )

        # verification success
        if response.status_code == 200:
            success = True
            break

        # user has not verified yet
        elif response.status_code == 202:
            await asyncio.sleep(3)

        # unable to verify (timeout) or there was never an a verification attempt with the given user
        else:
            break

    if success:
        roles = discord.utils.get(interaction.guild.roles, name='humanID-Verified')
        if roles:
            try:
                await author.add_roles(roles)
                outcome = 'Congratulations! You’ve been verified with humanID and been granted access to this server. To keep your identity secure and anonymous, all verification data is never stored and is immediately deleted upon completion.'
                requests.delete(
                    BACKEND_URL + '/api/removeEntry/?requestId={}'.format(requestId)
                )
            except discord.Forbidden:
                outcome = "I don't have the permission to add the humanID-Verified role, please contact humanID at discord@human-id.org."
            except discord.HTTPException as e:
                outcome = "An error occurred while trying to add the humanID-Verified role: {}".format(e)
    await interaction.edit_original_response(content=outcome)

    # log verification attempt into the log channel
    currentTime = time.gmtime(time.time())
    embed = discord.Embed(
        title='Verify Attempt',
        description='Status: {}'.format('Success' if success else 'Failure'),
        colour=discord.Colour.dark_gold(),
    )

    embed.set_footer(
        text=datetime.datetime(
            year=currentTime.tm_year,
            month=currentTime.tm_mon,
            day=currentTime.tm_mday,
            hour=currentTime.tm_hour,
            minute=currentTime.tm_min,
            second=currentTime.tm_sec
        )
    )
    embed.set_author(
        name=author.name,
        url=author.display_avatar.url,
        icon_url=author.display_avatar.url
    )

    await channels.send(embed=embed)

#-----------------------------------Version 2 - Setup----------------------------------------
# Sets up the configuration the admin would like
# updates the verified role's name, get-verified channel name, and channel privacy settings
# specify the settings via the parameters

# @bot.tree.command(name='setup')
# async def setup(interaction: discord.Interaction):
#     if not interaction.user.guild_permissions.administrator:
#         # only admins can run this commmand
#         await interaction.response.send_message(
#             'Access to the bot settings is only available to admins. Please contact an admin if you would like to change the settings.',
#             ephemeral=True
#         )
#         return

#     embed = discord.Embed(
#         title='Verify Attempt',
#         description='Status: {}'.format('Success'),
#         colour=discord.Colour.dark_gold(),
#     )
#     view = discord.ui.View()
#     # interaction.data gives the value after selecting an option
#     d = discord.ui.Select(
#         placeholder='temp TODO',
#         options=[
#             discord.SelectOption(label='Voice Channels', value='voice'),
#             discord.SelectOption(label='Text Channels', value='text'),
#             discord.SelectOption(label='Categories', value='category'),
#         ]
#     )

#     # code for buttons if wanted for QOL in the future TODO
#     view.add_item(d)
#     locked = discord.ui.Button(label='t')
#     view.add_item(locked)
#     locked = discord.ui.Button(label='test')
#     view.add_item(locked)

#     view.interaction_check = handleInteraction
#     await interaction.response.send_message(
#         embed=embed,
#         view=view,
#         ephemeral=True
#     )

# async def handleInteraction(interaction):
#     origMessage = interaction.message

#     if interaction.data['component_type'] == 2:
#         # button interaction
#         print('button')
#         return

#     chosen = interaction.data['values']
#     if chosen[0] in ['text', 'voice', 'category']:
#         # setup choices for channel selection
#         channelType = discord.ChannelType.text
#         maxSize = len(interaction.guild.text_channels)
#         if chosen[0] == 'voice':
#             channelType = discord.ChannelType.voice
#             maxSize = len(interaction.guild.voice_channels)

#         elif chosen[0] == 'category':
#             channelType = discord.ChannelType.category
#             maxSize = len(interaction.guild.categories)

#         chooseChannel = discord.ui.ChannelSelect(
#             channel_types=[channelType],
#             max_values=maxSize,
#         )
#         view = discord.ui.View()
#         view.add_item(chooseChannel)
#         view.interaction_check = handleInteraction
#         await interaction.response.edit_message(view=view)

#     else:
#         # hide channel
#         updatedChannels = []
#         verifiedRole = discord.utils.get(origMessage.guild.roles, name='Verified')
#         everyone = discord.utils.get(origMessage.guild.roles, name='@everyone')
#         for channelId in chosen:
#             # removes perms for non-verified users for the chosen channels
#             channel = await origMessage.guild.fetch_channel(int(channelId))
#             updatedChannels.append(channel.name)
#             await channel.set_permissions(verifiedRole, read_messages=True, send_messages=True)
#             await channel.set_permissions(everyone, read_messages=False, send_messages=False)

#         view = discord.ui.View()
#         embed = discord.Embed(
#             title='Successfully locked {} channel(s)'.format(len(chosen)),
#             description=', '.join(updatedChannels),
#             colour=discord.Colour.dark_gold(),
#         )
#         d = discord.ui.Select(
#             placeholder='temp TODO',
#             options=[
#                 discord.SelectOption(label='Voice Channels', value='voice'),
#                 discord.SelectOption(label='Text Channels', value='text'),
#                 discord.SelectOption(label='Categories', value='category'),
#             ]
#         )
#         view.add_item(d)
#         view.interaction_check = handleInteraction
#         await interaction.response.edit_message(embed=embed, view=view)

###################################
# The commands below are currently only used for testing/development
###################################

# Command -- /log
@bot.command('log')
async def log(ctx):
    channels = await ctx.guild.fetch_channels()

# Should be a slash command, which might be why "This Interaction Failed" error is there
@bot.command('test')
async def test(ctx):
    message = ctx.message
    embed = discord.Embed(
        title='Verify Attempt',
        description='Status: {}'.format('Success'),
        colour=discord.Colour.dark_gold(),
    )
    view = discord.ui.View()
    # interaction.data gives the value after selecting an option
    d = discord.ui.Select(
        placeholder='temp TODO',
        options=[
            discord.SelectOption(label='Voice Channels', value='voice'),
            discord.SelectOption(label='Text Channels', value='text'),
            discord.SelectOption(label='Categories', value='category'),
        ]
    )
    view.add_item(d)
    locked = discord.ui.Button(label='test')
    view.add_item(locked)

    # await message.channel.send(embed=embed, view=view)

# async def role_positions_setup(guild):
#     num_roles = len(guild.roles)
#     new_bot_position = num_roles - 1
#     new_verify_position = num_roles - 2
#     verified_role = discord.utils.get(guild.roles, name='Verified')
#     bot_role = discord.utils.get(guild.roles, name=bot_name)
#     positions = {
#         verified_role: new_verify_position,
#         bot_role: new_bot_position
#     }
#     new_positions = await guild.edit_role_positions(positions=positions)
#     roles = guild.roles
#     for role in new_positions:
#         print(role.name, ': ', role.position)

bot.run(TOKEN);


#
# Usage: simplejob.py <METHOD> <HOST>
# Ex: simplejob.py create http://localhost:8080
#
import requests
import json
import sys

METHOD = sys.argv[1]
URL = sys.argv[2]

api_group = "/api/v1/jobs"

simple_job = {
    "name": "pi",
    "namespace": "default",
    "maxRetries": 4,
    "containers": [
        {
            "name": "pi",
            "image": "perl",
            "command": ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"],
        },
    ],
}

simple_job_cron = {
    "name": "pi",
    "namespace": "default",
    "maxRetries": 1,
    "cron": "* * * * *",
    "containers": [
        {
            "name": "pi",
            "image": "perl",
            "command": ["perl", "-Mbignum=bpi", "-wle", "print bpi(50)"],
        },
    ],
}

def main():
    methods = {
        # Simple
        "create": create,
        "delete": delete,
        "fetch": fetch,
        "list_all": list_all,
        "list_default": list_default,

        # Scheduled
        "create_scheduled": create_scheduled,
        "delete_scheduled": delete_scheduled,
        "fetch_scheduled": fetch_scheduled,
        "list_all_scheduled": list_all_scheduled,
        "list_default_scheduled": list_default_scheduled,
        "update_scheduled": update_scheduled,
    }
    methods[METHOD]()

def create():
    """
    Create a SimpleJob
    """
    r = requests.post(
        f"{URL}{api_group}/simple/",
        data=json.dumps(simple_job),
    )
    print(r.text)

def fetch():
    """
    Fetch a SimpleJob
    """
    r = requests.get(
        f"{URL}{api_group}/simple/{simple_job['namespace']}/{simple_job['name']}",
    )
    print(r.text)

def list_all():
    """
    List all SimpleJobs
    """
    r = requests.get(
        f"{URL}{api_group}/simple/",
    )
    print(r.text)

def list_default():
    """
    List SimpleJobs from namespace 'default'
    """
    r = requests.get(
        f"{URL}{api_group}/simple/default",
    )
    print(r.text)

def delete():
    """
    Delete a SimpleJob
    """
    r = requests.delete(
        f"{URL}{api_group}/simple/{simple_job['namespace']}/{simple_job['name']}",
    )
    print(r.text)

def create_scheduled():
    """
    Create a scheduled SimpleJob
    """
    r = requests.post(
        f"{URL}{api_group}/scheduled/",
        data=json.dumps(simple_job_cron),
    )
    print(r.text)

def fetch_scheduled():
    """
    Fetch a scheduled SimpleJob
    """
    r = requests.get(
        f"{URL}{api_group}/scheduled/{simple_job_cron['namespace']}/{simple_job_cron['name']}",
    )
    print(r.text)

def list_all_scheduled():
    """
    List all scheduled SimpleJobs
    """
    r = requests.get(
        f"{URL}{api_group}/scheduled/",
    )
    print(r.text)

def list_default_scheduled():
    """
    List scheduled SimpleJobs from namespace 'default'
    """
    r = requests.get(
        f"{URL}{api_group}/scheduled/default",
    )
    print(r.text)

def delete_scheduled():
    """
    Delete a scheduled SimpleJob
    """
    r = requests.delete(
        f"{URL}{api_group}/scheduled/{simple_job_cron['namespace']}/{simple_job_cron['name']}",
    )
    print(r.text)

def update_scheduled():
    """
    Update a scheduled SimpleJob
    """
    simple_job_cron["cron"] = "9 9 * * *"
    simple_job_cron["maxRetries"] = 99

    r = requests.put(
        f"{URL}{api_group}/scheduled/{simple_job_cron['namespace']}/{simple_job_cron['name']}",
        data=json.dumps(simple_job_cron),
    )
    print(r.text)

if __name__ == "__main__":
    main()


import numpy as np
import pandas as pd

from keras.models import Sequential, load_model
from keras.layers import LSTM, Dropout, Dense, Activation
from keras.callbacks import ModelCheckpoint, TerminateOnNaN
from keras.optimizers import RMSprop

import keras.backend as K
import tensorflow as tf

from decimal import Decimal

def lstm(n_lstm_layers = 2, n_dense_layers = 1, n_lstm_nodes = 512, \
         dropout_rate = 0.4, n_keys_piano = 88, window_size = 16, \
         n_dur_nodes = 20, max_norm_value = None):
    """Generate a keras Sequential model of the form as described in Figure 16
    of https://www.tandfonline.com/doi/full/10.1080/25765299.2019.1649972"""
    if (max_norm_value):
        kernel_constraint = tf.keras.constraints.max_norm(max_norm_value)
    else:
        kernel_constraint = None
    model = Sequential()
    model.add(LSTM(n_lstm_nodes, return_sequences = True, input_shape = \
                   (window_size, n_keys_piano + n_dur_nodes,)))
    model.add(Dropout(dropout_rate))
    for i in range(1, n_lstm_layers - 1):
        model.add(LSTM(n_lstm_nodes, return_sequences = True, kernel_constraint = \
                                                            kernel_constraint))
        model.add(Dropout(dropout_rate))
    model.add(LSTM(n_lstm_nodes, kernel_constraint = kernel_constraint))
    model.add(Dropout(dropout_rate))
    model.add(Dense(n_lstm_nodes // 2, kernel_constraint = kernel_constraint))
    model.add(Activation('relu'))
    model.add(Dropout(dropout_rate))
    for i in range(n_dense_layers - 1):
        model.add(Dense(n_lstm_nodes // 2, kernel_constraint = \
                                             kernel_constraint))
        model.add(Dropout(dropout_rate))
    model.add(Dense(n_keys_piano + n_dur_nodes, kernel_constraint = \
                                                  kernel_constraint))
    model.add(Activation('sigmoid'))
    return model

def maestro_loss_wr(harshness, n_dur_nodes):
    """A loss function which, in addition to penalizing for misclassification on
    the first n_keys_piano elements, includes a term proportional to the
    relative error in the prediction of the last n_dur_nodes elements (whose
    mean represents the duration). The proportionality constant is the 'harshness'
    of the maestro in regards to timing."""
    def maestro_loss(ytrue, ypred):
        # Standard binary cross-entropy
        bce_loss = - K.mean(ytrue[:, :-n_dur_nodes] * K.log(ypred[:, \
                            :-n_dur_nodes]) + (1 - ytrue[:, :-n_dur_nodes]) * \
                            K.log(1 - ypred[:, :-n_dur_nodes]))

        # Duration error term
        dur_loss = 2 * harshness * K.mean(K.abs(K.mean(ytrue[:, -n_dur_nodes:], \
                       axis = 1) - K.mean(ypred[:, -n_dur_nodes:], axis = 1)) / \
                       (K.mean(ytrue[:, -n_dur_nodes:], axis = 1) + \
                       K.mean(ypred[:, -n_dur_nodes:], axis = 1) + K.epsilon()))

        if (dur_loss > bce_loss):   # Often times, ytrue[:, :-n_dur_nodes]
            return bce_loss * 2     # elements will be zero (for a rest). This
                                    # may spike dur_loss.  To control, I limit
                                    # it so that it never exceeds the bce_loss.
        return bce_loss + dur_loss

    return maestro_loss
def precision_mod_wr(n_dur_nodes):
    def precision_mod(ytrue, ypred):
        """Just a modified precision excluding the last n_dur_nodes elements
        (which are not classification nodes)"""

        true_positives = K.sum(K.round(ytrue[:, :-n_dur_nodes] * \
                                       ypred[:, :-n_dur_nodes]))
        pred_positives = K.sum(K.round(ypred[:, :-n_dur_nodes]))
        return true_positives / (pred_positives + K.epsilon())
    return precision_mod

def recall_mod_wr(n_dur_nodes):
    def recall_mod(ytrue, ypred):
        """Just a modified recall excluding the last n_dur_nodes elements (which
        are not classification nodes)"""

        true_positives = K.sum(K.round(ytrue[:, :-n_dur_nodes] * \
                                       ypred[:, :-n_dur_nodes]))
        poss_positives = K.sum(ytrue[:, :-n_dur_nodes])
        return true_positives / (poss_positives + K.epsilon())
    return recall_mod

def f1_score_mod_wr(n_dur_nodes):
    def f1_score_mod(ytrue, ypred):
        """Just a modified f1_score excluding the last n_dur_nodes elements
        (which are not classification nodes)"""

        precision = precision_mod_wr(n_dur_nodes)(ytrue, ypred)
        recall = recall_mod_wr(n_dur_nodes)(ytrue, ypred)
        return 2 * (precision * recall) / (precision + recall + K.epsilon())
    return f1_score_mod

# Test this versus the one below
def dur_error_wr(n_dur_nodes):
    def dur_error(ytrue, ypred):
        """A new metric that only gives information on the error in duration
        predictions"""

        return 2 * K.mean(K.abs((K.mean(ytrue[:, -n_dur_nodes:], axis = 1) - \
                   K.mean(ypred[:, -n_dur_nodes:], axis = 1)) / \
                   (K.mean(ytrue[:, -n_dur_nodes:], axis = 1) + \
                   K.mean(ypred[:, -n_dur_nodes:], axis = 1) + K.epsilon())))
    return dur_error

def maestro_dur_loss_wr(harshness, n_dur_nodes):
    """The second term of the maestro loss, based purely on error in duration
    predictions. To be used as a metric in order to decompose the loss
    components during analysis"""
    def maestro_dur_loss(ytrue, ypred):

        return 2 * harshness * K.mean(K.abs((K.mean(ytrue[:, -n_dur_nodes:], \
                   axis = 1) - K.mean(ypred[:, -n_dur_nodes:], axis = 1)) / \
                  (K.mean(ytrue[:, -n_dur_nodes:], axis = 1) + \
                  K.mean(ypred[:, -n_dur_nodes:], axis = 1) + K.epsilon())))
    return maestro_dur_loss

def get_optimizer(lr, clipnorm, clipvalue):
    """Return the RMSprop optimizer with the above parameters"""

    if (lr or clipnorm or clipvalue):
        if (lr):          # It's required that the first argument to RMSprop is
                          # not None
            return RMSprop(lr = lr, clipnorm = clipnorm, clipvalue = clipvalue)
        elif (clipnorm):
            return RMSprop(clipnorm = clipnorm, clipvalue = clipvalue)
        else: # clipvalue
            return RMSprop(clipvalue = clipvalue)
    return RMSprop()   # TypeError when all are None, so do this instead

def get_filename(n_dur_nodes, n_lstm_layers, n_dense_layers, n_lstm_nodes, \
                 dropout_rate, base_nm = 'best_maestro_model_ext_e2e', \
                 max_norm_value = None, lr = None, clipnorm = None,
                 clipvalue = None):
    """Get the filename to save the best model to based on the passed
    parameters."""

    filename = 'best_maestro_model_ext{0}_e2e_{1}_{2}_{3}_{4}'\
               .format(n_dur_nodes, n_lstm_layers, n_dense_layers, \
               n_lstm_nodes, str(dropout_rate).replace('.', 'pt'))
    if (max_norm_value):
        filename += '_mnv_{}'.format(Decimal(max_norm_value))
    if (lr):
        filename += '_lr_{}'.format('%.0e' % Decimal(lr))
    if (clipnorm):
        filename += '_cn_{}'.format(str(clipnorm).replace('.', 'pt'))
    if (clipvalue):
        filename += '_cv_{}'.format(str(clipvalue).replace('.', 'pt'))

    return filename

def generate_cols_dict(history):
    """Return a mapping of desired column names to the corresponding columns in
    the history dictionary (previously history.history where history is the
    return value of model.train)"""
    return {'maestro_loss': history['loss'], 'f1_score': \
            history['f1_score_mod'], 'precision': history['precision_mod'], \
            'recall': history['recall_mod'], 'dur_error': history['dur_error'],\
            'dur_loss': history['maestro_dur_loss'], 'val_maestro_loss': \
            history['val_loss'], 'val_f1_score': history['val_f1_score_mod'], \
            'val_precision': history['val_precision_mod'], \
            'val_recall': history['val_recall_mod'], 'val_dur_error': \
            history['val_dur_error'], 'val_dur_loss': \
            history['val_maestro_dur_loss']}

def save_performance_data(history, filename, path = \
                          '../model_data/performance_data/'):
    """Save the performance data stored in the history dictionary (previously
    history.history where history is the return value of model.train) to a csv
    file."""

    # In all preliminary tests model training has failed at some point when the
    # loss becomes NaN
    if (len(history['val_loss']) < len(history['loss'])):
        # a NaN during training
        for key, value in history.items():
            # pd.DataFrame requires value lengths to be equal:
            if (key[:3] == 'val'):
                value.append(np.nan)

    df = pd.DataFrame(generate_cols_dict(history))
    df.index.name = 'Epochs'
    df.to_csv(path + filename + '.csv')

def train_lstm_model(X_train, X_val, y_train, y_val, n_dur_nodes = 20, \
                     n_lstm_layers = 2, n_dense_layers = 1, n_lstm_nodes = 512,\
                     dropout_rate = 0.4, batch_size = 512, harshness = 0.05, \
                     lr = None, clipnorm = None, clipvalue = None, \
                     max_norm_value = None, epochs = 150):
    """Train a model using the passed parameters, the data, and using the
    RMSprop optimizer. Write the best model as a .h5 and a .csv containing
    columns for the training and validation custom loss and
    metrics. Returns nothing."""

    model = lstm(n_lstm_layers = n_lstm_layers, n_dense_layers = \
                 n_dense_layers, n_lstm_nodes = n_lstm_nodes, dropout_rate = \
                 dropout_rate, max_norm_value = max_norm_value)

    opt = get_optimizer(lr, clipnorm, clipvalue)

    model.compile(loss = maestro_loss_wr(harshness, n_dur_nodes), optimizer = \
                  opt, metrics = [f1_score_mod_wr(n_dur_nodes), \
                  recall_mod_wr(n_dur_nodes), precision_mod_wr(n_dur_nodes), \
                  dur_error_wr(n_dur_nodes), maestro_dur_loss_wr(harshness, \
                                                                 n_dur_nodes)])

    filename = get_filename(n_dur_nodes, n_lstm_layers, n_dense_layers, \
                            n_lstm_nodes, dropout_rate, \
                            max_norm_value = max_norm_value, lr = lr, \
                            clipnorm = clipnorm, clipvalue = clipvalue)

    mc = ModelCheckpoint('../models/' + filename + '.h5', monitor = 'val_loss',\
                         mode = 'min', save_best_only = True, verbose = 1)

    history = model.fit(X_train, y_train, batch_size = batch_size, epochs = \
                        epochs, validation_data = (X_val, y_val), verbose = 2, \
                        callbacks = [mc, TerminateOnNaN()])

    save_performance_data(history.history, filename)


import zlib
import socket
from packet import *
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

# Socket connection to the minecraft server
class TCPConnection(Packet):
    def __init__(self, addr, debug=False, timeout=10):
        Packet.__init__(self)
        self.encrypt = False
        self.debug = debug
        self.compression_threshold = None
        self.socket = socket.create_connection(addr, timeout=timeout)

    def read(self, length):
        result = bytearray()
        while len(result) < length:
            new = self.socket.recv(length - len(result))
            if len(new) == 0:
                raise IOError("Server didn't respond with information!")
            result.extend(new)
        if self.encrypt:
            result = bytearray(self.decryptor.update(bytes(result)))
        return result

    def write(self, data):
        self.socket.sendall(data)

    def receive_packet(self):
        packet_length = self.read_varint()
        packet_in = Packet()
        raw_data = self.read(packet_length)

        # Decompress if needed
        if self.compression_threshold is not None:
            raw_packet = Packet()
            raw_packet.receive(raw_data)
            data_length = raw_packet.read_varint()
            raw_data = raw_packet.read(len(raw_data))
            if data_length > 0:
                raw_data = zlib.decompress(raw_data)
        packet_in.receive(raw_data)
        return packet_in

    def send_packet(self, packet_out):
        # Compress if needed
        if self.compression_threshold is not None:
            data_length = len(packet_out.sent)
            raw_packet = packet_out.flush()
            if data_length < self.compression_threshold:
                packet_out.write_varint(0)
                packet_out.write(raw_packet)
            else:
                raw_packet = zlib.compress(raw_packet)
                packet_out.write_varint(len(raw_packet))
                packet_out.write(raw_packet)

        packet_data = packet_out.flush()
        packet_out.write_varint(len(packet_data))
        packet_out.write(packet_data)

        if self.encrypt:
            packet_data = packet_out.flush()
            packet_out.write(bytearray(self.encryptor.update(bytes(packet_data))))

        if self.debug:
            print('Sending packet: ' + str(packet_out.sent))
        self.write(packet_out.flush())

    # Configures the encryption from given key
    def configure_encryption(self, secret_key):
        self.cipher = Cipher(algorithms.AES(secret_key), modes.CFB8(secret_key), backend=default_backend())
        self.encryptor = self.cipher.encryptor()
        self.decryptor = self.cipher.decryptor()
        self.encrypt = True
        print('Encryption enabled')

    def close(self):
        self.socket.close()

    def __del__(self):
        self.socket.close()


#Calcular el area de un triangulo equilatero
#Se declara las variables Base y Altura
base=float(input("Ingrese la base del triangulo: ")) #Se pide ingresar los datos pedidos en el programa
altura=float(input("Ingrese la altura del triangulo: "))
#Funcion para calcular el area del triangulo
def Areatriangulo():
    #Formula para calcular el area
  Area=base*altura/2
  print("El area del triangulo equilatero es: ", Area)
  #Se retorna el area
  return Area
  #Se llama a la funcion
Areatriangulo()


class Endpoint(object):

    id = None
    centerLatency = None
    caches = None

    def __init__(self, id, centerLatency, caches):
        self.id = id
        self.centerLatency = centerLatency
        self.caches = caches

    def cost_in(self, problem):
        requests = problem.requests_for(self)
        costs = [r.cost_with(self.centerLatency) for r in requests]
        result = 0
        for i in costs:
            result += i
        return result

    def caches_in(self, problem):
        return [[problem.cache_with(id[0]), id[1]]  for id in self.caches]

    def solve(self, problem):
        caches = sorted(self.caches_in(problem), key=lambda c: c[1])
        requests = problem.requests_for(self)
        for cache in caches:
            requests = cache[0].solve(requests, problem)


# from mastermind.app.module_one.example import ExampleClass
from . import board
import random

MAX_COLORS = 10
MIN_COLORS = 6

class GameObject:
    def __init__(self):
        self.player = None
        self.board = Board()
        self.multi_color = False
        self.amount_color = MIN_COLORS
        self.board_history = []

    def set_player(self, name):
        self.player = Player(name)
        self.new_game()

    def new_game(self):
        self.board.setup_board(self.amount_color, self.multi_color)
        self.board_history = []

    def append_history(self, blocks):
        block_row = []

        for n in range(len(self.board.solution)):
            block_item = board.Block(blocks[n])

            if blocks[n] == self.board.solution[n]:
                block_item.black_pin = True
            elif blocks[n] in self.board.solution:
                block_item.white_pin = True

            block_row.append(block_item)

        self.board_history.append(block_row)

class Board:
    def __init__(self):
        self.positions = board.MIN_POISTION
        self.solution = []

    def setup_board(self, amount_color, multi):
        available_colors = []
        self.solution = []

        for s in range(0, 2 if multi else 1):
            for n in range(0, amount_color):
                available_colors.append(n)

        for i in range(0, self.positions):
            self.solution.append(available_colors.pop(
                random.randrange(0, len(available_colors))))

class Player:
    def __init__(self, name):
        self.name = name
        self.played = 0


from ..interface import EngineExecutorAggregatorFactory
from .type import CharMaskEngineRunConfig, CharMask

from .default import (
    char_mask_default_engine_executor_factory,
    CharMaskDefaultEngineInitConfig,
    CharMaskDefaultEngine,
)
from .external_ellipse import (
    char_mask_external_ellipse_engine_executor_factory,
    CharMaskExternalEllipseEngineInitConfig,
    CharMaskExternalEllipseEngine,
)

char_mask_engine_executor_aggregator_factory = EngineExecutorAggregatorFactory([
    char_mask_default_engine_executor_factory,
    char_mask_external_ellipse_engine_executor_factory,
])


from django.urls import path
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from django.contrib.auth.decorators import login_required
from . import views

app_name = 'app'

urlpatterns = [
    path('', views.index),
    url(r'^jobs-$', views.jobs, name='jobs'),
    url(r'^jobs/(?P<slug>[\w-]+)/$', views.job_detail, name='job_detail'),
    url(r'^browse/$', views.browse, name='browse'),
    url(r'^browse_jobs/$', views.browse_jobs, name='browse_jobs'),
    url(r'^jobs/company/(?P<slug>[\w-]+)/$', views.job_at_company, name='job_at_company'),
    url(r'^company/(?P<slug>[\w-]+)/$', views.company_detail, name='company_detail'),
    # url(r'^login/$', views.signin, name='login'),
    # url(r'^password_change/$', login_required(views.password_change), name='password_change'),
    url(r'^profile/(?P<user>[\w-]+)/$', login_required(views.profile), name='profile'),
    # url(r'^register/$', views.signup, name='register'),
    url(r'^resumes/$', login_required(views.resumes), name='resumes'),
    url(r'^resume/(?P<slug>[\w-]+)/$', login_required(views.resume_view), name='resume_view'),
    url(r'^resumes/new/$', login_required(views.upload_resume), name='upload_resume'),
    # others pages url
    url(r'how-it-works/$', views.how_it_works, name='how_it_works'),
]


import csv
import json
import pickle
import re
from typing import *

import pandas as pd
from gensim.models.doc2vec import Doc2Vec

filename = r'data/NOTEEVENTS.csv.gz'
divider = "\n|||\n"

def save_samples(no_samples: int):
    """Saves 'no_samples' amount of reports from the NOTEEVENTS table

    Parameters
    ----------
    no_samples : int
        The number of samples you want to save
    """
    read_file = pd.read_csv(filename, nrows=no_samples,
                            compression='gzip', error_bad_lines=False)
    with open('data/discharge_reports_' + str(no_samples) + 'samples.txt', 'w') as f:
        for item in read_file.TEXT:
            f.write(item + divider)

def save_array(array: List[str], filename: str):
    with open('data/' + filename, 'w') as f:
        for item in array:
            f.write(item + divider)

def save_dict(dictionary: dict, filename: str):
    """Keys are sorted Alphabetically"""
    with open('data/' + filename + '.json', 'w') as f:
        f.write(json.dumps(
            dict(sorted(dictionary.items()))
        ))

def save_classifier(model, algorithm: str = '', no_classes: str = '', feature_model: str = '', filename: str = ''):
    """Store trained model into a file

    Parameters
    ----------
    model
        The model to be saved
    algorithm : str
        Algorithm the classifier makes use of
    no_classes : str
        Number of classes the classifer will distinguish between
    feature_model : str
        The model used to word features
    filename : str, optional
        Custom filename specified by the user, by default a combination of the
        paramters listed are used
    """
    if not (filename):
        filename = algorithm + '_' + \
            str(no_classes) + 'classes' + '_' + feature_model

    pickle.dump(model, open('model/'+filename+'.sav', 'wb'))

def save_word_model(model: Doc2Vec, no_classes: str = '', filename: str = ''):

    if not (filename):
        filename = 'Doc2Vec' + '_' + str(no_classes) + "classes"

    model.save('model/' + filename + '.bin')

def read_file(filename: str, separator: str = '\n|||\n') -> List[str]:
    """Read txt file from data/'filename'"""
    with open('data/'+filename, 'r') as f:
        return f.read().split(separator)

def read_samples(no_samples: int = 0) -> List[str]:
    """Reads 'no_samples' amount of reports from the NOTEEVENTS table

    Parameters
    ----------
    no_samples : int
        The number of samples you want to read
    """
    if no_samples:
        read_file = pd.read_csv(
            filename, nrows=no_samples, compression='gzip', error_bad_lines=False)
    else:
        read_file = pd.read_csv(
            filename, compression='gzip', error_bad_lines=False)
    return read_file.TEXT

def read_json(filename: str) -> Dict:
    """Read json from data/'filename'.json"""
    with open('data/'+filename+'.json') as f:
        return json.load(f)

def read_header_ignore_words() -> List[str]:
    """List of Section Headers to ignore"""
    with open(r'data/section_header_count_ignore.txt') as f:
        return f.read().split("\n")

def read_classifier(filename: str):
    """Read saved classifier from file '.sav'"""
    return pickle.load(open('model/' + filename + '.sav', 'rb'))

def read_word_model(filename: str) -> Doc2Vec:
    """Read word embedding model"""
    return Doc2Vec.load('model/' + filename + '.bin')

if __name__ == "__main__":
    # print(read_samples(5))
    # print(read_json('section_header_count_greater_than_five')['abd'])
    read_header_ignore_words()


from . import schemas, models
from sqlalchemy.orm import Session
from fastapi import Depends, HTTPException, status, APIRouter, Response
from .database import get_db

router = APIRouter()

# [...] get all authors
@router.get('/')
def get_authors(db: Session = Depends(get_db), limit: int = 10, page: int = 1, search: str = ''):
    skip = (page - 1) * limit

    authors_query = db.query(models.Author).filter(
        models.Author.full_name.contains(search)).limit(limit).offset(skip)

    authors = []
    for author in authors_query:
        authors.append(author.get_info())
    return {'status': 'success', 'results': len(authors), 'authors': authors}

# [...] create author
@router.post('/', status_code=status.HTTP_201_CREATED)
def create_author(payload: schemas.AuthorCreateSchema, db: Session = Depends(get_db)):
    new_author = models.Author(**payload.dict())
    db.add(new_author)
    db.commit()
    db.refresh(new_author)
    return {"status": "success", "author": new_author}

# [...] get single record
@router.get('/{authorId}')
def get_author(authorId: str, db: Session = Depends(get_db)):
    author = db.query(models.Author).filter(models.Author.id == authorId).first()
    if not author:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
                            detail=f"No author with this id: {id} found")
    return {"status": "success", "author": author.get_info()}

# [...] edit record
@router.patch('/{authorId}')
def update_author(authorId: str, payload: schemas.AuthorCreateSchema, db: Session = Depends(get_db)):
    author_query = db.query(models.Author).filter(models.Author.id == authorId)
    db_author = author_query.first()

    if not db_author:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
                            detail=f'No author with this id: {authorId} found')
    update_data = payload.dict(exclude_unset=True)
    author_query.filter(models.Author.id == authorId).update(update_data,
                                                             synchronize_session=False)
    db.commit()
    db.refresh(db_author)
    return {"status": "success", "author": db_author}

# [...] delete record
@router.delete('/{authorId}')
def delete_author(authorId: str, db: Session = Depends(get_db)):
    author_query = db.query(models.Author).filter(models.Author.id == authorId)
    author = author_query.first()
    if not author:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
                            detail=f'No author with this id: {id} found')

    author_query.delete(synchronize_session=False)
    db.query(models.Book).filter(models.Book.author_id == authorId).delete()
    db.commit()
    return Response(status_code=status.HTTP_204_NO_CONTENT)


# coding: utf-8
"""
§ This file is part of SoCo.                                            §
§                                                                       §
§ SoCo is free software: you can redistribute it and/or modify          §
§ it under the terms of the GNU General Public License as published by  §
§ the Free Software Foundation, either version 3 of the License, or     §
§ (at your option) any later version.                                   §
§                                                                       §
§ SoCo is distributed in the hope that it will be useful,               §
§ but WITHOUT ANY WARRANTY; without even the implied warranty of        §
§ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         §
§ GNU General Public License for more details.                          §
§                                                                       §
§ You should have received a copy of the GNU General Public License     §
§ along with SoCo.  If not, see <http://www.gnu.org/licenses/>.         §
§                                                                       §
§ © 2016-2018 Odile Bénassy, Université Paris Sud                       §
§                                                                       §
"""

from flask_wtf import FlaskForm
from flask import flash
from flask_babelex import gettext
from wtforms import StringField, BooleanField, RadioField, DateField, DateTimeField, SelectField, SelectMultipleField, HiddenField, FieldList, FormField
from wtforms.fields import Label
from wtforms.validators import DataRequired, Optional, Length, Email
from soco.models import Evenement, Formulaire, Personne, Inscription, Lieu, Intervenant
from soco.auth.models import User
from soco import app
import datetime

class ClickStringField(StringField):
    def __init__(self, *args, **kwargs):
        objname = None
        if 'objname' in kwargs.keys():
            objname = kwargs['objname']
            del kwargs['objname']
        defaultvalue = None
        if 'defaultvalue' in kwargs.keys():
            defaultvalue = kwargs['defaultvalue']
            del kwargs['defaultvalue']
        clickfunc = None
        if 'clickfunc' in kwargs.keys():
            clickfunc = kwargs['clickfunc']
            del kwargs['clickfunc']
        super(ClickStringField, self).__init__(*args, **kwargs)
        if objname:
            self.ng_model = objname + '.' + self.name
        elif self.name:
            self.ng_model = self.name
        else:
            self.ng_model = None
        if defaultvalue:
            self.defaultvalue = defaultvalue
        else:
            self.defaultvalue = None
        if clickfunc:
            self.ng_click = clickfunc
        elif self.name:
            self.ng_click = "click_" + self.name
        else:
            self.ng_click = None

    def __call__(self, **kwargs):
        if hasattr(self, 'ng_model'):
            kwargs['ng-model'] = self.ng_model
        if hasattr(self, 'ng_click'):
            kwargs['ng-click'] = self.ng_click + '()'
        if hasattr(self, 'defaultvalue'):
            kwargs['defaultvalue'] = self.defaultvalue
        return super(ClickStringField, self).__call__(**kwargs)

class PickaDateField(DateField):
    def __init__(self, *args, **kwargs):
        objname, name = None, None
        if 'objname' in kwargs.keys():
            objname = kwargs['objname']
            del kwargs['objname']
        if '_name' in kwargs.keys():
            name = kwargs['_name'].replace("-", ".") # pour le sous-formulaire
        changefunc = None
        if 'changefunc' in kwargs.keys():
            changefunc = args['changefunc']
            del args['changefunc']
        super(PickaDateField, self).__init__(*args, **kwargs)
        if objname and name:
            self.ng_model = objname + '.' + name
        elif name:
            self.ng_model = name
        else:
            self.ng_model = None
        if changefunc:
            self.ng_change = changefunc
        elif self.name:
            self.ng_change = "calc_" + self.name.replace("evenement-", "")
        else:
            self.ng_change = None

    def __call__(self, **kwargs):
        if hasattr(self, 'ng_model'):
            kwargs['ng-model'] = self.ng_model
        if hasattr(self, 'ng_change'):
            kwargs['ng-change'] = self.ng_change + '()'
        kwargs['pickadate'] = "on"
        kwargs['week-starts-on'] = "1"
        kwargs['format'] = "dd/mm/yyyy"
        kwargs['size'] = 10
        return super(PickaDateField, self).__call__(**kwargs)

class SocoForm(FlaskForm):
    def flash_errors(self):
        for field, errors in self.errors.items():
            for error in errors:
                flash(u"Error in the %s field - %s" % (getattr(self, field).label.text, error))

class EvenementForm(SocoForm):
    objname = 'evenement'
    organisateurs = SelectMultipleField(gettext('Organisé par'), coerce=int, choices = [],
                                            description = gettext("Plusieurs choix possibles"))
    titre = StringField(gettext('Titre'), validators=[DataRequired(), Length(min=3, max=300)])
    sstitre = StringField(gettext('Sous-titre'))
    date = PickaDateField(gettext('Date'), objname=objname, format='%d/%m/%Y', validators=[DataRequired()])
    date_fin = PickaDateField(gettext('Date de fin'), objname=objname, format='%d/%m/%Y',
                                  description = gettext("Seulement dans le cas où l'événement dure plusieurs jours"))
    if app.config['AVEC_RECURRENCE']:
        recurrence = RadioField(gettext('Récurrence :'), default = '', choices = list(Evenement.RECURRENCE.items()))
    else:
        recurrence = HiddenField(gettext('Récurrence'))
    lieu = SelectField(
        gettext('Lieu'), coerce=int, choices = [],
        description=gettext('Choisissez la salle, ou le lieu, dans la liste. S\'il ne figure pas, laissez vide'))

    def __init__(self, **kwargs):
        SocoForm.__init__(self, **kwargs)
        self.organisateurs.choices = [ (u.id, u.get_gecos()) for u in User.query.filter(User.role!='superadmin').order_by(User.username).all() ]
        self.lieu.choices = [ (0, ' -- ') ] + [ (l.id, l.nom) for l in Lieu.query.order_by(Lieu.nom).all() ]

class FormulaireForm(SocoForm):
    objname = 'formulaire'
    evenement = FormField(EvenementForm)
    date_ouverture_inscriptions = PickaDateField(gettext("Date d'ouverture des inscriptions"), objname=objname,
                                                 format='%d/%m/%Y', validators=[DataRequired()])
    date_cloture_inscriptions = PickaDateField(gettext("Date de clôture des inscriptions"), objname=objname,
                                               format='%d/%m/%Y', validators=[DataRequired()])
    jour_par_jour = BooleanField(gettext('Voulez-vous que l\'inscription se fasse jour par jour ?'))
    champ_restauration_1 = BooleanField(
        gettext("Organisez-vous un repas/cocktail auquel vous voulez inviter les participants, ou encore, avez-vous une autre question à leur poser ? Si oui, cochez la case :"),
        description=gettext("Vous pouvez aussi vouloir poser une autre question, le texte est à votre discrétion")
        )
    texte_restauration_1 = ClickStringField(
        gettext("et précisez alors la question que vous souhaitez leur poser sur votre page d'inscription"),
        objname=objname, defaultvalue=gettext("Serez-vous des nôtres à midi ?"),
        description=gettext("Le texte de votre question (avec réponse par oui ou par non)"),
        clickfunc=""
        )
    champ_libre_1 = BooleanField(
        gettext("Souhaitez-vous poser une question supplémentaire aux participant-e-s ? Si oui, cochez la case :"))
    texte_libre_1 = StringField(gettext("et précisez le texte de la question :"))

    def validate(self):
        if not FlaskForm.validate(self):
            return False
        if self.date_ouverture_inscriptions.data > self.date_cloture_inscriptions.data:
            self.date_ouverture_inscriptions.errors.append(
                gettext("La date d'ouverture ne peut pas être antérieure à la date de clôture")
                )
            return False
        if (self.evenement.date_fin.data and self.date_cloture_inscriptions.data > self.evenement.date_fin.data) \
          or (not self.evenement.date_fin.data and self.date_cloture_inscriptions.data > self.evenement.date.data):
            self.date_ouverture_inscriptions.errors.append(
                gettext("La date de clôture ne peut pas être postérieure à la date de l'événement")
                )
            return False
        auj = datetime.date.today()
        if not self.date_ouverture_inscriptions.data or self.date_ouverture_inscriptions.data < auj:
            self.date_ouverture_inscriptions.data = auj
        return True

class InscriptionForm(SocoForm):
    nom = StringField(gettext('Nom'), validators=[DataRequired(), Length(min=2, max=30)], render_kw={'autocomplete':'family-name'})
    prenom = StringField(
        gettext('Prénom'),
        validators=[Optional(), Length(min=0, max=30)],
        description=gettext("Attention, pour le badge : prénom + nom = 26 caractères max."),
        render_kw={'autocomplete':'given-name'}
        )
    email = StringField(gettext('Adresse électronique'), validators=[DataRequired(), Email(), Length(min=0, max=70)],
                            render_kw={'autocomplete':'email'})
    telephone = StringField(gettext('Téléphone'), validators=[Optional(), Length(min=0, max=20)])
    organisation = StringField(
        gettext('Organisation'),
        validators=[DataRequired(), Length(min=0, max=40)],
        description=gettext("Attention, pour le badge : fonction + organisation = 32 caractères max."),
        render_kw={'autocomplete':'organization'}
        )
    fonction = StringField(gettext('Fonction'), validators=[Optional(), Length(min=0, max=40)])
    if app.config['AVEC_ETIQUETTES']:
        badge1 = StringField(gettext('Badge1'), validators=[DataRequired(), Length(min=1, max=27)], render_kw={'autocomplete':'off'})
        badge2 = StringField(gettext('Badge2'), validators=[DataRequired(), Length(min=1, max=33)], render_kw={'autocomplete':'off'})
    else:
        badge1 = StringField(gettext('Badge1'), validators=[], render_kw={'autocomplete':'off'})
        badge2 = StringField(gettext('Badge2'), validators=[], render_kw={'autocomplete':'off'})
    attestation_demandee = BooleanField(gettext('Cochez cette case si vous désirez une attestation de présence :'))
    jours_de_presence = FieldList(BooleanField('jour'), min_entries=0, max_entries=100)
    type_inscription = RadioField(
        'Type d\'inscription',
        choices=[
            ("presence", gettext("Vous assisterez à l'évenement")),
            ("interet", gettext("Vous n'assisterez pas à l'évenement, mais souhaitez établir un contact pour recevoir de l'information sur le sujet"))
            ])
    inscription_repas_1 = BooleanField(gettext('Repas 1'))
    inscription_repas_2 = BooleanField(gettext('Repas 2'))
    reponse_question_1 = StringField(gettext('Libre 1'))
    reponse_question_2 = StringField(gettext('Libre 2'))

    def __init__(self, formulaire, *args, **kwargs):
        FlaskForm.__init__(self, *args, **kwargs)
        self.formulaire = formulaire
        if not formulaire.champ_attestation:
            self.__delitem__('attestation_demandee')
        if formulaire.jour_par_jour or formulaire.evenement.recurrence:
            if formulaire.evenement.date_fin == formulaire.evenement.date:
                self.__delitem__('jours_de_presence')
            else:
                formulaire.evenement.calcule_jours()
                for i in range(len(formulaire.evenement.jours)):
                    j = formulaire.evenement.jours[i]
                    self.jours_de_presence.append_entry()
                    self.jours_de_presence.entries[i].value = "jour-" + j.strftime("%x")
                    self.jours_de_presence.entries[i].label = j.strftime("%A %d %b")
        if not formulaire.champ_type_inscription:
            self.__delitem__('type_inscription')
        if formulaire.champ_restauration_1:
            self.__getitem__('inscription_repas_1').label = Label('inscription_repas_1', formulaire.texte_restauration_1)
        else:
            self.__delitem__('inscription_repas_1')
        if formulaire.champ_restauration_2:
            self.__getitem__('inscription_repas_2').label = Label('inscription_repas_1', formulaire.texte_restauration_2)
        else:
            self.__delitem__('inscription_repas_2')
        if formulaire.champ_libre_1:
            self.__getitem__('reponse_question_1').label = Label('reponse_question_1', formulaire.texte_libre_1)
        else:
            self.__delitem__('reponse_question_1')
        if formulaire.champ_libre_2:
            self.__getitem__('reponse_question_2').label = Label('reponse_question_1', formulaire.texte_libre_2)
        else:
            self.__delitem__('reponse_question_2')

    def validate(self):
        if not FlaskForm.validate(self):
            self.flash_errors()
            return False
        return True

class IntervenantForm(InscriptionForm):
    besoin_materiel = SelectField(gettext('Matériel à prévoir'),
                                      choices = Intervenant.MATERIEL.items(),
                                      description = gettext("Éventuellement, matériel que nous devons prévoir pour votre intervention"))
    transport_aller = SelectField(gettext('Moyen de transport (trajet aller)'),
                                      choices = Intervenant.TRANSPORT.items(),
                                      description = gettext("Devons-nous prévoir votre transport aller ?"))
    ville_depart_aller = StringField(gettext('Gare, aéroport, ou ville de départ (trajet aller)'))
    horaire_depart_aller = StringField(gettext('Horaire de départ (trajet aller)'))
    transport_retour = SelectField(gettext('Moyen de transport (trajet retour)'),
                                      choices = Intervenant.TRANSPORT.items(),
                                      description = gettext("Devons-nous prévoir votre transport retour ?"))
    ville_arrivee_retour = StringField(gettext('Gare, aéroport, ou ville de destination (trajet retour)'))
    horaire_depart_retour = StringField(gettext('Horaire de départ (trajet retour)'))
    nuits = FieldList(BooleanField('nuit'), min_entries=0, max_entries=10)
    repas = FieldList(BooleanField('repas'), min_entries=0, max_entries=20)

    def __init__(self, formulaire, *args, **kwargs):
        InscriptionForm.__init__(self, formulaire, *args, **kwargs)
        formulaire.evenement.calcule_jours()
        for i in range(len(formulaire.evenement.nuits)):
            n = formulaire.evenement.nuits[i]
            self.nuits.append_entry()
            self.nuits.entries[i].value = "nuit-" + n.strftime("%y-%m-%d")
            self.nuits.entries[i].label = gettext("nuit du") + ' {day} ({weekday} {soir})' . format(
                day=n.day, weekday=gettext(n.strftime("%A")), soir=gettext("soir"))
        for i in range(len(formulaire.evenement.jours)):
            j = formulaire.evenement.jours[i]
            self.repas.append_entry()
            self.repas.entries[2 * i].value = "midi-" + j.strftime("%y-%m-%d")
            self.repas.entries[2 * i].label = '{day} ' . format(day=j.day) + ' ' + gettext('midi')
            self.repas.append_entry()
            self.repas.entries[2 * i + 1].value = "soir-" + j.strftime("%y-%m-%d")
            self.repas.entries[2 * i + 1].label = '{day} ' . format(day=j.day) + ' ' + gettext('soir')


"""
Will search through the database for all of the interval nodes that have been added to the database that are not apart
of a relative time line or universal timeline.
"""
import isodate
import datetime
import logging
from sleekxmpp.plugins.base import base_plugin
from rhobot.components.storage import StoragePayload
from rhobot.components.storage.enums import UpdateFlags
from rhobot.components.storage.namespace import NEO4J
from rhobot.components.storage.events import STORAGE_FOUND
from rhobot.namespace import TIMELINE
from rdflib.namespace import DCTERMS

logger = logging.getLogger(__name__)

class Maintainer(base_plugin):
    name = 'timeline_maintainer'
    description = 'Search database for unassociated intervals and associate them with the correct timeline.'
    dependencies = {'rho_bot_scheduler', 'rho_bot_storage_client', 'rho_bot_get_or_create',
                    'rho_bot_representation_manager', 'rho_bot_rdf_publish'}

    # Query that is used to find unassociated intervals.
    query = """
    MATCH (node:`%s`)
    WHERE NOT (node)-[:`%s`]->(:`%s`)
    RETURN node
    LIMIT 1
    """ % (TIMELINE.Interval, TIMELINE.timeline, TIMELINE.RelativeTimeLine)

    # Delays
    _work_to_do_delay = 1.0
    _no_work_delay = 600.0

    def plugin_init(self):
        """
        Subscribe to joining the channel event to see if there are missing associations.
        :return:
        """
        self.xmpp.add_event_handler(STORAGE_FOUND, self._storage_found)
        self.query = ' '.join(self.query.split())

    def post_init(self):
        """
        Finish configuring this plugin.
        :return:
        """
        super(Maintainer, self).post_init()
        self._storage_client = self.xmpp['rho_bot_storage_client']
        self._scheduler = self.xmpp['rho_bot_scheduler']
        self._get_or_create = self.xmpp['rho_bot_get_or_create']
        self._representation_manager = self.xmpp['rho_bot_representation_manager']
        self._rdf_publish = self.xmpp['rho_bot_rdf_publish']

    def _storage_found(self, *args):
        """
        Can now kick off the commands to be able to start finding the intervals.
        :return:
        """
        self.xmpp.del_event_handler(STORAGE_FOUND, self._storage_found)
        self._scheduler.schedule_task(self._start_process, delay=self._work_to_do_delay)

    def _start_process(self):
        """
        Kick off the processes to find the intervals and add them to the chain.
        :return:
        """
        promise = self._scheduler.defer(lambda: dict())
        promise = promise.then(self._find_work_node)
        promise = promise.then(self._get_interval_properties)
        promise = promise.then(self._get_timelines)
        promise = promise.then(self._update_interval)

        promise.then(self._scheduler.generate_promise_handler(self._reschedule, self._work_to_do_delay),
                     self._scheduler.generate_promise_handler(self._reschedule, self._no_work_delay))

    def handle_interval_modification(self, node_uri):
        """
        Handle work done to add/update the interval to the
        :param node_uri:
        :return:
        """
        try:
            promise = self._scheduler.defer(lambda: dict(node_uri=node_uri))
            promise = promise.then(self._get_interval_properties)
            promise = promise.then(self._get_timelines)
            promise = promise.then(self._update_interval)

            return promise
        except Exception as e:
            logger.error('Exception: ', e)

    def _find_work_node(self, session):
        """
        Find a node to work over.
        :param session:
        :return:
        """
        def _handle_cypher_result(_result):
            """
            Handle the results from the cypher result.  If there as no result found then reject the promise, otherwise
            update the session with the uri of the node, and
            :param _result:
            :return:
            """
            if not _result.results:
                raise Exception('No results to work')

            node_uri = _result.results[0].about

            session['node_uri'] = node_uri

            return session

        payload = StoragePayload()
        payload.add_property(key=NEO4J.cypher, value=self.query)
        promise = self._storage_client.execute_cypher(payload).then(_handle_cypher_result)

        return promise

    def _get_interval_properties(self, session):
        """
        Fetch the properties of the the node stored in the session.
        :param session:
        :return:
        """
        def _handle_get_results(_result):
            if not _result.about:
                # This is a weird case, and should never happen
                raise Exception('Node does not exist')

            session['node'] = _result
            return session

        payload = StoragePayload()
        payload.about = session['node_uri']
        promise = self._storage_client.get_node(payload).then(_handle_get_results)

        return promise

    def _get_timelines(self, session):
        """
        Create a promise list that will fetch all of the timelines that the interval should be connected to.
        :param session:
        :return:
        """
        start_date_string = session['node'].properties.get(str(TIMELINE.start), None)
        end_date_string = session['node'].properties.get(str(TIMELINE.end), None)

        start_date_time = isodate.parse_datetime(start_date_string[0])
        start_date = datetime.datetime(start_date_time.year, start_date_time.month, start_date_time.day,
                                       tzinfo=start_date_time.tzinfo)

        if end_date_string:
            end_date_time = isodate.parse_datetime(end_date_string[0])
            end_date = datetime.datetime(end_date_time.year, end_date_time.month, end_date_time.day,
                                         tzinfo=start_date_time.tzinfo)
        else:
            end_date = start_date

        promises = []

        date_difference = end_date - start_date

        for day in range(0, date_difference.days+1):
            delta = datetime.timedelta(days=day)
            timeline_date = start_date + delta

            promise = self._find_or_create_relative_map_for_date(timeline_date)

            promises.append(promise)

        promise = self._scheduler.create_promise_list(*promises).then(
            self._scheduler.generate_promise_handler(self._store_found_timelines, session))

        return promise

    def _store_found_timelines(self, result, session):
        session['timelines'] = result
        return session

    def _find_or_create_relative_map_for_date(self, date):
        """
        Find or create a relative timeline scale that connects to an origin map with the correct date value.
        :param date: date object
        :return:
        """
        def _handle_find_node(_result):
            if not _result.about:
                raise Exception('Result not found')

            return _result

        origin = isodate.isodatetime.datetime_isoformat(date)

        search_payload = StoragePayload()
        search_payload.add_type(TIMELINE.OriginMap)
        search_payload.add_property(TIMELINE.origin, origin)

        promise = self._get_or_create(search_payload)
        promise = promise.then(_handle_find_node)
        promise = promise.then(self._get_range_timeline)

        return promise

    def _get_range_timeline(self, timeline_map):
        """
        Get or create the range timeline for the origin map that was previously found.
        :param timeline_map: the timeline map.
        :return:
        """
        time_lines = timeline_map.references.get(str(TIMELINE.rangeTimeLine), None)
        if time_lines:
            return time_lines[0]

        def _handle_create_and_update_session(_result):
            timeline = _result.results[0].about

            update_payload = StoragePayload()
            update_payload.about = timeline_map.about
            update_payload.add_reference(TIMELINE.rangeTimeLine, timeline)

            # Publish the create event
            self._rdf_publish.publish_all_results(_result, created=True)

            _promise = self._storage_client.update_node(update_payload)
            _promise = _promise.then(self._scheduler.generate_promise_handler(self._rdf_publish.publish_all_results,
                                                                              created=False))
            _promise = _promise.then(lambda s: timeline)

            return _promise

        # otherwise it needs to be created and then return.
        create_payload = StoragePayload()
        create_payload.add_type(TIMELINE.RelativeTimeLine)
        create_payload.add_reference(DCTERMS.creator, self._representation_manager.representation_uri)

        promise = self._storage_client.create_node(create_payload).then(_handle_create_and_update_session)

        return promise

    def _update_interval(self, session):
        """

        Now that the timeline stuff has been found, update the interval as well.
        :param session:
        :return:
        """
        def return_session(result):
            self._rdf_publish.publish_all_results(result, created=False)
            return session

        update_payload = StoragePayload()
        update_payload.about = session['node'].about
        update_payload.add_reference(TIMELINE.timeline, session['timelines'])

        update_payload.add_flag(UpdateFlags.REPLACE_DEFINED, True)

        return self._storage_client.update_node(update_payload).then(return_session)

    def _reschedule(self, session, delay):
        """
        Reschedule the task.
        :param session:
        :param delay:
        :return:
        """
        self._scheduler.schedule_task(self._start_process, delay=delay)

timeline_maintainer = Maintainer


import time

from flask import Blueprint, g, jsonify, request, render_template

from api.exceptions import NoClass
from utils.misc import get_traceback, logger

from .control import REControl

blue_print = Blueprint('recommender', __name__, url_prefix='/recommender')

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

@blue_print.route('/get-food-recommendations/<user_id>', methods=['GET'])
def get_food_recommendations(user_id):
	start_time = time.time()

	N = int(request.args.get('N', 10))
	model_name = request.args.get('model', 'lsa').lower()
	model_version = request.args.get('version', 'v1.0.0')

	try:
		recommender_engine = REControl(g.db_main, g.db_ai, g.fs_ai)
		response = recommender_engine.get_food_recommendations(model_name, model_version, int(user_id), int(N))
	except NoClass as e:
		logger('FOODPIE_RECOMMENDER', 'ERR', get_traceback(e))
		logger('FOODPIE_RECOMMENDER', 'ERR', e.__str__())
		return jsonify({'message': e.__str__()}), e.http_status()
	except Exception as e:
		logger('FOODPIE_RECOMMENDER', 'ERR', get_traceback(e))
		return jsonify({'message': 'Unknown error! Please try after sometime.'}), 500

	end_time = time.time()
	logger('FOODPIE_RECOMMENDER', 'EXE_TIME', 'Execution time of get_food_recommendations() for user_id={} with N={} is {}.'.format(user_id, N, end_time-start_time))
	return jsonify(response), 200

@blue_print.route('/update-model/<model_name>/<model_version>', methods=['GET'])
def update_model(model_name, model_version):
	start_time = time.time()

	try:
		recommender_engine = REControl(g.db_main, g.db_ai, g.fs_ai)
		response = recommender_engine.update_model(model_name, model_version)
	except NoClass as e:
		logger('FOODPIE_RECOMMENDER', 'ERR', get_traceback(e))
		logger('FOODPIE_RECOMMENDER', 'ERR', e.__str__())
		return jsonify({'message': e.__str__()}), e.http_status()
	except Exception as e:
		logger('FOODPIE_RECOMMENDER', 'ERR', get_traceback(e))
		return jsonify({'message': 'Unknown error! Please try after sometime.'}), 500

	end_time = time.time()
	logger('FOODPIE_RECOMMENDER', 'EXE_TIME', 'Execution time of update_model() for {}_{} is {}.'.format(model_name, model_version, end_time-start_time))
	return jsonify(response), 200


import matplotlib.pyplot as plt
import numpy as np
from scipy.io import wavfile
from playsound import playsound

def audio_filter():
    playsound("audios/Keepers.wav")

    sampFreq, sound = wavfile.read("audios/Keepers.wav")
    print(sound.dtype, sampFreq)

    sound = sound / 2.0**15
    sound = sound[:, 0]

    length_in_s = sound.shape[0] / sampFreq
    print("Audio length", length_in_s)

    plt.plot(sound[:], "r")
    plt.xlabel("Sound signal")
    plt.tight_layout()
    plt.show()

    time = np.arange(sound.shape[0]) / sound.shape[0] * length_in_s
    plt.plot(time, sound[:], "r")
    plt.xlabel("time, signal")
    plt.tight_layout()
    plt.show()

    yerr = (
        0.005 * np.sin(2 * np.pi * 6000.0 * time)
        + 0.008 * np.sin(2 * np.pi * 8000.0 * time)
        + 0.006 * np.sin(2 * np.pi * 2500.0 * time)
    )
    signal = sound + yerr
    plt.plot(time[6000:7000], signal[6000:7000])
    plt.xlabel("time, s")
    plt.show()

    fft_spectrum = np.fft.rfft(signal)
    freq = np.fft.rfftfreq(signal.size, d=1.0 / sampFreq)
    print("Fourier spectrum", fft_spectrum)
    fft_spectrum_abs = np.abs(fft_spectrum)

    plt.plot(freq, fft_spectrum_abs)
    plt.xlabel("frequency, Hz")
    plt.ylabel("Amplitude, units")
    plt.show()

    for i, f in enumerate(freq):
        if f > 5900 and f < 6100:
            fft_spectrum[i] = 0.0

    noiseless_signal = np.fft.irfft(fft_spectrum)

    plt.plot(time, noiseless_signal, "r")
    plt.xlabel("time, signal")
    plt.tight_layout()
    plt.show()

    wavfile.write("audios/Noisy_Audio.wav", sampFreq, signal)
    wavfile.write("audios/Noiseless_Audio.wav", sampFreq, noiseless_signal)
    playsound("audios/Noisy_Audio.wav")
    playsound("audios/Noiseless_Audio.wav")

if __name__ == "__main__":
    audio_filter()


def printSummary(results):

    #column 1: index
    index_max_len = 3
    #column 2: name
    name_max_len = 4
    #column 3: enable
    enable_max_len = 7
    #column 4: status
    status_max_len = 6
    #column 5: Last-Update
    date_max_len = 11
    #column 6: ip count
    count_max_len = 5

    for result in results:
        tlen = len(result['name'])
        name_max_len = (name_max_len if(name_max_len > tlen) else tlen)
        if result['enable']:
            if result['status'] == 'OK':
                tlen = len(result['date'])
                date_max_len = (date_max_len if (date_max_len > tlen) else tlen)

    table_fmt = '| %%-%ds | %%-%ds | %%-%ds | %%-%ds | %%-%ds | %%-%ds |' % (index_max_len, name_max_len, enable_max_len, status_max_len, date_max_len, count_max_len)

    index = 0
    separator = '+-'+ '-'*index_max_len+ '-+-'+ '-'*name_max_len+ '-+-'+ '-'*enable_max_len+ '-+-'+ '-'*status_max_len+ '-+-'+ '-'*date_max_len+ '-+-'+ '-'*count_max_len+ '-+'
    print(separator)
    print(table_fmt % ('No.', 'Name', 'Enable', 'Status', 'Last Update', 'Count'))
    print(separator)

    for result in results:
        index = index + 1
        if result['enable']:
            if result['status'] == 'OK':
                print(table_fmt % (index, result['name'], result['enable'], result['status'], result['date'], result['count']))
            else:
                print(table_fmt % (index, result['name'], result['enable'], result['status'], result['message'], '-'))
        else:
            print(table_fmt % (index, result['name'], result['enable'], '-', '-', '-'))
    print(separator)


import scrapy
from dgut_spider.handlePic import handle
from datetime import datetime
from scrapy.http import FormRequest
from scrapy.selector import Selector
from dgut_spider.items import FreeChoiceItem
import json

class FreeChoiceSpider(scrapy.Spider):
    name = "FreeChoice"
    custom_settings = {
            'ITEM_PIPELINES': {
                'dgut_spider.pipelines.FreeChoicePipeline': 300
                }
            }

    def __init__(self, Sel_XNXQ='', Sel_XQXX=''):
        self.getUrl = 'http://jwxt.dgut.edu.cn/jwweb/ZNPK/KBFB_RXKBSel.aspx' # first
        self.vcodeUrl = 'http://jwxt.dgut.edu.cn/jwweb/sys/ValidateCode.aspx' # second
        self.postUrl = 'http://jwxt.dgut.edu.cn/jwweb/ZNPK/KBFB_RXKBSel_rpt.aspx' # third
        self.findSessionId = None # to save cookies
        self.Sel_XNXQ = Sel_XNXQ
        self.Sel_XQXX = Sel_XQXX

    def start_requests(self):
        request = scrapy.Request(self.getUrl,
                callback = self.downloadPic)
        yield request

    def downloadPic(self, response):
        # download the picture
        # find the session id
        self.findSessionId = response.headers.getlist('Set-Cookie')[0].decode().split(";")[0].split("=")

        request = scrapy.Request(self.vcodeUrl,
                cookies = {self.findSessionId[0]: self.findSessionId[1]},
                callback = self.getAndHandleYzm)
        yield request

    def getAndHandleYzm(self, response):
        yzm = handle(response.body)

        yield FormRequest(self.postUrl,
                formdata={
                        'Sel_XNXQ': self.Sel_XNXQ,
                        'Sel_XQXX': self.Sel_XQXX,
                        'txt_yzm': yzm
                        },
                headers = {
                        'Referer': self.getUrl,
                        'Cookie': self.findSessionId[0] + '=' + self.findSessionId[1]
                    },
                callback=self.parse)

    def parse(self, response):
        body = response.body.decode('gbk').encode('utf-8').decode('utf-8')
        num = body.find('alert')
        if num != -1:
            yield scrapy.Request(self.vcodeUrl+'?t='+'%.f' % (datetime.now().microsecond / 1000),
                    headers = {
                            'Referer': self.getUrl,
                            'Cookie': self.findSessionId[0] + '=' + self.findSessionId[1]
                        },
                    callback=self.getAndHandleYzm)

        else:
            sel = Selector(text=body)
            table = sel.xpath('/html/body/table[2]/td').extract()

            i = 0
            j = 10
            while i != len(table):
                everyRow = table[i:j] # len(tmp) == 10, it means every row, 10 column data

                tmpList = []
                rowList = []
                for each in everyRow:
                    selText = Selector(text=each)
                    data = selText.xpath('//td/text()').extract()
                    tmpList.append(data)

                # if tmpList[index] is empty, then make tmpList[index] == ''
                for each in tmpList:
                    if not each: # empty list
                        rowList.append('')
                    else:
                        rowList.append(each[0])

                item = FreeChoiceItem()
                item['XNXQ'] = self.Sel_XNXQ
                item['snum'] = rowList[0]
                item['course'] = rowList[1]
                item['credit'] = rowList[2]
                item['teacher'] = rowList[3]
                item['title'] = rowList[4]
                item['classNum'] = rowList[5]
                item['stuNum'] = rowList[6]
                item['week'] = rowList[7]
                item['classTime'] = rowList[8]
                item['location'] = rowList[9]
                item['campus'] = self.Sel_XQXX
                yield item

                i += 10
                j += 10


from argparse import ArgumentParser
from tqdm import tqdm
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import os

def get_files(condor_input):
    csv_files = []
    for folder in os.listdir(condor_input):
        if folder.startswith('job_'):
            tmp_files = os.listdir(os.path.join(condor_input, folder, 'outFiles'))
            for file in tmp_files:
                if file.endswith('.csv'):
                    csv_files.append(os.path.join(condor_input, folder, 'outFiles', file))
    return csv_files

def buildPlot(infodb, output_file):

    # build the histo
    infodb["Date"]= pd.to_datetime(infodb["Date"])
    infodb_selected = infodb[(infodb['Date'] >= "2016-01-01") & (infodb['Date'] <= "2021-10-31")]
    fig, ax = plt.subplots()
    ax.plot(infodb_selected['Date'].values, infodb_selected['ExposureTime'].values, label="Exposure Time", color="cornflowerblue")

    ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m"))
    ax.xaxis.set_minor_formatter(mdates.DateFormatter("%b"))

    _ = plt.xticks(rotation=30)

    fig.autofmt_xdate()

    plt.ylim(0, 8e+4)
    plt.xlabel('Date')
    plt.ylabel('Exposure Time (s)')

    plt.savefig('{}.pdf'.format(output_file))

def main(args=None):
    parser = ArgumentParser(
        usage="Usage: %(prog)s [options]", description="Flight DATA statistics - Condor Engine")
    parser.add_argument("-i", "--input", type=str,
                        dest='input', help='input HTCondor directory')
    parser.add_argument("-o", "--output", type=str,
                        dest='output', help='output file')
    parser.add_argument("-v", "--verbose", dest='verbose', default=False,
                        action='store_true', help='run in high verbosity mode')

    opts = parser.parse_args(args)

    # Read output csv files
    files = get_files(opts.input)
    # Build final dataframe and sort by date
    complete_df = pd.concat([pd.read_csv(file) for file in files], ignore_index=True)
    complete_df = complete_df.sort_values(by="Date")
    complete_df.to_csv('{}.csv'.format(opts.output), index=False)
    # Build the plot
    if opts.output:
        buildPlot(complete_df, opts.output)

if __name__ == '__main__':
    main()


#!/usr/bin/env python

import os
import smtplib
import string
'''
Mail module - contains convenience functions for sending emails from
python.
'''

def smptmail(toaddrs,
             subject=None,
             message='',
             fromaddr='',
             mailserver=None):
    '''
    toaddrs is either a string or list of email addresses

    mailserver is a string defining your mailserver hostname
    '''

    if type(toaddrs) is str:
        to = toaddrs
    else:
        to = string.join(toaddrs,',')

    # Add the From: and To: headers at the start!
    msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n"
           % (fromaddr, to, subject))

    msg=msg+message
    server = smtplib.SMTP(MAILSERVER)
    server.set_debuglevel(0)
    server.sendmail(fromaddr, toaddrs, msg)
    server.quit()

from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders

def mail_attachment(fromaddr=None,
                    toaddrs=None,
                    subject='[mail_attachment]: ',
                    msgtext='',
                    attachment=None,
                    mailserver=None):
    '''
    attachment is a path to a file you want to attach
    '''

    for toaddr in toaddrs:
        msg = MIMEMultipart()
        msg['From'] = fromaddr
        msg['To'] = toaddr
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject

        msg.attach(MIMEText(msgtext))
        if attachment is not None:
            part = MIMEBase('application',"octet-stream")
            part.set_payload(open(attachment,'rb').read())
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition','attachment; filename = "%s"' % os.path.basename(attachment))
            msg.attach(part)

        server = smtplib.SMTP(mailserver)
        server.sendmail(fromaddr,toaddr,msg.as_string())
        server.quit()


import numpy as np
import tensorflow as tf
from time import time

def hadamard_transform(u, axis=-1):
    """Multiply H_n @ u where H_n is the Hadamard matrix of dimension n x n.
    n must be a power of 2.
    Parameters:
        u: Tensor of shape (..., n)
        normalize: if True, divide the result by 2^{m/2} where m = log_2(n).
    Returns:
        product: Tensor of shape (..., n)
    """
    if axis != -1:
        u = tf.transpose(u, -1, axis)

    n = u.shape[-1]
    m = int(np.log2(n))
    assert n == 1 << m, 'n must be a power of 2'
    x = u[..., np.newaxis]
    for d in range(m)[::-1]:
        x = tf.concat((x[..., ::2, :] + x[..., 1::2, :], x[..., ::2, :] - x[..., 1::2, :]), axis=-1)
    y = tf.squeeze(x, axis=-2) / 2**(m / 2)

    if axis != -1:
        y = tf.transpose(y, -1, axis)

    return y

class SoftThreshold2(tf.keras.layers.Layer):
    def __init__(self, num_features, **kwargs):
        super(SoftThreshold2, self).__init__(**kwargs)
        self.num_features = num_features

    def build(self, input_shape):
        #self.variable = tf.Variable(np.random.uniform(0., 0.1, self.num_features), trainable=True, dtype=tf.float32)
        v = np.zeros((self.num_features, self.num_features))
        for i in range(self.num_features):
            v[:, i] = (i + np.arange(self.num_features))/(10*self.num_features);
        self.variable = tf.Variable(v, trainable=True, dtype=tf.float32)
        self.w = tf.Variable(np.ones((self.num_features,self.num_features)), trainable=True, dtype=tf.float32)

    def get_config(self):
        config = super(SoftThreshold2, self).get_config()
        config.update({"num_features": self.num_features})
        return config

    def call(self, inputs):
        x = tf.math.multiply(inputs, self.w)
        a = tf.math.abs(x)
        r = tf.keras.layers.ReLU()(a-self.variable)
        t = tf.math.tanh(x)
        return tf.keras.layers.Multiply()([t, r])
def find_min_power(x, p=2):
    y = 1
    while y<x:
        y *= p
    return y

def fwht2_layer(x, Hadamard_size = 0):
    input_size = x.shape.as_list()[-2]
    if Hadamard_size < 1:
        Hadamard_size = input_size
    Hadamard_size = find_min_power(Hadamard_size, 2)
    if Hadamard_size>input_size:
        f_1 = tf.pad(x, [[0, 0], [0, Hadamard_size-input_size], [0, Hadamard_size-input_size], [0, 0]])
    else:
        f_1 = x
    f_2 = tf.transpose(f_1, [0, 3, 2, 1]) #0123->0331

    f_3 = hadamard_transform(f_2)
    f_4 = tf.transpose(f_3, [0, 1, 3, 2]) #0321->0312
    f_5 = hadamard_transform(f_4)
    f_6 = SoftThreshold2(Hadamard_size)(f_5)

    f_7 = hadamard_transform(f_6)
    f_8 = tf.transpose(f_7, [0, 1, 3, 2]) #0312->0321
    f_9 = hadamard_transform(f_8)
    y = tf.transpose(f_9, [0, 3, 2, 1]) #0321->0123
    if Hadamard_size>input_size:
        y = y[:, :input_size, :input_size, :]
    return y

num_features = 1024
input_size = 8
num = 10

f_1 = tf.keras.Input(shape=(input_size, input_size, num_features), name="input")
f_2 = fwht2_layer(f_1)
model = tf.keras.Model(inputs=f_1, outputs=f_2)
model.compile()
model.summary()

x = np.random.rand(num, input_size, input_size, num_features).astype(np.float32)

start = time()
y = model.predict(x)
end = time()
time1 = end-start

saved_model_path = "./fwht/saved_model"
model.save(saved_model_path)

# TODO(b/156102192)
optimize_lite_model = False

converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_path)

lite_model_content = converter.convert()

with open("./fwht/lite_model.tflite", "wb") as f:
  f.write(lite_model_content)
print("Wrote %sTFLite model of %d bytes." %
      ("optimized " if optimize_lite_model else "", len(lite_model_content)))

# interpreter = tf.lite.Interpreter(model_content=lite_model_content)
interpreter = tf.lite.Interpreter(model_path="./fwht/lite_model.tflite")

yy = np.zeros((num, input_size, input_size, num_features)).astype(np.float32)
start = time()
for i in range(num):
    interpreter.allocate_tensors()
    interpreter.set_tensor(interpreter.get_input_details()[0]['index'], x[i:i+1, :, :])
    interpreter.invoke()
    yy[i:i+1, :, :] = interpreter.get_tensor(interpreter.get_output_details()[0]['index'])
end = time()
time2 = end-start

print(time1)
print(time2)


from unittest import TestCase

from PyQt4 import QtGui, QtTest

from openlp.core.common import Registry
from openlp.core.ui import filerenameform
from tests.interfaces import MagicMock, patch
from tests.helpers.testmixin import TestMixin

class TestStartFileRenameForm(TestCase, TestMixin):

    def setUp(self):
        """
        Create the UI
        """
        Registry.create()
        self.setup_application()
        self.main_window = QtGui.QMainWindow()
        Registry().register('main_window', self.main_window)
        self.form = filerenameform.FileRenameForm()

    def tearDown(self):
        """
        Delete all the C++ objects at the end so that we don't have a segfault
        """
        del self.form
        del self.main_window

    def window_title_test(self):
        """
        Test the windowTitle of the FileRenameDialog
        """
        # GIVEN: A mocked QDialog.exec_() method
        with patch('PyQt4.QtGui.QDialog.exec_') as mocked_exec:

            # WHEN: The form is executed with no args
            self.form.exec_()

            # THEN: the window title is set correctly
            self.assertEqual(self.form.windowTitle(), 'File Rename', 'The window title should be "File Rename"')

            # WHEN: The form is executed with False arg
            self.form.exec_(False)

            # THEN: the window title is set correctly
            self.assertEqual(self.form.windowTitle(), 'File Rename', 'The window title should be "File Rename"')

            # WHEN: The form is executed with True arg
            self.form.exec_(True)

            # THEN: the window title is set correctly
            self.assertEqual(self.form.windowTitle(), 'File Copy', 'The window title should be "File Copy"')

    def line_edit_focus_test(self):
        """
        Regression test for bug1067251
        Test that the file_name_edit setFocus has called with True when executed
        """
        # GIVEN: A mocked QDialog.exec_() method and mocked file_name_edit.setFocus() method.
        with patch('PyQt4.QtGui.QDialog.exec_'):
            mocked_set_focus = MagicMock()
            self.form.file_name_edit.setFocus = mocked_set_focus

            # WHEN: The form is executed
            self.form.exec_()

            # THEN: the setFocus method of the file_name_edit has been called with True
            mocked_set_focus.assert_called_with()

    def file_name_validation_test(self):
        """
        Test the file_name_edit validation
        """
        # GIVEN: QLineEdit with a validator set with illegal file name characters.

        # WHEN: 'Typing' a string containing invalid file characters.
        QtTest.QTest.keyClicks(self.form.file_name_edit, 'I/n\\v?a*l|i<d> \F[i\l]e" :N+a%me')

        # THEN: The text in the QLineEdit should be the same as the input string with the invalid characters filtered
        # out.
        self.assertEqual(self.form.file_name_edit.text(), 'Invalid File Name')


def main():
    n = int(input())
    i_2 = 1
    i_1 = 1
    if n in (0, 1):
        return 1
    for _ in range(n - 1):
        res = i_2 + i_1
        i_2 = i_1
        i_1 = res
    return i_1

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