#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copy from Aladdin, not my own coding!!

Just for use of learning and reference!

"""

"""
let's talk about character-level LSTM

1. identiy the tensor size, tensor.Size([]) = tensor(22), 0-D tensor, you can conver it to tensor([22]) = tensor.Size([1]) by view(1)
2. view(-1) is used for unrolling
3. idea: we have a corpus, let's see a very long string, you first get_random_sample (length of 250) by randomly pick a start_index, then end_index is determined,
    afte that, the tensor input would be this 250-long substring[:-1], tensor target would be [1:], each character's LSTM output is the predicted next character.
    Let's say batch=5, character_total =100, so the input would be tensor.Size([5,250]), each entry has been converted to a index, the nth character in 100 corpus.
    we feed each column into model one by one, for each column, it is tensor.Size([5]), embedding layer (100, 256), each entry will be a index, so it will return a
    256 of length vector, result in tensor.Size([5,256]). before fed into LSTM, unsqueeze(1) to tensor.Size([5,1,256]). the hidden size is 256, but we connect a FC
    layer, so the output size become 100. Each character(column) will have a loss, we use crossEntropyLoss, so loss(y_pred,y), y_pred is tensor.Size([5,1,100])
    [$$$$$$$$$ I think it should be [5,100]$$$$$$$$$$$$$$$$], y is tensor.Size([5]), which is exactly the tensor target's corresponding column. We will accumulate
    all individual character's loss together, backprop to finish the training. Remember every character (LSTM cell) use the (hidden,cell) from last cell.

    In the prediction phase, we have initial several character, we only iterate say we have 5 characters, we only iterate first4, we only care the (hidden,cell),
    the prediction starts with the last character, the output of the last character will be served as next input. we can define predict_Length, here, we will temparature
    and torch.multinomial to get the most possible character.

    All the time, there's only one LSTM cell. (hidden, cell) is contagious and get passed on.
"""

import torch
import torch.nn as nn
import string
import random
import sys
import unidecode

# Device configuration
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Get characters from string.printable
all_characters = string.printable
n_characters = len(all_characters)   # 100
file = unidecode.unidecode(open("/Users/ligk2e/Desktop/Machine-Learning-Collection/ML/Projects/text_generation_babynames/data/names.txt").read())

class RNN(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super(RNN, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers

        self.embed = nn.Embedding(input_size, hidden_size)
        self.lstm = nn.LSTM(hidden_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x, hidden, cell):
        out = self.embed(x)
        out, (hidden, cell) = self.lstm(out.unsqueeze(1), (hidden, cell))
        out = self.fc(out.reshape(out.shape[0], -1))
        return out, (hidden, cell)

    def init_hidden(self, batch_size):
        hidden = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)
        cell = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device)
        return hidden, cell

class Generator:
    def __init__(self):
        self.chunk_len = 250
        self.num_epochs = 5000
        self.batch_size = 1
        self.print_every = 50
        self.hidden_size = 256
        self.num_layers = 2
        self.lr = 0.003

    def char_tensor(self, string):
        tensor = torch.zeros(len(string)).long()
        for c in range(len(string)):
            tensor[c] = all_characters.index(string[c])
        return tensor

    def get_random_batch(self):
        start_idx = random.randint(0, len(file) - self.chunk_len)
        end_idx = start_idx + self.chunk_len + 1
        text_str = file[start_idx:end_idx]
        text_input = torch.zeros(self.batch_size, self.chunk_len)
        text_target = torch.zeros(self.batch_size, self.chunk_len)

        for i in range(self.batch_size):
            text_input[i, :] = self.char_tensor(text_str[:-1])
            text_target[i, :] = self.char_tensor(text_str[1:])

        return text_input.long(), text_target.long()

    def generate(self, initial_str="A", predict_len=100, temperature=0.85):
        hidden, cell = self.rnn.init_hidden(batch_size=self.batch_size)
        initial_input = self.char_tensor(initial_str)
        predicted = initial_str

        for p in range(len(initial_str) - 1):
            _, (hidden, cell) = self.rnn(
                initial_input[p].view(1).to(device), hidden, cell
            )

        last_char = initial_input[-1]

        for p in range(predict_len):
            output, (hidden, cell) = self.rnn(
                last_char.view(1).to(device), hidden, cell
            )
            output_dist = output.data.view(-1).div(temperature).exp()
            top_char = torch.multinomial(output_dist, 1)[0]
            predicted_char = all_characters[top_char]
            predicted += predicted_char
            last_char = self.char_tensor(predicted_char)

        return predicted

    # input_size, hidden_size, num_layers, output_size
    def train(self):
        self.rnn = RNN(
            n_characters, self.hidden_size, self.num_layers, n_characters
        ).to(device)

        optimizer = torch.optim.Adam(self.rnn.parameters(), lr=self.lr)
        criterion = nn.CrossEntropyLoss()
        #writer = SummaryWriter(f"runs/names0")  # for tensorboard

        print("=> Starting training")

        for epoch in range(1, self.num_epochs + 1):
            inp, target = self.get_random_batch()
            hidden, cell = self.rnn.init_hidden(batch_size=self.batch_size)

            self.rnn.zero_grad()
            loss = 0
            inp = inp.to(device)
            target = target.to(device)

            for c in range(self.chunk_len):
                output, (hidden, cell) = self.rnn(inp[:, c], hidden, cell)
                loss += criterion(output, target[:, c])

            loss.backward()
            optimizer.step()
            loss = loss.item() / self.chunk_len

            if epoch % self.print_every == 0:
                print(f"Loss: {loss}")
                print(self.generate())

            #writer.add_scalar("Training loss", loss, global_step=epoch)

gennames = Generator()
gennames.train()


import wikipedia as wiki

def get_wiki_data(search_item):
    ########## getiing sentance from wikipedia################################
    result = wiki.page(wiki.search(search_item)[0])
    result_list = result.summary
    count = 0
    words = " "
    for i in range(len(result_list)):
        if count>=3:
            break
        else:
             words = words+result_list[i]
        if result_list[i] == '.':
            count +=1

    if words != " ":
        return words
    else:
        return "failed"


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

from PIL import Image , ImageDraw , ImageFilter
import Tkinter as tk
import math

#화면 사이즈 구하기
root = tk.Tk()

width = root.winfo_screenwidth()
height = root.winfo_screenheight()

del root

#배경 이미지와 타겟이미지 선언
wallpaper = Image.new(size = (width,height), color="white",mode="RGB")

img = Image.open("target.jpg")

#비율 기준으로 가로맞춤 및 세로마춤 판단
x, y = img.size

if float(height)/float(width) >= float(y)/float(x) :
    zoomf = float(width)/float(x)
    zoomb = float(height)/float(y)
else:
    zoomf = float(height)/float(y)
    zoomb = float(width)/float(x)

#앞뒤로 배치될 이미지 생성
front = img.resize((int(x*zoomf),int(y*zoomf)), Image.ANTIALIAS)
back = img.resize((int(x*zoomb),int(y*zoomb)), Image.ANTIALIAS)

del img

#뒤에 배치될 이미지는 아웃 포커싱을 위해 블러처리
back = back.filter(ImageFilter.GaussianBlur(10))

#각 이미지 배치및 저장
try:
    wallpaper.paste(back,(width/2-back.size[0]/2,height/2-back.size[1]/2),back)
    wallpaper.paste(front,(width/2-front.size[0]/2,height/2-front.size[1]/2),front)
except:
    wallpaper.paste(back,(width/2-back.size[0]/2,height/2-back.size[1]/2))
    wallpaper.paste(front,(width/2-front.size[0]/2,height/2-front.size[1]/2))

wallpaper.save("export.png","PNG")


from MemeGenerator.file_helper import FileHelper
from PIL import Image, ImageDraw, ImageFont
import os
import shutil

class MemeGenerator:
    """ Set instance attributes """

    def __init__(self, output_dir):
        self.output_dir = output_dir
        self.default_font = './fonts/LilitaOne-Regular.ttf'
        self.default_font_size = 35
        self.text_margins = (25, 35)

    def make_meme(self, img_path, text, author, width=500):
        """ Try to open supplied image, resize and add text to meme """

        if width > 500:
            width = 500

        try:
            img = Image.open(img_path)
        except Exception as e:
            print(e)
            return Exception()

        """ Set aspect ratio of resized image """
        ratio = width / float(img.size[0])
        height = int(ratio * float(img.size[1]))
        img = img.resize((width, height), Image.NEAREST)

        """ Draw body of quote """
        draw = ImageDraw.Draw(img)
        font, w, h = self.generate_suitable_font_with_dimensions(
            draw, width, text)
        draw.text(((width - w) / 2, self.text_margins[1] - h / 2),
                  text, font=font, fill='white')

        """ Draw author of quote """
        draw = ImageDraw.Draw(img)
        font, w, h = self.generate_suitable_font_with_dimensions(
            draw, width, author)
        draw.text(((width - w) / 2, height - (h / 2 + self.text_margins[1])),
                  author, font=font, fill='white')

        """ Try to remove exsisting temporary directory """
        try:
            shutil.rmtree(self.output_dir)
        except Exception as e:
            print(e)

        """ Try to add temporary directory """
        try:
            os.mkdir(self.output_dir)
        except Exception as e:
            print(e)

        """ Generate new file name based on submitted meme extension """
        rand_numb = FileHelper.return_random_file_name()
        file_split = img_path.split('.')
        ext = file_split[-1]

        file_path = f"{self.output_dir}/{rand_numb}.{ext}"

        """ Try to save generated meme """
        try:
            img.save(file_path)
        except Exception as e:
            print(e)

        """ Return meme's file path """
        return file_path

    def generate_suitable_font_with_dimensions(self, draw, width, message):
        """ Function that tries to fit text into given meme
            dimensions by continually reducing font size until text fits
            within given margins
        """

        font = ImageFont.truetype(self.default_font, size=35)
        w, h = draw.textsize(message, font=font)
        for i in range(self.default_font_size - 1):
            if width - w < self.text_margins[0]:
                font = ImageFont.truetype(self.default_font, size=35 - (i + 1))
                w, h = draw.textsize(message, font=font)
        return font, w, h


import colorgram

# extract 30 colors from the image
colors = colorgram.extract("damien_hirst.jpg", 30)
rgb_colors = []

for color in colors:
    red = color.rgb.r
    green = color.rgb.g
    blue = color.rgb.b
    cols = (red, green, blue)
    rgb_colors.append(cols)

print(rgb_colors)


import discord
from discord.ext import commands

class Abberantics:
    colour = 0xFF4500
    apexrole = 658508587496112193
    csgorole = 658508867172564992
    mwrole = 658508851372359690
    fortrole = 658509013666889759
    owrole = 658509166498807848
    r6role = 658509196764905492
    rlrole = 664996153288556595
    valrole = 701097388265308220
    eventsrole = 719761318684524556
    naerole = 657046413716357171
    nawrole = 657046579550879772
    eurole = 657046628800397315
    ocerole = 664998820610048000
    pcrole = 677171133199548483
    psrole = 701593482208477214
    xboxrole = 701593449014624344
    switchrole = 701593535618613397
    staff = 653741741249396796
    comprole = 934898482920181870

    class VerifyButton(discord.ui.View):
        def __init__(self, bot):
            self.bot = bot
            super().__init__(timeout=None)

        @discord.ui.button(label="Verify", style=discord.ButtonStyle.green, emoji="✅", custom_id="AEVerification")
        async def verifybutton(self, button, interaction):
            await aeverify(self.bot, interaction)

    class GoToChannel(discord.ui.View):
        def __init__(self):
            super().__init__(timeout=None)
            self.add_item(discord.ui.Button(label="Verify now!", url="https://discord.gg/GEWxYrWzfn"))

class Check:
    def guild(guild_id=None):
        async def guild_check(ctx):
            return ctx.guild.id == guild_id or ctx.author.id == 839248459704959058
        return commands.check(guild_check)

class Friends(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    @Check.guild(652725365856272394)
    async def aeverificationembedpanelpost(self, ctx: commands.Context):
        guild = self.bot.get_guild(652725365856272394)
        view = Abberantics.VerifyButton(self.bot)
        embed = discord.Embed(title="Welcome to Abberantics Esports!",
                              description=f"To get started, please press the button that says `✅ Verify`!",
                              colour=Abberantics.colour).set_image(url=guild.banner.url)
        await ctx.send(embed=embed, view=view)
        await ctx.message.delete()

    @commands.Cog.listener()
    async def on_member_join(self, member: discord.Member):
        if member.guild.id == 652725365856272394:
            await member.add_roles(member.guild.get_role(941173849834266715))
            view = Abberantics.GoToChannel()
            await self.bot.get_channel(654613761537081345).send(f"Welcome to Abberantics Esports {member.mention}! Please read the rules the <#652738269800431626> and then click the button below to begin verification to get access to the rest of the chats! If you run into any issues getting into the community please @ the Staff role ;)", view=view)

def setup(bot):
    bot.add_cog(Friends(bot))

class GameSelect(discord.ui.Select):
    def __init__(self, verifyinteraction, games):
        self.games = games
        options = []
        options.append(discord.SelectOption(label="Reset", value="remove all"))
        for game in games:
            game = games[game]
            options.append(discord.SelectOption(label=game.name, value=game.id, emoji=game.icon))
        super().__init__(placeholder="Please select your game roles!", options=options, custom_id=f"game-{verifyinteraction.user.id}")

    async def callback(self, interaction: discord.Interaction):
        member = interaction.guild.get_member(int(interaction.user.id))
        if interaction.data["values"][0] == "remove all":
            for game in self.games:
                game = self.games[game]
                await member.remove_roles(game)
            return await interaction.response.send_message("Successfully reset game roles", ephemeral=True)
        role = interaction.guild.get_role(int(interaction.data["values"][0]))
        if role not in member.roles:
            await member.add_roles(role)
            await interaction.response.send_message(f"Successfully added {role.mention}!", ephemeral=True)
        elif role in member.roles:
            await member.remove_roles(role)
            await interaction.response.send_message(f"Successfully removed {role.mention}!", ephemeral=True)

class GameSelectView(discord.ui.View):
    def __init__(self, verifyinteraction, games):
        super().__init__(timeout=None)
        self.value = None
        self.add_item(GameSelect(verifyinteraction, games))

    @discord.ui.button(label="Continue", style=discord.ButtonStyle.green, custom_id="gamecontinue", row=1)
    async def gamecontinue(self, button: discord.ui.Button, interaction: discord.Interaction):
        self.value = True
        self.stop()

class PingSelect(discord.ui.Select):
    def __init__(self, verifyinteraction, pings):
        self.pings = pings
        options = []
        options.append(discord.SelectOption(label="Reset", value="remove all"))
        for ping in pings:
            ping = pings[ping]
            options.append(discord.SelectOption(label=ping.name, value=ping.id, emoji=ping.icon))
        super().__init__(placeholder="Please select what you'd like to be pinged for!", options=options, custom_id=f"ping-{verifyinteraction.user.id}")

    async def callback(self, interaction: discord.Interaction):
        member = interaction.guild.get_member(int(interaction.user.id))
        if interaction.data["values"][0] == "remove all":
            for ping in self.pings:
                ping = self.pings[ping]
                await member.remove_roles(ping)
            return await interaction.response.send_message("Successfully reset ping roles", ephemeral=True)
        role = interaction.guild.get_role(int(interaction.data["values"][0]))
        if role not in member.roles:
            await member.add_roles(role)
            await interaction.response.send_message(f"Successfully added {role.mention}!", ephemeral=True)
        elif role in member.roles:
            await member.remove_roles(role)
            await interaction.response.send_message(f"Successfully removed {role.mention}!", ephemeral=True)

class PingSelectView(discord.ui.View):
    def __init__(self, verifyinteraction, pings):
        super().__init__(timeout=None)
        self.value = None
        self.add_item(GameSelect(verifyinteraction, pings))

    @discord.ui.button(label="Continue", style=discord.ButtonStyle.green, custom_id="pingcontinue", row=1)
    async def pingcontinue(self, button: discord.ui.Button, interaction: discord.Interaction):
        self.value = True
        self.stop()

class RegionSelect(discord.ui.Select):
    def __init__(self, verifyinteraction, regions):
        self.regions = regions
        options = []
        for region in regions:
            region = regions[region]
            options.append(discord.SelectOption(label=region.name, value=region.id, emoji=region.icon))
        super().__init__(placeholder="Please select what region you are in!", options=options, custom_id=f"region-{verifyinteraction.user.id}")

    async def callback(self, interaction: discord.Interaction):
        member = interaction.guild.get_member(int(interaction.user.id))
        role = interaction.guild.get_role(int(interaction.data["values"][0]))
        if role not in member.roles:
            await member.add_roles(role)
            await interaction.response.send_message(f"Successfully added {role.mention}!", ephemeral=True)
        elif role in member.roles:
            await member.remove_roles(role)
            await interaction.response.send_message(f"Successfully removed {role.mention}!", ephemeral=True)

class RegionSelectView(discord.ui.View):
    def __init__(self, verifyinteraction, regions):
        super().__init__(timeout=None)
        self.value = None
        self.add_item(GameSelect(verifyinteraction, regions))

    @discord.ui.button(label="Continue", style=discord.ButtonStyle.green, custom_id="regioncontinue", row=1)
    async def regioncontinue(self, button: discord.ui.Button, interaction: discord.Interaction):
        self.value = True
        self.stop()

class PlatformSelect(discord.ui.Select):
    def __init__(self, verifyinteraction, platforms):
        self.platforms = platforms
        options = []
        options.append(discord.SelectOption(label="Reset", value="remove all"))
        for platform in platforms:
            platform = platforms[platform]
            options.append(discord.SelectOption(label=platform.name, value=platform.id, emoji=platform.icon))
        super().__init__(placeholder="Please select what platform(s) you play on!", options=options, custom_id=f"platform-{verifyinteraction.user.id}")

    async def callback(self, interaction: discord.Interaction):
        member = interaction.guild.get_member(int(interaction.user.id))
        if interaction.data["values"][0] == "remove all":
            for platform in self.platforms:
                platform = self.platforms[platform]
                await member.remove_roles(platform)
            return await interaction.response.send_message("Successfully reset platform roles", ephemeral=True)
        role = interaction.guild.get_role(int(interaction.data["values"][0]))
        if role not in member.roles:
            await member.add_roles(role)
            await interaction.response.send_message(f"Successfully added {role.mention}!", ephemeral=True)
        elif role in member.roles:
            await member.remove_roles(role)
            await interaction.response.send_message(f"Successfully removed {role.mention}!", ephemeral=True)

class PlatformSelectView(discord.ui.View):
    def __init__(self, verifyinteraction, platforms):
        super().__init__(timeout=None)
        self.value = None
        self.add_item(GameSelect(verifyinteraction, platforms))

    @discord.ui.button(label="Finish", style=discord.ButtonStyle.green, custom_id="platformfinish", row=1)
    async def platformfinish(self, button: discord.ui.Button, interaction: discord.Interaction):
        self.value = True
        self.stop()

async def aeverify(bot, interaction: discord.Interaction):
    user = interaction.guild.get_member(interaction.user.id)
    guild = interaction.guild
    for channel in interaction.channel.category.channels:
        if channel.name[7:] == user.name.lower():
            return await interaction.response.send_message(f"You already have a verification ticket open at {channel.mention}!", ephemeral=True)
    overwrites = {
        interaction.guild.default_role: discord.PermissionOverwrite(read_messages=False),
        interaction.user: discord.PermissionOverwrite(read_messages=True, send_messages=False, add_reactions=False, read_message_history=True),
        interaction.guild.get_role(Abberantics.staff): discord.PermissionOverwrite(view_channel=True, manage_channels=True, manage_permissions=True, send_messages=True, manage_messages=True)
    }
    channel = await interaction.channel.category.create_text_channel(name=f"verify-{user.name}", overwrites=overwrites)
    await interaction.response.send_message(embed=discord.Embed(description=f"Verification Ticket Successfully created in {channel.mention}!", colour=bot.green), ephemeral=True)
    games = {
        "apex": interaction.guild.get_role(Abberantics.apexrole),
        "csgo": interaction.guild.get_role(Abberantics.csgorole),
        "mw": interaction.guild.get_role(Abberantics.mwrole),
        "fortnite": interaction.guild.get_role(Abberantics.fortrole),
        "ow": interaction.guild.get_role(Abberantics.owrole),
        "r6": interaction.guild.get_role(Abberantics.r6role),
        "rl": interaction.guild.get_role(Abberantics.rlrole),
        "val": interaction.guild.get_role(Abberantics.valrole)}
    pings = {
        "events": interaction.guild.get_role(Abberantics.eventsrole),
        "comp": interaction.guild.get_role(Abberantics.comprole)}
    regions = {
        "nae": interaction.guild.get_role(Abberantics.naerole),
        "naw": interaction.guild.get_role(Abberantics.nawrole),
        "eu": interaction.guild.get_role(Abberantics.eurole),
        "oce": interaction.guild.get_role(Abberantics.ocerole)}
    platforms = {
        "pc": interaction.guild.get_role(Abberantics.pcrole),
        "ps": interaction.guild.get_role(Abberantics.psrole),
        "xbox": interaction.guild.get_role(Abberantics.xboxrole),
        "switch": interaction.guild.get_role(Abberantics.switchrole)}
    view = GameSelectView(interaction, games)
    gamesembed = discord.Embed(description="Please select the games you play from the menu below!\n**PRESS THE \"`✅ CONTINUE`\" BUTTON TO PROCEED.**", color=Abberantics.colour).set_author(icon_url=interaction.guild.icon.url, name="Abberantics Verification")
    await channel.send(content=user.mention, embed=gamesembed, view=view)
    await view.wait()
    isfinished = view.value
    while isfinished != True:
        await view.wait()
        isfinished = view.value
    pingsembed = discord.Embed(description="We don't want to ping you for things you aren't interested in, so select what you'd like to be pinged for below!\n\n**PRESS THE \"`✅ CONTINUE`\" BUTTON TO PROCEED.**", color=Abberantics.colour).set_author(icon_url=interaction.guild.icon.url, name="Abberantics Verification")
    view = PingSelectView(interaction, pings)
    await channel.send(embed=pingsembed, view=view)
    await view.wait()
    isfinished = view.value
    while isfinished != True:
        await view.wait()
        isfinished = view.value
    regionembed = discord.Embed(description="Please select what region you are in from the menu below!\n**PRESS THE \"`✅ CONTINUE`\" BUTTON TO PROCEED.**", color=Abberantics.colour).set_author(icon_url=interaction.guild.icon.url, name="Abberantics Verification")
    view = RegionSelectView(interaction, regions)
    await channel.send(embed=regionembed, view=view)
    await view.wait()
    isfinished = view.value
    while isfinished != True:
        await view.wait()
        isfinished = view.value
    platformembed = discord.Embed(description="Please select what platforms you play on from the menu below!\n**PRESS THE \"`✅ CONTINUE`\" BUTTON TO PROCEED.**", color=Abberantics.colour).set_author(icon_url=interaction.guild.icon.url, name="Abberantics Verification")
    view = PlatformSelectView(interaction, platforms)
    await channel.send(embed=platformembed, view=view)
    await view.wait()
    isfinished = view.value
    while isfinished != True:
        await view.wait()
        isfinished = view.value
    if user.id != 839248459704959058:
        nickname = user.display_name
        await user.edit(nick=f"[NH] {nickname}")
    await user.add_roles(guild.get_role(653072985682346017))
    await user.remove_roles(guild.get_role(941173849834266715))
    await channel.delete()
    await bot.get_channel(652725365856272397).send(f"Welcome {user.mention} to {guild.name}!")


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import streamlit as st
import plotly.express as px
import statsmodels.api as sm
import io

def app():
        # Web App Title
        st.markdown('''
        # **The Plotly Web App**
        This is the **plotly App**
        **Credit:** App built in `Python` + `Streamlit` by [Sartaj AHmed]
        ---
        ''')

        # Upload CSV file From PC
        st.header("Ulpoad you csv File")
        uploaded_file2 = st.file_uploader("Upload your input CSV file", type=["csv"])
        st.markdown("""
        [Example CSV input file](https://github.com/sartajbalti/Desi_Machine_Learning/blob/master/streamlitwork/Iris.csv)
        """)
        if uploaded_file2 is not None:

            def load_csv():
                csv = pd.read_csv(uploaded_file2)
                return csv
            df = load_csv()
            if st.checkbox('Show  Dataset'):
                num=st.number_input('No. of Rows',5,10)
                head=st.radio('View from top (head) or bottom (tail)',('Head','Tail'))

                if head=='Head':
                    st.dataframe(df.head(num))
                    st.title("Summary Statment")
                    st.write(df.describe())
                    buffer = io.StringIO()
                    df.info(buf=buffer)
                    s = buffer.getvalue()
                    st.text(s)
                else:
                    st.dataframe(df.tail(num))

            st.header("Using Plotly you can make animmation plot by selecting the values according to the data set")
            con = df.columns

            x = st.selectbox("Select the value for x  ", con)
            y = st.selectbox("Select the value for y  ", con)
            s = st.selectbox("Select the value for Size  ", con)
            c = st.selectbox("Select the value for color   ", con)
            h = st.selectbox("Select the value for hover   ", con)
            ag = st.selectbox("Select the value for Animation group", con)
            af = st.selectbox("Select the value for Animation frame", con)

            #df = df[df['date']== cont]
            # Plotting
            fig = px.scatter(df, x=x, y=y, size=s, color=c, hover_name = h ,
            log_x=True, size_max = 1000, range_x=[100,10000000], range_y =[100,2000], animation_frame=af,animation_group = ag)
            fig.update_layout(width=800, height=600)
            st.write(fig)
            if st.checkbox('Check the box to click here to make a histogram', key='hi'):
                st.header("Please Select the value to make a Histogram")
                con1 = df.columns
                z = st.selectbox("Select the value for x  ", con1, key='hist')
                st.markdown("**Stacked values in Histogram In plotly different values can be shown in one column by using the color argument.**")
                f= st.selectbox("Select the value for Color  ", con1, key='hist')
                fig1 = px.histogram(df, x=z, color = f)
                st.write(fig1)

        else:
            st.info('Awaiting for CSV file to be uploaded. Hun krdo upload file kam karny k lea bhaee')
            if st.checkbox('Check the box to use Example Dataset', key='head'):
                # Example data
                def load_data():
                    a = pd.read_csv('newdata.csv')
                    return a
                df = load_data()
                if st.checkbox('Show  Dataset'):
                    num=st.number_input('No. of Rows',5,10)
                    head=st.radio('View from top (head) or bottom (tail)',('Head','Tail'))

                    if head=='Head':
                        st.dataframe(df.head(num))
                        st.title("Summary Statment")
                        st.write(df.describe())
                        buffer = io.StringIO()
                        df.info(buf=buffer)
                        s = buffer.getvalue()
                        st.text(s)
                    else:
                        st.dataframe(df.tail(num))

                fig = px.scatter(df, x='total_cases', y='total_deaths', size='new_cases', color='location', hover_name='location',
                log_x=True, size_max = 1000, range_x=[100,10000000], range_y =[100,2000], animation_frame='date',animation_group = 'location')
                fig.update_layout(width=800, height=600)
                st.write(fig)
                if st.checkbox('Check the box to click here to make a histogram', key='hi'):
                    st.header("Please Select the value to make a Histogram")
                    con1 = df.columns
                    z = st.selectbox("Select the value for x  ", con1, key='hist')
                    fig1 = px.histogram(df, x=z)
                    st.write(fig1)


import datetime
import shutil

import matplotlib
import os
import time
import copy

import torch
from PIL import Image, ImageFont
from numpy import random
from torch.utils.data import DataLoader

from confusion_matrix import plot_confusion_matrix_from_data
from evaluation.overall_evaluation import OverallEvaluation

import pandas as pd

from random_seed import set_random_seed

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

def train_cnn_model(
        model,
        criterion,
        optimizer,
        scheduler,
        training_dataset,
        validation_dataset,
        test_dataset,
        batch_size,
        device,
        num_epochs=25):
    import time

    start = time.time()

    network = model.network
    network.to(device)
    LOAD_MODEL = '/home/rfischer/Documents/DeepHumor/deephumor/final_models/transfer_learning.pth'
    #LOAD_MODEL = False

    optimizer = optimizer(params=model.optimization_parameters)
    scheduler = scheduler(optimizer=optimizer)

    train_dl = DataLoader(dataset=training_dataset, batch_size=batch_size, shuffle=False, num_workers=0)
    val_dl = DataLoader(dataset=validation_dataset, batch_size=batch_size, shuffle=False, num_workers=0)
    test_dl = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False, num_workers=0)
    dataloaders = {
        "train": train_dl,
        "val": val_dl,
        "test": test_dl,
    }
    datasets = {
        "val": validation_dataset,
        "test": test_dataset,
    }

    evaluations = {
        "train": OverallEvaluation(
            num=len(dataloaders["train"]), batch_size=batch_size
        ).add_evaluations(model.train_evaluations),
        "val": OverallEvaluation(
            num=len(dataloaders["val"]), batch_size=batch_size
        ).add_evaluations(model.validation_evaluations),
    }
    target_path = os.path.abspath("../../models/{0}_cnn_model.pth".format(
        str(datetime.datetime.today()).replace('-', '').replace(':', '').replace(' ', '_')
    ))

    if not LOAD_MODEL:
        since = time.time()

        best_network_wts = copy.deepcopy(network.state_dict())
        best_acc = 0.0

        patience = 0

        for epoch in range(num_epochs):
            print('Epoch {}/{}'.format(epoch, num_epochs - 1))
            print('-' * 10)

            # Each epoch has a training and validation phase
            for phase in ['train', 'val']:
                evaluations[phase].reset()

                if phase == 'train':
                    scheduler.step()
                    network.train()  # Set network to training mode
                else:
                    network.eval()   # Set network to evaluate mode

                # Iterate over data.
                for data in dataloaders[phase]:
                    inputs, labels = model.get_input_and_label(data)
                    inputs = inputs.to(device)
                    labels = labels.to(device)

                    # zero the parameter gradients
                    optimizer.zero_grad()

                    # forward
                    # track history if only in train
                    with torch.set_grad_enabled(phase == 'train'):
                        outputs = network(inputs)
                        labels = model.get_labels(labels=labels)

                        loss = criterion(outputs, labels)

                        preds = model.get_predictions(outputs=outputs)

                        # backward + optimize only if in training phase
                        if phase == 'train':
                            loss.backward()
                            optimizer.step()

                    # statistics
                    evaluations[phase].add_entry(predictions=preds, actual_label=labels, loss=loss.item())

                print('{0} evaluation:\n {1}'.format(
                    phase, str(evaluations[phase])))

            # deep copy the network
            epoch_acc = evaluations['val'].accuracy_evaluation.accuracy
            if epoch_acc > best_acc:
                print("New Best!")
                best_acc = epoch_acc
                best_network_wts = copy.deepcopy(network.state_dict())
                torch.save(network.state_dict(), target_path)
                patience = 0
            else:
                patience += 1

            if patience > 4:
                print("ran out of patience")
                break

            print()

        end = time.time()
        print("Time of training ", end - start)

        time_elapsed = time.time() - since
        print('Training complete in {:.0f}m {:.0f}s'.format(
            time_elapsed // 60, time_elapsed % 60))
        print('Best val Acc: {:4f}'.format(best_acc))

        # load best model weights
        network.load_state_dict(best_network_wts)
    else:
        #network.load_state_dict({"state_dict": torch.load(LOAD_MODEL)})
        network.load_state_dict(torch.load(LOAD_MODEL))
    set_random_seed(42)

    # do test evaluation
    network.eval()  # Set network to evaluate mode

    DETAIL_DIR = '../../detail/'
    shutil.rmtree(DETAIL_DIR)
    os.mkdir(DETAIL_DIR)
    from PIL import Image
    from PIL import ImageFont
    from PIL import ImageDraw
    font = ImageFont.truetype("../../font.ttf", 24)

    for phase in ['val', 'test']:
        relevant_activations = {}
        evaluations['val'].reset()
        # Iterate over data.

        all_predictions = []
        all_labels = []

        #f, axes = plt.subplots(7, 2, figsize=(128, 128), sharex=True)

        import matplotlib.image as image
        for data in dataloaders[phase]:
            inputs, labels = model.get_input_and_label(data)
            inputs = inputs.to(device)
            labels = labels.to(device)

            # forward
            outputs = network(inputs)
            if len(relevant_activations) < 7:
                if phase == 'test':
                    cid, _, _ = data
                    for j in range(inputs.size(0) - 1):
                        label = int(labels[j].cpu().detach().numpy())
                        if label not in relevant_activations:
                            output = torch.nn.functional.softmax(outputs[j]).cpu().detach().numpy()
                            cur_id = int(cid[j])

                            output = pd.DataFrame(data={
                                key: output[key] for key in range(1, 8)
                            }, index=['data']).T
                            output.reset_index(level=0, inplace=True)
                            output.rename(columns={"index": "Funniness", "data": "Probability"}, inplace=True)
                            matplotlib.pyplot.xlim(0.0, 1.0)

                            title = '{} for Image {}'.format('Validation' if phase == 'val' else 'Test', label)
                            clean_title = title.replace(' ', '_')
                            f = {'family': 'serif', 'serif': ['computer modern roman']}
                            plt.rc('font', **f)
                            #sns.set(rc={'figure.figsize': (11.7, 8.27)})
                            with sns.plotting_context(font_scale=1.5):
                                ax = sns.barplot(
                                    x='Probability',
                                    y='Funniness',
                                    data=output,
                                    color="b",
                                    ci=None,
                                    orient='h',
                                    dodge=False

                                )
                                ax.set_title('True Funniness {}'.format(label), fontsize=18)
                                ax.set_xlabel('Probability', fontsize=18)
                                ax.set_ylabel('Funniness', fontsize=18)
                                ax.tick_params(labelsize=16)

                                ds = datasets[phase]
                                row = ds.df.iloc[cur_id]
                                filename = os.path.join(ds.root_dir, row['filename'])
                                punchline = row['punchline'].replace('\\n', ' ')
                                print("punchline", punchline)
                                #plt.show()
                                plt.tight_layout()
                                plt.savefig(os.path.join(DETAIL_DIR, clean_title + '.png'))

                            img = Image.open(filename)
                            draw = ImageDraw.Draw(img)

                            import textwrap
                            lines = textwrap.wrap(punchline, width=40)

                            w = img.width
                            h = img.height - len(lines) * font.getsize('|')[1] - 10

                            draw.rectangle(((0, h - 10), (w, img.height + 10)), fill='white')

                            y_text = h
                            for line in lines:
                                width, height = font.getsize(line)
                                draw.text(((w - width) / 2, y_text), line, font=font)
                                y_text += height

                            img.save(os.path.join(DETAIL_DIR, clean_title + '_cartoon.jpg'))

                            #shutil.copyfile(filename, os.path.join(DETAIL_DIR, clean_title + '_cartoon.jpg'))

                            #img = np.asarray(Image.open(filename).convert("L"))
                            #img = image.imread(filename)
                            #axes[label - 1, 0].axis('off')
                            #plt.figure(figsize=(20, 2))
                            #axes[label - 1, 0].imshow(random.rand(8, 90), cmap='gray', aspect='auto', interpolation='nearest')

                            #print(label, " ", output, " ", cur_id)

                            relevant_activations[label] = 42
            else:
                break

            labels = model.get_labels(labels=labels)
            preds = model.get_predictions(outputs=outputs)
            #print(inputs)

            # statistics
            evaluations['val'].add_entry(predictions=preds, actual_label=labels, loss=42)

            all_predictions += list(preds.cpu().numpy())
            all_labels += list(labels.cpu().numpy())
        plt.show()

        df = pd.DataFrame(data={
            "predictions": all_predictions,
            "labels": all_labels,
        })
        df.to_csv('{}_{}.csv'.format(target_path, phase), sep=';')

        print('{0} evaluation:\n {1}'.format(
            phase, str(evaluations['val'])))
        """
        plot_confusion_matrix_from_data(
            y_test=all_labels,
            predictions=all_predictions,
            columns=[
                'funniness 1',
                'funniness 2',
                'funniness 3',
                'funniness 4',
                'funniness 5',
                'funniness 6',
                'funniness 7',
            ],
            title='{} confusion matrix'.format('Validation' if phase=='val' else 'Test')
        )
        """

    return network


import asyncio
import contextlib
import json
import locale
import logging
import os.path
import signal
import subprocess
from asyncio.subprocess import PIPE, create_subprocess_exec

import psutil

import lambentlight.server as server
from .config import default_folder as default
from .resources import LocalResource
from .tools import rmtree

logger = logging.getLogger("lambentlight")

def get_resources_in_dir(path, datafolder):
    """
    Gets the resources installed in the folder.
    """
    # If the directory does not exists, return
    if not os.path.isdir(path):
        return

    # Iterate over the items inside of the resources directory
    for found in os.scandir(path):
        # If is not a directory, continue to the next iteration
        if not found.is_dir():
            continue
        # Get the name of the directory
        name = os.path.basename(found.path)
        # If is called .git, skip it (just in case)
        if name == ".git":
            continue
        # If it has [], is a subdirectory so also fetch those
        if name.startswith("[") and name.endswith("]"):
            yield from get_resources_in_dir(found.path, datafolder)
            continue
        # Otherwise, yield a resource
        yield LocalResource(datafolder, found.path)

class DataFolder:
    """
    Represents an independent folder with Resources.
    """
    def __init__(self, manager, path: str):
        self.manager = manager
        self.path = os.path.abspath(path)
        self.name = os.path.basename(self.path)
        self.config = {}
        self.build = None
        self.process = None
        self.process_info = None
        self.reload_configuration()

    def __iter__(self):
        yield "name", self.name
        yield "path", self.path

    @property
    def proc_info(self):
        """
        The information of the process.
        """
        if self.is_running:
            with self.process_info.oneshot():
                return {
                    "pid": self.process.pid,
                    "cpu": self.process_info.cpu_percent(),
                    "mem": self.process_info.memory_info().rss,
                    "build": dict(self.build)
                }
        else:
            return None

    @property
    def is_running(self):
        """
        Checks if the server is running or not.
        """
        return self.process is not None and self.process.returncode is None

    @property
    def can_be_used(self):
        """
        Checks if the Data Folder can be used for a server.
        """
        return os.path.isdir(self.path)

    @property
    def resources(self):
        """
        Returns an iterator with the list of Local Resources.
        """
        yield from get_resources_in_dir(os.path.join(self.path, "resources"), self)

    async def send_command(self, command: str):
        """
        Sends a command to the console, if is running.
        """
        # If the server is not running, return
        if not self.is_running:
            return
        # Otherwise, send it to stdin
        self.process.stdin.write(command)
        await self.process.stdin.drain()

    async def start(self, build, terminate=False):
        """
        Starts or Restarts the game server.
        """
        # Make sure to stop the server
        await self.stop(terminate)

        # If the build is not ready to be used, download it
        if not build.is_ready:
            if not await build.download():
                logger.error("The server can't be started")
                return False
        # Make sure that the Data Folder is there
        if not self.can_be_used:
            logger.error("Unable to start the server because the Data Folder is not present")
            return False
        # Get the token and return if is invalid
        token = self.config.get("token_cfx", None)
        if not token:
            logger.info(f"Unable to start {self.name}: Token not set")
            raise server.MissingTokenException(self)

        # Format the launch parameters
        params = [
            "+set", "citizen_dir", f"\"{build.citizen_dir}\"",
            "+set", "sv_licenseKey", token,
            "+set", "gamename", self.config["game"]
        ]
        # And add the exec arguments
        for config in self.config["exec"]:
            params.append("+exec")
            params.append(config)

        # Select the correct creation flags
        flags = subprocess.CREATE_NEW_PROCESS_GROUP if server.is_windows else 0

        # Then, start the process and save it
        process = await create_subprocess_exec(build.executable, *params, cwd=self.path,
                                               stdin=PIPE, stdout=PIPE, stderr=PIPE, creationflags=flags)
        self.process = process
        self.build = build
        self.process_info = psutil.Process(process.pid)
        self.process_info.cpu_percent()
        asyncio.create_task(self.read_process_stdout())
        logger.info(f"Started Data Folder {self.name} with Build {build.name}")
        return True

    async def stop(self, terminate=False, wait=True):
        """
        Stops or Terminates the game server.
        """
        # If the process is running
        if self.is_running:
            # Stop the process by force or gracefully
            if terminate:
                self.process.terminate()
            else:
                self.process.send_signal(signal.CTRL_BREAK_EVENT if server.is_windows else signal.SIGINT)
            # And wait for it to be closed (if required)
            if wait:
                await self.process.wait()
        # Finally, set the process and build to None
        self.process = None
        self.build = None
        self.process_info = None

    def reload_configuration(self):
        """
        Reloads the configuration specific to this Data Folder.
        """
        path = os.path.join(self.path, "lambentlight.json")

        # If the file is there, load it
        if os.path.isfile(path):
            newconfig = {}
            with open(path) as file:
                loaded = json.load(file)
                for key, item in default.items():
                    if key in loaded:
                        newconfig[key] = loaded[key]
                    else:
                        newconfig[key] = item
                self.config = newconfig
        # Otherwise, use the default values
        else:
            logger.warning(f"Data Folder {self.name} does not has a LambentLight Configuration File")
            self.config = default

    async def delete(self, *, stop=False):
        """
        Deletes the Data Folder.
        """
        # If the server is running, stop it or raise an exception
        if self.is_running:
            if stop:
                await self.stop(wait=True)
            else:
                raise server.InUseException(self)

        # Then, just delete the directory
        with contextlib.suppress(FileNotFoundError):
            rmtree(self.path)
        # And remove the data folder from the list
        with contextlib.suppress(ValueError):  # Avoiding race conditions
            self.manager.folders.remove(self)

    async def read_process_stdout(self):
        """
        Reads the STDOUT of the process.
        """
        # If there is no process or it has exited, return
        if not self.is_running:
            return

        # Otherwise, start sending the lines to the WS Clients
        async for line in self.process.stdout:
            data = {
                "folder": self.name,
                "message": line.decode(locale.getpreferredencoding(False)).strip("\n")
            }
            await self.manager.send_data("console", data)