import pandas as pd
import openpyxl
import os
import urllib
import datetime
from db_utils.base import Session, Session_ax
import matplotlib.pyplot as plt
import seaborn as sns
from extract_info import get_armoires_etuves, GetPrice, moteur2demarrer, var2art, map_moteur
from tqdm import tqdm

with Session() as session:
    # Read table: dimensional_ax.schema_special_plus
    df = pd.read_sql('SELECT * FROM dimensional_ax.schema_special_plus', session.bind)

# df.to_csv('schema_special.csv', index=False)

#  DISTRIBUTION EQUIPMENTS
types = df['Type']
# Count the number of each type
types_count = types.groupby(types).count()
# Sort values
types_count.sort_values(inplace=True, ascending=False)
# Keep only the first 10
types_count = types_count[:10]
# Plot
plt.figure(figsize=(9, 6))
plt.bar(types_count.index, types_count.values)
plt.title("Distribution équipements")
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

#  Fix number of motors Soufflage
for i, row in df.iterrows():
    if pd.isna(row['MS1']):
        df.at[i, 'Nb_MS'] = 0
    elif pd.isna(row['MS2']):
        df.at[i, 'Nb_MS'] = 1
    elif pd.isna(row['MS3']):
        df.at[i, 'Nb_MS'] = 2
    elif pd.isna(row['MS4']):
        df.at[i, 'Nb_MS'] = 3

#  Fix number of motors Extraction
for i, row in df.iterrows():
    if pd.isna(row['ME1']):
        df.at[i, 'Nb_ME'] = 0
    elif pd.isna(row['ME2']):
        df.at[i, 'Nb_ME'] = 1
    elif pd.isna(row['ME3']):
        df.at[i, 'Nb_ME'] = 2
    elif pd.isna(row['ME4']):
        df.at[i, 'Nb_ME'] = 3

# ETUVE
# Filter only etuve
df_etuve = df.loc[df['Type'] == 'ETUVE'].copy()

# NOMBRE DE MOTEURS
# Plot Nb_MS distribution
fig, ax = plt.subplots(1, 1, figsize=(9, 6))

# Calculate frequencies for column Nb_MS
freq_MS = df_etuve['Nb_MS'].value_counts()
freq_ME = df_etuve['Nb_ME'].value_counts()

# Put distribution of Nb_MS and Nb_ME side by side. Same width, use an offset
plt.bar(freq_MS.index - 0.2, freq_MS.values, width=0.4, label='Soufflage')
plt.bar(freq_ME.index + 0.2, freq_ME.values, width=0.4, label='Extraction')
plt.title("Nombre de moteurs - Etuves")
plt.legend()
plt.tight_layout()
plt.show()

# Puissance moteurs
df_etuve['Tot_puiss_MS'] = df_etuve['MS1'].fillna(0) + df_etuve['MS2'].fillna(0)  + df_etuve['MS3'].fillna(0)  + df_etuve['MS4'].fillna(0)
df_etuve['Tot_puiss_ME'] = df_etuve['ME1'].fillna(0)  + df_etuve['ME2'].fillna(0)  + df_etuve['ME3'].fillna(0)  + df_etuve['ME4'].fillna(0)
df_etuve['Mean_puiss_MS'] = df_etuve['Tot_puiss_MS'] / df_etuve['Nb_MS']
df_etuve['Mean_puiss_ME'] = df_etuve['Tot_puiss_ME'] / df_etuve['Nb_ME']

# Make a boxplot for MS and ME (share x axis)
fig, ax = plt.subplots(2, 1, figsize=(9, 10), sharex=True)
sns.boxplot(y=df_etuve['Mean_puiss_MS'], ax=ax[0], x=df_etuve['Nb_MS'])
ax[0].set_title("Puissance moyenne moteurs soufflage")
sns.boxplot(y=df_etuve['Mean_puiss_ME'], ax=ax[1], x=df_etuve['Nb_ME'])
ax[1].set_title("Puissance moyenne moteurs extraction")
plt.tight_layout()
plt.show()

get_price = GetPrice()

#  Plot motors prices as scatter X=power, Y=price
fig, ax = plt.subplots(1, 1, figsize=(9, 6))
x = [ motor['power'] for motor in map_moteur]
y = [ get_price.get_price(motor['code']) for motor in map_moteur]
y_demarr = [ get_price.get_price(motor['code']) + get_price.get_price(moteur2demarrer(motor['power'])) for motor in map_moteur]
ax.scatter(x, y, label='Prix Moteur', color='red', marker='x')
ax.scatter(x, y_demarr, label='Prix Moteur + Demarrer', color='blue', marker='o')

#  add a simple linear regression line for y_demarr
import numpy as np
from scipy.stats import linregress
slope, intercept, r_value, p_value, std_err = linregress(x, y_demarr)
x_line = np.linspace(0, max(x), 100)
y_line = slope * x_line + intercept
ax.plot(x_line, y_line, label='Regression', color='green')

plt.xlabel('Puissance moteur (kW)')
plt.ylabel('Prix (€)')
plt.legend()
# Add grid
plt.grid()
#  Show rounded equation of regression line by adding a text box
#  https://stackoverflow.com/questions/15910019/annotate-data-points-while-plotting-from-pandas-dataframe
text = "y = {:.1f}x + {:.0f}".format(slope, intercept)
props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
ax.text(0.05, 0.8, text, transform=ax.transAxes, fontsize=14,
        verticalalignment='top', bbox=props)

plt.title('Prix moteurs en fonction de la puissance')
plt.tight_layout()
#  Save figure in ./plots
plt.savefig('./plots/price_motor.png')
plt.show()

# DISTRIBUTION PUISSANCE MOTEURS
df_etuve = get_armoires_etuves(cache=False)
df1 = df_etuve.loc[(df_etuve['Nb_MS'] == 1) & (df_etuve['Nb_ME'] == 1)].copy()

#  Make a bubble plot using df1 where x = puissance soufflage, y = puissance extraction, size = nb armoires
distinct_cases = df1.groupby(['MS1', 'ME1'], as_index=False)['Num_AF'].count()
# Add number of armoires as text on each bubble
distinct_cases['text'] = distinct_cases['Num_AF'].apply(lambda x: str(x))

#  Plot
fig, ax = plt.subplots(1, 1, figsize=(9, 6))
ax.scatter(distinct_cases['MS1'], distinct_cases['ME1'], s=distinct_cases['Num_AF']*10)
# Add text
for i, txt in enumerate(distinct_cases['text']):
    ax.annotate(txt, (distinct_cases['MS1'].iloc[i], distinct_cases['ME1'].iloc[i]))
plt.xlabel('Puissance soufflage (kW)')
plt.ylabel('Puissance extraction (kW)')
plt.title('Distribution des puissances moteurs- pour les étuves Nb_MS=1, Nb_ME=1')
plt.tight_layout()
#  Save figure in ./plots
plt.savefig('./plots/distribution_puissances.png')
plt.show()

# DISTRIBUTION NOMBRE DE MOTEURS
# Make a bubble plot using df_etuve where x= Nb_MS, y = Nb_ME, size = nb armoires
distinct_cases = df_etuve.groupby(['Nb_MS', 'Nb_ME'], as_index=False)['Num_AF'].count()
#  Plot
fig, ax = plt.subplots(1, 1, figsize=(9, 6))
ax.scatter(distinct_cases['Nb_MS'], distinct_cases['Nb_ME'], s=distinct_cases['Num_AF']*10)
plt.xlabel('Nombre de moteurs soufflage')
plt.ylabel('Nombre de moteurs extraction')
plt.title('Distribution des nombres de moteurs - pour les étuves')
plt.tight_layout()
#  Save figure in ./plots
plt.savefig('./plots/distribution_nb_moteurs.png')
plt.show()


from ctypes.wintypes import tagSIZE
from django.shortcuts import get_object_or_404, render, redirect
from app import forms
from app.forms import CommentForm, NewUserForm, SubscribeForm
from app.models import Post, Comment, Tag, Profile, WebsiteMeta
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth.models import User
from django.db.models import Count
from django.contrib.auth import login

def index(request):
  posts=Post.objects.all()
  top_posts=Post.objects.all().order_by('-view_count')[0:3]
  new_posts=Post.objects.all().order_by('-last_updated')[0:3]
  featured_post = Post.objects.filter(is_featured = True)
  subscribe_form = SubscribeForm()
  subscribe_successful = None
  website_info = None

  if WebsiteMeta.objects.all().exists():
    website_info = WebsiteMeta.objects.all()[0]

  if featured_post:
    featured_post = featured_post[0]

  if request.POST:
    subscribe_form = SubscribeForm(request.POST)
    if subscribe_form.is_valid():
      subscribe_form.save()
      request.session['subscribed'] = True
      subscribe_successful = 'Subscribed Successfully'
      subscribe_form = SubscribeForm()

  context={'posts': posts, "new_posts":new_posts, 'top_posts':top_posts, 'subscribe_form':subscribe_form, 'subscribe_successful':subscribe_successful, 'featured_post':featured_post, 'website_info': website_info}
  return render(request, 'app/index.html', context)

def post_page(request, slug):
  post = Post.objects.get(slug = slug)
  comments = Comment.objects.filter(post = post, parent=None)
  form = CommentForm()

  bookmarked = False
  if post.bookmarks.filter(id = request.user.id).exists():
    bookmarked = True
  is_bookmarked = bookmarked

  liked = False
  if post.likes.filter(id = request.user.id).exists():
    liked = True
  is_liked = liked

  liked_count = post.number_of_likes()

  if request.POST:
    comment_form = CommentForm(request.POST)
    if comment_form.is_valid:
      # parent_obj = None
      if request.POST.get('parent'):
        parent = request.POST.get('parent')
        parent_obj = Comment.objects.get(id=parent)
        if parent_obj:
          comment_reply = comment_form.save(commit=False)
          comment_reply.parent = parent_obj
          comment_reply.post = post
          comment_reply.save()
      else:
        comment = comment_form.save(commit=False)
        post_id = request.POST.get('post_id')
        post = Post.objects.get(id = post_id)
        comment.post = post
        comment.save()
      return HttpResponseRedirect(reverse('post_page', kwargs={'slug':slug}))

  if post.view_count is None:
    post.view_count = 1
  else:
    post.view_count = post.view_count + 1
  post.save()

  recent_posts = Post.objects.exclude(id = post.id).order_by('-last_updated')[0:3]
  top_authors = User.objects.annotate(number=Count('post')).order_by('-number')
  tags = Tag.objects.all()
  related_posts = Post.objects.exclude(id=post.id).filter(author=post.author)[0:3]

  context = {'post': post, 'form':form, 'comments':comments, 'is_bookmarked':is_bookmarked, 'is_liked':is_liked, 'liked_count':liked_count, 'recent_posts':recent_posts, 'top_authors':top_authors, 'tags':tags, 'related_posts':related_posts }
  return render(request, 'app/post.html', context)

def tag_page(request, slug):
  tag = Tag.objects.get(slug=slug)
  top_posts = Post.objects.filter(tags__in=[tag.id]).order_by('-view_count')[0:2]
  new_posts = Post.objects.filter(tags__in=[tag.id]).order_by('-last_updated')[0:2]
  tags = Tag.objects.all()
  context = {'tag':tag, 'top_posts':top_posts, 'new_posts':new_posts, 'tags':tags}
  return render(request, 'app/tag.html', context)

def author_page(request, slug):
  profile = Profile.objects.get(slug=slug)
  top_posts = Post.objects.filter(author=profile.user).order_by('-view_count')[0:2]
  new_posts = Post.objects.filter(author=profile.user).order_by('-last_updated')[0:2]
  top_authors = User.objects.annotate(number=Count('post')).order_by('-number')[0:2]

  context = {'profile': profile, 'top_posts':top_posts, 'new_posts':new_posts, 'top_authors':top_authors}
  return render(request, 'app/author.html', context)

def search_posts(request):
  search_query = request.GET.get('q') if request.GET.get('q') else ''
  posts = Post.objects.filter(title__icontains=search_query)
  context = {'posts':posts, 'search_query':search_query}
  return render(request, 'app/search.html', context)

def about(request):
  website_info = None
  if WebsiteMeta.objects.all().exists():
    website_info = WebsiteMeta.objects.all()[0]
  context = {'website_info':website_info}
  return render(request, 'app/about.html', context)

def register_user(request):
  form = NewUserForm()
  if request.method =='POST':
    form = NewUserForm(request.POST)
    if form.is_valid():
      user = form.save()
      login(request, user)
      return redirect('/')
  context = {'form': form}
  return render(request, 'registration/registration.html', context)

def clean_username(self):
  username = self.cleaned_data['username'].lower()
  new = User.objects.filter(username = username)
  if new.count():
    raise forms.ValidationError('User already exists')
  return username

def clean_email(self):
  email = self.cleaned_data['email'].lower()
  new = User.objects.filter(email = email)
  if new.count():
    raise forms.ValidationError('Email already exists')
  return email

def clean_password2(self):
  password1 = self.cleaned_data['password1']
  password2 = self.cleaned_data['password2']
  if password1 and password2 and password2 != password1:
    raise forms.ValidationError('Passwords must be the same')
  return password2

def bookmark_post(request, slug):
  post = get_object_or_404(Post, id=request.POST.get('post_id'))
  if post.bookmarks.filter(id=request.user.id).exists():
    post.bookmarks.remove(request.user)
  else:
    post.bookmarks.add(request.user)
  return HttpResponseRedirect((reverse('post_page', args=[str(slug)])))

def like_post(request, slug):
  post = get_object_or_404(Post, id=request.POST.get('post_id'))
  if post.likes.filter(id=request.user.id).exists():
    post.likes.remove(request.user)
  else:
    post.likes.add(request.user)
  return HttpResponseRedirect((reverse('post_page', args=[str(slug)])))

def all_bookmarked_posts(request):
  all_bookmarked_posts = Post.objects.filter(bookmarks=request.user)
  context = {'all_bookmarked_posts':all_bookmarked_posts}
  return render(request, 'app/all_bookmarked_posts.html', context)

def all_posts(request):
  all_posts = Post.objects.all()
  context = {'all_posts':all_posts}
  return render(request, 'app/all_posts.html', context)

def all_liked_posts(request):
  all_liked_posts = Post.objects.filter(likes=request.user)
  context = {'all_liked_posts':all_liked_posts}
  return render(request, 'app/all_liked_posts.html', context)


import sqlite3
import tkinter as tk
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
import fileworker

class Doctor(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.grid_columnconfigure(0, weight=1)

        label = tk.Label(self, text="DOCTORS MENU", font=('Helvetica', 16))
        main_frame = MainFrame(self, self.controller)
        button = tk.Button(self, text="Back", font=('Helvetica', 14), width=20, bg="#669", fg='White', bd=1, command=lambda: controller.show_frame("StartPage"))

        label.grid(row=0, column=0, pady=(20, 0))
        main_frame.grid(row=1, column=0, pady=25, ipady=5)
        button.grid(row=2, column=0, pady=0)

    def menubar(self, root):
        menubar = tk.Menu(root, tearoff=0)

        fileMenu = tk.Menu(menubar, tearoff=0)
        fileMenu2 = tk.Menu(fileMenu, tearoff=0)

        menubar.add_cascade(label="File", menu=fileMenu)
        fileMenu.add_cascade(label="Export as...", menu=fileMenu2)
        fileMenu2.add_command(label="*.docx", command=fileworker.export_docx)
        fileMenu2.add_command(label="*.xlsx", command=fileworker.export_xlsx)
        fileMenu.add_separator()
        fileMenu.add_command(label="Quit", command=quit)
        menubar.add_command(label="Help", command=self.show_help)

        return menubar

    def show_help(self):
        text = '''Information for help'''
        window = tk.Toplevel()
        label = tk.Label(window, text=text, font=("Helvetica", 10), bd=1, relief='sunken', justify="left")
        label.pack(pady=10, padx=10, ipady=10, ipadx=10)
        button = tk.Button(window, text='Close', command=window.destroy)
        button.pack(pady=(0, 10))

class MainFrame(tk.LabelFrame):
    def __init__(self, parent, controller):
        tk.LabelFrame.__init__(self, parent)
        self.controller = controller
        self.columnconfigure(0, weight=0)
        self.columnconfigure(1, weight=0)
        self.columnconfigure(2, weight=1)
        self.columnconfigure(3, weight=0)

        self.photo = tk.PhotoImage(file=r"C:\Users\kripi\Downloads\refresh.png")
        refresh_button = tk.Button(self, image=self.photo, command=lambda: self.update_trv())
        refresh_button.grid(row=0, column=4, padx=(0, 10))
        self.trv = ttk.Treeview(self, columns=(1, 2, 3, 4, 5, 6), show='headings', height=13)
        self.trv.grid(row=0, column=0, columnspan=3, pady=10, padx=10)
        self.scroll_bar = ttk.Scrollbar(self, orient="vertical")
        self.scroll_bar.grid(row=0, column=3, sticky='ns', padx=(0, 10), pady=10)
        self.trv.configure(yscrollcommand=self.scroll_bar.set)
        self.scroll_bar.configure(command=self.trv.yview)
        self.trv.bind('<ButtonRelease-1>', self.clicker)

        self.trv.heading(1, text="ID")
        self.trv.column(1, width=10)
        self.trv.heading(2, text="Full name")
        self.trv.column(2, width=200)
        self.trv.heading(3, text="Speciality")
        self.trv.column(3, width=150)
        self.trv.heading(4, text="Appointment cost")
        self.trv.column(4, width=110)
        self.trv.heading(5, text="Payroll percentage")
        self.trv.column(5, width=110)
        self.trv.heading(6, text="Salary")
        self.trv.column(6, width=100)

        self.update_trv()

        info_text = """To add a doctor, fill out the form and click the 'Add' button.\nTo update/delete a doctor, click on desired doctor in table and click the 'Update'/'Delete' button."""
        info_label = tk.Label(self, text=info_text, font=("Helvetica", 10), bd=1, relief='sunken', justify="left")
        label1 = tk.Label(self, text="Full name:")
        label2 = tk.Label(self, text="Speciality:")
        label3 = tk.Label(self, text="Appointment cost:")
        label4 = tk.Label(self, text="Payroll percentage:")
        self.entry1 = tk.Entry(self)
        self.entry2 = tk.Entry(self)
        self.entry3 = tk.Entry(self)
        self.entry4 = tk.Entry(self)
        button_add = tk.Button(self, text="Add", width=20, command=lambda: self.add_doctor())
        button_update = tk.Button(self, text="Update", width=20, command=lambda: self.update_doctor())
        button_delete = tk.Button(self, text="Delete", width=20, command=lambda: self.delete_doctor())
        button_clear = tk.Button(self, text='Clear', width=20, command=lambda: self.clear_fields())

        self.entry1.grid(row=2, column=1, sticky='w', padx=0, pady=0)
        self.entry2.grid(row=3, column=1, sticky='w', padx=0, pady=0)
        self.entry3.grid(row=4, column=1, sticky='w', padx=0, pady=0)
        self.entry4.grid(row=5, column=1, sticky='w', padx=0, pady=0)
        info_label.grid(row=1, columnspan=3, sticky='we', padx=10, pady=(0, 10), ipadx=10, ipady=5)
        label1.grid(row=2, column=0, sticky='w', padx=10, pady=0)
        label2.grid(row=3, column=0, sticky='w', padx=10, pady=0)
        label3.grid(row=4, column=0, sticky='w', padx=10, pady=0)
        label4.grid(row=5, column=0, sticky='w', padx=10, pady=0)
        button_add.grid(row=2, column=2, sticky='w', padx=10, pady=0)
        button_update.grid(row=3, column=2, sticky='w', padx=10, pady=0)
        button_delete.grid(row=4, column=2, sticky='w', padx=10, pady=0)
        button_clear.grid(row=5, column=2, sticky='w',padx=10)

    def clear_fields(self):
        self.entry1.delete(0, END)
        self.entry2.delete(0, END)
        self.entry3.delete(0, END)
        self.entry4.delete(0, END)

    def clicker(self, e):
        self.clear_fields()
        selected = self.trv.focus()
        values = self.trv.item(selected, 'values')

        self.entry1.insert(0, values[1])
        self.entry2.insert(0, values[2])
        self.entry3.insert(0, values[3])
        self.entry4.insert(0, values[4])

    def update_trv(self):
        for i in self.trv.get_children():
            self.trv.delete(i)
        con = sqlite3.connect('polyclinic.db')
        cur = con.cursor()
        for i in cur.execute('SELECT * FROM doctor'):
            self.trv.insert('', 'end', values=i)

    def add_doctor(self):
        con = sqlite3.connect("polyclinic.db")
        cur = con.cursor()
        dname = self.entry1.get()
        dspec = self.entry2.get()
        acost = self.entry3.get()
        perc = self.entry4.get()

        try:
            if dname is None or len(dname) == 0 or dname.isnumeric():
                raise ValueError
            if dspec is None or len(dspec) == 0 or dspec.isnumeric():
                raise ValueError
            if int(acost) < 0:
                raise ValueError
            if int(perc) < 0:
                raise ValueError
        except ValueError:
            messagebox.showerror("Error!", "Input correct values!")
        else:
            values = (dname, dspec, acost, perc)
            sql = """\
                   INSERT INTO doctor (doctor_name, doctor_speciality, appointment_cost, payroll_percentage)
                   VALUES (?,?,?,?);
               """
            cur.execute(sql, values)
            con.commit()
            cur.close()
            con.close()
            self.clear_fields()
            self.update_trv()

    def update_doctor(self):
        con = sqlite3.connect("polyclinic.db")
        cur = con.cursor()
        try:
            did = self.trv.item(self.trv.selection())['values'][0]
            dname = self.entry1.get()
            dspec = self.entry2.get()
            acost = self.entry3.get()
            perc = self.entry4.get()

            if did is None:
                raise IndexError
            if dname is None or len(dname) == 0 or dname.isnumeric():
                raise ValueError
            if dspec is None or len(dspec) == 0 or dname.isnumeric():
                raise ValueError
            if int(acost) < 0:
                raise ValueError
            if int(perc) < 0:
                raise ValueError
        except ValueError:
            messagebox.showerror("Error!", "Input correct values!")
        except IndexError:
            messagebox.showerror("Error!", "Select doctor to update!")
        else:
            if messagebox.askyesno("Confirm updation!", "Are you sure?"):
                cur.execute('UPDATE doctor SET doctor_name = ?, doctor_speciality = ?, appointment_cost = ?, payroll_percentage = ? WHERE id = ?;', (dname, dspec, acost, perc, did))
                con.commit()
                cur.close()
                con.close()
                self.clear_fields()
                self.update_trv()

    def delete_doctor(self):
        con = sqlite3.connect("polyclinic.db")
        cur = con.cursor()
        try:
            did = self.trv.item(self.trv.selection())['values'][0]
            lst = []
            for row in cur.execute('SELECT id FROM doctor;'):
                for key in row:
                    lst.append(key)
            if int(did) not in lst:
                raise ValueError
            if did is None:
                raise IndexError
        except ValueError:
            messagebox.showerror("Error!", "No such doctor!")
        except IndexError:
            messagebox.showerror("Error!", "Select doctor to delete!")
        else:
            if messagebox.askyesno("Confirm deleting!", "Are you sure?"):
                cur.execute('DELETE FROM receipt WHERE doctor_id = ?', (did,))
                con.commit()
                cur.execute('DELETE FROM doctor WHERE id = ?', (did,))
                con.commit()
                cur.close()
                con.close()
                self.clear_fields()
                self.update_trv()


import numpy as np
from ..utils import Dataset
from .interface import TopicModel
from .man_model.layers import *
from .man_model.models import *
from .man_model import utils
import torch.utils.data as data_utils

def create_minibatch(data, label,z, batch_size):
    rng = np.random.RandomState(10)

    while True:
        # Return random data samples of a size 'minibatch_size' at each iteration
        ixs = rng.randint(data.shape[0], size=batch_size)
        yield data[ixs], label[ixs], z[ixs]

def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    e_x = np.exp(x - np.max(x, axis=1).reshape(-1, 1))
    return e_x / np.sum(e_x, axis=1).reshape(-1, 1)

class MultinomialAdversarialNetwork(TopicModel):
    def __init__(self, k, m, domains, model_params=None, log_params=None):
        super().__init__(k,m,model_params,log_params)
        self.domains = domains
        self.loss = 'gr'
        self.clf = None

    def prepare_data(self,d):
        """
        Assume d is a dictionary of dataset where d[domain] = another dataset class
        Assume labeled domain = train set, unlabeled = test
        """
        train_loaders, train_iters = {}, {}
        for domain in self.domains:
            features, target = torch.from_numpy(d[domain].X.todense()), torch.from_numpy(d[domain].y)
            train = data_utils.TensorDataset(features,target)
            train_loaders[domain] = DataLoader(train, self.model_params['batch_size'], shuffle = True)
            train_iters[domain] = iter(train_loaders[domain])
        return train_loaders, train_iters

    def fit(self, d, *args, **kwargs):
        X = d.X
        y = d.y.reshape((-1, 1))
        z = d.z.reshape((-1,1))
        n_samples = d.X.shape[0]
        batch_size = self.model_params["batch_size"]
        if issparse(X):
            X = X.todense()
        #minibatches = create_minibatch(X, y, z, batch_size)
        train_loaders, train_iters = self.prepare_data(d)

        #Training
        F_s = MlpFeatureExtractor(X.shape[1], [1000,500],128, 0.4)
        F_d = {}
        for domain in self.domains:
            F_d[domain] = MlpFeatureExtractor(X.shape[1], [1000,500],128, 0.4)

        C = SentimentClassifier(3, 128+64,128+64, 1,0.4, True)
        D = DomainClassifier(3, 128, 128,len(self.domains), 'gr', 0.4, True)

        F_s, C, D = F_s.to('cuda'), C.to('cuda'), D.to('cuda')
        for f_d in F_d.values():
            f_d = f_d.to('cuda')
        # optimizers
        optimizer = optim.Adam(itertools.chain(*map(list, [F_s.parameters() if F_s else [], C.parameters()] + [f.parameters() for f in F_d.values()])), lr=0.0001)
        optimizerD = optim.Adam(D.parameters(), lr=0.0001)
        # training
        best_acc, best_avg_acc = defaultdict(float), 0.0

        for epoch in range(kwargs["training_epochs"]):
            F_s.train()
            C.train()
            D.train()
            for f in F_d.values():
                f.train()

            # training accuracy
            correct, total = defaultdict(int), defaultdict(int)
            # D accuracy
            d_correct, d_total = 0, 0
            # conceptually view 1 epoch as 1 epoch of the first domain
            num_iter = len(train_loaders[self.domains[0]])
            for i in tqdm(range(num_iter)):
                # D iterations
                utils.freeze_net(F_s)
                map(utils.freeze_net, F_d.values())
                utils.freeze_net(C)
                utils.unfreeze_net(D)
                # optional WGAN n_critic trick
                n_critic = 5

                for _ in range(n_critic):
                    D.zero_grad()
                    loss_d = {}
                    # train on both labeled and unlabeled domains
                    for domain in self.domains:
                        # targets not used
                        #Thay unlabeled_loaders/iters = train_loaders/iters?
                        d_inputs, _, d_targets = utils.endless_get_next_batch(
                            train_loaders, train_iters, domain)
                        shared_feat = F_s(d_inputs)
                        d_outputs = D(shared_feat)
                        # D accuracy
                        _, pred = torch.max(d_outputs, 1)
                        d_total += len(d_inputs)
                        if self.loss.lower() == 'l2':
                            _, tgt_indices = torch.max(d_targets, 1)
                            d_correct += (pred==tgt_indices).sum().item()
                            l_d = functional.mse_loss(d_outputs, d_targets)
                            l_d.backward()
                        else:
                            d_correct += (pred==d_targets).sum().item()
                            l_d = functional.nll_loss(d_outputs, d_targets)
                            l_d.backward()
                        loss_d[domain] = l_d.item()
                    optimizerD.step()

                # F&C iteration
                utils.unfreeze_net(F_s)
                map(utils.unfreeze_net, F_d.values())
                utils.unfreeze_net(C)
                utils.freeze_net(D)
                #if opt.fix_emb:
                #    utils.freeze_net(F_s.word_emb)
                #    map(utils.freeze_net, F_d.values())
                F_s.zero_grad()
                for f_d in F_d.values():
                    f_d.zero_grad()
                C.zero_grad()
                shared_feats, domain_feats = [], []
                for domain in self.domains:
                    inputs, targets = utils.endless_get_next_batch(
                            train_loaders, train_iters, domain)
                    targets = targets.to('cuda')
                    shared_feat = F_s(inputs)
                    shared_feats.append(shared_feat)
                    domain_feat = F_d[domain](inputs)
                    domain_feats.append(domain_feat)
                    features = torch.cat((shared_feat, domain_feat), dim=1)
                    c_outputs = C(features)
                    l_c = functional.nll_loss(c_outputs, targets)
                    l_c.backward(retain_graph=True)
                    # training accuracy
                    _, pred = torch.max(c_outputs, 1)
                    total[domain] += targets.size(0)
                    correct[domain] += (pred == targets).sum().item()
                # update F with D gradients on all domains
                for domain in self.domains:
                    d_inputs, _ = utils.endless_get_next_batch(
                            unlabeled_loaders, unlabeled_iters, domain)
                    shared_feat = F_s(d_inputs)
                    d_outputs = D(shared_feat)
                    if self.loss.lower() == 'gr':
                        d_targets = utils.get_domain_label(self.loss, domain, len(d_inputs))
                        l_d = functional.nll_loss(d_outputs, d_targets)
                        log.debug(f'D loss: {l_d.item()}')
                        if opt.lambd > 0:
                            l_d *= -opt.lambd
                    elif self.loss.lower() == 'l2':
                        d_targets = utils.get_random_domain_label(opt.loss, len(d_inputs))
                        l_d = functional.mse_loss(d_outputs, d_targets)
                        if opt.lambd > 0:
                            l_d *= opt.lambd
                    l_d.backward()

                optimizer.step()

            # end of epoch
            log.info('Ending epoch {}'.format(epoch+1))


import torch
from torch.distributions.distribution import Distribution
from torch.distributions.multinomial import Multinomial
from torch.distributions import Categorical
import torch
import numpy as np

# Referencef
# https://pytorch.org/docs/stable/distributions.html
# https://pytorch.org/docs/stable/_modules/torch/distributions/multinomial.html

print("-----------------------------------------")
print('Multinomial Distribution\n')

m = Categorical(torch.tensor([ 0.25, 0.25, 0.25, 0.25 ]))
print(m.sample())  # equal probability of 0, 1, 2, 3

m = Categorical(torch.tensor([ 0.8, 0.15, 0.05]))
sample = m.sample()
print(sample)
print(type(sample))  # equal probability of 0, 1, 2, 3
print(m.log_prob(sample))

probs_2d = [0.1, 0.9]
probs_2d = torch.Tensor(probs_2d)
sample_2d = torch.multinomial(probs_2d, 1, True)
print(sample_2d)

# Multinomial = (100, torch.tensor([1, 1]))
# x = m.sample()
# print(x)
# print(type(x))
# Multinomial(torch.tensor([1., 1., 1., 1.])).log_prob(x)

# https://pytorch.org/docs/stable/distributions.html#categorical
print("-----------------------------------------\n")

#
#
# print("-----------------------------------------")
# print('Torch Cat Sum\n')
# torch.manual_seed(999)
# print("##########  Input   ##########")
# x = torch.randn(2, 2)
# y = torch.randn(2, 2)
# print(x)
# print(y)
# print("##########  torch cat   ##########")
# z = torch.cat((x,y))
# print(z)
# z = torch.cat((x,y),0)
# print(z)
# z = torch.cat((x,y),1)
# print(z)
# print("##########  torch cat sum   ##########")
# z = torch.cat((x,y)).sum()
# print(z)
# print("-----------------------------------------")

# a.append(torch.randn(1))
# a.append(torch.randn(1))
# a.append(torch.randn(1))
# print(a)
# print(np.shape(a))
# # print(torch.sum(a)) #<-- 계산이 안됨.
# print(torch.cat(a).sum())

9. Basic for Reinforcement (numpy, pytorch, nn)/reinforce_test.py


import scrapy
from COTO.items import CotoItem
from COTO.itemsloaders import CotoItemLoader

class TarantulaSpider(scrapy.Spider):
    name = 'tarantula'
    custom_settings = {
        'ITEM_PIPELINES': {
            #'COTO.pipelines.CotoPipeline': 300
        }
    }
    allowed_domains = ['cotodigital3.com.ar']
    # start_urls      = ['https://www.cotodigital3.com.ar/sitios/cdigi/browse/catalogo-frescos/_/N-1ewuqo6?Nf=product.endDate%7CGTEQ+1.670976E12%7C%7Cproduct.startDate%7CLTEQ+1.670976E12&Nr=AND%28product.sDisp_200%3A1004%2Cproduct.language%3Aespa%C3%B1ol%2COR%28product.siteId%3ACotoDigital%29%29']
    start_urls = [
        'https://www.cotodigital3.com.ar/sitios/cdigi/browse/catalogo-electro-informatica/_/N-u4pa0j']
    visited_pages = []

    def parse(self, response):
        products = response.css('#products li.clearfix')

        for product in products:
            product_item = CotoItemLoader(item=CotoItem(), selector=product)
            product_item.add_css('name', 'div.descrip_full::text')
            product_item.add_css('price', 'span.atg_store_newPrice::text')
            try:
                product_item.add_css('discount', 'span.price_discount::text')
            except Exception:
                product_item.add_css('discount', 'span.atg_store_newPrice::text')

            yield product_item.load_item()

        pages = response.css('div.atg_store_pagination a ::attr(href)')

        next_page = None

        for page in pages:
            total_page = 'cotodigital3.com.ar' + page.get()
            if total_page not in self.visited_pages:
                next_page = total_page
                self.visited_pages.append(next_page)

        if next_page != None:
            yield response.follow(next_page, callback=self.parse)


import requests
from bs4 import BeautifulSoup

url = 'http://www.ibm.com'
data = requests.get(url).text
soup = BeautifulSoup(data, 'html.parser')

for link in soup.find_all('a', href= True):
    print(link.get('href'))

for link in soup.find_all('img'):
    print(link)
    print(link.get('src'))


from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import FAISS, Milvus, Pinecone, Chroma
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
from models.llm_model import get_openai_model, get_huggingfacehub
import pinecone
import streamlit as st
from config.templates import bot_template, user_template
from config.keys import Keys
from PyPDF2 import PdfReader

def extract_text_from_PDF(files):
    # 参考官网链接：https://python.langchain.com/docs/modules/data_connection/document_loaders/pdf
    # 加载多个PDF文件
    text = ""
    for pdf in files:
        pdf_reader = PdfReader(pdf)
        for page in pdf_reader.pages:
            text += page.extract_text()
    return text

def split_content_into_chunks(text):
    # 参考官网链接：https://python.langchain.com/docs/modules/data_connection/document_transformers/text_splitters/character_text_splitter
    text_spliter = CharacterTextSplitter(separator="\n",
                                         chunk_size=500,
                                         chunk_overlap=80,
                                         length_function=len)
    chunks = text_spliter.split_text(text)
    return chunks

def save_chunks_into_vectorstore(content_chunks, embedding_model):
    # 参考官网链接：https://python.langchain.com/docs/modules/data_connection/vectorstores/
    # ① FAISS
    # pip install faiss-gpu (如果没有GPU，那么 pip install faiss-cpu)
    vectorstore = FAISS.from_texts(texts=content_chunks,
                                      embedding=embedding_model)

    # ② Pinecone
    # 官网链接：https://python.langchain.com/docs/integrations/vectorstores/pinecone
    # Pinecone官网链接：https://docs.pinecone.io/docs/quickstart
    # pip install pinecone-client==2.2.2
    # 初始化
    # pinecone.init(api_key=Keys.PINECONE_KEY, environment="asia-southeast1-gcp")
    # # 创建索引
    # index_name = "pinecone-chatbot-demo"
    # # 检查索引是否存在，如果不存在，则创建
    # if index_name not in pinecone.list_indexes():
    #     pinecone.create_index(name=index_name,
    #                           metric="cosine",
    #                           dimension=1536)
    # vectorstore = Pinecone.from_texts(texts=content_chunks,
    #                                       embedding=embedding_model,
    #                                       index_name=index_name)

    # ③ Milvus, pip install pymilvus
    # 官网链接：https://python.langchain.com/docs/integrations/vectorstores/milvus
    # vectorstore = Milvus.from_texts(texts=content_chunks,
    #                                     embedding=embedding_model,
    #                                     connection_args={"host": "localhost", "port": "19530"},
    # )

    return vectorstore

def get_chat_chain(vector_store):
    # ① 获取 LLM model
    llm = get_openai_model()
    #llm = get_huggingfacehub(model_name="google/flan-t5-xxl")

    # ② 存储历史记录
    # 参考官网链接：https://python.langchain.com/docs/use_cases/question_answering/how_to/chat_vector_db
    # 用于缓存或者保存对话历史记录的对象
    memory = ConversationBufferMemory(
        memory_key='chat_history', return_messages=True)
    # ③ 对话链
    conversation_chain = ConversationalRetrievalChain.from_llm(
        llm=llm,
        retriever=vector_store.as_retriever(),
        memory=memory
    )
    return conversation_chain

def process_user_input(user_input):
    if st.session_state.conversation is not None:
        # 调用函数st.session_state.conversation，并把用户输入的内容作为一个问题传入，返回响应。
        response = st.session_state.conversation({'question': user_input})
        # session状态是Streamlit中的一个特性，允许在用户的多个请求之间保存数据。
        st.session_state.chat_history = response['chat_history']
        # 显示聊天记录
        # chat_history : 一个包含之前聊天记录的列表
        for i, message in enumerate(st.session_state.chat_history):
            # 用户输入
            if i % 2 == 0:
                st.write(user_template.replace(
                    "{{MSG}}", message.content), unsafe_allow_html=True) # unsafe_allow_html=True表示允许HTML内容被渲染
            else:
                # 机器人响应
                st.write(bot_template.replace(
                    "{{MSG}}", message.content), unsafe_allow_html=True)


'''
Setup for the fast-align algorithm for pairwise sequence alignment and
sequence distance calculation.
'''

# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path

here = path.abspath(path.dirname(__file__))

# Get the long description from the README file
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name='fast-align',

    # Versions should comply with PEP440.  For a discussion on
	# single-sourcing
    # the version across setup.py and the project code, see
    # https://packaging.python.org/en/latest/single_source_version.html
    version='0.0.0',

    description='Fast pairwise string alignment using breadth-first-search',
    long_description=long_description,

    # The project's main homepage.
    url='https://github.com/enewe101/fast-align',

    # Author details
    author='Edward Newell',
    author_email='edward.newell@gmail.com',

    # Choose your license
    license='MIT',

    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
    classifiers=[
        # How mature is this project? Common values are
        #   3 - Alpha
        #   4 - Beta
        #   5 - Production/Stable
        'Development Status :: 3 - Alpha',

        # Indicate who your project is intended for
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Build Tools',

        # Pick your license as you wish (should match "license" above)
        'License :: OSI Approved :: MIT License',

        # Specify the Python versions you support here.
        'Programming Language :: Python :: 2.7',
    ],

    # What does your project relate to?
    keywords= 'pairwise sequence alignment string matching distance',

    # You can just specify the packages manually here if your project is
    # simple. Or you can use find_packages().
    packages=['fast_align'],
    install_requires=[]
)


import discord
from discord.ext import commands

class Core(commands.Cog):
	def __init__(self,bot,config):
		self.bot = bot
		self.config = config
	def listStr(self,listIn):
		strOut=""
		if len(listIn)==1:
			strOut=listIn[0]
		elif len(listIn)==2:
			strOut=f"{listIn[0]} and {listIn[1]}"
		else:
			for i in listIn[:-1]:
				strOut+=i+", "
			strOut+="and "+listIn[-1]
		return strOut
	@commands.command()
	async def info(self, ctx):
		embed = discord.Embed(title="Bot Info")
		ownerNames=[]
		for i in self.config["owner_ids"]:
			tempUser= await self.bot.fetch_user(i)
			try:
				ownerNames.append(str(tempUser))
			except:
				ownerNames.append("Unknown")
		embed.add_field(name="Owner(s)",value=self.listStr(ownerNames))
		cogNames=[]
		for i in self.bot.cogs:
			cogNames.append(i)
		embed.add_field(name="Extension(s)",value=self.listStr(cogNames))
		links=[]
		for i in self.config["links"]:
			links.append("[{0}]({1})".format(i, self.config["links"][i]))
		embed.add_field(name="GitHub",value="\n".join(links))
		await ctx.send(None,embed=embed)

cogs=[Core]


import os
import pandas as pd
from pandas import DataFrame
import pickle

os.chdir('C:/Users/user/Desktop/social_media')

#데이터 전처리(매크로, 뉴스 등 의미없는 계정 삭제)
tweet_df = pd.read_csv('twitter_data.csv',encoding='utf-8')
del_names=pd.read_table('del_names.txt',header=None)
#총 255개의 계정 삭제

#의미없는 계정 삭제
del_idx=[]
for i in del_names:
    for j in enumerate(list(tweet_df.username)):
        if i==j[1]:
            del_idx.append(j[0])

complete_df=tweet_df[['author_id','username','text']]
complete_df=complete_df.drop(del_idx)
#6010개의 트윗만 남김(author_id, username, text)

DataFrame.to_csv(complete_df, 'complete_df.csv', encoding='utf-8-sig',index=False)
complete_df=pd.read_csv('complete_df.csv')

#%%text tokenize
from nltk.tokenize import word_tokenize
from nltk.tag import pos_tag
from konlpy.tag import Komoran

komoran=Komoran()

noun=[]
for i in list(complete_df.text):
    noun.append(komoran.nouns(i))

complete_df['noun']=noun
#토큰화 및 명사 추출

token_df=complete_df

del token_df['text']
#R로 읽을 때 text열로 인한 에러 발생 -> 제거하고 진행

DataFrame.to_csv(complete_df, 'token_df.csv', encoding='utf-8-sig',index=False)
complete_df=pd.read_csv('token_df.csv')


import glob as glob, shutil,os, json, mido
from os.path import join
from pypianoroll import Multitrack
from tqdm import tqdm
''' pypianoroll == 0.5.3!!!!'''

class MidiFileProcessor(Multitrack):
    def __init__(
        self,
        fldr,
        #savez,
    ) -> None:
        self.fldr = fldr # the folder where your midis are saved
        #self.savez = savez

    def get_items(
        self,
    ) -> None:
        files = glob.glob(join(self.fldr, '*[mM][iI][dD]'))
        str_files, clean_files = [], []

        progress_bar = tqdm(total=len(files), desc="Cleaning Files", unit="file", ncols=80)

        for f in files:
            try:
                gud_f =Multitrack(f)
                len(gud_f.tracks)
                str_files +=[f]
                clean_files += [gud_f]
            except (ValueError, IndexError, OSError, mido.midifiles.meta.KeySignatureError) as e:
                continue

            progress_bar.update(1)

        progress_bar.close()

        return str_files, clean_files

    def most_common(
        self,
        lst,
    ) -> None:
        return max(set(lst), key=lst.count)

    def get_listItems(
        self,
        n_tracks: int=0,
    ) -> None:
        #os.makedirs(self.savez, exist_ok=True)
        str_files, clean_files = self.get_items()

        tracks = [len(f.tracks) for f in clean_files]
        mc = self.most_common(tracks)
        ## support for own track input
        if n_tracks > 0:
            mc = n_tracks

        cocon = "The most common have {} tracks".format(mc)
        '''loop'''
        common = []
        for f, c in zip(str_files, clean_files):
            if len(c.tracks) == mc:
                common +=[f]
                #print('moving:', f, 'with no. of tracks ', len(m.tracks))
                #shutil.move(f, self.savez)
        os.makedirs('utilities', exist_ok=True)

        with open('utilities/common_files.json', 'w') as outfile:
            json.dump(common, outfile)

        with open('utilities/mc.txt', 'w') as mc_file:
            mc_file.write(cocon)


import matplotlib.pyplot as plt
import matplotlib as mpl
import networkx as nx
import os
import pickle as pk
from functions import *

# %%
getcontext().prec = 200
mpl.style.use('seaborn-deep')
mpl.rcParams['text.usetex'] = True
mpl.rcParams['font.family'] = 'serif'
mpl.rcParams['text.latex.preamble'] = r'\usepackage{bm}'

# %% Figure and Data paths
FIG_PATH = 'figs/'
if not os.path.isdir(FIG_PATH):
    os.makedirs(FIG_PATH)

DATA_PATH = 'data/'
if not os.path.isdir(DATA_PATH):
    os.makedirs(DATA_PATH)

# %% Setup
N = 10
M = 3
np.random.seed(0)

#%% Graph
G = np.random.choice([0.0, 1.0], size=(N, N), p=[0.5, 0.5])
G = G + np.eye(N)
G = (G > 0) * 1.0

A = np.zeros((N,N))
A = G / G.sum(axis=0)

# %%Check that A^i converges
print('A is primitive: ', np.all(np.isclose(np.linalg.matrix_power(A, 100),
                                            np.linalg.matrix_power(A, 101))))

# %% Hypotheses
theta = np.array([1., 2., 3.]) * 0.6
var = 1
x = np.linspace(-10, 10, 1000)
dt = (max(x) - min(x)) / len(x)

#%% Initialization
np.random.seed(0)
mu_0 = np.random.rand(N,M)
mu_0 = mu_0 / np.sum(mu_0, axis = 1)[:, None]

#%% Monte Carlo runs
delta = 0.2
N_MC = 10000
N_ITER = 100

MU_mc1 = []
for i in range(N_MC):
    csi = []
    for l in range(0, N):
        csi.append(theta[0] + np.sqrt(var) * np.random.randn(N_ITER))
    csi = np.array(csi)
    if i % 10000 == 0:
        print(i)
    m_aux = np.array(asl(mu_0, csi, A, N_ITER, theta, var, delta, is_gaussian=True))
    MU_mc1.append((np.argmax(m_aux, axis=2) != 0) * 1)

#%% Compute prob. of error for agents 1 and 10
p1 = sum(MU_mc1)[:,0] / N_MC
p9 = sum(MU_mc1)[:,9] / N_MC

# %% Save data
# pk.dump((p1, p9), open( DATA_PATH + "p_error.p", "wb" ) )
# p1, p9 = pk.load( open( DATA_PATH + "p_error.p", "rb" ) )

# %% Plot prob. of error
p1[0] = 1.0
p9[0] = 1.0
f, ax = plt.subplots(1, 1, figsize=(6,3))
ax.plot(p1, color='C5', linewidth=2)
ax.plot(p9, color='C0', linewidth=2)
ax.tick_params(axis='both', which='major', labelsize=18)
ax.set_yscale('log')
ax.set_xlim([0, len(p1) - 1])
ax.set_ylim([3e-4,2])
ax.set_xlabel(r'$i$', fontsize=18)
ax.set_ylabel(r'$p_{k,i}^{(\delta)}$', fontsize=18)
ax.legend(['Agent 1', 'Agent 10'], fontsize=18, ncol=2)
ax.annotate(r'$p^{(\delta)}_{1}=7.7 \times 10^{-3}$', (.65, p1[-1]-0.0008),
            xycoords=('axes fraction', 'data'), color='k', fontsize=16, va='center')
ax.annotate(r'$p^{(\delta)}_{10}=1.8 \times 10^{-3}$', (.65, p9[-1]+0.01),
            xycoords=('axes fraction', 'data'), color='k', fontsize=16, va='center')
f.savefig(FIG_PATH + '3.pdf', bbox_inches='tight')


import random
import numpy as np

import torch

from hyper_dti.settings import constants

def get_collate(mode, split):
    """ Wrapper for different collate functions. """
    if mode == 'pairs':
        return collate_triplets
    elif mode == 'drug':
        return collate_drug
    elif split == 'train':
        return collate_target
    else:
        return collate_target_eval

def collate_triplets(elem_dicts):
    """ Data loading for individual drug-target-interaction triplets. """
    batch = {'pids':  [], 'targets': torch.Tensor(), 'mids': [], 'drugs': torch.Tensor()}
    labels = torch.Tensor()

    for elem_dict in elem_dicts:
        label = torch.tensor(elem_dict['label']).unsqueeze(0)
        labels = label if len(labels) == 0 else torch.cat((labels, label), 0)
        batch['mids'].append(elem_dict['mid'])
        drug = torch.tensor(elem_dict['drug']).float().unsqueeze(0)
        batch['drugs'] = drug if len(batch['drugs']) == 0 else torch.cat((batch['drugs'], drug), 0)
        batch['pids'].append(elem_dict['pid'])
        target = torch.tensor(elem_dict['target']).float().unsqueeze(0)
        batch['targets'] = target if len(batch['targets']) == 0 else torch.cat((batch['targets'], target), 0)

    return batch, labels

def collate_target_single(elem_dicts):
    elem_dict = elem_dicts[0]
    labels = torch.tensor(elem_dict['label'])

    batch = {}
    batch['mids'] = [elem_dict['mid']]
    batch['drugs'] = torch.tensor(elem_dict['drug']).float()
    batch['pids'] = [elem_dict['pid']]
    batch['targets'] = torch.tensor(elem_dict['target']).float()

    return batch, labels

def collate_drug(elem_dicts):
    """ Data loading for interactions based on drug compound. """
    batch = {'pids': [], 'targets': None, 'mids': [], 'drugs': []}
    labels = torch.Tensor()

    for elem_dict in elem_dicts:
        batch_labels = torch.tensor(elem_dict['label'])
        labels = torch.cat((labels, batch_labels), 0)
        batch['mids'].append(elem_dict['mid'])
        drugs = torch.tensor(elem_dict['drugs']).float().unsqueeze(0)
        batch['drugs'] = drugs if len(batch['drugs']) == 0 else torch.cat((batch['drugs'], drugs), 0)
        batch['pids'].append(elem_dict['pid'])

    return batch, labels

def collate_target_eval(elem_dicts):
    """ Data loading for interactions based on protein target, without over- or under-sampling. """
    return collate_target(elem_dicts, eval=True)

def collate_target(elem_dicts, eval=False):
    """ Data loading for interactions based on protein target. """
    batch = {'pids': [], 'targets': torch.Tensor(), 'mids': [], 'drugs': []}
    labels = torch.Tensor()

    for elem_dict in elem_dicts:
        labeled_pairs = list(zip(elem_dict['mid'], elem_dict['drug'], elem_dict['label']))
        # Oversample for low frequency or shuffle otherwise
        if not eval and len(labeled_pairs) < constants.OVERSAMPLING:
            labeled_pairs = random.choices(labeled_pairs, k=constants.OVERSAMPLING)
        elif not eval and constants.MAIN_BATCH_SIZE != -1:
            if len(labeled_pairs) < constants.MAIN_BATCH_SIZE:
                random.shuffle(labeled_pairs)
            else:
                labeled_pairs = random.sample(labeled_pairs, k=constants.MAIN_BATCH_SIZE)
        else:
            random.shuffle(labeled_pairs)
        elem_dict['mid'], elem_dict['drug'], elem_dict['label'] = zip(*labeled_pairs)

        batch_labels = torch.tensor(elem_dict['label'])
        labels = torch.cat((labels, batch_labels), 0)

        batch['mids'].append(elem_dict['mid'])
        batch['drugs'].append(torch.tensor(np.stack(elem_dict['drug'], axis=0)).float())

        batch['pids'].append([elem_dict['pid'] for _ in range(len(elem_dict['mid']))])
        target = torch.tensor(elem_dict['target']).float().unsqueeze(0)
        batch['targets'] = target if len(batch['targets']) == 0 else torch.cat((batch['targets'], target), 0)

    return batch, labels


from bottle import template, route, run, request, get, post
from tinydb import TinyDB, Query
import backend
from datetime import datetime

db = TinyDB('./database.json')
players = db.table("players")
matches = db.table('matches')

@route('/classifica')
def classifica():
    page = ''
    page += ''
    page += ''
    page += '
Classifica

'
    for voice in players.all()[0].keys():
        header = '' + voice + '	'
        page += header
    page += '
'
    for player in players:
        element = '
' + player['name'] + '	' + str(player['elo']) + '
'
        page += element
    page += '
'
    return page

@get('/newmatch')
def newmatch():
    page = '<form action="/newmatch" method="POST">'

    date = '
<input type="date" name="date" value='+datetime.now().strftime("%Y-%m-%d") + '></input>
'
    page += date

    player1 = '
<select name="player1">'
    for player in players.all():
        option = '<option value=' + player['name'] + '>' + player['name'] + '</option>'
        player1 += option
    player1 += '</select>'
    page += player1

    player2 = '<select name="player2">'
    for player in players.all():
        option = '<option value=' + player['name'] + '>' + player['name'] + '</option>'
        player2 += option
    player2 += '</select>
'
    page += player2

    win1 = '
<input type="radio" name="res1" value=1 label="giocatore 1"/>'
    win2 = '<input type="radio" name="res1" value=0 label="giocatore 2"/>
'
    page += win1 + win2
    page += '<input type="submit" value="INVIA">'
    page += '</form>'

    page += matches_table()

    return (page)

@post('/newmatch')
def newmatch():
    date = request.forms.get('date')
    player1 = request.forms.get('player1')
    player2 = request.forms.get('player2')
    elo1 = players.search(Query().name == player1)[0]['elo']
    elo2 = players.search(Query().name == player2)[0]['elo']
    exp1 = backend.expected_result(elo1, elo2)
    exp2 = backend.expected_result(elo2, elo1)
    res1 = int(request.forms.get('res1'))
    # res2 should be 1 when res1 is 0 and viceversa
    res2 = 1 - res1
    backend.new_match(date, player1, player2,elo1,elo2,exp1,exp2,res1,res2)
    page = ('
Match added
New match')
    page += matches_table()
    return page

@route('/hello/<name>')
def saluto(name='Stranger'):
    return template('Hello {{name}}, how are you?', name=name)

def matches_table():
    today = datetime.now().strftime("%Y-%m-%d")
    today_matches = backend.get_today_matches(today)
    table = '

Giocatore 1	Giocatore 2	Risultato
'
    for match in today_matches:
        row = '
' + match['player1'] + '	' + match['player2'] + '	' + str(match['res1']) + ' - ' + str(match['res2']) + '
'
        table += row
    table += '
'
    return table

run(host='localhost',port=1990, debug=True)

### https://bottlepy.org/docs/dev/tutorial.html#installation


import os, json, time
import pandas as pd
import datetime
from dash import dash, dcc, html, callback_context
import plotly.express as px
from dash.dependencies import Input, Output, State
import dash_daq as daq
import dash_bootstrap_components as dbc
import PiCar
import socket

df = None
car = PiCar.SensorCar(filter_depth=2)

def get_ip_address():
    """Ermittlung der IP-Adresse im Netzwerk

    Returns:
        str: lokale IP-Adresse
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("8.8.8.8", 80))
    socket_ip = s.getsockname()[0]
    s.close()
    return socket_ip

def getLoggerFiles():
    """Files im Ordner "Logger" auflisten

    Returns:
        list: Log-Dateien
    """
    fileList = []
    outputList = []
    if os.path.isdir("Logger"):
        fileList = os.listdir("Logger")
        for file in fileList:
            if file.partition(".")[2] == "log":
                outputList.append(file)
            outputList.sort()
            outputList.reverse()
    return outputList

def getLogItemsList():
    """Definition der Spaltennamen für die Daten im Logfile

    Returns:
        list: Spaltennamen
    """
    return [
        "time",
        "v",
        "dir",
        "st_angle",
        "US",
        "IR1",
        "IR2",
        "IR3",
        "IR4",
        "IR5",
    ]

def load_data_to_df(pfad):
    """aktualisiert die Daten im Dataframe

    Args:
        pfad (str): Dateipfad zum File das geladen werden soll
    """
    global df
    df = pd.read_json(os.path.join("Logger", pfad))
    df.columns = getLogItemsList()

FP_LISTE = [  # Liste der auswählbaren Fahrprogramme
    {"label": "FP 1, vor-zurück", "value": 1},
    {"label": "FP 2, im Kreis", "value": 2},
    {"label": "FP 3, US-Testfahrt", "value": 3},
    {"label": "FP 4, Erkundungsfahrt", "value": 4},
    {"label": "FP 5, LineFollower", "value": 5},
    {"label": "FP 6, LineFollower Eng", "value": 6},
    {"label": "FP 7, LineFollower Eng + Hindernis", "value": 7},
]

kpi_1 = dbc.Card([dbc.CardBody([html.H6("vMax"), html.P(id="kpi1")])])
kpi_2 = dbc.Card([dbc.CardBody([html.H6("vMin"), html.P(id="kpi2")])])
kpi_3 = dbc.Card([dbc.CardBody([html.H6("vMean"), html.P(id="kpi3")])])
kpi_4 = dbc.Card([dbc.CardBody([html.H6("time"), html.P(id="kpi4")])])
kpi_5 = dbc.Card([dbc.CardBody([html.H6("vm"), html.P(id="kpi5")])])

row_joystick = dbc.Row(
    [
        dbc.Col([html.P("Manuell on/off"), dbc.Switch(id="sw_manual")], width=4),
        dbc.Col(
            daq.Joystick(id="joystick", size=100, className="mb-3"),
            width=4,
        ),
        dbc.Col(
            [
                html.P(id="value_joystick"),
            ],
            width=4,
        ),
    ]
)
CARD_ManuelleSteuerung = dbc.Card(
    [
        dbc.Row(
            [  # Titel Manuelle Steuerung
                html.H3(
                    id="label_test",
                    children="Manuelle Steuerung",
                    style={
                        "textAlign": "left",
                        "paddingTop": 20,
                        "paddingBottom": 20,
                    },
                )
            ]
        ),
        dbc.Row(
            [  # Slider Speed
                dbc.Col([html.H6("max. speed:")], width=4),
                dbc.Col(
                    [
                        dcc.Slider(
                            min=0,
                            max=100,
                            step=10,
                            id="slider_speed",
                            value=40,
                            updatemode="drag",
                        )
                    ],
                    width=8,
                ),
            ]
        ),
        row_joystick,
    ],
)

COL_Logfiles = [
    dbc.Row(
        [
            html.H2(  # Überschrift
                id="title_Logfiles",
                children="Logfiles",
                style={"textAlign": "center", "paddingBottom": 20},
            ),
            dcc.Dropdown(  # Dropdown Logfiles
                id="dd_Logfiles",
                placeholder="Bitte Logging-File wählen!",
                options=getLoggerFiles(),
                value="0",
                multi=False,
                style={"color": "black"},
            ),
        ]
    ),
    dbc.Row(
        [
            dbc.Col([kpi_1], width=4),
            dbc.Col([kpi_2], width=4),
            dbc.Col([kpi_3], width=4),
        ],
        style={"paddingTop": 20, "paddingBottom": 20},
    ),
    dbc.Row(
        [
            dbc.Col([kpi_4], width=4),
            dbc.Col([kpi_5], width=4),
        ],
        style={"paddingBottom": 20},
    ),
    dbc.Row(
        [
            html.H3(id="titel_LogDetails", children="Plot-Line Auswahl"),
            dcc.Dropdown(  # Dropdown Log-Details
                id="dd_LogDetails",
                options=getLogItemsList()[1:],
                value=getLogItemsList()[1:4],
                multi=True,
                style={"color": "black"},
            ),
            # dcc.Checklist(
            #     id="cl_Graph_Lines", options=getLogGraphList(),
            # ),
        ],
        style={"paddingBottom": 10},
    ),
]
COL_Fahrzeugsteuerung = [  # Col Fahrzeugsteuerung
    dbc.Row(
        [  # Titel
            html.H2(
                id="titel_Fahrzeugsteuerung",
                children="Fahrzeugsteuerung",
                style={
                    "textAlign": "center",
                    "paddingBottom": 20,
                },
            )
        ]
    ),
    dbc.Row(
        [  # Dropdown Fahrprogramm
            dcc.Dropdown(
                id="dd_Fahrprogramm",
                placeholder="Bitte Fahrprogramm wählen:",
                options=FP_LISTE,
                value=0,
                style={"color": "black"},
            )
        ]
    ),
    dbc.Row(
        [  # Buttons
            dbc.Col(
                [
                    dbc.Button(
                        children="Start Prog",
                        id="btn_start",
                        color="dark",
                        className="me-1",
                        n_clicks=0,
                    )
                ],
                width=4,
            ),
            dbc.Col(
                [],
                width=4,
            ),
            dbc.Col(
                [
                    dbc.Button(
                        children="STOP",
                        id="btn_stop",
                        color="dark",
                        className="me-1",
                        n_clicks=0,
                    )
                ],
                width=4,
            ),
        ],
        style={"paddingTop": 20, "paddingBottom": 20},
        justify="center",
    ),
    dbc.Row(
        [
            CARD_ManuelleSteuerung,
        ]
    ),
]

app = dash.Dash(
    __name__,
    external_stylesheets=[dbc.themes.SUPERHERO],
    meta_tags=[
        {"name": "viewport"},
        {"content": "width = device,width, initial-scale=1.0"},
    ],
)

app.layout = dbc.Container(
    [
        dbc.Row(
            [  # Row 1
                dbc.Col(
                    [  # Col 1
                        html.H1(
                            id="title_main",
                            children="Camp2Code - Gruppe 4",
                            style={
                                "textAlign": "center",
                                "marginTop": 40,
                                "marginBottom": 40,
                            },
                        )
                    ],
                    width=12,
                ),
            ],
            justify="center",
        ),
        dbc.Row(
            [  # Row 2
                dbc.Col(  # Logfile-Handling
                    COL_Logfiles,
                    width=5,
                    # style={"backgroundColor": "darkgrey"},
                ),
                dbc.Col([], width=2),  # Col Space
                dbc.Col(
                    COL_Fahrzeugsteuerung,
                    width=5,
                    # style={"backgroundColor": "darkgrey"},
                ),
            ],
            justify="center",
        ),
        dbc.Row(
            [
                dcc.Graph(id="plot_Logfile"),
                html.P(
                    id="Fussnote",
                    children="hier das Copyright ;)",
                    style={"textAlign": "right"},
                ),
                html.Div(id="dummy"),
                html.Div(id="dummy2"),
                dcc.Interval(id="intervall_10s", interval=10000),
                dcc.Interval(
                    id="interval_startup",
                    max_intervals=1,
                ),
            ],
            style={"paddingTop": 10, "paddingBottom": 10},
        ),  # Row 3
    ]
)

@app.callback(
    Output("value_joystick", "children"),
    Input("joystick", "angle"),
    Input("joystick", "force"),
    State("sw_manual", "value"),
    State("slider_speed", "value"),
)
def joystick_values(angle, force, switch, max_Speed):
    """Steuerung über Joystick
        berechnet anhand der Joystick-Werte den Lenkeinschlag
        und zusätzlich mit der eingestellten Maximalgeschwindigkeit die Fahrgeschwindigkeit

    Args:
        angle (float): Winkelwert des Joysticks
        force (float): Kraftweg des Joysticks
        switch (bool): Schalter "manuelle Fahrt"
        max_Speed (int): Wert Slider "slider_speed"

    Returns:
        str: gibt die ermittelten Sollwerte zurück
    """
    debug = ""
    if angle != None and force != None:
        if switch:
            power = round(force, 1)
            winkel = 0
            dir = 0
            if force == 0:
                winkel = 0
                dir = 0
                car.drive(0, 0)
                car.steering_angle = 0
            else:
                power = power * max_Speed
                if power > max_Speed:
                    power = max_Speed
                if angle <= 180:
                    dir = 1
                    winkel = round(45 - (angle / 2), 0)
                else:
                    dir = -1
                    winkel = round(((angle - 180) / 2) - 45, 0)
                car.drive(int(power), dir)
                car.steering_angle = winkel
                debug = f"Angle: {winkel} speed: {power} dir: {dir}"
        else:
            debug = "Man. mode off"
            car.drive(0, 0)
            car.steering_angle = 0
    else:
        debug = "None-Value"
    return debug

def computeKPI(data):
    """Berechnung der Kenndaten des Log-Files

    Args:
        data (pandas.DataFrame): Log-Daten als DataFrame

    Returns:
        tuple of str: berechnete Werte
    """
    vmax = data["v"].max()
    vmin = data["v"][1:].min()
    vmean = round(data["v"].mean(), 2)
    duration = round(data["time"].max(), 2)
    route = round(vmean * duration, 2)
    return vmax, vmin, vmean, duration, route

@app.callback(
    Output(component_id="kpi1", component_property="children"),
    Output(component_id="kpi2", component_property="children"),
    Output(component_id="kpi3", component_property="children"),
    Output(component_id="kpi4", component_property="children"),
    Output(component_id="kpi5", component_property="children"),
    Input("dd_Logfiles", "value"),
)
def update_KPI_DD(logFile):
    """Aktualisieren der Kennwerte nach auswahl eines neuen Files

    Args:
        logFile (str): nur wegen input nötig

    Returns:
        str: setzt die "children" der kpi's
    """
    global df
    time.sleep(0.2)  # damit das File erst geladen werden kann
    try:
        vmax, vmin, vmean, duration, route = computeKPI(df)
        return vmax, vmin, vmean, duration, route
    except:
        return 0, 0, 0, 0, 0

@app.callback(
    Output("plot_Logfile", "figure"),
    Input("dd_Logfiles", "value"),
    Input("dd_LogDetails", "value"),
)
def selectedLog(logFile, logDetails):
    """Auswahl des Logfiles

    Args:
        logFile (str): Log-File
        logDetails (list): Liste mit Elementen die angezeigt werden sollen

    Returns:
        plotly figure: Graph mit ausgewählten Daten
    """
    global df
    if logFile != "0":
        load_data_to_df(logFile)
        # df = pd.read_json(os.path.join("Logger", logFile))
        # time.sleep(0.1)
        # df.columns = getLogItemsList()
        if logDetails != []:
            fig = px.line(df, x="time", y=logDetails, title=logFile)
        else:
            fig = px.line(df, x="time", y="st_angle", title=logFile)
        return fig
    else:
        return px.line()

@app.callback(
    Output("dd_Logfiles", "options"),
    Input("intervall_10s", "n_intervals"),
)
def updateFileList(value):
    """alle 10 Sekunden den Logger-Ordner auf neue Files prüfen"""
    return getLoggerFiles()

@app.callback(
    Output("sw_manual", "value"),
    Input("btn_start", "n_clicks"),
    Input("btn_stop", "n_clicks"),
    State("dd_Fahrprogramm", "value"),
    State("slider_speed", "value"),
)
def button_action(btn_start, btn_stop, fp, speed):
    """Buttons "Start" und "Stop" verarbeiten

    Returns:
        int: Schalter für manuellen Betrieb auf 0 setzen
    """
    changed_id = [p["prop_id"] for p in callback_context.triggered][0]
    if "btn_start" in changed_id:
        car.generischerFahrparcour(fp, speed)

    if "btn_stop" in changed_id:
        car._active = False
        car._worker.shutdown(wait=True)
        time.sleep(1)
    return 0

if __name__ == "__main__":
    app.run_server(debug=True, host=get_ip_address())


import logging
import pytest
import copy
import os
import ldap
from lib389._constants import *
from lib389.topologies import topology_st as topo

from lib389.replica import Replicas
from lib389.agreement import Agreements
from lib389.utils import ds_is_older

pytestmark = pytest.mark.tier1

DEBUGGING = os.getenv("DEBUGGING", default=False)
if DEBUGGING:
    logging.getLogger(__name__).setLevel(logging.DEBUG)
else:
    logging.getLogger(__name__).setLevel(logging.INFO)
log = logging.getLogger(__name__)

notnum = 'invalid'
too_big = '9223372036854775807'
overflow = '9999999999999999999999999999999999999999999999999999999999999999999'

replica_dict = {'nsDS5ReplicaRoot': 'dc=example,dc=com',
                'nsDS5ReplicaType': '3',
                'nsDS5Flags': '1',
                'nsDS5ReplicaId': '65534',
                'nsds5ReplicaPurgeDelay': '604800',
                'nsDS5ReplicaBindDN': 'cn=u',
                'cn': 'replica'}

agmt_dict = {'cn': 'test_agreement',
             'nsDS5ReplicaRoot': 'dc=example,dc=com',
             'nsDS5ReplicaHost': 'localhost.localdomain',
             'nsDS5ReplicaPort': '5555',
             'nsDS5ReplicaBindDN': 'uid=tester',
             'nsds5ReplicaCredentials': 'password',
             'nsDS5ReplicaTransportInfo': 'LDAP',
             'nsDS5ReplicaBindMethod': 'SIMPLE'}

repl_add_attrs = [('nsDS5ReplicaType', '-1', '4', overflow, notnum, '1'),
                  ('nsDS5Flags', '-1', '2', overflow, notnum, '1'),
                  ('nsDS5ReplicaId', '0', '65536', overflow, notnum, '1'),
                  ('nsds5ReplicaPurgeDelay', '-2', too_big, overflow, notnum, '1'),
                  ('nsDS5ReplicaBindDnGroupCheckInterval', '-2', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaTombstonePurgeInterval', '-2', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaProtocolTimeout', '-1', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaReleaseTimeout', '-1', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaBackoffMin', '0', too_big, overflow, notnum, '3'),
                  ('nsds5ReplicaBackoffMax', '0', too_big, overflow, notnum, '6'),
                  ('nsds5ReplicaKeepAliveUpdateInterval', '59', too_big, overflow, notnum, '60'),]

repl_mod_attrs = [('nsDS5Flags', '-1', '2', overflow, notnum, '1'),
                  ('nsds5ReplicaPurgeDelay', '-2', too_big, overflow, notnum, '1'),
                  ('nsDS5ReplicaBindDnGroupCheckInterval', '-2', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaTombstonePurgeInterval', '-2', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaProtocolTimeout', '-1', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaReleaseTimeout', '-1', too_big, overflow, notnum, '1'),
                  ('nsds5ReplicaBackoffMin', '0', too_big, overflow, notnum, '3'),
                  ('nsds5ReplicaBackoffMax', '0', too_big, overflow, notnum, '6'),
                  ('nsds5ReplicaKeepAliveUpdateInterval', '59', too_big, overflow, notnum, '60'),]

agmt_attrs = [
              ('nsds5ReplicaPort', '0', '65535', overflow, notnum, '389'),
              ('nsds5ReplicaTimeout', '-1', too_big, overflow, notnum, '6'),
              ('nsds5ReplicaBusyWaitTime', '-1', too_big, overflow, notnum, '6'),
              ('nsds5ReplicaSessionPauseTime', '-1', too_big, overflow, notnum, '6'),
              ('nsds5ReplicaFlowControlWindow', '-1', too_big, overflow, notnum, '6'),
              ('nsds5ReplicaFlowControlPause', '-1', too_big, overflow, notnum, '6'),
              ('nsds5ReplicaProtocolTimeout', '-1', too_big, overflow, notnum, '6')
              ]

def replica_reset(topo):
    """Purge all existing replica details"""
    replicas = Replicas(topo.standalone)
    for r in replicas.list():
        r.delete()

def replica_setup(topo):
    """Add a valid replica config entry to modify
    """
    replicas = Replicas(topo.standalone)
    for r in replicas.list():
        r.delete()
    return replicas.create(properties=replica_dict)

def agmt_reset(topo):
    """Purge all existing agreements for testing"""
    agmts = Agreements(topo.standalone)
    for a in agmts.list():
        a.delete()

def agmt_setup(topo):
    """Add a valid replica config entry to modify
    """
    # Reset the agreements too.
    replica = replica_setup(topo)
    agmts = Agreements(topo.standalone, basedn=replica.dn)
    for a in agmts.list():
        a.delete()
    return agmts.create(properties=agmt_dict)

def perform_invalid_create(many, properties, attr, value):
    my_properties = copy.deepcopy(properties)
    my_properties[attr] = value
    with pytest.raises(ldap.LDAPError) as ei:
        many.create(properties=my_properties)
    return ei.value

def perform_invalid_modify(o, attr, value):
    with pytest.raises(ldap.LDAPError) as ei:
        o.replace(attr, value)
    return ei.value

@pytest.mark.parametrize("attr, too_small, too_big, overflow, notnum, valid", repl_add_attrs)
def test_replica_num_add(topo, attr, too_small, too_big, overflow, notnum, valid):
    """Test all the number values you can set for a replica config entry

    :id: a8b47d4a-a089-4d70-8070-e6181209bf92
    :parametrized: yes
    :setup: standalone instance
    :steps:
        1. Use a value that is too small
        2. Use a value that is too big
        3. Use a value that overflows the int
        4. Use a value with character value (not a number)
        5. Use a valid value
    :expectedresults:
        1. Add is rejected
        2. Add is rejected
        3. Add is rejected
        4. Add is rejected
        5. Add is allowed
    """
    replica_reset(topo)

    replicas = Replicas(topo.standalone)

    # Test too small
    perform_invalid_create(replicas, replica_dict, attr, too_small)
    # Test too big
    perform_invalid_create(replicas, replica_dict, attr, too_big)
    # Test overflow
    perform_invalid_create(replicas, replica_dict, attr, overflow)
    # test not a number
    perform_invalid_create(replicas, replica_dict, attr, notnum)
    # Test valid value
    my_replica = copy.deepcopy(replica_dict)
    my_replica[attr] = valid
    replicas.create(properties=my_replica)

@pytest.mark.parametrize("attr, too_small, too_big, overflow, notnum, valid", repl_mod_attrs)
def test_replica_num_modify(topo, attr, too_small, too_big, overflow, notnum, valid):
    """Test all the number values you can set for a replica config entry

    :id: a8b47d4a-a089-4d70-8070-e6181209bf93
    :parametrized: yes
    :setup: standalone instance
    :steps:
        1. Replace a value that is too small
        2. Repalce a value that is too big
        3. Replace a value that overflows the int
        4. Replace a value with character value (not a number)
        5. Replace a vlue with a valid value
    :expectedresults:
        1. Value is rejected
        2. Value is rejected
        3. Value is rejected
        4. Value is rejected
        5. Value is allowed
    """
    replica = replica_setup(topo)

    # Value too small
    perform_invalid_modify(replica, attr, too_small)
    # Value too big
    perform_invalid_modify(replica, attr, too_big)
    # Value overflow
    perform_invalid_modify(replica, attr, overflow)
    # Value not a number
    perform_invalid_modify(replica, attr, notnum)
    # Value is valid
    replica.replace(attr, valid)

@pytest.mark.xfail(reason="Agreement validation current does not work.")
@pytest.mark.parametrize("attr, too_small, too_big, overflow, notnum, valid", agmt_attrs)
def test_agmt_num_add(topo, attr, too_small, too_big, overflow, notnum, valid):
    """Test all the number values you can set for a replica config entry

    :id: a8b47d4a-a089-4d70-8070-e6181209bf94
    :parametrized: yes
    :setup: standalone instance
    :steps:
        1. Use a value that is too small
        2. Use a value that is too big
        3. Use a value that overflows the int
        4. Use a value with character value (not a number)
        5. Use a valid value
    :expectedresults:
        1. Add is rejected
        2. Add is rejected
        3. Add is rejected
        4. Add is rejected
        5. Add is allowed
    """

    agmt_reset(topo)
    replica = replica_setup(topo)

    agmts = Agreements(topo.standalone, basedn=replica.dn)

    # Test too small
    perform_invalid_create(agmts, agmt_dict, attr, too_small)
    # Test too big
    perform_invalid_create(agmts, agmt_dict, attr, too_big)
    # Test overflow
    perform_invalid_create(agmts, agmt_dict, attr, overflow)
    # test not a number
    perform_invalid_create(agmts, agmt_dict, attr, notnum)
    # Test valid value
    my_agmt = copy.deepcopy(agmt_dict)
    my_agmt[attr] = valid
    agmts.create(properties=my_agmt)

@pytest.mark.xfail(reason="Agreement validation current does not work.")
@pytest.mark.parametrize("attr, too_small, too_big, overflow, notnum, valid", agmt_attrs)
def test_agmt_num_modify(topo, attr, too_small, too_big, overflow, notnum, valid):
    """Test all the number values you can set for a replica config entry

    :id: a8b47d4a-a089-4d70-8070-e6181209bf95
    :parametrized: yes
    :setup: standalone instance
    :steps:
        1. Replace a value that is too small
        2. Replace a value that is too big
        3. Replace a value that overflows the int
        4. Replace a value with character value (not a number)
        5. Replace a vlue with a valid value
    :expectedresults:
        1. Value is rejected
        2. Value is rejected
        3. Value is rejected
        4. Value is rejected
        5. Value is allowed
    """

    agmt = agmt_setup(topo)

    # Value too small
    perform_invalid_modify(agmt, attr, too_small)
    # Value too big
    perform_invalid_modify(agmt, attr, too_big)
    # Value overflow
    perform_invalid_modify(agmt, attr, overflow)
    # Value not a number
    perform_invalid_modify(agmt, attr, notnum)
    # Value is valid
    agmt.replace(attr, valid)

@pytest.mark.skipif(ds_is_older('1.4.1.4'), reason="Not implemented")
@pytest.mark.bz1546739
def test_same_attr_yields_same_return_code(topo):
    """Test that various operations with same incorrect attribute value yield same return code

    :id: 4bae88d7-0da8-4a71-b062-9d0ff4e472cf
    :setup: standalone instance
    :steps:
        1. Purge all replica details
        2. Perform an invalid create operation
        3. Setup replica
        4. Perform an invalid modify operation
    :expectedresults:
        1. Success
        2. Value is rejected
        3. Success
        4. Value is rejected
    """
    attr = 'nsDS5ReplicaId'

    replica_reset(topo)
    replicas = Replicas(topo.standalone)
    e = perform_invalid_create(replicas, replica_dict, attr, too_big)
    assert type(e) is ldap.UNWILLING_TO_PERFORM

    replica = replica_setup(topo)
    e = perform_invalid_modify(replica, attr, too_big)
    assert type(e) is ldap.UNWILLING_TO_PERFORM

if __name__ == '__main__':
    # Run isolated
    # -s for DEBUG mode
    CURRENT_FILE = os.path.realpath(__file__)
    pytest.main(["-s", CURRENT_FILE])