from PyQt6 import QtWidgets, uic
from PyQt6.QtCore import QUrl, QFileInfo, QDir, QTime, Qt
from PyQt6.QtGui import QIcon, QShortcut, QKeySequence
from PyQt6.QtWidgets import QFileDialog
from my_py_code.custom_music_listitem import MusicPlayerCustomQWidget
import eyed3

from my_py_code.player import VideoPlayerMain

class MusicPlayer(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.song_index = None
        self.main_music_play = VideoPlayerMain()
        self.bool_color = True
        self.play_music = None
        self.music_playlist = None
        self.next_music = None
        self.prev_music = None
        self.bool_sound = True
        self.music_media_playlist = None
        self.music_media_player = None
        self.music_sound_slider = None
        self.music_slider = None
        self.music_size = None
        self.music_point = None
        self.music_point_2 = None
        self.current_music_file_name = None
        self.music_sound = None
        self.stop_music = None
        self.add_music_file = None
        uic.loadUi('./gui/music_player.ui', self)

        self.list = []
        self.item = []
        self.music_list = []

        self.load_widgets_find()  # find widgets
        self.load_clicked()  # clicked buttons

    def load_widgets_find(self):
        #  music player
        self.music_playlist = self.findChild(QtWidgets.QListWidget, 'music_playlist')
        self.play_music = self.findChild(QtWidgets.QPushButton, 'play_music')
        self.play_music.setIcon(QIcon('./gui/qrc/play.png'))
        self.stop_music = self.findChild(QtWidgets.QPushButton, 'stop_music')
        self.add_music_file = self.findChild(QtWidgets.QPushButton, 'add_music_file')
        self.music_sound = self.findChild(QtWidgets.QPushButton, 'music_sound')
        self.music_point = self.findChild(QtWidgets.QLabel, 'music_point')
        self.music_point_2 = self.findChild(QtWidgets.QLabel, 'music_point_2')
        self.current_music_file_name = self.findChild(QtWidgets.QLabel, 'current_music_file_name')
        self.music_size = self.findChild(QtWidgets.QLabel, 'music_size')
        self.music_slider = self.findChild(QtWidgets.QSlider, 'music_slider')
        self.music_sound_slider = self.findChild(QtWidgets.QSlider, 'music_sound_slider')
        self.prev_music = self.findChild(QtWidgets.QPushButton, 'prev_music')
        self.next_music = self.findChild(QtWidgets.QPushButton, 'next_music')
        self.music_sound = self.findChild(QtWidgets.QPushButton, 'music_sound')

    def load_clicked(self):
        #  music
        self.music_sound_slider.valueChanged[int].connect(self.change_music_volume)
        self.add_music_file.clicked.connect(self.music_files)
        self.play_music.clicked.connect(self.play_music_pause)
        self.stop_music.clicked.connect(self.main_music_play.handleQuit)
        self.next_music.clicked.connect(self.nextSong)
        self.prev_music.clicked.connect(self.prevSong)
        self.music_sound.clicked.connect(self.music_sound_mute)
        self.music_slider.sliderMoved.connect(self.set_position)

        self.music_playlist.itemDoubleClicked.connect(self.music_player_list_item_clicked)

        k = self.main_music_play.audioOutput.volume()
        print(k)
        k = int(k * 100)
        self.music_sound_slider.setValue(k)

        self.main_music_play.mediaPlayer.positionChanged.connect(self.positionChang)
        self.main_music_play.mediaPlayer.durationChanged.connect(self.durationChang)
        # shot cut

        self.shortcut = QShortcut(QKeySequence(Qt.Key.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.music_playlist.itemClicked.connect(self.item_clicked)

    '''
    music player
    '''

    def item_clicked(self):
        for i in range(0, len(self.list)):
            if i % 2 == 0:
                self.list[i].frame.setStyleSheet("#frame{"
                                                 "border:none;"
                                                 "background-color: rgb(234, 234, 234);"
                                                 "}"
                                                 "#frame:hover{"
                                                 "background-color:rgb(176, 227, 227);"
                                                 "}")
            else:
                self.list[i].frame.setStyleSheet("#frame{"
                                                 "border:none;"
                                                 "background-color:rgb(250, 250, 250);"
                                                 "}"
                                                 "#frame:hover{"
                                                 "background-color:rgb(176, 227, 227);"
                                                 "}")

        x = self.music_playlist.currentRow()
        self.list[x].frame.setStyleSheet("background-color: #99c5c5;")

    def current_file_name(self):
        filename2 = QFileInfo(self.music_list[self.song_index])
        self.current_music_file_name.setText(filename2.fileName())

    def music_files(self):
        count_music = len(self.music_list)
        music_location = QDir.homePath() + "/Music"
        songs = QFileDialog.getOpenFileNames(self, "Open Song", music_location, "Sound Files (*.mp3 *.wav "
                                                                                "*.flac* *.m4a"
                                                                                "*.mpa *.wma)")

        self.song_index = 0
        (music_list, f_type) = songs

        for filepath in music_list:
            self.music_list.append(filepath)
            if filepath != '':
                url = QUrl.fromLocalFile(filepath)
                # self.music_media_playlist.addMedia(url)
                filename = QFileInfo(filepath)
                position = int(eyed3.load(filepath).info.time_secs)
                hour = position // 3600
                min = (position % 3600) // 60
                sec = position % 60
                duration = ''
                if hour < 10:
                    duration += '0' + str(hour) + ':'
                else:
                    duration += str(hour) + ':'
                if min < 10:
                    duration += '0' + str(min) + ':'
                else:
                    duration += str(min) + ':'
                if sec < 10:
                    duration += '0' + str(sec) + ':'
                else:
                    duration += str(sec)
                self.list.append(MusicPlayerCustomQWidget(None, filepath,
                                                          filename.completeSuffix(),
                                                          str(round(float(filename.size()) / (2 ** 20), 2)),
                                                          duration,
                                                          self.bool_color
                                                          ))
                if self.bool_color:
                    self.bool_color = False
                else:
                    self.bool_color = True
                self.item.append(QtWidgets.QListWidgetItem(self.music_playlist))
                self.current_song_name = f'{music_list[self.song_index]}'
        if count_music == 0 and len(music_list) != 0:
            self.main_music_play.loadFilm(self.current_song_name)

        for i in range(len(self.list)):
            self.item[i].setSizeHint(self.list[i].sizeHint())
            self.music_playlist.setItemWidget(self.item[i], self.list[i])

    def set_position(self, position):
        self.main_music_play.mediaPlayer.setPosition(position)

    def play_music_pause(self):
        if self.main_music_play.play():
            self.play_music.setIcon(QIcon('./gui/qrc/play.png'))
        else:
            self.play_music.setIcon(QIcon('./gui/qrc/pause.png'))

    def nextSong(self):
        self.song_index += 1
        if self.song_index < len(self.music_list):
            self.next_song_name = f'{self.music_list[self.song_index]}'
        else:
            self.song_index = 0
            self.next_song_name = f'{self.music_list[self.song_index]}'
        self.main_music_play.loadFilm(self.next_song_name)
        self.current_song_name = self.next_song_name

    def prevSong(self):
        self.song_index -= 1
        if self.song_index >= 0:
            self.previous_song_name = f'{self.music_list[self.song_index]}'
        else:
            self.song_index = len(self.music_list) - 1
            self.previous_song_name = f'{self.music_list[self.song_index]}'

        self.main_music_play.loadFilm(self.previous_song_name)
        self.current_song_name = self.previous_song_name

    def music_sound_mute(self):
        if self.main_music_play.audioOutput.isMuted():
            self.music_sound.setIcon(QIcon('./gui/qrc/sound.png'))
            self.main_music_play.audioOutput.setMuted(False)
        else:
            self.music_sound.setIcon(QIcon('./gui/qrc/no_sound.png'))
            self.main_music_play.audioOutput.setMuted(True)

    def change_music_volume(self, value):
        self.main_music_play.audioOutput.setMuted(False)
        if value == 0:
            self.music_sound.setIcon(QIcon('./gui/qrc/no_sound.png'))
        else:
            self.music_sound.setIcon(QIcon('./gui/qrc/sound.png'))
        self.main_music_play.audioOutput.setVolume(value / 100)

    def music_player_list_item_clicked(self):
        item_row = self.music_playlist.currentRow()
        clicked_music = f'{self.music_list[item_row]}'
        self.main_music_play.loadFilm(clicked_music)

    def positionChang(self, position):
        self.music_slider.setValue(position)
        mtime = QTime(0, 0, 0, 0)
        time1 = self.main_music_play.mediaPlayer.position()
        mtime = mtime.addMSecs(time1)
        self.music_point.setText(mtime.toString())
        self.current_file_name()
        # default next song
        position = self.main_music_play.mediaPlayer.duration()
        if position // 1000 == time1 // 1000:
            self.nextSong()

    def durationChang(self, duration):
        self.music_slider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.main_music_play.mediaPlayer.duration())
        self.music_point_2.setText(mtime.toString())

    def volumeUp(self):
        self.main_music_play.audioOutput.setVolume(self.main_music_play.audioOutput.volume() + 0.05)
        k = self.main_music_play.audioOutput.volume()
        k = int(k * 100)
        self.music_sound_slider.setValue(k)

    def volumeDown(self):
        self.main_music_play.audioOutput.setVolume(self.main_music_play.audioOutput.volume() - 0.05)
        k = self.main_music_play.audioOutput.volume()
        k = int(k * 100)
        self.music_sound_slider.setValue(k)


from playsound import playsound
from time import sleep
import argparse
import os

parser = argparse.ArgumentParser(description = "")
parser.add_argument("seconds", help = "")
args = parser.parse_args()

def fu(seconds):
    s = int(seconds)

    while True:
        sleep(1)
        if s > 0:
            s -= 1
            print(s)
        if s == 0:
            playsound('/sdb2/PythonProjects/bell')
            os.system("exit")
            return
        pass

fu(args.seconds)


"""Database singleton"""
# pylint: disable=global-statement
import sqlite3

# PATH = '/run/statx-ajax/.db'
PATH = '.statx-ajax.db'

_DB_CONN: sqlite3.Connection = None

def get_conn() -> sqlite3.Connection:
    """Get Database connection"""
    global _DB_CONN

    if _DB_CONN:
        return _DB_CONN

    try:
        # connect
        connection = sqlite3.connect(PATH)
    except Exception as exc:
        raise ValueError('Database not initialized') from exc

    connection.row_factory = sqlite3.Row

    # set global and return
    _DB_CONN = connection
    return connection


from tkinter import *
from tkinter import ttk
from tkinter import simpledialog
from PIL import ImageTk, Image
import random
from graph_plot import graph
from bubbleSort import bubble_sort
from bucketsort import bucketSort
from quicksort import quick_sort
from mergesort import merge_sort
from insertionsort import insertionSort
from countsort import countingSort
from radixsort import radixSort
from heapifysort import heapSort
from hybridquicksort import hybrid_quick_sort
from problem_b import problem

root= Tk()
root.title('Sorting Algorithm Project')
image_O = Image.open('data.jpg')
bck_end = ImageTk.PhotoImage(image_O)
root.geometry('900x600+200+80')
lbl = Label(root,image=bck_end)
lbl.place(x=0,y=0)
root.config(bg='#082A46')

# Heading Algorithms
mainlabel = Label(root,text="Algorithms: ", font=("new roman",16,"italic bold"),bg="#E5A5FF",width=10,fg="black",relief=GROOVE,bd=5)
mainlabel.place(x=0,y=0)

# Showing Algorithm options such as Bubble Sort
select_algorithm= StringVar()
algo_menu= ttk.Combobox(root,width=15,font=("new roman",19,"italic bold"),textvariable=select_algorithm,
                        values=['Bubble Sort','Merge Sort','Quick Sort','Insertion Sort','Count Sort','Radix Sort','Heap Sort','Bucket Sort','Hybrid Quick Sort','Problem 8.2.4'])
algo_menu.place(x=145,y=0)
algo_menu.current(0)  #by default bubble sort

# showing data in form of bars in canvas(Black BOX)
def drawData(data,colorArray,mssg=None):
    canvas.delete("all") # it will delete previous data( Data Bars) if this function is  previously run
    if (mssg!= None):
        canvas.create_text(len(mssg)+250,15,text=mssg,font=("new roman",15,"italic bold"),fill="orange")
    canvas_height=450
    canvas_width=870
    x_width= canvas_width / (len(data)+1)
    # spacing between the bars
    offset=10
    spacing_bet_rect=10
    normalised_data=[(i)/max(data) for i in data]  # in order to avoid the small bars
    #creating bar with respect to the number
    for i , height in enumerate(normalised_data):
        x0=i*x_width + offset + spacing_bet_rect
        y0= canvas_height - height * 400  # we have multiplied 400 because we will normalised our values with one
                                        #one formula so that our data won't exceed our canvas
        x1= (i+1)* x_width
        y1= canvas_height

        canvas.create_rectangle(x0,y0,x1,y1,fill=colorArray[i])
        canvas.create_text(x0+2,y0,anchor=SW,text=str(data[i]),font=("new roman",15,"italic bold"),fill="orange")

    root.update_idletasks() # it will show every step of algorithm for e.g comparision between number in bubble sort

#start button for running the  algorithm
def StartAlgorithm():
    global data
    # if not data: return

    if algo_menu.get() == 'Quick Sort':
        quick_sort(data, 0, len(data)-1, drawData, speedscale.get())

    elif algo_menu.get() == 'Bubble Sort':
        bubble_sort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Bucket Sort':
        bucketSort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Merge Sort':
        merge_sort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Insertion Sort':
        insertionSort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Count Sort':
        countingSort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Radix Sort':
        radixSort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Heap Sort':
        heapSort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Hybrid Quick Sort':
        hybrid_quick_sort(data, drawData, speedscale.get())
    elif algo_menu.get() == 'Problem 8.2.4':
        start = simpledialog.askinteger("Input","Starting Point",parent=root)
        end = simpledialog.askinteger("Input","Ending Point",parent=root)
        problem(data, start,end, drawData, speedscale.get())
    # drawData(data, ['green' for x in range(len(data))])
#it will generate the bars according to the number given
def Generate():
    global data
    print('Select Algorithm'+select_algorithm.get())
    # min value
    minivalue=int(minvalue.get())
    maxivalue=int(maxvalue.get())
    sizeevalue=int(sizevalue.get())
    data=[]
    if(algo_menu.get() == 'Bucket Sort'):
		    for _ in range(sizeevalue):
		        data.append(round(random.uniform(0, 1), 2))

    else:
        for _ in range(sizeevalue):
            data.append(random.randrange(minivalue,maxivalue+1))

    drawData(data,["#A90042" for x in range (len(data))])

random_generate = Button(root,text="Generate",bg="#F7A4A4",font=("arial",12,"italic bold"),relief=SUNKEN,
                        activebackground="#05945B",activeforeground="white",bd=5,width=10,command=Generate)
random_generate.place(x=750,y=60)

#Defines the tag of size of array that should be generated
sizevaluelabel=Label(root,text ="Size: ", font=("new roman",12,"italic bold"),bg="#EEF1FF",
                    width=10,fg="black",height=2,relief=GROOVE,bd=5)
sizevaluelabel.place(x=0,y=60)

#Defines the size of array that should be generated
sizevalue= Scale(root,from_=0,to=30,resolution=1,bg="#B1AFFF",orient=HORIZONTAL,font=("arial",14,"italic bold"),
                    relief=GROOVE,bd=2,width=10)
sizevalue.place(x=120,y=60)

#Defines the tag of size of array that should be generated
minvaluelabel=Label(root,text ="Min Value: ", font=("new roman",12,"italic bold"),bg="#EEF1FF",
                    width=10,fg="black",height=2,relief=GROOVE,bd=5)
minvaluelabel.place(x=250,y=60)

#Defines the size of array that should be generated
minvalue= Scale(root,from_=0,to=10,resolution=1,orient=HORIZONTAL,bg="#B1AFFF",font=("arial",14,"italic bold"),
                    relief=GROOVE,bd=2,width=10)
minvalue.place(x=370,y=60)

#Defines the tag of size of array that should be generated
maxvaluelabel=Label(root,text ="Max Value: " ,font=("new roman",12,"italic bold"),bg="#EEF1FF",
                    width=10,fg="black",height=2,relief=GROOVE,bd=5)
maxvaluelabel.place(x=500,y=60)

#Defines the size of array that should be generated
maxvalue= Scale(root,from_=0,to=100,resolution=1,orient=HORIZONTAL,bg="#B1AFFF",font=("arial",14,"italic bold"),
                    relief=GROOVE,bd=2,width=10)
maxvalue.place(x=620,y=60)

# start the algorithm
start= Button(root,text="Start",bg="#BDBDD7",font=("arial",12,"italic bold"),relief=SUNKEN,
                        activebackground="#05945B",activeforeground="white",bd=5,width=10,command=StartAlgorithm)
start.place(x=750,y=0)

#speed of the algorithm
speedlabel=Label(root,text ="Speed: ", font=("new roman",12,"italic bold"),bg="#EEF1FF",
                    width=10,fg="black",height=2,relief=GROOVE,bd=5)
speedlabel.place(x=400,y=0)

speedscale= Scale(root,from_=0.1,to=5.0,resolution=0.2,length=200,digits=2,bg="#B1AFFF",orient=HORIZONTAL,font=("arial",14,"italic bold"),
                    relief=GROOVE,bd=2,width=10)
speedscale.place(x=520,y=0)

graph_label=Button(root,text="Graphical Reprsentation",bg="#F7A4A4",font=("arial",12,"italic bold"),relief=SUNKEN,
                        activebackground="#05945B",activeforeground="white",bd=5,width=20,command=graph)
graph_label.place(x=350,y=120)

#define the box in which whole algorithm will be visualize
canvas=Canvas(root,width=870,height=450,bg="black")
canvas.place(x=10,y=180)

root.mainloop() # main driver which will run whole Gui


import re
import asyncio
import aiohttp
import discord
from discord.ext import commands

class steam(commands.Cog):
    '''Steam spezifische Commands'''

    def __init__(self, bot):
        self.bot = bot
        self.steamSpyAPIURL = 'https://steamspy.com/api.php'
        self.steamCurrentPlayerAPIURL = 'http://api.steampowered.com/ISteamUserStats/GetNumberOfCurrentPlayers/v0001/?appid='
        self.steamMarketAPIURL = 'http://store.steampowered.com/api/appdetails/?appids='

    @commands.command(pass_context=True)
    @commands.cooldown(1, 2, commands.cooldowns.BucketType.server)
    async def steam(self, ctx, appid: str):
        '''Gibt Informationen zu einem Spiel bei Steam aus

        Beispiel:
        -----------

        :steam 570
        '''
        await self.bot.send_typing(ctx.message.channel)
        steamSpyURL = f'{self.steamSpyAPIURL}?request=appdetails&appid={appid}'
        async with aiohttp.get(steamSpyURL) as r:
            spyJSON = await r.json()

        steamCurrentPlayerURL = f'{self.steamCurrentPlayerAPIURL}{appid}'
        async with aiohttp.get(steamCurrentPlayerURL) as r:
            currentPlayerJSON = await r.json()

        steamMarketURL = f'{self.steamMarketAPIURL}{appid}'
        async with aiohttp.get(steamMarketURL) as r:
            marketJSON = await r.json()

        owner = '{:,}'.format(spyJSON['owners']).replace(',', '.')
        owner += ' ± '
        owner += '{:,}'.format(spyJSON['owners_variance']).replace(',', '.')

        try:
            price = str(int(marketJSON[appid]['data']['price_overview']['final']) / 100) + '€'
            if marketJSON[appid]['data']['price_overview']['discount_percent'] != 0:
                price += ' (-{}%)'.format(marketJSON[appid]['data']['price_overview']['discount_percent'])
        except KeyError:
            price = 'Free'

        embed = discord.Embed(color=0x2F668D, title=spyJSON['name'], url=f'http://store.steampowered.com/app/{appid}')
        embed.set_footer(text='AppID: {}'.format(spyJSON['appid']))
        embed.set_thumbnail(url=f'http://cdn.akamai.steamstatic.com/steam/apps/{appid}/header.jpg')
        embed.add_field(name='Name', value=spyJSON['name'], inline=True)
        embed.add_field(name='Score Rank', value=spyJSON['score_rank'], inline=True)
        embed.add_field(name='Preis', value=price, inline=True)
        embed.add_field(name='Besitzer', value=owner, inline=True)
        embed.add_field(name='Derzeitige Spieler', value=currentPlayerJSON['response']['player_count'], inline=True)
        embed.add_field(name='Durchschnittliche Spieler gestern', value=spyJSON['ccu'], inline=True)
        embed.add_field(name='Entwickler', value=spyJSON['developer'], inline=True)
        embed.add_field(name='Publisher', value=spyJSON['publisher'], inline=True)
        if marketJSON[appid]['data']['short_description'] != '' and marketJSON[appid]['data']['short_description'] != None:
            discription = re.sub(re.compile('<.*?>'), '', marketJSON[appid]['data']['short_description'])
            embed.add_field(name='Beschreibung', value=discription, inline=False)
        embed.add_field(name='Link', value=f'http://store.steampowered.com/app/{appid}', inline=False)

        await self.bot.say(embed=embed)

    @steam.error
    async def steam_error(self, error, ctx):
        if isinstance(error, commands.errors.CommandOnCooldown):
            seconds = str(error)[34:]
            await self.bot.say(f':alarm_clock: Cooldown! Versuche es in {seconds} erneut')
        if isinstance(error, discord.ext.commands.errors.CommandInvokeError):
            await self.bot.say(':x: Konnte keine Verbindung zum Steam API aufbauen')

async def setup(bot):
    await bot.add_cog(steam(bot))


"""
Simple contact form for FeinCMS. The default form class has name, email,
subject and content fields, content being the only one which is not required.
You can provide your own comment form by passing an additional
``form=YourClass`` argument to the ``create_content_type`` call.
"""

from django import forms
from django.core.mail import send_mail
from django.db import models
from django.http import HttpResponseRedirect
from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _

class ContactForm(forms.Form):
    name = forms.CharField(label=_("name"))
    email = forms.EmailField(label=_("email"))
    subject = forms.CharField(label=_("subject"))

    content = forms.CharField(widget=forms.Textarea, required=False, label=_("content"))

class ContactFormContent(models.Model):
    form = ContactForm

    email = models.EmailField()
    subject = models.CharField(max_length=200)

    class Meta:
        abstract = True
        verbose_name = _("contact form")
        verbose_name_plural = _("contact forms")

    @classmethod
    def initialize_type(cls, form=None):
        if form:
            cls.form = form

    def process(self, request, **kwargs):
        if request.GET.get("_cf_thanks"):
            self.rendered_output = render_to_string(
                "content/contactform/thanks.html", {"content": self}, request=request
            )
            return

        if request.method == "POST":
            form = self.form(request.POST)

            if form.is_valid():
                send_mail(
                    form.cleaned_data["subject"],
                    render_to_string(
                        "content/contactform/email.txt", {"data": form.cleaned_data}
                    ),
                    form.cleaned_data["email"],
                    [self.email],
                    fail_silently=True,
                )

                return HttpResponseRedirect("?_cf_thanks=1")
        else:
            initial = {"subject": self.subject}
            if request.user.is_authenticated():
                initial["email"] = request.user.email
                initial["name"] = request.user.get_full_name()

            form = self.form(initial=initial)

        self.rendered_output = render_to_string(
            "content/contactform/form.html",
            {"content": self, "form": form},
            request=request,
        )

    def render(self, **kwargs):
        return getattr(self, "rendered_output", "")


from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from django.views.generic import ListView, DetailView, CreateView

from movies.modelforms import CreateMoviesForm, CreateFromVideo
from movies.models import Movies

from etc_files import get_movie, get_movie_file

class MovieList(ListView):
    model = Movies
    template_name = 'movie_list.html'
    queryset = Movies.objects.all()
    context_object_name = 'movies'

class MovieDetails(DetailView):
    model = Movies
    template_name = 'movie_detail.html'
    queryset = Movies.objects.all()
    context_object_name = 'movie'

class MovieCreate(CreateView):
    template_name = 'movie_create.html'
    model = Movies
    form_class = CreateMoviesForm
    queryset = Movies.objects.all()
    success_url = reverse_lazy('movie:list')

class MovieAutoCreate(CreateView):
    template_name = "movie_auto.html"
    # form_class = Auto

    def get(self, request, *args, **kwargs):
        return render(request, template_name=self.template_name)

    def post(self, request, *args, **kwargs):
        print("CRAWLING")
        data = request.POST
        d = {}
        for key, value in data.items():
            d[key] = value

        del d['csrfmiddlewaretoken']

        directory = d["directory"]
        get_movie(directory)
        return redirect(reverse_lazy('movie:list'))

class addMovieWithFile(CreateView):
    template_name = "movie_create_file.html"
    # form_class = CreateFromVideo
    f = CreateFromVideo()

    def get(self, request, *args, **kwargs):
        return render(request, template_name=self.template_name, context={'form': self.f})

    def post(self, request, *args, **kwargs):
        data = request.POST
        d = {}
        for key, value in data.items():
            d[key] = value

        del d['csrfmiddlewaretoken']

        video = d['video']
        name = d['name']
        get_movie_file(video, name)
        return redirect(reverse_lazy('movie:list'))


import ctypes
import sys
import pickle
import logging
from ..base import _LIB, check_call
from .base import create

__all__ = ['KVStoreServer']

class KVStoreServer(object):
    """The key-value store server."""
    def __init__(self, kvstore):
        """Initialize a new KVStoreServer.

        Parameters
        ----------
        kvstore : KVStore
        """
        self.kvstore = kvstore
        self.handle = kvstore.handle
        self.init_logginig = False

    def _controller(self):
        """Return the server controller."""
        def server_controller(cmd_id, cmd_body, _):
            """Server controler."""
            if not self.init_logginig:
                # the reason put the codes here is because we cannot get
                # kvstore.rank earlier
                head = '%(asctime)-15s Server[' + str(
                    self.kvstore.rank) + '] %(message)s'
                logging.basicConfig(level=logging.DEBUG, format=head)
                self.init_logginig = True

            if cmd_id == 0:
                try:
                    optimizer = pickle.loads(cmd_body)
                except:
                    raise
                self.kvstore.set_optimizer(optimizer)
            else:
                print(f"server {self.kvstore.rank}, unknown command ({cmd_id}, {cmd_body})")
        return server_controller

    def run(self):
        """Run the server, whose behavior is like.

        >>> while receive(x):
        ...     if is_command x: controller(x)
        ...     else if is_key_value x: updater(x)
        """
        _ctrl_proto = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p, ctypes.c_void_p)
        check_call(_LIB.MXKVStoreRunServer(self.handle, _ctrl_proto(self._controller()), None))

def _init_kvstore_server_module():
    """Start server/scheduler."""
    is_worker = ctypes.c_int()
    check_call(_LIB.MXKVStoreIsWorkerNode(ctypes.byref(is_worker)))
    if is_worker.value == 0:
        kvstore = create('dist')
        server = KVStoreServer(kvstore)
        server.run()
        sys.exit()

_init_kvstore_server_module()


#!/usr/bin/env python
# -*- coding: utf-8 -*- getSentence.py
# -*- coding: utf-8 -*- @author LxEgotist
# -*- coding: utf-8 -*- @description
# -*- coding: utf-8 -*- @created 2020-11-09T18:11:34.138Z+08:00
# -*- coding: utf-8 -*- @last-modified 2020-11-09T18:18:27.061Z+08:00
#
from pathlib import Path
import json,random
data_pth=Path('.')/'LxBot'/'data'
def getSentence(type:str)->str:
	with open(data_pth/'sentence.json','r') as f:
		js=json.load(f)
	return random.choice(js)


#!/usr/bin/env python
from distutils.core import setup
from os.path import dirname, realpath
from setuptools import find_packages
from setuptools.command.test import test as TestCommand
import sys

pip_requirements = 'requirements.txt'

class Tox(TestCommand):
    """The test command should install and then run tox.

    Based on http://tox.readthedocs.org/en/latest/example/basic.html
    """
    def finalize_options(self):
        super().finalize_options()
        self.test_args = []
        self.test_suite = True

    def run_tests(self):
        import tox  # Import here, because outside eggs aren't loaded.
        sys.exit(tox.cmdline(self.test_args))

setup(
    # Basic Metadata
    name='django_jinja_middleware',
    version=open('VERSION').read().strip(),
    author='Luke Sneeringer',
    author_email='luke@sneeringer.com',
    url='https://github.com/lukesneeringer/django-jinja/',

    # Additional information
    description=' '.join((
        'Django middleware class that takes TemplateResponses and',
        'renders them with Jinja, instead of the Django stock',
        'templating language. For Python 2 or Python 3, and Django >= 1.4',
    )),
    license='New BSD',

    # How to do the install...
    install_requires=open(pip_requirements, 'r').read().strip().split('\n'),
    packages=[i for i in find_packages() if i.startswith('django_jinja')],
    provides=['django_jinja'],

    # Running tests
    tests_require=['tox'],
    cmdclass={'test': Tox },

    # Data files
    package_data={
        'django_jinja': ['VERSION'],
    },

    # searches and classifications
    keywords='django,jinja,middleware',
    classifiers=[
        'Development Status :: 5 - Production/Stable',
        'Environment :: Web Environment',
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3.3',
        'Topic :: Software Development',
    ],
)


import unittest
import random
import logging

from migen import *
from migen.genlib.record import *

from tbsupport import *
from core_init import resolve_defaults
from configparser import ConfigParser

from fifo_network import Network, MultiNetwork

def get_generators(self, num_rounds):
    sent = [[] for _ in range(self.tb.config.addresslayout.num_pe)]
    received = [[] for _ in range(self.tb.config.addresslayout.num_pe)]
    num_sent = [[0 for _ in range(self.tb.config.addresslayout.num_pe)] for _ in range(self.tb.config.addresslayout.num_pe)]
    for node in self.tb.graph:
        for neighbor in self.tb.graph[node]:
            sender_pe = self.tb.config.addresslayout.pe_adr(node)
            dest_pe = self.tb.config.addresslayout.pe_adr(neighbor)
            msg = {"dest_id": neighbor, "sender": node, "payload": 0, "barrier":0, "dest_pe": dest_pe}
            sent[sender_pe].append(msg)
            num_sent[sender_pe][dest_pe] += 1
            received[dest_pe].append(msg)

    # print("Messages to send:")
    # for pe in range(self.tb.config.addresslayout.num_pe):
    #     print("PE {}: {}".format(pe, sent[pe]))

    def gen_input(pe, num_rounds):
        fpga = pe // self.tb.config.addresslayout.num_pe_per_fpga
        local_pe = pe % self.tb.config.addresslayout.num_pe_per_fpga
        network_interface = self.tb.dut[fpga].network_interface[local_pe]
        for roundpar in range(num_rounds):
            messages = sent[pe].copy()
            while messages:
                msg = messages.pop(random.randrange(len(messages)))
                yield (network_interface.msg.dest_id.eq(msg["dest_id"]))
                yield (network_interface.msg.sender.eq(msg["sender"]))
                yield (network_interface.msg.payload.eq(msg["payload"]))
                yield (network_interface.msg.barrier.eq(msg["barrier"]))
                yield (network_interface.msg.roundpar.eq(roundpar))
                yield (network_interface.dest_pe.eq(msg["dest_pe"]))
                yield (network_interface.valid.eq(random.choice([0,1])))
                yield
                while not ((yield network_interface.valid) and (yield network_interface.ack)):
                    yield (network_interface.valid.eq(1)) #random.choice([0,1])
                    yield
            messages = [{"dest_id": num_sent[pe][i], "sender": pe << log2_int(self.tb.config.addresslayout.num_nodes_per_pe), "payload": 0, "barrier": 1, "dest_pe": i} for i in range(self.tb.config.addresslayout.num_pe)]
            while messages:
                msg = messages.pop(random.randrange(len(messages)))
                yield (network_interface.msg.dest_id.eq(msg["dest_id"]))
                yield (network_interface.msg.sender.eq(msg["sender"]))
                yield (network_interface.msg.payload.eq(msg["payload"]))
                yield (network_interface.msg.barrier.eq(msg["barrier"]))
                yield (network_interface.msg.roundpar.eq(roundpar))
                yield (network_interface.dest_pe.eq(msg["dest_pe"]))
                yield (network_interface.valid.eq(random.choice([0,1])))
                yield
                while not ((yield network_interface.valid) and (yield network_interface.ack)):
                    yield (network_interface.valid.eq(1)) #random.choice([0,1])
                    yield
        yield (network_interface.valid.eq(0))
        yield

    def gen_output(pe, num_rounds):
        fpga = pe // self.tb.config.addresslayout.num_pe_per_fpga
        local_pe = pe % self.tb.config.addresslayout.num_pe_per_fpga
        apply_interface = self.tb.dut[fpga].apply_interface[local_pe]
        logger = logging.getLogger('gen_output')
        for roundpar in range(num_rounds):
            messages = received[pe].copy()
            logger.info("PE {} entering round {}.".format(pe, roundpar))
            logger.debug("Messages expected: {}".format(messages))
            while messages:
                yield (apply_interface.ack.eq(random.choice([0,1])))
                if (yield apply_interface.valid) and (yield apply_interface.ack):
                    dest_id = yield apply_interface.msg.dest_id
                    sender = yield apply_interface.msg.sender
                    payload = yield apply_interface.msg.payload
                    barrier = yield apply_interface.msg.barrier
                    rnd = yield apply_interface.msg.roundpar
                    logger.debug("PE {} received message ({} -> {})".format(pe, sender, dest_id))
                    self.assertFalse(barrier)
                    self.assertEqual(rnd, roundpar)
                    for msg in messages:
                        if (msg["dest_id"] == dest_id) and (msg["sender"] == sender):
                            messages.remove(msg)
                            break
                    else:
                        self.fail("PE {} received message it wasn't supposed to: {} -> {} (dest_pe={})".format(pe, sender, dest_id, self.tb.config.addresslayout.pe_adr(dest_id)))
                yield
            logger.info("PE {} received all messages of round {}".format(pe, roundpar))

            while True:
                yield (apply_interface.ack.eq(random.choice([0,1])))
                if (yield apply_interface.valid) and (yield apply_interface.ack):
                    dest_id = yield apply_interface.msg.dest_id
                    sender = yield apply_interface.msg.sender
                    payload = yield apply_interface.msg.payload
                    barrier = yield apply_interface.msg.barrier
                    rnd = yield apply_interface.msg.roundpar
                    logger.debug("PE {} received barrier (round {})".format(pe, rnd))
                    self.assertTrue(barrier)
                    self.assertEqual(rnd, roundpar, "PE {} expected round {} but received round {}".format(pe, roundpar, rnd))
                    break
                yield
            yield
        yield (apply_interface.ack.eq(0))

    @passive
    def gen_timeout(cycles):
        time = 0
        while time < cycles:
            yield
            time += 1
        self.fail("Timeout")

    return [gen_input(i,num_rounds) for i in range(self.tb.config.addresslayout.num_pe)] + [gen_output(i,num_rounds) for i in range(self.tb.config.addresslayout.num_pe)] + [gen_timeout(500*num_rounds)]

class NetworkCase(SimCase, unittest.TestCase):
    class TestBench(Module):
        def __init__(self):
            configparser = ConfigParser()
            configparser['arch'] = {'num_pe' : 8}
            configparser['graph'] = {}
            configparser['app'] = {'algo': "bfs"}
            configparser['logging'] = {'log_file_name': "unittest_network", 'disable_logfile': False}

            self.config = resolve_defaults(configparser, num_nodes=32, num_edges=32*4)
            self.graph = self.config.adj_dict

            self.submodules.dut = [Network(self.config)]

    def test_network(self):
        num_rounds = 3
        self.run_with(get_generators(self, num_rounds), vcd_name="unittest_network.vcd")

class MultiNetworkCase(SimCase, unittest.TestCase):
    class TestBench(Module):
        def __init__(self):
            configparser = ConfigParser()
            configparser['arch'] = {'num_pe': 4, 'num_fpga': 2}
            configparser['graph'] = {}
            configparser['app'] = {'algo': "bfs"}
            configparser['logging'] = {'log_file_name': "unittest_network", 'disable_logfile': False}

            self.config = resolve_defaults(configparser, num_nodes=32, num_edges=32*4)
            self.graph = self.config.adj_dict

            self.submodules.dut = [MultiNetwork(self.config, fpga_id=i) for i in range(self.config.addresslayout.num_fpga)]

            # inter-core communication
            for i in range(self.config.addresslayout.num_fpga):
                core_idx = 0
                for j in range(self.config.addresslayout.num_fpga - 1):
                    if i == j:
                        core_idx += 1
                    if j < i:
                        if_idx = i - 1
                    else:
                        if_idx = i
                    # print("Connecting core {} out {} to core {} in {}".format(i, j, core_idx, if_idx))
                    self.comb += self.dut[i].external_network_interface_out[j].connect(self.dut[core_idx].external_network_interface_in[if_idx])
                    core_idx += 1

    def test_network(self):
        num_rounds = 3
        self.run_with(get_generators(self, num_rounds), vcd_name="test_network.vcd")

if __name__ == "__main__":
    random.seed(42)
    unittest.main()


from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
import time
import csv

def crawlPlayerLinks(rootUrl,year):
    bio = dict()
    parseFlag = 0
    count = 1
    try:
        # url that we are scraping
        url = rootUrl
        # this is the html from the given url
        html = urlopen(url)
        soup = BeautifulSoup(html, "html.parser")
        parseFlag = 1
    except:
        print ("Unable to Parse Draft Page")

    if parseFlag == 1:
        results = soup.find('table', {"id" : "stats"}).find('tbody').find_all('tr')

        sampleSize = len(results)

        for result in results:
            if count <= sampleSize:
                flag = 0
                try:
                    result1 = result.find('td', {"data-stat" : "player"}).find('a')
                    result2 = result.find('td', {"data-stat" : "college_name"})
                    result3 = result.find('td', {"data-stat" : "pick_overall"})
                    bio['link'] = result1["href"]
                    bio['name'] = result1.text
                    bio['year'] = year
                    bio['pick'] = result3["csk"]
                    if result2["csk"] == "Zzz":
                        bio["university"] = ""
                    else:
                        bio["university"] = result2["csk"]
                        flag = 1
                except:
                    pass
                if flag == 1:
                    time.sleep(2)
                    crawlPlayerStats("http://www.basketball-reference.com" + bio['link'], bio)
            print (count," / ",sampleSize, " Completed")
            count = count + 1

def crawlPlayerStats(playerUrl, bio):
    stats = dict()
    parseFlag = 0
    crawled = 0
    try:
        # url that we are scraping
        url = playerUrl
        # this is the html from the given url
        html = urlopen(url)
        soup = BeautifulSoup(html, "html.parser")
        parseFlag = 1
    except:
        print ("Unable to Parse Player Page")
        print (bio)

    if parseFlag == 1:
        try:
            result = soup.find('div', { "id" : "wrap" }).find('div',  {"id" : "content"}).find('div',  {"id" : "all_all_college_stats"})
            result = str(result)
            result = result.replace("<!--","").replace("-->","")
            soup = BeautifulSoup(result, "html.parser")
            results = soup.find('div', {"class" : "table_outer_container"}).find('div', {"id":"div_all_college_stats"}).find('table').find('tfoot').find('tr').findAll('td', {"class" : "right"})
            stats_length = len(results)
            if stats_length == 23:
                for result in results:
                    stats[result["data-stat"]] = result.text
                crawled = 1
            else:
                print ("Unknown number of stats")
                print (bio)
            if crawled == 1:
                print ("Sucessful Crawl ...")
                bio_summary = []
                stats_summary = []
                bio_summary.extend((bio['pick'],bio['year'],bio['name'],bio["university"],bio['link']))
                stats_summary.extend((stats['g'],stats['mp'],stats['fg'],stats['fga'],stats['fg3'],stats['fg3a'],stats['ft'],stats['fta'],stats['orb'],stats['trb'],stats['ast'],stats['stl'],stats['blk'],stats['tov'],stats['pf'],stats['pts'],stats['fg_pct'],stats['fg3_pct'],stats['ft_pct'],stats['mp_per_g'],stats['pts_per_g'],stats['trb_per_g'],stats['ast_per_g']))
                bio_summary_str = ','.join(map(str, bio_summary))
                stats_summary_str = ','.join(map(str, stats_summary))
                summary =  bio_summary_str + "," + stats_summary_str
                # bio_summary = ",".join(bio.values())
                # stats_summary = ",".join(stats.values())
                # summary = bio_summary + ","  + stats_summary
                # bio_key = ','.join(bio.keys())
                # stats_key = ','.join(stats.keys())
                # summary_key = bio_key + ","  + stats_key
                storeCsv(summary, bio["year"])

        except:
            print ("College Stats not Found")
            print (bio)

def storeCsv(summary, year):
    filename = "Datasets/" + year + "Draft.csv"
    with open(filename,'a') as file:
        file.write(summary)
        file.write('\n')
    print ("Stored Sucessfully")

for i in range(2003,2004):
    print ("Initiated Crawler for :", str(i))
    year = str(i)
    rootUrl = "https://www.basketball-reference.com/draft/NBA_" + year + ".html"
    crawlPlayerLinks(rootUrl, year)


# pounds = int(input())
#
# dollars = pounds*1.31
# print(f"{dollars:.3f}")

from forex_python.converter import CurrencyRates

pounds = int(input("Amount in GBP: "))
c = CurrencyRates()
currency_rate = c.get_rate("BGP", "USD")
dollars = pounds * currency_rate

print(f"{dollars:.3f}")

3. Data Types and Variables - Lab/3.5. Pounds to Dollars.py


from unittest import TestCase
from jsoncfg.config_classes import (
    ValueNotFoundNode, ConfigJSONScalar, ConfigJSONObject, ConfigJSONArray, JSONConfigNodeTypeError, ConfigNode,
    JSONConfigIndexError,
)
from jsoncfg import JSONConfigValueNotFoundError, JSONParserParams, JSONValueMapper
from jsoncfg import (
    loads_config, node_location, node_exists, node_is_object, node_is_array,
    node_is_scalar, ensure_exists, expect_object, expect_array, expect_scalar,
)

from .utils import WrapCallable

TEST_JSON_STRING = """
{
    int: 5,
    float: 1.5,
    str: "strval",
    null: null,
    true: true,
    false: false,
    array: [{a:0},{b:1}],
    obj: {},
}
"""

class TestValueNotFoundNode(TestCase):
    def test_len(self):
        config = loads_config('{}')
        not_found_node = config.woof
        self.assertIsInstance(not_found_node, ValueNotFoundNode)
        self.assertRaises(JSONConfigValueNotFoundError, lambda: len(not_found_node))

    def test_iter(self):
        config = loads_config('{}')
        not_found_node = config.woof
        self.assertIsInstance(not_found_node, ValueNotFoundNode)
        self.assertRaises(JSONConfigValueNotFoundError, lambda: iter(not_found_node))

    def test_indexing(self):
        config = loads_config('{}')
        not_found_node = config.woof
        self.assertIsInstance(not_found_node, ValueNotFoundNode)
        case0 = not_found_node[100][100]
        self.assertRaises(JSONConfigValueNotFoundError, case0)
        case1 = not_found_node['a']['b']
        self.assertRaises(JSONConfigValueNotFoundError, case1)

class TestJSONValueMapper(TestCase):
    def test_call(self):
        self.assertRaises(NotImplementedError, JSONValueMapper(), None)

class TestConfigNode(TestCase):
    def test_value_fetch(self):
        config = loads_config('{a:0, b:{}, c:[]}')
        scalar = config.a
        obj = config.b
        array = config.c
        not_found = config.d

        self.assertIsInstance(scalar, ConfigJSONScalar)
        self.assertIsInstance(obj, ConfigJSONObject)
        self.assertIsInstance(array, ConfigJSONArray)
        self.assertIsInstance(not_found, ValueNotFoundNode)

        default = object()
        self.assertEqual(scalar(default), 0)
        self.assertEqual(obj(default), {})
        self.assertEqual(array(default), [])
        self.assertEqual(not_found(default), default)

    def test_value_fetch_not_json_value_mapper_instance(self):
        config = loads_config('{a:0}')
        self.assertRaisesRegexp(TypeError, r'1 isn\'t a JSONValueMapper instance!',
                                WrapCallable(config.a), 0, 1)

    def test_unimplemented_fetch_unwrapped_value(self):
        self.assertRaises(NotImplementedError, ConfigNode(0, 0)._fetch_unwrapped_value)

class TestConfigJSONScalar(TestCase):
    def test_len(self):
        config = loads_config('[0]', parser_params=JSONParserParams(root_is_array=True))
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to access the __len__ of a scalar config object\.',
            len,
            config[0],
        )

    def test_iter(self):
        config = loads_config('[0]', parser_params=JSONParserParams(root_is_array=True))
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to iterate a scalar value\.',
            iter,
            config[0],
        )

    def test_contains(self):
        config = loads_config('[0]', parser_params=JSONParserParams(root_is_array=True))
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to access the __contains__ magic method of a scalar config object\.',
            config[0].__contains__,
            0,
        )

    def test_getattr(self):
        config = loads_config('[0]', parser_params=JSONParserParams(root_is_array=True))
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to get an item from a scalar as if it was an object\.',
            config[0].__getattr__,
            'woof',
        )

    def test_getitem(self):
        config = loads_config('[0]', parser_params=JSONParserParams(root_is_array=True))
        self.assertRaisesRegexp(
            TypeError,
            r'You are allowed to index only with string or integer\.',
            config[0].__getitem__,
            None,
        )
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to index into a scalar as if it was an array\.',
            config[0].__getitem__,
            0,
        )
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to get an item from a scalar as if it was an object\.',
            config[0].__getitem__,
            'item',
        )

    def test_repr(self):
        config = loads_config('[0]', parser_params=JSONParserParams(root_is_array=True))
        repr(config[0])

class TestConfigJSONObject(TestCase):
    def test_len(self):
        config = loads_config('{k0:0, k1:1}')
        self.assertEqual(len(config), 2)

    def test_iter(self):
        config = loads_config('{k0:0, k1:1}')
        result = {k: v() for k, v in config}
        self.assertDictEqual(result, {'k0': 0, 'k1': 1})

    def test_contains(self):
        config = loads_config('{k0:0}')
        self.assertTrue('k0' in config)
        self.assertFalse('k1' in config)

    def test_getitem(self):
        config = loads_config(TEST_JSON_STRING)
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to index into an object as if it was an array\.',
            config.__getitem__,
            0,
        )
        self.assertRaisesRegexp(
            TypeError,
            r'You are allowed to index only with string or integer\.',
            config.__getitem__,
            None,
        )
        self.assertIsInstance(config.not_found, ValueNotFoundNode)

    def test_item_not_found(self):
        config = loads_config(TEST_JSON_STRING)
        self.assertRaises(JSONConfigValueNotFoundError, config.nonexistent)

    def test_repr(self):
        config = loads_config(TEST_JSON_STRING)
        repr(config)

class TestConfigJSONArray(TestCase):
    @staticmethod
    def loads_array_config(json_string):
        return loads_config(json_string, JSONParserParams(root_is_array=True))

    def test_len(self):
        config = self.loads_array_config('[0, 1]')
        self.assertEqual(len(config), 2)

    def test_iter(self):
        config = self.loads_array_config('[0, 1]')
        items = set(config_val() for config_val in config)
        self.assertSetEqual(items, {0, 1})

    def test_contains(self):
        config = self.loads_array_config('[]')
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to access the __contains__ magic method of an array\.',
            config.__contains__,
            0,
        )

    def test_getattr(self):
        config = loads_config(TEST_JSON_STRING)
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to get an item from an array as if it was an object\.',
            config.array.__getattr__,
            'item',
        )

    def test_getitem(self):
        config = loads_config(TEST_JSON_STRING)
        self.assertEquals(config.array[0].a(), 0)
        self.assertEquals(config.array[1].b(), 1)
        self.assertRaisesRegexp(
            TypeError,
            r'You are allowed to index only with string or integer\.',
            config.array.__getitem__,
            None,
        )
        self.assertRaisesRegexp(
            JSONConfigNodeTypeError,
            r'You are trying to get an item from an array as if it was an object\.',
            config.array.__getitem__,
            'item',
        )

    def test_getitem_with_negative_index(self):
        config = loads_config(TEST_JSON_STRING)
        self.assertDictEqual(config.array[-1](), {'b': 1})
        self.assertDictEqual(config.array[-2](), {'a': 0})
        self.assertRaises(
            JSONConfigIndexError,
            config.array.__getitem__,
            -3,
        )
        self.assertRaises(
            JSONConfigIndexError,
            config.array.__getitem__,
            2,
        )

    def test_repr(self):
        config = loads_config(TEST_JSON_STRING)
        repr(config.array)

class TestUtilityFunctions(TestCase):
    def test_node_location(self):
        config = loads_config('\n{k0:0}')
        location = node_location(config)
        self.assertEquals(location, (2, 1))
        self.assertEquals(location.line, 2)
        self.assertEquals(location.column, 1)

    def test_node_location_with_value_not_found_node(self):
        config = loads_config('{}')
        self.assertRaises(JSONConfigValueNotFoundError, node_location, config.a)

    def test_node_location_with_invalid_value(self):
        self.assertRaisesRegexp(TypeError, r'Expected a config node but received a list instance.',
                                node_location, [])

    def test_node_exists(self):
        config = loads_config('{k0:0}')
        self.assertTrue(node_exists(config))
        self.assertTrue(node_exists(config.k0))
        self.assertFalse(node_exists(config.not_found))

    def test_node_is_object(self):
        config = loads_config('{k0:0}')
        self.assertTrue(node_is_object(config))
        self.assertFalse(node_is_object(config.k0))
        self.assertFalse(node_is_object(config.not_found))

    def test_node_is_array(self):
        config = loads_config('{a:[0]}')
        self.assertTrue(node_is_array(config.a))
        self.assertFalse(node_is_array(config.a[0]))
        self.assertFalse(node_is_array(config.not_found))

    def test_node_is_scalar(self):
        config = loads_config('{a:[0]}')
        self.assertFalse(node_is_scalar(config.a))
        self.assertTrue(node_is_scalar(config.a[0]))
        self.assertFalse(node_is_scalar(config.not_found))

    def test_ensure_exists(self):
        config = loads_config('{}')
        self.assertIs(config, ensure_exists(config))
        self.assertRaises(JSONConfigValueNotFoundError, ensure_exists, config.a)
        self.assertRaises(TypeError, ensure_exists, None)

    def test_expect_object(self):
        config = loads_config('{a:0}')
        self.assertIs(config, expect_object(config))
        self.assertRaises(JSONConfigValueNotFoundError, expect_object, config.b)
        self.assertRaises(JSONConfigNodeTypeError, expect_object, config.a)
        self.assertRaises(TypeError, expect_object, None)

    def test_expect_array(self):
        config = loads_config('{a:[0]}')
        self.assertIs(config.a, expect_array(config.a))
        self.assertRaises(JSONConfigValueNotFoundError, expect_array, config.not_found)
        self.assertRaises(JSONConfigNodeTypeError, expect_array, config.a[0])
        self.assertRaises(TypeError, expect_array, None)

    def test_expect_scalar(self):
        config = loads_config('{a:[0]}')
        self.assertIs(config.a[0], expect_scalar(config.a[0]))
        self.assertRaises(JSONConfigValueNotFoundError, expect_scalar, config.not_found)
        self.assertRaises(JSONConfigNodeTypeError, expect_scalar, config)
        self.assertRaises(TypeError, expect_scalar, None)


import torch
from torch import nn

class Discriminator(nn.Module):
    def __init__(self, cfg):
        super(Discriminator, self).__init__()
        self.cfg = cfg
        self.device = torch.device(self.cfg.Device)
        self.discriminator = nn.Sequential(
            nn.Conv2d(3, 64, 4, 2, 1, bias=False), nn.LeakyReLU(0.2),
            nn.Conv2d(64, 128, 4, 2, 1, bias=False), nn.BatchNorm2d(128), nn.LeakyReLU(0.2),
            nn.Conv2d(128, 256, 4, 2, 1, bias=False), nn.BatchNorm2d(256), nn.LeakyReLU(0.2),
            nn.Conv2d(256, 256, 4, 2, 1, bias=False), nn.BatchNorm2d(256), nn.LeakyReLU(0.2),
            nn.Conv2d(256, 512, 4, 2, 1, bias=False), nn.BatchNorm2d(512), nn.LeakyReLU(0.2),
            nn.Conv2d(512, 512, 4, 2, 1, bias=False), nn.BatchNorm2d(512), nn.LeakyReLU(0.2),
            nn.Conv2d(512, 1, 3, 1, bias=False))
        self.to(self.device)

    def forward(self, x):
        return self.discriminator(x).view(x.shape[0],-1)


import random
import unittest
from contextlib import contextmanager
from datetime import datetime
from typing import Optional

from django.core.exceptions import ValidationError
from django.utils import timezone
from hypothesis import given
from hypothesis.extra.django import TestCase as HypTestCase
from hypothesis.extra.django import from_model
from hypothesis.strategies import (
    SearchStrategy,
    integers,
    just,
    lists,
    none,
    one_of,
    sampled_from,
    text,
    tuples,
)
from model_bakery import baker

from apps.rubrics.fixtures import make_test_rubric
from apps.rubrics.forms import ChoiceForm, QuestionForm
from apps.rubrics.models.rubric import (
    Choice,
    Question,
    QuestionResponse,
    Rubric,
    RubricResponse,
    value_is_numeric,
)
from apps.rubrics.tests.base import TestBase

def fixed_decimals(
    min_value: float = 0, max_value: float = 1, num_decimals=3
) -> SearchStrategy:
    power_of_ten = 10**num_decimals
    return integers(
        min_value=(min_value * power_of_ten), max_value=(max_value * power_of_ten)
    ).map(lambda x: x / power_of_ten)

def sane_text(min_size=0, max_size=1024) -> SearchStrategy:
    return text(
        alphabet=[chr(i) for i in range(33, 126)],
        min_size=min_size,
        max_size=max_size,
    )

def question_type() -> SearchStrategy:
    return sampled_from(Question.CHOICE_TYPES)

def question_type_and_weight() -> SearchStrategy:
    return one_of(
        tuples(sampled_from(Question.CHOICE_TYPES), fixed_decimals()),
        tuples(
            sampled_from(
                sorted(set(Question.available_types()) - set(Question.CHOICE_TYPES))
            ),
            just(0),
        ),
    )

def questions(rubric: Rubric) -> SearchStrategy:
    def create_question(type_and_weight: tuple) -> SearchStrategy:
        return from_model(
            Question,
            rubric=just(rubric),
            question_type=just(type_and_weight[0]),
            weight=just(type_and_weight[1]),
            short_description=sane_text(),
        )

    return question_type_and_weight().flatmap(create_question)

def rubric_with_questions(
    min_questions: int = 0, max_questions: Optional[int] = None
) -> SearchStrategy:
    def add_questions(rubric: Rubric) -> SearchStrategy:
        return lists(
            elements=questions(rubric),
            min_size=min_questions,
            max_size=max_questions,
            unique=True,
        ).flatmap(lambda _: just(rubric))

    return from_model(Rubric).flatmap(add_questions)

def create_rubric_with_questions_and_choices():
    rubric = baker.make(Rubric)
    for _ in range(0, 10):
        required = bool(random.getrandbits(1))
        question = baker.make(Question, rubric=rubric, required=required)
        if question.show_choices():
            for a in range(0, 5):
                baker.make(Choice, question=question)

    return rubric

class RubricTests(HypTestCase):
    @given(sane_text(min_size=1))
    def test_create_rubric(self, name: str):
        rubric = Rubric.objects.create(name=name)
        self.assertEqual(rubric.name, name)
        self.assertQuerysetEqual(
            Rubric.objects.all(), ["<Rubric: %s>" % name], transform=repr
        )

    def test_create_rubric_fails_for_empty_name(self):
        with self.assertRaises(ValidationError):
            Rubric.objects.create(name="")
        self.assertQuerysetEqual(Rubric.objects.all(), [])

class QuestionTests(HypTestCase):
    @classmethod
    def setUpClass(cls):
        super(QuestionTests, cls).setUpClass()
        cls.rubric = create_rubric_with_questions_and_choices()

    def test_is_allowed_type(self):
        self.assertTrue(Question.is_allowed_type(Question.LONG_TEXT))
        self.assertFalse(Question.is_allowed_type("Some Google Type"))

    def test_is_allowed_sort(self):
        self.assertTrue(Question.is_allowed_sort(Question.AUTO_SORT))
        self.assertFalse(Question.is_allowed_sort("Some Google Sort"))

    def test_num_choices(self):
        for number, question in enumerate(self.rubric.question_set.all(), start=1):
            with self.subTest("Question %(number)s", number=number):
                if question.show_choices():
                    self.assertIsInstance(question.num_choices_display(), int)
                    self.assertEqual(question.num_choices_display(), 5)
                else:
                    self.assertEqual(question.num_choices_display(), "-")

    @given(question_type=sane_text())
    def test_invalid_question_type_raises_error(self, question_type):
        with self.assertRaises(ValidationError):
            baker.make(Question, rubric=self.rubric, question_type=question_type)

    @given(
        sort_option=one_of(sane_text().filter(lambda x: x != "A" and x != "M"), none())
    )
    def test_invalid_sort_option_raises_error(self, sort_option):
        with self.assertRaises(
            ValidationError,
            msg="No error raised for sort_option {}".format(sort_option),
        ):
            baker.make(
                Question,
                rubric=self.rubric,
                question_type=Question.LONG_TEXT,
                choice_sort=sort_option,
            )

    @given(fixed_decimals(min_value=0.001))
    def test_unweighted_question_type_with_non_zero_weight_raises_value_error(
        self, weight
    ):
        with self.assertRaises(ValidationError):
            baker.make(
                Question,
                rubric=self.rubric,
                question_type=Question.LONG_TEXT,
                weight=weight,
            )

    def test_add_choice(self):
        def add_choices(question):
            question.add_choice(1, "Low")
            question.add_choice(10, "High")

        with self.subTest("%(type)s question", type=Question.SCALE_TYPE):
            question = baker.make(
                Question, question_type=Question.SCALE_TYPE, rubric=self.rubric
            )
            add_choices(question)
            self.assertQuerysetEqual(
                question.choice_set.order_by("description").all(),
                ["<Choice: High>", "<Choice: Low>"],
                transform=repr,
            )

        with self.subTest("%(type)s question", type=Question.LONG_TEXT):
            question = baker.make(
                Question, question_type=Question.LONG_TEXT, rubric=self.rubric
            )
            with self.assertRaises(ValidationError):
                add_choices(question)

    @given(question_type_and_weight(), question_type_and_weight())
    def test_question_type_changed(self, q1: (str, float), q2: (str, float)):
        question = baker.make(Question, question_type=q1[0], weight=0)  # type: Question
        self.assertEqual(question.question_type, q1[0])
        question.question_type = q2[0]
        self.assertEqual(question.question_type, q2[0])

        if q1[0] == q2[0]:
            self.assertFalse(question.question_type_changed())
        else:
            self.assertTrue(question.question_type_changed())

    @given(question_type_and_weight(), question_type_and_weight())
    def test_question_type_changed_compatibility(
        self, q1: (str, float), q2: (str, float)
    ):
        compatible_types = (Question.SCALE_TYPE, Question.SINGLE_SELECT_TYPE)
        question = baker.make(Question, question_type=q1[0], weight=0)  # type: Question
        self.assertEqual(question.question_type, q1[0])
        question.question_type = q2[0]
        self.assertEqual(question.question_type, q2[0])

        if q1[0] == q2[0]:
            self.assertFalse(question.question_type_changed_compatibility())
        elif (q1[0] in compatible_types) and (q2[0] in compatible_types):
            self.assertFalse(question.question_type_changed_compatibility())
        else:
            self.assertTrue(question.question_type_changed_compatibility())

class QuestionFormTests(HypTestCase):
    @classmethod
    def setUpClass(cls):
        super(QuestionFormTests, cls).setUpClass()
        cls.rubric = baker.make(Rubric)  # type: Rubric
        cls.data = {
            "rubric": cls.rubric.pk,
            "order": 1,
            "short_description": "Test Question",
            "long_description": "This question is very important",
            "help_text": "This is help text for the question",
            "weight": 0,
            "question_type": Question.SCALE_TYPE,
            "choice_sort": Question.MANUAL_SORT,
            "required": True,
        }
        data = cls.data.copy()
        data["rubric"] = cls.rubric
        cls.question = Question.objects.create(**data)  # type: Question

    def get_test_data_and_form(
        self, updated_data: dict, instance: Question = None
    ) -> tuple:
        data = self.data.copy()
        if updated_data:
            data.update(updated_data)
        form = QuestionForm(data, instance=instance)
        return data, form

    def success_test(self, instance: Question = None, **updated_data):
        data, form = self.get_test_data_and_form(updated_data, instance=instance)
        self.assertTrue(form.is_valid())
        question = form.save(commit=False)
        for key, value in data.items():
            if key == "rubric":
                self.assertEqual(value, question.rubric.pk)
            else:
                self.assertEqual(value, getattr(question, key, None))

    def failed_test(self, instance: Question = None, **updated_data):
        data, form = self.get_test_data_and_form(updated_data, instance=instance)
        self.assertFalse(form.is_valid())
        with self.assertRaises(ValueError):
            form.save(commit=False)

    def test_valid_data(self):
        self.success_test()

    def test_invalid_question_type(self):
        self.failed_test(question_type="invalid question type")

    def test_invalid_sort(self):
        self.failed_test(choice_sort="Q")

    def test_negative_weight(self):
        self.failed_test(weight=-0.5)

    def test_weight_with_non_choice_type(self):
        self.failed_test(weight=0.5, question_type=Question.LONG_TEXT)

    def test_instance_with_numeric_choices_and_zero_weight(self):
        self.question.weight = 1
        self.question.save()
        baker.make(Choice, question=self.question, key="1")
        self.success_test(instance=self.question, weight=0)

    def test_instance_with_numeric_choices_and_positive_weight(self):
        self.question.weight = 0
        self.question.save()
        baker.make(Choice, question=self.question, key="1")
        self.success_test(instance=self.question, weight=1)

    def test_instance_with_non_numeric_choices_and_zero_weight(self):
        self.question.weight = 0
        self.question.save()
        baker.make(Choice, question=self.question, key="test")
        self.success_test(instance=self.question, weight=0)

    def test_instance_with_non_numeric_choices_and_positive_weight(self):
        self.question.weight = 0
        self.question.save()
        baker.make(Choice, question=self.question, key="test")
        self.failed_test(instance=self.question, weight=1)

class ChoiceTests(TestBase):
    @classmethod
    def setUpClass(cls):
        super(ChoiceTests, cls).setUpClass()
        cls.question = baker.make(Question)  # type: Question

    def choice_test_with_positive_weight(self, key):
        self.question.weight = 1.000
        kwargs = {
            "question": self.question,
            "order": 1,
            "key": key,
            "description": "description",
        }
        if not value_is_numeric(key):
            with self.assertRaises(ValidationError):
                Choice.validate(**kwargs)
            c = Choice(**kwargs)
            with self.assertRaises(ValidationError):
                c.save()
        else:
            with self.assertNoException(ValidationError):
                Choice.validate(
                    question=self.question, order=1, key=key, description="description"
                )
            c = Choice(**kwargs)
            with self.assertNoException(ValidationError):
                c.save()

    def choice_test_with_zero_weight(self, key):
        self.question.weight = 0
        kwargs = {
            "question": self.question,
            "order": 1,
            "key": key,
            "description": "description",
        }
        with self.assertNoException(ValidationError):
            Choice.validate(**kwargs)
        c = Choice(**kwargs)
        with self.assertNoException(ValidationError):
            c.save()

    @given(sane_text(min_size=1))
    def test_scale_question_with_positive_weight(self, key):
        self.question.question_type = Question.SCALE_TYPE
        self.choice_test_with_positive_weight(key)

    @given(sane_text(min_size=1))
    def test_scale_question_with_zero_weight(self, key):
        self.question.question_type = Question.SCALE_TYPE
        self.choice_test_with_zero_weight(key)

    @given(sane_text(min_size=1))
    def test_single_select_question_with_positive_weight(self, key):
        self.question.question_type = Question.SINGLE_SELECT_TYPE
        self.choice_test_with_positive_weight(key)

    @given(sane_text(min_size=1))
    def test_single_select_question_with_zero_weight(self, key):
        self.question.question_type = Question.SINGLE_SELECT_TYPE
        self.choice_test_with_zero_weight(key)

    @given(sane_text(min_size=1))
    def test_multi_select_question_with_positive_weight(self, key):
        self.question.question_type = Question.MULTI_SELECT_TYPE
        self.choice_test_with_positive_weight(key)

    @given(sane_text(min_size=1))
    def test_multi_select_question_with_zero_weight(self, key):
        self.question.question_type = Question.MULTI_SELECT_TYPE
        self.choice_test_with_zero_weight(key)

    def test_long_text_question_disallows_choices(self):
        self.question.question_type = Question.LONG_TEXT
        self.question.weight = 0
        kwargs = {
            "question": self.question,
            "order": 1,
            "key": "key",
            "description": "description",
        }
        with self.assertRaises(ValidationError):
            Choice.validate(**kwargs)
        c = Choice(**kwargs)
        with self.assertRaises(ValidationError):
            c.save()

class ChoiceFormTests(HypTestCase):
    def setUp(self):
        self.question = baker.make(Question)  # type: Question

    def update_question(self, question_type, weight):
        self.question.question_type = question_type
        self.question.weight = weight
        self.question.save()

    def success_test(self, data):
        form = ChoiceForm(data)
        self.assertTrue(form.is_valid())
        choice = form.save()
        self.assertEqual(choice.order, data["order"])
        self.assertEqual(choice.key, data["key"])
        self.assertEqual(choice.description, data["description"])

    def failed_test(self, data):
        form = ChoiceForm(data)
        self.assertFalse(form.is_valid())
        with self.assertRaises(ValueError):
            form.save()

    def test_scale_question_with_positive_weight(self):
        self.update_question(Question.SCALE_TYPE, 1.000)

        data = {
            "question": self.question.pk,
            "order": 1,
            "key": "1",
            "description": "description",
        }
        self.success_test(data)

        data = {
            "question": self.question.pk,
            "order": 2,
            "key": "key",
            "description": "description",
        }
        self.failed_test(data)

    def test_scale_question_with_zero_weight(self):
        self.update_question(Question.SCALE_TYPE, 0)

        data = {
            "question": self.question.pk,
            "order": 1,
            "key": "1",
            "description": "description",
        }
        self.success_test(data)

        data = {
            "question": self.question.pk,
            "order": 2,
            "key": "key",
            "description": "description",
        }
        self.success_test(data)

    def test_single_select_question_with_positive_weight(self):
        self.update_question(Question.SINGLE_SELECT_TYPE, 1.000)

        data = {
            "question": self.question.pk,
            "order": 1,
            "key": "1",
            "description": "description",
        }
        self.success_test(data)

        data = {
            "question": self.question.pk,
            "order": 2,
            "key": "key",
            "description": "description",
        }
        self.failed_test(data)

    def test_single_select_question_with_zero_weight(self):
        self.update_question(Question.SINGLE_SELECT_TYPE, 0)

        data = {
            "question": self.question.pk,
            "order": 1,
            "key": "1",
            "description": "description",
        }
        self.success_test(data)

        data = {
            "question": self.question.pk,
            "order": 2,
            "key": "key",
            "description": "description",
        }
        self.success_test(data)

    def test_multi_select_question_with_positive_weight(self):
        self.update_question(Question.MULTI_SELECT_TYPE, 1.000)

        data = {
            "question": self.question.pk,
            "order": 1,
            "key": "1",
            "description": "description",
        }
        self.success_test(data)

        data = {
            "question": self.question.pk,
            "order": 2,
            "key": "key",
            "description": "description",
        }
        self.failed_test(data)

    def test_multi_select_question_with_zero_weight(self):
        self.update_question(Question.MULTI_SELECT_TYPE, 0)

        data = {
            "question": self.question.pk,
            "order": 1,
            "key": "1",
            "description": "description",
        }
        self.success_test(data)

        data = {
            "question": self.question.pk,
            "order": 2,
            "key": "key",
            "description": "description",
        }
        self.success_test(data)

    def test_long_text_question_with_positive_weight(self):
        with self.assertRaises(ValidationError):
            self.update_question(Question.LONG_TEXT, 1.000)

    def test_long_text_question_with_zero_weight(self):
        self.update_question(Question.LONG_TEXT, 0)

        data = {
            "question": self.question.pk,
            "order": 1,
            "key": "1",
            "description": "description",
        }
        self.failed_test(data)

        data = {
            "question": self.question.pk,
            "order": 2,
            "key": "key",
            "description": "description",
        }
        self.failed_test(data)

class RubricResponseTests(HypTestCase):
    def make_rubric_response(self, rubric=None):
        if not rubric:
            rubric = create_rubric_with_questions_and_choices()
        rub_resp = RubricResponse(rubric=rubric)
        rub_resp.save()
        return rub_resp

    def test_has_response(self, rubric=None):
        if not rubric:
            rubric = create_rubric_with_questions_and_choices()

        rubric_response = self.make_rubric_response(rubric=rubric)
        self.assertFalse(rubric_response.has_response)

        q_resp = rubric_response.questionresponse_set.first()
        self.assertIsNotNone(q_resp)
        self.assertFalse(q_resp.question_answered)

        self.answer_question(q_resp)
        self.assertTrue(rubric_response.has_response)
        self.assertTrue(q_resp.question_answered)

    def test_complete(self, rubric=None):
        if not rubric:
            rubric = create_rubric_with_questions_and_choices()

        rubric_response = self.make_rubric_response(rubric=rubric)
        self.assertFalse(rubric_response.complete)

        q_resp = rubric_response.questionresponse_set.first()
        self.assertIsNotNone(q_resp)
        self.assertFalse(q_resp.question_answered)

        self.answer_question(q_resp)
        self.assertTrue(q_resp.question_answered)
        self.assertFalse(rubric_response.complete)

        for q_resp in rubric_response.questionresponse_set.filter(
            question__required=True
        ):
            self.answer_question(q_resp)

        self.assertTrue(rubric_response.complete)

    @staticmethod
    def answer_question(question_resp):
        question = question_resp.question
        if question.question_type == Question.LONG_TEXT:
            question_resp.update_response("This is some long text")
        elif question.question_type == Question.MULTI_SELECT_TYPE:
            choices = [choice[0] for choice in question.choices()]
            question_resp.update_response(choices)
        else:
            question_resp.update_response(next(question.choices()))

    def test_last_submitted(self):
        rub_response = make_rubric_response()

        self.assertIsNone(rub_response.last_submitted)

        answer_rubric_response(rub_response)

        self.assertIsNotNone(rub_response.last_submitted)
        self.assertIsInstance(rub_response.last_submitted, datetime)
        elapsed_seconds = (timezone.now() - rub_response.last_submitted).seconds
        self.assertEqual(elapsed_seconds, 0)

    def test_score(self):
        rub_response = make_rubric_response()

        self.assertEqual(
            rub_response.score(), 0, "Score is not zero before answering the Rubric"
        )

        answer_rubric_response(rub_response)

        self.assertAlmostEqual(
            rub_response.score(), 1.665, 3, "Score incorrect after answering the Rubric"
        )

def make_rubric_response(rubric=None):
    rubric = rubric or make_test_rubric()

    return baker.make(RubricResponse, rubric=rubric)

def answer_rubric_response(rubric_response):
    for q_resp in rubric_response.questionresponse_set.all():
        if q_resp.question.question_type == Question.MULTI_SELECT_TYPE:
            q_resp.update_response(["1", "2"])
        elif q_resp.question.question_type == Question.LONG_TEXT:
            q_resp.update_response(
                "This is a long text response.\nThis is a second line"
            )
        else:
            q_resp.update_response("1")

class QuestionResponseTests(HypTestCase):
    def test_empty_responses(self):
        rub_response = make_rubric_response()
        for response in rub_response.questionresponse_set.select_related(
            "question"
        ).all():
            if response.question.question_type == Question.MULTI_SELECT_TYPE:
                self.assertEqual(
                    response.response,
                    [],
                    "Empty response not equal to %s for question type %s"
                    % ([], response.question.question_type),
                )
            else:
                self.assertEqual(
                    response.response,
                    None,
                    "Empty response not equal to %s for question type %s"
                    % (None, response.question.question_type),
                )

    def test_empty_responses_external(self):
        rub_response = make_rubric_response()
        for response in rub_response.questionresponse_set.select_related(
            "question"
        ).all():
            if response.question.question_type == Question.MULTI_SELECT_TYPE:
                self.assertEqual(
                    response.response_external(),
                    [],
                    "Empty external response not equal to %s for question type %s"
                    % ([], response.question.question_type),
                )
            else:
                self.assertEqual(
                    response.response_external(),
                    None,
                    "Empty external response not equal to %s for question type %s"
                    % (None, response.question.question_type),
                )

    def generic_response_test(self, check_response: callable):
        rub_response = make_rubric_response()
        answer_rubric_response(rub_response)

        for response in rub_response.questionresponse_set.select_related(
            "question"
        ).all():
            check_response(response)

    def test_response(self):
        value_dict = {
            Question.LONG_TEXT: "This is a long text response.\nThis is a second line",
            Question.MULTI_SELECT_TYPE: ["1", "2"],
            "default": "1",
        }

        def check_response(response: QuestionResponse):
            value = value_dict.get(
                response.question.question_type, value_dict["default"]
            )
            self.assertEqual(
                response.response,
                value,
                "Response not equal to %s for question type %s"
                % (value, response.question.question_type),
            )

        self.generic_response_test(check_response)

    def test_response_external(self):
        value_dict = {
            Question.LONG_TEXT: "This is a long text response.\nThis is a second line",
            Question.MULTI_SELECT_TYPE: ["Choice 1", "Choice 2"],
            "default": "Choice 1",
        }

        def check_response(response: QuestionResponse):
            value = value_dict.get(
                response.question.question_type, value_dict["default"]
            )
            self.assertEqual(
                response.response_external(),
                value,
                "Response not equal to %s for question type %s"
                % (value, response.question.question_type),
            )

        self.generic_response_test(check_response)

    def test_score_and_unweighted_score(self):
        def check_response(response: QuestionResponse):
            q_type = response.question.question_type
            if q_type == Question.LONG_TEXT:
                with self.assertRaises(TypeError):
                    response.score()
            elif q_type == Question.MULTI_SELECT_TYPE:
                self.assertAlmostEqual(response.score(), 0.999, places=3)
                self.assertAlmostEqual(response.unweighted_score(), 3)
            else:
                self.assertAlmostEqual(response.score(), 0.333)
                self.assertAlmostEqual(response.unweighted_score(), 1)

        self.generic_response_test(check_response)

    # Choice was updated so that non-numeric choices could not be saved for weighted questions.
    @unittest.expectedFailure
    def test_score_for_non_numeric_choices(self):
        rubric = baker.make(Rubric, name="Test Rubric")
        rub_response = make_rubric_response(rubric)

        question_type = Question.SINGLE_SELECT_TYPE
        question = baker.make(
            Question,
            rubric=rubric,
            short_description="Question %s" % question_type,
            long_description="This is for question %s" % question_type,
            help_text="This is help text for question %s" % question_type,
            weight=1,
            question_type=question_type,
            required=True,
        )
        choices = baker.make(Choice, _quantity=4, question=question)
        q_resp = baker.make(
            QuestionResponse, rubric_response=rub_response, question=question
        )
        q_resp.update_response(choices[0].key)
        self.assertEqual(
            q_resp.score(),
            0,
            msg="Score should be zero for questions with non-numeric choices",
        )

        question_type = Question.MULTI_SELECT_TYPE
        question = baker.make(
            Question,
            rubric=rubric,
            short_description="Question %s" % question_type,
            long_description="This is for question %s" % question_type,
            help_text="This is help text for question %s" % question_type,
            weight=1,
            question_type=question_type,
            required=True,
        )
        choices = baker.make(Choice, _quantity=4, question=question)
        q_resp = baker.make(
            QuestionResponse, rubric_response=rub_response, question=question
        )
        q_resp.update_response([choices[0].key, choices[1].key])
        self.assertEqual(
            q_resp.score(),
            0,
            msg="Score should be zero for questions with non-numeric choices",
        )

    def test_last_saved_date(self):
        rub_response = make_rubric_response()

        for response in rub_response.questionresponse_set.select_related(
            "question"
        ).all():
            self.assertIsNone(response.last_submitted)

        answer_rubric_response(rub_response)
        now = timezone.now()

        for response in rub_response.questionresponse_set.select_related(
            "question"
        ).all():
            self.assertIsNotNone(response.last_submitted)
            self.assertIsInstance(response.last_submitted, datetime)
            elapsed_seconds = (now - response.last_submitted).seconds
            self.assertEqual(elapsed_seconds, 0)

    def test_clear_response(self):
        rub_response = make_rubric_response()
        answer_rubric_response(rub_response)

        for response in rub_response.questionresponse_set.all():
            with self.subTest(response.question.question_type):
                self.assertTrue(response.question_answered)
                response.clear_response()
                self.assertFalse(response.question_answered)

    def test_new_question_is_added_to_response(self):
        rub_response = make_rubric_response()  # type: RubricResponse

        question = baker.make(
            Question,
            rubric=rub_response.rubric,
            short_description="Additional test question",
        )  # type: Question

        self.assertTrue(
            rub_response.questionresponse_set.filter(
                question__short_description="Additional test question"
            ).exists()
        )

        response = rub_response.questionresponse_set.get(
            question__short_description="Additional test question"
        )  # type: QuestionResponse
        self.assertEqual(question, response.question)

    def test_deleted_question_is_removed_from_response(self):
        rub_response = make_rubric_response()  # type: RubricResponse
        num_question_responses = rub_response.questionresponse_set.count()

        question = rub_response.questionresponse_set.first().question  # type: Question

        question.delete()
        self.assertEqual(
            rub_response.questionresponse_set.count(), num_question_responses - 1
        )
        self.assertQuerysetEqual(
            rub_response.questionresponse_set.all(),
            [
                "Test Rubric: Question SINGLE SELECT",
                "Test Rubric: Question MULTI SELECT",
                "Test Rubric: Question LONG TEXT",
            ],
            transform=lambda x: x.question.__str__(),
            ordered=False,
        )

class QuestionResponseClearingTests(HypTestCase):
    @classmethod
    def setUpClass(cls):
        super(QuestionResponseClearingTests, cls).setUpClass()
        cls.rubric = make_test_rubric()

    def setUp(self):
        super(QuestionResponseClearingTests, self).setUp()
        self.rub_response = make_rubric_response(self.rubric)
        answer_rubric_response(self.rub_response)

    def get_question_and_response(
        self, question_type: str
    ) -> (Question, QuestionResponse):
        question = self.rub_response.rubric.question_set.filter(
            question_type=question_type
        ).first()  # type: Question
        response = self.rub_response.questionresponse_set.get(
            question_id=question.id
        )  # type: QuestionResponse

        self.assertTrue(response.question_answered)

        return question, response

    def get_choice_and_response(self, question_type: str) -> (Choice, QuestionResponse):
        question, response = self.get_question_and_response(question_type)
        choice = question.choice_set.first()  # type: Choice
        return choice, response

    @staticmethod
    def update_question_type(question: Question, new_type: str) -> None:
        question.question_type = new_type
        question.save()

    @staticmethod
    def refresh_response(response: QuestionResponse) -> QuestionResponse:
        # Refreshing the response since refresh_from_db doesn't seem to work
        return QuestionResponse.objects.get(id=response.id)  # type: QuestionResponse

    @contextmanager
    def assertOnlyResponseForChoiceCleared(self, question_type: str):
        choice, response = self.get_choice_and_response(question_type)
        yield choice
        self.assertOnlyGivenResponseCleared(response)

    def assertOnlyGivenResponseCleared(self, response: QuestionResponse) -> None:
        for r in self.rub_response.questionresponse_set.all():
            if r.pk == response.pk:
                self.assertFalse(r.question_answered)
            else:
                self.assertTrue(r.question_answered)

    def assertNoResponsesCleared(self):
        for r in self.rub_response.questionresponse_set.all():
            self.assertTrue(r.question_answered)

    @given(question_type())
    def test_clear_responses_when_question_type_changed(self, new_type):
        question, response = self.get_question_and_response(Question.LONG_TEXT)
        self.update_question_type(question, new_type)

        if new_type == Question.LONG_TEXT:
            self.assertNoResponsesCleared()
        else:
            self.assertOnlyGivenResponseCleared(response)

    def test_responses_are_not_cleared_for_special_case(self):
        # Scale type and Single select type are the same with different widgets, so nothing
        # is cleared in this special case.
        for starting_type, new_type in (
            (Question.SCALE_TYPE, Question.SINGLE_SELECT_TYPE),
            (Question.SINGLE_SELECT_TYPE, Question.SCALE_TYPE),
        ):
            with self.subTest("{} -> {}".format(starting_type, new_type)):
                question, response = self.get_question_and_response(starting_type)
                self.update_question_type(question, new_type)
                self.assertNoResponsesCleared()

    @given(question_type().filter(lambda x: x in Question.CHOICE_TYPES))
    def test_clear_responses_when_choice_changes(self, question_type):
        with self.assertOnlyResponseForChoiceCleared(question_type) as choice:
            choice.key = 10000
            choice.save()

    @given(question_type().filter(lambda x: x in Question.CHOICE_TYPES))
    def test_clear_responses_when_choice_deleted(self, question_type):
        with self.assertOnlyResponseForChoiceCleared(question_type) as choice:
            choice.delete()

    @given(question_type().filter(lambda x: x in Question.CHOICE_TYPES))
    def test_clear_responses_when_choice_added(self, question_type):
        with self.assertOnlyResponseForChoiceCleared(question_type) as choice:
            baker.make(Choice, question=choice.question, key=10000)


import os
from setuptools import setup, find_packages

setup_py_dir = os.path.dirname(os.path.realpath(__file__))
need_files = []

setup(
    name='robot-agents',
    version='0.0.1',
    author="Elena Rampone",
    author_email="elena.rampone@iit.it",
    description="Robot Agents: toolkit to develop and test RL algorithms on robotic manipulation tasks",
    python_requires='>=3.*',
    install_requires=['stable_baselines'],
)


import urllib.request, urllib.error #urlにアクセスするライブラリ
from bs4 import BeautifulSoup #parseHTMLとXMLのパーサー
import re # for Regular expression
import datetime # for year,month and day
import unicodedata # example -> unicodedata.normalize('NFKC', text) 全角から半角

from plugins import dateReplaceDict # 臨時時刻表の対応表

def getDate(dateStr): # dateStr:'today' or 'yyyy/mm/dd'
    '''
    日付と曜日を辞書型で返す
    '''
    if dateStr=='today':
        date = datetime.date.today()
    else:
        date = datetime.datetime.strptime(dateStr, '%Y/%m/%d')

    date = {
        'day':str(date.strftime('%Y%m%d')),
        'dayOfTheWeek':str(date.weekday())
    }
    return date

def replaceMulti(str, replaceDict):
    '''
    複数の文字列を置換する
    strをreplaceDictに照らし合わせて置換を行う
    '''
    for key, value in replaceDict.items():
        str = str.replace(key, value)
    return str

def optimizeKey(tag, replaceDict):
    '''
    今日の日付から参照すべき時刻表を判断すべく，keyを最適化する(kihon or yyyymmddのフォーマットに)
    '''
    key = replaceMulti(tag.attrs['href'], replaceDict)

    key = unicodedata.normalize('NFKC', key) # 全角数字や記号を半角に変換
    key = replaceMulti(key, dateReplaceDict.getDateDict()) # dateReplaceDictに応じてkeyの値を変換

    key = key.replace('_', '')
    return key

def getURL(urlDict):
    '''
    今日の日付と曜日(today)を元に適切な時刻表を返す
    '''
    # 日付と曜日を辞書型で取得
    date = getDate('today') # dateStr:'today' or 'yyyy/mm/dd'

    # targetURLの共通部分を指定
    targetURL = 'http://www.teu.ac.jp'

    if date['day'] in str(urlDict.keys()): # 今日の日付に該当する臨時時刻表があればそのURLを指定
        for key in urlDict.keys():
            if date['day'] in key:
                targetURL += urlDict[key]
                break
    elif date['dayOfTheWeek']=='6': # 今日が一般の日曜日なら運行がないので，Noneを指定
        targetURL = None
    elif date['dayOfTheWeek']=='5': # 今日が一般の土曜日なら基本時刻表（土曜日）のURLを指定
        targetURL += urlDict['saturday']
    else: # それ以外なら基本時刻表（平日）のURLを指定
        targetURL += urlDict['weekday']
    return targetURL

def getTarget(topURL, target): # target:'url' or 'list'
    '''
    topURLからtargetに応じたデータを返す(url:適切なURL, list:利用可能な時刻表のリスト)
    '''
    urlDict = {} # 時刻表のURLリスト（key:日付などURLの判別材料, value:URLそのもの）

    try:
        # topURLで指定されたページにあるバス時刻表へのリンク（aタグ & bus.htmlの文字列部分一致）を全て取得しtagsに格納
        html= urllib.request.urlopen(topURL)
        bsObj = BeautifulSoup(html, 'lxml')
        tags = bsObj.findAll(href=re.compile('bus.html'))
    except urllib.error.HTTPError:
        print('HTTPError')
    except:
        import traceback
        traceback.print_exc()
        print('Error')

    # tagsのaタグ内のhref(tags)から余分な文字列を削除
    replaceDict = dict.fromkeys(['/campus/access/', '_bus.html', 'bus.html'], '')
    for tag in tags:
        key = optimizeKey(tag, replaceDict) # kind of url, yyyymmdd
        if key not in 'delete':
            value = tag.attrs['href'] # url
            urlDict.setdefault(key, value)

    # targetに応じたデータを返す(url:適切なURL, list:利用可能な時刻表のリスト)
    if(target=='list'):
        return urlDict.keys()
    else:
        return getURL(urlDict)