import hashlib
import json
from typing import List
from zipfile import ZipFile

import yaml
from django.contrib import admin
from django.core.files.base import ContentFile
from django.db import models, transaction
from django.db.models import QuerySet
from django.forms import ModelForm, FileField, CharField
from django.shortcuts import redirect
from django.utils import timezone
from model_utils.managers import InheritanceManager

class Evaluation(models.Model):
    TYPES = {
        'SEL': 'Image selection',
        'CLS': 'Image classification'
    }

    title = models.CharField(max_length=100)
    created_at = models.DateTimeField()
    type = models.CharField(max_length=10, choices=TYPES.items())
    total_questions = models.IntegerField()

    def __str__(self):
        return f'{self.title} ({Evaluation.TYPES[self.type]})'

class Question(models.Model):
    evaluation = models.ForeignKey(Evaluation, on_delete=models.CASCADE)
    text = models.CharField(max_length=1000)
    order = models.IntegerField()
    objects = InheritanceManager()

    def get_real_answer(self, answer):
        raise NotImplemented()

class ImageClassificationQuestion(Question):
    image = models.ImageField()
    answers = models.TextField()

    @property
    def choices(self):
        parsed_answers = json.loads(self.answers)
        return list(zip(range(len(parsed_answers)), parsed_answers))

    def get_real_answer(self, answer):
        return answer

class ImageSelectionQuestion(Question):
    """
    Example:
          ::
        ImageSelectionQuestion(
            evaluation=e,
            text='Test test',
            order=0,
            left_image=ContentFile(b1, 'li0.png'),
            right_image=ContentFile(b2, 'ri0.png')
        ).save()

    """
    left_image = models.ImageField()
    right_image = models.ImageField()

    def _neeed_flip(self):
        hash = int(hashlib.sha1(f"{self.id}".encode()).hexdigest(), 16)
        return hash % 2 == 0

    def get_left_image(self):
        if self._neeed_flip():
            return self.right_image
        else:
            return self.left_image

    def get_right_image(self):
        if self._neeed_flip():
            return self.left_image
        else:
            return self.right_image

    def get_real_answer(self, answer):
        if self._neeed_flip():
            return 1 - answer
        return answer

class EvaluationForm(ModelForm):
    images = FileField()
    question = CharField(max_length=1000)

@admin.register(Evaluation)
class EvaluationAdmin(admin.ModelAdmin):
    list_display = ['id', 'title', 'type', 'total_questions', 'created_at']
    ordering = ['created_at']
    actions = ['export_result']
    readonly_fields = ['created_at', 'total_questions']
    list_editable = ['title']
    list_display_links = None
    form = EvaluationForm

    def export_result(self, request, queryset: QuerySet):
        return redirect('export_result', id=queryset.all()[0].id)

    @transaction.atomic
    def save_model(self, request, obj, form: ModelForm, change):
        if change:
            super().save_model(request, obj, form, True)
        else:
            data = form.cleaned_data
            evaluation: Evaluation = Evaluation(title=data['title'],
                                                type=data['type'],
                                                created_at=timezone.now(),
                                                total_questions=0)
            evaluation.save()

            if data['type'] == 'SEL':
                zip_parser = self.make_selection_questions_from_zip
            else:
                zip_parser = self.make_classification_questions_from_zip

            evaluation.total_questions = zip_parser(
                data['images'],
                data['question'],
                evaluation
            )

            evaluation.save()

    @staticmethod
    def make_selection_questions_from_zip(zip_file_stream, question_text, evaluation):
        try:
            with ZipFile(zip_file_stream) as images:
                baseline_images = EvaluationAdmin.get_fnames_with_prefix(
                    images, 'baseline/'
                )
                proposed_images = EvaluationAdmin.get_fnames_with_prefix(
                    images, 'proposed/'
                )

                # Remove all prefixes and exts to match names
                # proposed/first.jpg -> first
                baseline_image_names = {
                    name.rsplit('/', 1)[1].rsplit('.', 1)[0] for name in baseline_images
                }
                proposed_image_names = {
                    name.rsplit('/', 1)[1].rsplit('.', 1)[0] for name in proposed_images
                }

                if baseline_image_names != proposed_image_names:
                    raise Exception(
                        "Proposed and baseline image sets doesn't match"
                    )

                image_names = baseline_image_names

                total_questions = len(image_names)

                if total_questions == 0:
                    raise Exception("There must be at least one question")

                questions = []
                for no, name in enumerate(sorted(image_names)):
                    # Get image bytes without knowing extension
                    baseline_bytes = images.read(
                        EvaluationAdmin.get_fnames_with_prefix(images, f'baseline/{name}')[0]
                    )
                    proposed_bytes = images.read(
                        EvaluationAdmin.get_fnames_with_prefix(images, f'proposed/{name}')[0]
                    )

                    q = ImageSelectionQuestion(
                        evaluation=evaluation, text=question_text,
                        order=no,
                        left_image=ContentFile(baseline_bytes, f'{evaluation.id}_{no}_l.jpg'),
                        right_image=ContentFile(proposed_bytes, f'{evaluation.id}_{no}_r.jpg')
                    )
                    q.save()
                    questions.append(q)
            return total_questions
        except Exception as e:
            raise Exception('Zip parsing failed. Most likely the structure is wrong') from e

    @staticmethod
    def get_fnames_with_prefix(zip: ZipFile, prefix: str) -> List[str]:
        filenames = [item.filename for item in zip.filelist]
        return [name for name in filenames if name.startswith(prefix) and len(name) > len(prefix)]

    @staticmethod
    def make_classification_questions_from_zip(zip_file_stream, question_text, evaluation):
        try:
            with ZipFile(zip_file_stream) as images:
                image_names = EvaluationAdmin.get_fnames_with_prefix(
                    images, 'images/'
                )

                with images.open('answers.yml') as yml_stream:
                    answers = json.dumps(yaml.load(yml_stream))

                total_questions = len(image_names)
                if total_questions == 0:
                    raise Exception("There must be at least one question")

                questions = []
                for no, name in enumerate(image_names):
                    image_bytes = images.read(name)

                    q = ImageClassificationQuestion(
                        evaluation=evaluation, text=question_text,
                        order=no,
                        answers=answers,
                        image=ContentFile(image_bytes, f'{evaluation.id}_{no}.jpg'),
                    )
                    q.save()
                    questions.append(q)
            return total_questions
        except Exception as e:
            raise Exception('Zip parsing failed. Most likely the structure is wrong') from e

__all__ = ['Evaluation', 'Question', 'ImageSelectionQuestion', 'ImageClassificationQuestion']


from django.shortcuts import render
from django.http import JsonResponse
from .models import DatosFormularioRechazoMpInMe
from django.http import HttpResponseRedirect
from django.urls import reverse

# Create your views here.

def rechazo_mp_in_me(request):
    return render(request, 'rechazo_mp_in_me/r_informe_rechazo_mp_in_me.html')

def vista_rechazo_mp_in_me(request):
    if request.method == 'POST' and request.is_ajax():
        nombre_tecnologo = request.POST.get('nombre_tecnologo')
        fecha_registro = request.POST.get('fecha_registro')
        nombre_proveedor = request.POST.get('nombre_proveedor')
        numero_factura = request.POST.get('numero_factura')
        nombre_transportista = request.POST.get('nombre_transportista')
        nombre_producto = request.POST.get('nombre_producto')
        fecha_elaboracion = request.POSt.get('fecha_elaboracion')
        lote = request.POST.get('lote')
        fecha_vencimiento = request.POST.get('fecha_vencimiento')
        motivo_rechazo = request.POST.get('motivo_rechazo')
        cantidad_producto_involucrado = request.POST.get('cantidad_producto_involucrado')
        unidad_de_medida = request.POST.get('unidad_de_medida')
        clasificacion = request.POST.get('clasificacion')

        datos = DatosFormularioRechazoMpInMe(
            nombre_tecnologo=nombre_tecnologo,
            fecha_registro=fecha_registro,
            nombre_proveedor=nombre_proveedor,
            numero_factura=numero_factura,
            nombre_transportista=nombre_transportista,
            nombre_producto=nombre_producto,
            fecha_elaboracion=fecha_elaboracion,
            lote=lote,
            fecha_vencimiento=fecha_vencimiento,
            motivo_rechazo=motivo_rechazo,
            cantidad_producto_involucrado=cantidad_producto_involucrado,
            unidad_de_medida=unidad_de_medida,
            clasificacion=clasificacion
            )
        datos.save()

        return JsonResponse({'mensaje': 'Datos guardados exitosamente'})

def redireccionar_selecciones(request):
    url_selecciones = reverse('vista_selecciones')
    return HttpResponseRedirect(url_selecciones)


from __future__ import division
import random
from copy import deepcopy
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
import time

numElements = 1000
numMin = -1000
numMax = 1000
arrElements = []
times = []

def ordenamientoPorInsercion(unaLista):
    moves = 0
    for indice in range(1,len(unaLista)):
        valorActual = unaLista[indice]
        posicion = indice

        while posicion>0 and unaLista[posicion-1]>valorActual:
            unaLista[posicion]=unaLista[posicion-1]
            posicion = posicion-1
            moves+=1
        unaLista[posicion]=valorActual
        moves+=1
    # print "Insertion: "+str(unaLista)
    return moves

def shellSort(alist):
    moves = 0
    sublistcount = len(alist)//2
    while sublistcount > 0:
      for start_position in range(sublistcount):
        for i in range(start_position+sublistcount,len(alist),sublistcount):

            current_value = alist[i]
            position = i

            while position>=sublistcount and alist[position-sublistcount]>current_value:
                alist[position]=alist[position-sublistcount]
                moves+=1
                position = position-sublistcount

            alist[position]=current_value
            moves+=1
      sublistcount = sublistcount // 2
    # print "ShellSort: "+str(alist)
    return moves

# Python program for implementation of MergeSort
def mergeSort(arr, moves):
    if len(arr) >1:
        mid = len(arr)//2 #Finding the mid of the array
        L = arr[:mid] # Dividing the array elements
        R = arr[mid:] # into 2 halves

        moves = mergeSort(L, moves) # Sorting the first half
        moves = mergeSort(R, moves) # Sorting the second half

        i = j = k = 0

        # Copy data to temp arrays L[] and R[]
        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                moves+=1
                i+=1
            else:
                arr[k] = R[j]
                moves+=1
                j+=1
            k+=1

        # Checking if any element was left
        while i < len(L):
            arr[k] = L[i]
            moves+=1
            i+=1
            k+=1

        while j < len(R):
            arr[k] = R[j]
            moves+=1
            j+=1
            k+=1
    return moves

# Init QuickSort
movesQuick = 0
def quickSort(alist):
   quickSortHelper(alist,0,len(alist)-1)
#    print("QuickSort: "+str(alist))

def quickSortHelper(alist,first,last):
   if first<last:

       splitpoint = partition(alist,first,last)

       quickSortHelper(alist,first,splitpoint-1)
       quickSortHelper(alist,splitpoint+1,last)

def partition(alist,first,last):
   global movesQuick
   pivotvalue = alist[first]

   leftmark = first+1
   rightmark = last

   done = False
   while not done:

       while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
           leftmark = leftmark + 1

       while alist[rightmark] >= pivotvalue and rightmark >= leftmark:
           rightmark = rightmark -1

       if rightmark < leftmark:
           done = True
       else:
           temp = alist[leftmark]
           alist[leftmark] = alist[rightmark]
           movesQuick+=1
           alist[rightmark] = temp
           movesQuick+=1

   temp = alist[first]
   alist[first] = alist[rightmark]
   movesQuick+=1
   alist[rightmark] = temp
   movesQuick+=1

   return rightmark
# End QuickSort

# Starts HEAP SORT
movesHeap = 0
def heapify(arr, n, i):
    global movesHeap
    largest = i # Initialize largest as root
    l = 2 * i + 1     # left = 2*i + 1
    r = 2 * i + 2     # right = 2*i + 2

    # See if left child of root exists and is
    # greater than root
    if l < n and arr[i] < arr[l]:
        largest = l

    # See if right child of root exists and is
    # greater than root
    if r < n and arr[largest] < arr[r]:
        largest = r

    # Change root, if needed
    if largest != i:
        arr[i],arr[largest] = arr[largest],arr[i] # swap
        movesHeap+=2
        # Heapify the root.
        heapify(arr, n, largest)

# The main function to sort an array of given size
def heapSort(arr):
    global movesHeap
    n = len(arr)

    # Build a maxheap.
    for i in range(n, -1, -1):
        heapify(arr, n, i)

    # One by one extract elements
    for i in range(n-1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i] # swap
        movesHeap+=2
        heapify(arr, i, 0)
    # print "HeapSort : "+str(arr)

# Ends HEAP SORT

# Starts bucket sort
movesBucket = 0
def insertionSort(b):
    for i in range(1, len(b)):
        up = b[i]
        j = i - 1
        while j >=0 and b[j] > up:
            b[j + 1] = b[j]
            j -= 1
        b[j + 1] = up
    return b

def bucketSort(x):
    global movesBucket
    arr = []
    slot_num = 10 # 10 means 10 slots, each
                  # slot's size is 0.1
    for i in range(slot_num):
        arr.append([])

    # Put array elements in different buckets
    for j in x:
        index_b = int(slot_num * j)
        arr[index_b].append(j)

    # Sort individual buckets
    for i in range(slot_num):
        arr[i] = insertionSort(arr[i])
    # concatenate the result
    k = 0
    for i in range(slot_num):
        for j in range(len(arr[i])):
            x[k] = arr[i][j]
            movesBucket += 1
            k += 1
    return x

# Ends bucket sort
for i in range(numElements):
    arrElements.append(random.randint(numMin,numMax))
# print "Arreglo original"+str(arrElements)

firstTime = int(round(time.time() * 1000))
movesIns = ordenamientoPorInsercion(arrElements[:])
lastTime = int(round(time.time() * 1000))
times.append(lastTime - firstTime)

firstTime = int(round(time.time() * 1000))
movesShell = shellSort(arrElements[:])
lastTime = int(round(time.time() * 1000))
times.append(lastTime - firstTime)

firstTime = int(round(time.time() * 1000))
movesMerge = mergeSort(deepcopy(arrElements), 0)
lastTime = int(round(time.time() * 1000))
times.append(lastTime - firstTime)

# print "MergeSort: "+str(arrayMerge)
firstTime = int(round(time.time() * 1000))
quickSort(arrElements[:])
lastTime = int(round(time.time() * 1000))
times.append(lastTime - firstTime)

firstTime = int(round(time.time() * 1000))
heapSort(arrElements[:])
lastTime = int(round(time.time() * 1000))
times.append(lastTime - firstTime)

arrBucket = []
for i in range(numElements):
    bucketValue = (random.randrange(10,100))/100
    arrBucket.append(bucketValue)

firstTime = int(round(time.time() * 1000))
bucketSort(arrBucket[:])
lastTime = int(round(time.time() * 1000))
times.append(lastTime - firstTime)

# print "Arreglo original"+str(arrElements)
# print "Moves Insertion: "+str(movesIns)
# print "Moves ShellSort: "+str(movesShell)
# print "Moves MergeSort: "+str(movesMerge)
# print "Moves QuickSort: "+str(movesQuick)
# print "Moves HeapSort : "+str(movesHeap)
# print "Moves Bucket :"+str(movesBucket)

names = ["Insertion","ShellSort","MergeSort","QuickSort","HeapSort","BucketSort"]
movesAll = [int(movesIns),int(movesShell),int(movesMerge),int(movesQuick),int(movesHeap),int(movesBucket) ]

y_pos = np.arange(len(names))
plt.figure(figsize=(20, 5))
plt.subplot(1,2,1)
plt.bar(y_pos, movesAll,align='center')
plt.xticks(y_pos, names)
plt.ylabel('Movimientos')

plt.subplot(1,2,2)
plt.bar(y_pos, times,align='center')
plt.xticks(y_pos, names)
plt.ylabel('Tiempo (milisegundos)')

plt.suptitle('Metodos de ordenamiento')

plt.show()


from wackynode import WackyNode

class WackyQueue:
    """The Class WackyQueue"""

    def __init__(self):
        # REPRESENTATION INVARIANTS
        # _head_even is the head of the even linked list
        # initially set to None
        # _head_odd si the head of odd linked list
        # initially set to None
        # if WackyQueue is not empty
        #    then the _head_odd is the first element
        #    of our list
        #
        # if WackyQueue is not empty and extracthigh
        #     _head_odd is the first to be removed
        # if negate all and 1 item in WackyQueue
        #       negate the <pri> of _head_odd only
        self._head_even = None
        self._head_odd = None

    def __str__(self):
        '''
        (WackyQueue) -> str
        This is the string representation
        of this class where it returns
        the relationship between the linked lists
        '''
        curr_even = self.getevenlist()
        curr_odd = self.getoddlist()
        order_even = ''
        order_odd = ''
        # as long as curr is not Null
        # if the next node is not null
        # add the item of the node and point
        # to the second item
        # if it is the last node point it to
        while curr_even:
            if curr_even.get_next():
                order_even += str(curr_even.get_item())\
                              + '|' + str(curr_even.get_priority()) + ' --> '
            else:
                order_even += str(curr_even.get_item()) +\
                              '|' + str(curr_even.get_priority()) + ' --> NONE'

            curr_even = curr_even.get_next()

        # Do the same thing but for the odd list
        while curr_odd:
            if curr_odd.get_next():
                order_odd += str(curr_odd.get_item())\
                             + '|' + str(curr_odd.get_priority()) + ' --> '
            else:
                order_odd += str(curr_odd.get_item())\
                             + '|' + str(curr_odd.get_priority()) + ' --> NONE'

            curr_odd = curr_odd.get_next()

        return order_even + '\n' + order_odd

    def extracthigh(self):
        """
        (WackyQueue) -> object
        The first item in the
        WackyQueue will be removed and
        returned
        REQ: WackyQueue must not be isempty
        """
        # initialize our current's and previous
        # items in both lists
        curr_even = self._head_even
        curr_odd = self._head_odd

        # take the first item of the queue
        first_item = curr_odd.get_item()

        # Base case 1:
        # where there is only 1 item in the queue
        # clear the list
        if not curr_even:
            self._head_odd = None
            self._head_even = None

        # Base case 2:
        # there are 2 item's
        # remove the first and
        # make the second into the first
        elif curr_even and not curr_odd.get_next():
            self._head_even = None
            self._head_odd = curr_even

        # let even list be 2n and odd 2n + 1
        # if an item is removed from the list
        # then 2n - 1 = 2n - 1 and 2n + 1 - 1 = 2n
        # this indicates the all element's in even is now in odd list
        # and all elements in odd is now in even's list
        else:
            nex_odd = curr_odd.get_next()
            self._head_odd = curr_even
            self._head_even = nex_odd

        return first_item

    def getoddlist(self):
        """
        (WackyQueue) -> WackyNode
        Return the head of the odd list of
        the WackyQueue
        REQ: must not be isempty
        """
        return self._head_odd

    def getevenlist(self):
        """
        (WackyQueue) -> WackyNode
        Returns the head of the even list in the
        WackyQueue
        REQ: must be at least two items in WackyQueue
        """
        return self._head_even

    def isempty(self):
        """
        (WackyQueue) -> bool
        A boolean indicating whether
        WackyQueue is empty or not
        """
        return not self._head_odd

    def negateall(self):
        """
        (WackyQueue) -> NoneType
        negates the priorities of the elements
        in the queue
        REQ: must not be isempty
        """
        # let list = [a,b,c,...,2n,2(n+1)]
        # where a,b,c are <obj> in linked list
        # and 2n and 2n+1 are
        # even and odd last element respectively
        # odd = [a,c,...,2n+1]
        # even = [b,...,2n]
        # once negated
        # list = [-2(n+1),-2n ,...,-c,-b,-a]
        # odd = [-2n,...,-b,-6]
        # even = [-2(n+1),-c,-a]
        # so just reverse each list separately
        # and swap their heads since the smallest <pri>
        # becomes the biggest integer

        # if there is one item in WackyNode
        # just negate its priority
        if self._head_odd and not self._head_even:
            self._head_odd.set_priority(-self._head_odd.get_priority())

        # more than one item in WackyNode
        else:
            curr = self._head_odd
            prev = None

            # negate the odd <pri>
            # reverse the odd list
            while curr:
                curr.set_priority(-curr.get_priority())
                nex = curr.get_next()
                curr.set_next(prev)
                prev = curr
                curr = nex

            # point the head of odd to the new head
            # which was the previous odd tail
            self._head_odd = prev

            curr = self._head_even
            prev = None

            # negate the even <pri>
            # reverse the even list
            while curr:
                curr.set_priority(-curr.get_priority())
                nex = curr.get_next()
                curr.set_next(prev)
                prev = curr
                curr = nex

            # point the head of even to the new head
            # which was the previous even tail
            self._head_even = prev

            curr_even = self._head_even
            curr_odd = self._head_odd

            # swap the two list's
            self._head_even = None
            self._head_odd = None
            self._head_even = curr_odd
            self._head_odd = curr_even

    def insert(self, obj, pri):
        """
        (WackyQueue, int) -> NoneType
        Insert the object with priorities
        into the WackyQueue
        """
        curr = WackyNode(obj, pri)
        # CASE 1:
        # WackyQueue is empty
        if self.isempty():
            self._head_odd = curr

        # CASE 2:
        # There DNE head of even and
        # curr <pri> is <= head of odds <pri>
        elif not self._head_even and \
                self._head_odd.get_priority() >= curr.get_priority():

            self._head_even = curr
        # There DNE head of even and
        # curr <pri> is > head of odd
        elif not self._head_even and \
                self._head_odd.get_priority() < curr.get_priority():

            self._head_even = self._head_odd
            self._head_odd = curr

        # CASE 3:
        # if curr <pri> > head of odd <pri>
        # set head of odd to curr
        # head of even is the next of head of odd
        # head of odd is the new head of even
        elif curr.get_priority() > self._head_odd.get_priority():
            curr_odd = self._head_odd
            curr_even = self._head_even
            self._head_odd = curr
            self._head_even = curr_odd
            self._head_odd.set_next(curr_even)

        # CASE4:
        # if curr<pri> <= head of odd<pri> and curr <pri> > head of even
        # curr will be the new head of even and
        # next odd will be the previous head of even
        elif self._head_odd.get_priority() \
                >= curr.get_priority() > self._head_even.get_priority():

            # initialize our nodes
            prev_even = self._head_even
            curr_even = prev_even.get_next()
            prev_odd = self._head_odd
            curr_odd = prev_odd.get_next()

            # if there is one item in both list's
            # swap curr with even then set the previous
            # even item to the odd list
            if not curr_odd and not curr_even:
                self._head_even = curr
                prev_odd.set_next(prev_even)

            # if there is more than one item
            # in one or both list's
            else:
                self._head_even = curr
                prev_odd.set_next(prev_even)
                self._head_even.set_next(curr_odd)

        else:
            # CASE 5:
            # In the loop, check for
            # parallel(even and odd list has same # of elements)
            # first and then check for
            # adjacent(odd list has 1 more element than even)
            # current node that is need to be inserted = curr
            # using curr_of_odd and curr_of_even
            curr_even = self._head_even
            curr_odd = self._head_odd

            prev_even = None
            prev_odd = None
            adj = True

            while curr_even:
                # if  current_odd <pri> >= curr <pri> > curr_even <pri>
                # then swap the curr with current even
                # and swap nodes after the odd
                # with current even and make them the next evens
                if curr_odd.get_priority() >= \
                        curr.get_priority() > curr_even.get_priority():

                    # if parallel(even and odd has same number of items)
                    # make curr(new node) the current even
                    # and the next even is the next odd
                    if not curr_odd.get_next():
                        prev_even.set_next(None)
                        prev_even.set_next(curr)
                        nex_odd = curr_odd.get_next()
                        curr_odd.set_next(None)
                        curr_odd.set_next(curr_even)
                        curr_even.set_next(nex_odd)

                    # if adjacent(odd has one more element)
                    # make curr(new node) the current even and the next
                    # odd the current even and the next even the next odd
                    else:
                        nex_odd = curr_odd.get_next()
                        prev_even.set_next(None)
                        prev_even.set_next(curr)
                        curr_odd.set_next(None)
                        curr_odd.set_next(curr_even)
                        curr_even = curr
                        curr_even.set_next(nex_odd)

                    curr_even = None

                # if curr<pri> <= curr_even.<pri> > curr_odd.get_next()<pri>
                # curr will be swapped with current_odd
                # then current_odd will be the next current even
                # the nodes after current even will be the next of curr
                elif curr_odd.get_next() and \
                        curr_even.get_priority() >= curr.get_priority()\
                        > curr_odd.get_next().get_priority():

                    prev_odd = curr_odd
                    curr_odd = curr_odd.get_next()
                    prev_even = curr_even
                    curr_even = curr_even.get_next()
                    prev_even.set_next(None)
                    prev_even.set_next(curr_odd)
                    prev_odd.set_next(None)
                    prev_odd.set_next(curr)
                    curr_odd = curr
                    curr_odd.set_next(curr_even)
                    adj = False
                    curr_even = None

                else:
                    # traverse through the list's
                    prev_even = curr_even
                    curr_even = curr_even.get_next()
                    prev_odd = curr_odd
                    curr_odd = curr_odd.get_next()

            # Case 6
            # when out of the loop, check if
            # curr_of_odd and curr_of even are both
            # none at the same time
            # if their not then curr_odd has one
            # more element in
            # the list
            # If didn't insert a
            # node prior, insert it according to it
            if prev_even and not curr_odd:

                if curr.get_priority() <= prev_even.get_priority():
                    prev_odd.set_next(curr)

            else:
                # iff is adjacent and pri <= previous odd <pri>
                if adj and curr.get_priority() <= prev_odd.get_priority():
                    prev_even.set_next(curr)

    def changepriority(self, obj, pri):
        """
        (WackyQueue, object, int) -> NoneType
        changes the <pri> of the <obj> in the
        WackyQueue if it exist.
        """
        # target is the <obj>
        # we are trying to mutate
        target = None
        # CASE 0:
        # list is empty
        if self.isempty():
            target = None

        else:
            tail_odd = None
            # CASE 1:
            # if 1 item in WackyQueue and <pri> differs
            # change the <pri>
            if not self._head_even and self._head_odd.get_item() is obj and \
                    self._head_odd.get_priority() != pri:
                self._head_odd.set_priority(pri)
            # CASE 2:
            # there are two items in WackyQueue
            elif self._head_even and not self._head_odd.get_next():

                # target is head of even and <pri> differs
                # delete head of even and insert target to reorder
                if obj is self._head_even.get_item() and \
                                self._head_even.get_priority() != pri:

                    target = self._head_even.get_item()
                    self._head_even = None

                # target is head of odd and <pri> differs
                # delete head of odd and insert it later
                # head of even is our new head of odd
                elif obj is self._head_odd.get_item() and \
                        self._head_odd.get_priority() != pri:

                    target = self._head_odd.get_item()
                    self._head_odd = None
                    self._head_odd = self._head_even
                    self._head_even = None

                else:
                    # <obj> DNE in WackyQueue
                    target = None
            else:
                curr_odd = self._head_odd
                curr_even = self._head_even

                prev_odd = None
                prev_even = None
                # CASE 3:
                # traverse through both even and odd list
                # and find the object with that priority
                # once object is found set the previous node
                # of the same object to next and the next node
                # of the same object to the previous node
                # if target <pri> !=  <pri> then proceed
                # then use our insert method and insert the object
                # self.insert(object.get_item(), object.get_priority())
                # else don't mutate list

                while curr_even and curr_odd:
                    # CASE 0 (ODD CASES):
                    # <obj> is on the odd list
                    if curr_odd.get_item() == obj and\
                                    curr_odd.get_priority() != pri:
                        # <obj> is found delete it from the WackyQueue and
                        # insert it later
                        target = curr_odd.get_item()

                        # CASE 0(ODD)
                        # there are more than 3 elements in WackyQueue
                        # <obj> is the head of odd
                        # delete head of odd to insert it later
                        # current even is the new head of odd
                        # next odds are the head of even
                        if curr_odd is self._head_odd and\
                                self._head_odd.get_next():

                            nex_odd = self._head_odd.get_next()
                            curr_even = self._head_even
                            self._head_odd = None
                            self._head_even = None
                            self._head_odd = curr_even
                            self._head_even = nex_odd

                        # CASE 1(ODD):
                        # odd and even have equal # elements
                        # delete curr odd and make
                        # current even the next element
                        elif not curr_odd.get_next():
                            prev_even.set_next(None)
                            prev_odd.set_next(curr_even)

                        # CASE 3(ODD):
                        # odd list has 1 more element
                        # If the both list are same size:
                        # delete the current odd and and even
                        # make the current even the next odd
                        else:
                            nex_odd = curr_odd.get_next()
                            prev_even.set_next(None)
                            curr_odd.set_next(None)
                            prev_even.set_next(nex_odd)
                            prev_odd.set_next(curr_even)

                        # break loop
                        curr_odd = None

                    # CASE 1:
                    # three items in the list
                    # <obj> is the third item in WackyQueue
                    # delete the third item insert later
                    elif obj is self._head_odd.get_next().get_item() and \
                            self._head_odd.get_next().get_priority()\
                            != pri and not self._head_even.get_next():
                        target = self._head_odd.get_item()
                        self._head_odd.set_next(None)
                        curr_odd = None

                    # CASE 2(EVEN CASES):
                    # <obj> is on the even list
                    elif obj is curr_even.get_item() and\
                            curr_even.get_priority() != pri:

                        # <obj> is found, delete it and insert it later
                        target = curr_even.get_item()

                        # CASE 0(EVEN):
                        # 3 items in WackyQueue
                        # <obj> is the head of even
                        # delete the head of even insert it later
                        # head of odd is the new head of even
                        if obj is self._head_even.get_item() and \
                                not self._head_even.get_next()\
                                and self._head_odd.get_next():

                            self._head_even = None
                            self._head_even = self._head_odd.get_next()
                            self._head_odd.set_next(None)

                        # CASE 1(EVEN):
                        # odd and even have equal # elements
                        elif curr_odd.get_next():
                            # SPECIAL CASE:
                            # <obj> is the even head
                            # delete the head of even to
                            # insert it later head of odd is
                            # the new head of even
                            # what ever is after current even is the
                            # next of head of odd
                            if obj is self._head_even.get_item():
                                nex_even = curr_even.get_next()
                                self._head_even = None
                                self._head_even = self._head_odd.get_next()
                                self._head_odd.set_next(None)
                                self._head_odd.set_next(nex_even)
                            # GENERAL CASE:
                            # delete previous even and current odd
                            # next odd is the new current even
                            # and next even is the current odd
                            else:
                                nex_even = curr_even.get_next()
                                nex_odd = curr_odd.get_next()
                                prev_even.set_next(None)
                                prev_even.set_next(nex_odd)
                                curr_odd.set_next(None)
                                curr_odd.set_next(nex_even)

                        # break the loop
                        curr_even = None

                    # CASE 3(GENERAL ODD CASE):
                    # odd and even have equal # elements
                    elif not curr_odd.get_next() and\
                            curr_odd.get_item() is obj:
                        # <obj> is found delete from the list
                        # delete current odd
                        # delete current even
                        # current even is the new
                        # current odd
                        target = curr_odd.get_item()
                        prev_odd.set_next(None)
                        prev_even.set_next(None)
                        prev_odd.set_next(curr_even)
                        # break the loop
                        curr_even = None

                    # traverse through both even
                    # and odd list
                    else:
                        prev_odd = curr_odd
                        curr_odd = curr_odd.get_next()
                        prev_even = curr_even
                        curr_even = curr_even.get_next()
                        prev_tail_even = curr_even
                        tail_odd = curr_odd

                # prev_odd.set_next(None)
            # insert the target <obj> if
            # <obj> was found in either list's
            if target:
                self.insert(target, pri)
            # prev_tail_even.set_next(None)

if __name__ == '__main__':
    my_queue = WackyQueue()
    print("check_lists____test_case_1____\n")
    my_queue.insert('A', 10)
    my_queue.negateall()
    print()
    print(my_queue)
    my_queue.insert('B', 8)
    my_queue.negateall()
    print()
    print(my_queue)
    my_queue.insert('C', 8)
    my_queue.insert('C', 12)
    my_queue.insert('D', 8.5)
    my_queue.insert('E', 11)
    my_queue.insert('E', 11.23)
    my_queue.insert('E', 9.23)
    my_queue.insert('C', 8.2)
    my_queue.insert('C', 8.3)
    my_queue.insert('H', 7)
    my_queue.insert('H', 9)
    print(my_queue)
    print("\n____test_case_isempty____\n")
    empty_queue = WackyQueue()
    print('Expected: False\t\tGot: ' + str(my_queue.isempty()))
    print('Expected: True\t\tGot: ' + str(empty_queue.isempty()))
    print("\nChanged_PRIORITY\n")
    my_queue.changepriority('B', 11)
    my_queue.changepriority('H', 11)
    print(my_queue)
    print("\n____NEGATE_ALL___\n")
    my_queue.negateall()
    print(my_queue)
    print("\n____EXTRACT_HIGH___\n")
    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))

    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))

    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))

    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))

    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))
    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))
    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))
    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))
    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))
    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))
    print("Removed: " + str(my_queue.extracthigh()))
    print(my_queue)
    print("is_empty:\t" + str(my_queue.isempty()))
    print("Removed: " + str(my_queue.extracthigh()))
    print("is_empty:\t" + str(my_queue.isempty()))
    print("\ncheck_lists____test_case_2____\n")
    my_queue = WackyQueue()
    my_queue.insert('A', 100)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'A'> to pri<8>\n")
    my_queue.changepriority('A', 8)
    print(my_queue)
    print("\nInsert_obj<'B'>_pri<90>")
    my_queue.insert('B', 90)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'C'> to pri<100>\n")
    my_queue.changepriority('C', 8)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'B'> to pri<20>\n")
    my_queue.changepriority('B', 20)
    print(my_queue)
    print("\nInsert_obj<'L'>_pri<30>")
    my_queue.insert('L', 30)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'rand'> to pri<200>\n")
    my_queue.changepriority('rand', 200)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'B'> to pri<35>\n")
    my_queue.changepriority('B', 35)
    print(my_queue)
    print("\nInsert_obj<'D'>_pri<100.01>")
    my_queue.insert('D', 100.01)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'D'> to pri<-2>\n")
    my_queue.changepriority('D', -2)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'L'> to pri<-3>\n")
    my_queue.changepriority('L', -3)
    print(my_queue)
    print("\nInsert_obj<'H'>_pri<1>")
    my_queue.insert('H', 1)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'H'> to pri<-5>\n")
    my_queue.changepriority('H', -5)
    print(my_queue)
    print("\nInsert_obj<'N'>_pri<36>")
    my_queue.insert('N', 36)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'N'> to pri<-1>\n")
    my_queue.changepriority('p', 100000)
    my_queue.changepriority('N', -1)
    print(my_queue)
    print("\nInsert_obj<'O'>_pri<-40>")
    my_queue.insert('O', -40)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'H'> to pri<40>\n")
    my_queue.changepriority('H', 40)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'A'> to pri<0>\n")
    my_queue.changepriority('A', 0)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'D'> to pri<-20>\n")
    my_queue.changepriority('D', -20)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'N'> to pri<-40>\n")
    my_queue.changepriority('N', -40)
    print(my_queue)
    print("\nChanged_PRIORITY obj<'0'> to pri<4>\n")
    my_queue.changepriority('q', 4)
    my_queue.changepriority('O', 4)
    print(my_queue)
    print("\n____NEGATE_ALL___\n")
    my_queue.negateall()
    print(my_queue)
    while not my_queue.isempty():
        x = my_queue.extracthigh()
        print("REMOVED:\t" + str(x) +
              " \tISEMPTY:\t" + str(my_queue.isempty()))
    print("Look at the queue")
    print(my_queue)
    print("\ncheck_lists____test_case_2____\n")
    my_queue2 = WackyQueue()
    my_queue2.insert('A', 11)
    my_queue2.insert('A', 9)
    my_queue2.insert('A', 8)
    my_queue2.insert('A', 5)
    my_queue2.insert('A', 6)
    my_queue2.insert('A', 5)
    my_queue2.insert('A', 13)
    my_queue2.insert('A', 12)
    my_queue2.insert('A', 10)
    my_queue2.insert('A', 0)
    print(my_queue2)
    print("\n____extract_high_test_1____\n")
    my_queue3 = WackyQueue()
    my_queue3.insert('A', 5)
    my_queue3.insert('B', 4)
    my_queue3.insert('C', 3)
    my_queue3.insert('D', 2)
    print(my_queue3)
    print("REMOVED_ITEM:\t" + str(my_queue3.extracthigh()))
    print(my_queue3)
    print("REMOVED_ITEM:\t" + str(my_queue3.extracthigh()))

    print("QUEUE_IS_EMPTY:\t" + str(my_queue3.isempty()))
    print("\n____negate_test_1____\n")
    my_queue4 = WackyQueue()
    my_queue4.insert('A', 4)
    my_queue4.insert('B', 3)
    my_queue4.insert('C', 2)
    my_queue4.insert('D', 1)
    print(my_queue4)
    my_queue4.negateall()
    print("___________NEGATE_ALL__________")
    print(str(my_queue4) + '\n')
    print(str(my_queue) + '\n')
    my_queue.negateall()
    print(my_queue)
    my_queue = WackyQueue()
    for i in range(6):
        for j in 'ABCD':
            my_queue.insert(j, i)
    print(my_queue)
    for i in range(30):
        for j in "ABCD":
            my_queue.changepriority(j, i)
    print()
    # my_queue.changepriority('A', -1)
    # my_queue.changepriority('C', -1)
    # my_queue.changepriority('B', -1)
    # my_queue.changepriority('A', 100)
    # my_queue.changepriority('D', 200)
    # my_queue.changepriority('LD', 200)
    my_queue.insert('L', -2)
    # my_queue.insert('DD', -2)
    my_queue.changepriority('L', 200)
    # my_queue.negateall()
    print(my_queue)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr  4 21:42:57 2020

@author: kurmich
"""

from boxcell import *
from atom import AtomicForces
epsilon = 0.000001

idsort = lambda af: af.id

def get_interactions(filename, t_start, t_end, types, interacting = False, sortkey = idsort):
    assert t_start <= t_end
    r_time = False
    r_atom_count = False
    r_boundary = False
    r_atoms = False
    skip = False
    dim = 0
    t = 0
    max_r = 0
    pbcX, pbcY, pbcZ = False, False, False #boundary periodicity flags
    all_res = []
    all_bounds = []
    times = []
    cur_b = []
    res = dict()
    with open(filename) as file:
        for line in file:
            #check what kind of data to expect in this line
            if r_time:
                time = int(line)
                times.append(time)
                #print("Time step: %d" %time)
                r_time = False
            elif r_atom_count:
                count = int(line)
                res = dict()
                #print("# of atoms: %d" %count)
                r_atom_count = False
            elif r_boundary:
                if dim > 0:
                    words = line.strip().split()
                    lo, hi = map(float, words)
                    if   dim == 3: bounds.set_x_bounds(lo, hi)
                    elif dim == 2: bounds.set_y_bounds(lo, hi)
                    elif dim == 1: bounds.set_z_bounds(lo, hi)
                dim -= 1
                if dim == 0:
                    all_bounds.append(bounds)
                    r_boundary = False
            elif r_atoms:
                if 'ITEM: TIMESTEP' in line:
                    r_atoms = False
                    r_time = True
                else:

                    if skip:
                        continue
                    line = line.strip()
                    #print(line)
                    '''Return a list of the words in the string, using sep as the delimiter string.
                    If maxsplit is given, at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements).
                    If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made).'''
                    words = line.split(' ', 9)
                    if len(words) > 9:
                        a_id, mol, atype, x, y, z, fx, fy, fz, arributes  = words
                    elif len(words) == 9:
                        a_id, mol, atype, x, y, z, fx, fy, fz  = words
                    a_id, mol, atype, x, y, z, fx, fy, fz = int(a_id), int(mol), int(atype), float(x), float(y), float(z), float(fx), float(fy), float(fz)
                    if atype not in types: continue
                    if interacting and abs(fx) < epsilon and abs(fy) < epsilon and abs(fz) < epsilon: continue
                    #choose interacting atoms
                    radius = (x**2 + y**2)**(1/2)
                    if atype not in res: res[atype] = []
                    res[atype].append(AtomicForces(a_id, mol, atype, x, y, z, fx, fy, fz))
                    max_r = max(max_r, radius)

            #set what kind of data to expect in next lines
            if 'ITEM: TIMESTEP' in line:
                if len(res) != 0:
                    for type, atom_forces in res.items():
                        l = sorted(atom_forces, key = sortkey)
                        res[type] = l
                    all_res.append(res)
                elif len(times) > 0:
                    times.pop()
                r_time = True
                t += 1
                if t > t_end:
                    break
                if t < t_start:
                    skip = True
                else:
                    skip = False
                #print("Next is timestep")
            elif 'ITEM: NUMBER OF ATOMS' in line:
                r_atom_count = True
                #print("Next is number of atoms")
            elif 'ITEM: BOX BOUNDS' in line:
                words = line.strip().split()
                pbcX = True if words[-3] == "pp" else False
                pbcY = True if words[-2] == "pp" else False
                pbcZ = True if words[-1] == "pp" else False
                r_boundary = True
                bounds = Boundary(line)
                dim = 3
                #print("Next 3 lines are bondaries")
            elif 'ITEM: ATOMS' in line:
                r_atoms = True
                atr_line = line[line.index('S')+1:]
                atr_words = atr_line.split(' ')
                #print("Atom coordinate lines are coming")
    if len(res) != 0:
        for type, atom_forces in res.items():
            l = sorted(atom_forces, key = sortkey)
            res[type] = l
        all_res.append(res)
    elif len(times) > 0:
        times.pop()
    return all_res, all_bounds, times

def get_frames(filename, t_start, t_end, types = None):
    assert t_start <= t_end
    r_time = False
    r_atom_count = False
    r_boundary = False
    r_atoms = False
    skip = False
    d = 0
    t = 0
    max_r = 0
    cur_frame = None
    real_count = 0
    frames = []
    #type_count = {}
    #for type in types:
     #   type_count[type] = 0
    with open(filename) as file:
        for line in file:
            #check what kind of data to expect in this line
            if r_time:
                time = int(line)
                print("Time step: %d" %time)
                r_time = False
            elif r_atom_count:
                count = int(line)
                if not skip:
                    cur_frame = np.zeros([count, 8])
                print("# of atoms: %d" %count)
                r_atom_count = False
            elif r_boundary:
                d -= 1
                r_boundary = False if d == 0 else True
            elif r_atoms:
                if 'ITEM: TIMESTEP' in line:
                    r_atoms = False
                else:
                    #print("reading atoms")
                   # print(len(line.split(' ')))
                    if skip:
                        continue

                    id, mol, type, x, y, z, fx, fy, fz, _  = line.split(' ')
                    id, mol, type, x, y, z, fx, fy, fz = int(id), int(mol), int(type), float(x), float(y), float(z), float(fx), float(fy), float(fz)
                    #if types is not None and type in types and time == t_start:
                    #    typecount[type] += 1
                    #if type not in types: continue
                    cur_frame[id-1, 0], cur_frame[id-1, 1] = mol, type
                    cur_frame[id-1, 2], cur_frame[id-1, 3], cur_frame[id-1, 4] = x, y, z
                    cur_frame[id-1, 5], cur_frame[id-1, 6], cur_frame[id-1, 7] = fx, fy, fz

            #set what kind of data to expect in next lines
            if 'ITEM: TIMESTEP' in line:
                if cur_frame is not None and not skip:
                    frames.append(cur_frame)
                r_time = True
                t += 1
                if t > t_end:
                    break
                if t < t_start:
                    skip = True
                else:
                    skip = False
                print("Next is timestep")
            elif 'ITEM: NUMBER OF ATOMS' in line:
                r_atom_count = True
                print("Next is number of atoms")
            elif 'ITEM: BOX BOUNDS pp pp mm' in line:
                r_boundary = True
                d = 3
                print("Next 3 lines are bondaries")
            elif 'ITEM: ATOMS' in line:
                r_atoms = True
                print("Atom coordinate lines are coming")
    return  frames

def get_pair_interactions(filename, t_start, t_end):
    assert t_start <= t_end
    r_time = False
    r_entry_count = False
    r_boundary = False
    r_entries = False
    skip = False
    d = 0
    t = 0
    pair_counts = []
    all_pair_ids = []
    res = []
    with open(filename) as file:
        for line in file:
            #check what kind of data to expect in this line
            if r_time:
                time = int(line)
                print("Time step: %d" %time)
                r_time = False
            elif r_entry_count:
                count = int(line)
                pair_counts.append(count)
                res = []
                print("# of pair ids: %d" %count)
                r_entry_count = False
            elif r_boundary:
                d -= 1
                r_boundary = False if d == 0 else True
            elif r_entries:
                if 'ITEM: TIMESTEP' in line:
                    r_entries = False
                else:
                    #print("reading atoms")
                   # print(len(line.split(' ')))
                    if skip:
                        continue
                    line = line.strip()
                    id1, id2  = line.split(' ')
                    id1, id2 = int(id1), int(id2)
                    res.append((id1, id2))

            #set what kind of data to expect in next lines
            if 'ITEM: TIMESTEP' in line:
                if len(res) != 0:
                    all_pair_ids.append(res)
                r_time = True
                t += 1
                if t > t_end:
                    break
                if t < t_start:
                    skip = True
                else:
                    skip = False
                print("Next is timestep")
            elif 'ITEM: NUMBER OF ENTRIES' in line:
                r_entry_count = True
                print("Next is number of entries")
            elif 'ITEM: BOX BOUNDS' in line:
                r_boundary = True
                d = 3
                print("Next 3 lines are bondaries")
            elif 'ITEM: ENTRIES' in line:
                r_entries = True
                print("Pair id lines are coming")
    return all_pair_ids, pair_counts


from docarray import DocumentArray
from jina import Flow
from executor import OCRMyPDF

# print-to-pdf of https://courses.cs.vt.edu/csonline/AI/Lessons/VisualProcessing/OCRscans_files/bowers.jpg
docs = DocumentArray.from_files("./data/bowers*.pdf")

flow = (
    Flow()
    .add(uses=OCRMyPDF, name="ocrpdf")
    .add(uses="jinahub://PDFSegmenter", name="segmenter", install_requirements=True)
)

with flow:
    output = flow.index(docs, show_progress=True)

for chunk in output[0].chunks:
    print(chunk)
    if hasattr(chunk, "text"):
        print(chunk.text)


from telethon import TelegramClient, events, Button
import requests
#from headers import headers
#import urls
import os
import requests
import cryptg
import asyncio
import shutil
import subprocess
from mega import Mega
mega = Mega()
m = mega.login()
#from flask import request

client = TelegramClient('anfghohn',1416135,"2aae0d7ca32b01970b2c6770a4c0cf8e").start(bot_token="1877241556:AAEPrZiiAH1RVfJRs1RKu-liXXeQTGbc2Ow")

@client.on(events.NewMessage(pattern='/diskusage'))
async def handler(event):
    chat = await event.get_chat()
    stat = shutil.disk_usage("/app/templates/download")
    await client.send_message(chat,str(stat))

@client.on(events.NewMessage(pattern="/url"))
async def handler(event):
    link =event.text.split(' ')[1]
    l =event.text.split(' ')[2]
    chat = await event.get_chat()

    s = f"http://pdisk.net/api/ndisk_manager/video/create?link_type=link&content_src={link}&source=2000&uid=83773722&title={l}&description=telegram"
    r = requests.get(s).json()
    z=r['data']["item_id"]
   # await event.delete()
   # client.delete_messages()
    markup  = client.build_reply_markup(Button.url("ðŸ“€ PDisk ðŸ“€",f"http://m.pdisk.net/share-video?videoid={z}"))
    await client.send_message(chat, "link will working depends on size it takes half or more ... ", buttons=markup)

            #rgx = w
@client.on(events.NewMessage(pattern='/magnet'))
async def handler(event):
    link =event.text.split(' ')[1]
    l =link.split('/')[-1]
    chat = await event.get_chat()

    s = f"http://pdisk.net/api/ndisk_manager/video/create?link_type=magnet&content_src={link}&source=2000&uid=83773722&title={l}&description=telegram"
    r = requests.get(s).json()
    z=r['data']["item_id"]
   # await event.delete()
   # client.delete_messages()
    markup  = client.build_reply_markup(Button.url("ðŸ“€ PDisk ðŸ“€",f"http://m.pdisk.net/share-video?videoid={z}"))
    await client.send_message(chat, "link will working depends on size it takes half or more ... ", buttons=markup)

@client.on(events.NewMessage(pattern='/pdisk'))
async def handler(event):
   #
    chat = await event.get_chat()
    print(chat)
    dw = await event.get_reply_message()
    links =event.text.split(" ")[1]
    await client.send_message(chat,"ðŸŒ  downloading ðŸŒ ")
    ss=await dw.download_media(links)
    shutil.move(f"/app/{links}",f"/app/templates/download/{links}")
    await client.send_message(chat,f"wait few minutes ...{links}")

    link =f"https://asulinkgen.herokuapp.com/files/{links}"
    l =link.split('/')[-1]
    s = f"http://pdisk.net/api/ndisk_manager/video/create?link_type=link&content_src={link}&source=2000&uid=83773722&title={l}&description=telegram"
    r = requests.get(s).json()
    z=r['data']["item_id"]
   # await event.delete()
   # client.delete_messages()
    markup  = client.build_reply_markup(Button.url("ðŸ“€ PDisk ðŸ“€",f"http://m.pdisk.net/share-video?videoid={z}"))
    await client.send_message(chat, "link will working depends on size it takes half or more ... ", buttons=markup)
    #os.remove(f"/app/templates/download/{links}")
@client.on(events.NewMessage(pattern='(?i)/ls'))

async def handler(event):

    chat = await event.get_chat()

    link =event.text.split(" ")[1]

    c = subprocess.getoutput(f"pip install {link}")
    print (c)
    await client.send_message(chat,"finish")
@client.on(events.NewMessage(pattern='(?i)/upload'))
async def handler(event):
    chat = await event.get_chat()
    print(chat)
    dw = await event.get_reply_message()
    links =event.text.split(" ")[1]
    await client.send_message(chat,"ðŸŒ  Downloading ðŸŒ ")
    ss=await dw.download_media(links)
    shutil.move(f"/app/{links}",f"/app/templates/download/{links}")
    await client.send_message(chat,f"https://asulinkgen.herokuapp.com/files/{links}")

      #  os.rename(ss,links)

    if os.path.exists(f"/app/Download/{chat.username}"):
        await client.send_message(chat,"downloading")
        ss=await dw.download_media()
        await client.send_message(chat,f"https://asulinkgen.herokuapp.com/u?url={ss}")

@client.on(events.NewMessage(pattern='(?i)/del'))

async def handler(event):

    chat = await event.get_chat()

    print(chat.username)

    #dw = await event.get_reply_message()

  #  shutil.rmtree("./Downloads/")
  #  os.mkdir("./Downloads")
   # await client.send_message(chat,"ss")
@client.on(events.NewMessage(pattern='/torrent'))
async def handler(event):
    link =event.text.split(' ')[1]
    l =link.split('/')[-1]
    chat = await event.get_chat()
    s = f"http://pdisk.net/api/ndisk_manager/video/create?link_type=magnet&content_src={link}&source=2000&uid=83773722&title={l}&description=telegram"
    r = requests.get(s).json()
    z=r['data']["item_id"]
    await event.delete()
   # client.delete_messages()
    markup  = client.build_reply_markup(Button.url(" ðŸ”¥ torrentðŸ”¥",f"https://asulinkgen.herokuapp.com/e?url={z}"))
    await client.send_message(chat, "link only after one hour dead torrent not working .....", buttons=markup)

            #rgx = w

client.start()
client.run_until_disconnected()


import logging
import sys

import torch
from x_temporal.utils.dist_helper import is_master_proc

logs = set()

def init_log(name, level=logging.INFO):
    if (name, level) in logs:
        return

    logs.add((name, level))
    logger = logging.getLogger(name)
    logger.setLevel(level)
    ch = logging.StreamHandler(stream=sys.stdout)
    ch.setLevel(level)

    logger.addFilter(lambda record: is_master_proc())

    format_str = f'%(asctime)s-%(filename)s#%(lineno)d:%(message)s'
    formatter = logging.Formatter(format_str)
    ch.setFormatter(formatter)
    logger.addHandler(ch)

def get_log_format(multi_class=False):
    if multi_class:
        return  ('Epoch: [{2}/{3}]\tIter: [{0}/{1}]\t'
                 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t'
                 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t'
                 'Loss {loss.val:.4f} ({loss.avg:.4f})\t'
                 'mAP {mAP.val:.3f} ({mAP.avg:.3f})\t'
                 'LR {lr:.4f}')
    else:
        return  ('Epoch: [{2}/{3}]\tIter: [{0}/{1}]\t'
                 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t'
                 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t'
                 'Loss {loss.val:.4f} ({loss.avg:.4f})\t'
                 'Prec@1 {top1.val:.3f} ({top1.avg:.3f})\t'
                 'Prec@5 {top5.val:.3f} ({top5.avg:.3f})\t'
                 'LR {lr:.4f}')


# -*- coding: utf-8 -*-
"""
Created on Sun Mar 20 22:02:54 2022

@author: Karel
"""

import matplotlib.pyplot as plt
import cv2
import os
import kornia as K
import kornia.feature as KF
import numpy as np
import torch
import pydegensac
from kornia_moons.feature import *
import glob
import pandas as pd
import time
from joblib import Parallel, delayed
import multiprocessing

def get_local_descriptors(img, cv2_sift_kpts, kornia_descriptor):
    if len(cv2_sift_kpts) == 0:
        return np.array([])

    # We will not train anything, so let's save time and memory by no_grad()
    with torch.no_grad():
        kornia_descriptor.eval()
        timg = K.color.rgb_to_grayscale(K.image_to_tensor(img, False).float() / 255.)
        lafs = laf_from_opencv_SIFT_kpts(cv2_sift_kpts)
        patches = KF.extract_patches_from_pyramid(timg, lafs, 32)
        B, N, CH, H, W = patches.size()
        # Descriptor accepts standard tensor [B, CH, H, W], while patches are [B, N, CH, H, W] shape
        # So we need to reshape a bit :)
        descs = kornia_descriptor(patches.view(B * N, CH, H, W)).view(B * N, -1)
    return descs.detach().cpu().numpy()

def get_local_descriptors_aff(img, cv2_sift_kpts, kornia_descriptor):
  if len(cv2_sift_kpts) == 0:
    return np.array([])

  # We will not train anything, so let's save time and memory by no_grad()
  with torch.no_grad():
    kornia_descriptor.eval()
    timg = K.color.rgb_to_grayscale(K.image_to_tensor(img, False).float() / 255.)
    lafs = laf_from_opencv_SIFT_kpts(cv2_sift_kpts)
    affine = KF.LAFAffNetShapeEstimator(True)
    orienter = KF.LAFOrienter(32, angle_detector=KF.OriNet(True))
    orienter.eval()
    affine.eval()
    lafs_new = orienter(affine(lafs,timg),timg)
    patches = KF.extract_patches_from_pyramid(timg, lafs_new, 32)
    B, N, CH, H, W = patches.size()
    # Descriptor accepts standard tensor [B, CH, H, W], while patches are [B, N, CH, H, W] shape
    # So we need to reshape a bit :)
    descs = kornia_descriptor(patches.view(B * N, CH, H, W)).view(B * N, -1)
  return descs.detach().cpu().numpy()

def sift_korniadesc_matching(fname1, fname2, descriptor):
    img1 = cv2.cvtColor(cv2.imread(fname1), cv2.COLOR_BGR2RGB)
    img2 = cv2.cvtColor(cv2.imread(fname2), cv2.COLOR_BGR2RGB)

    sift = cv2.SIFT_create(8000)
    kps1 = sift.detect(img1, None)
    kps2 = sift.detect(img2, None)
    # That is the only change in the pipeline -- descriptors
    descs1 = get_local_descriptors(img1, kps1, descriptor)
    descs2 = get_local_descriptors(img2, kps2, descriptor)
    if ((len(kps1)) == 0 ):
      return(0,len(kps2),0)
    if (len(kps2) <= 7 ):
      return(len(kps1),len(kps2),0)
    # The rest is the same, as for SIFT
    dists, idxs = KF.match_smnn(torch.from_numpy(descs1), torch.from_numpy(descs2), 0.95)
    #print(len(kps1), len(kps2), (idxs.shape[0]))
    if ((idxs.shape[0]) < 8 ):
      return(len(kps1),len(kps2),0)

    tentatives = cv2_matches_from_kornia(dists, idxs)
    src_pts = np.float32([kps1[m.queryIdx].pt for m in tentatives]).reshape(-1, 2)
    dst_pts = np.float32([kps2[m.trainIdx].pt for m in tentatives]).reshape(-1, 2)
    F, inliers_mask = pydegensac.findFundamentalMatrix(src_pts, dst_pts, 0.75, 0.99, 100000)
    #draw_params = dict(matchColor=(255, 255, 0), # draw matches in yellow color
    #                  singlePointColor=None,
    #                  matchesMask=inliers_mask.ravel().tolist(), # draw only inliers
    #                  flags = 2)
    #img_out = cv2.drawMatches(img1, kps1, img2, kps2, tentatives, None, **draw_params)
    #plt.figure()
    #fig, ax = plt.subplots(figsize=(15, 15))
    #ax.imshow(img_out, interpolation='nearest')
    #plt.show()
    nMatches = inliers_mask.sum();
    #print(f'{inliers_mask.sum()} inliers found')
    #print(inliers_mask)
    return (len(kps1),len(kps2),nMatches)

def compute(test_images,r_image,id):
    hardnet = KF.HardNet(True)
    print(r_image)
    start = time.time()
    #for r_image in ref_images:
    df = pd.DataFrame(columns=['ref', 'test', 'ref_id', 'test_id', 'matches', 'nkey_ref', 'nkey_test'])
    for t_image in test_images:
        nkey_ref, nkey_test, nMatchesFound = sift_korniadesc_matching(r_image, t_image, hardnet)
        #print(nkey_test,nkey_ref,nMatchesFound,t_image[-7:-4])
        data = {'ref': os.path.split(r_image)[1],
                'test': os.path.split(t_image)[1],
                'ref_id': r_image[-7:-4],
                'test_id': t_image[-7:-4],
                'matches': nMatchesFound,
                'nkey_ref': nkey_ref,
                'nkey_test': nkey_test
        }
        df = df.append(data,ignore_index=True)
        #print(str(r_image[-7:-4]) + " " + str(t_image[-7:    -4]) + " " + str(nMatchesFound))
    filename = "./" + str(id) + "/hardnet_sub_0" + str(id) + "_ref_none_" + str(r_image[-7:-4]) + "_atlas.csv"
    #filename = "./4/hardnet_sub_04_ref_rseqb_toOrig_" + str(r_image[-7:-4]) + "_test.csv"
    df.to_csv(filename,header=None, index=None, sep=' ', mode='w')
    #print(filename)
    end = time.time()
    #print("Time to compute: " + str(end - start))

#####################################################################################
fname1 = "./images/subj07_anatomical_3T_Glasgow_1mm_Crop_1_defaced_z098.png"
##input image
filelist1 = glob.glob("f:\\work\\OwnCloud\\projects\\ImProCo\\data\\OpenNeuroDataset\\sub-03\\anat\\min-rot-sculp-eq\\*.png")
##testing atlas
filelist2 = glob.glob("f:\\work\\OwnCloud\\projects\\ImProCo\\data\\atlas\\t1_icbm_normal_1mm_pn0_rf0\\sculp-eq\\*.png")
#filelist2 = glob.glob("f:\\work\\OwnCloud\\projects\\ImProCo\\data\\OpenNeuroDataset\\noise-07\\gauss\\30\\*.png")
#filelist2 = glob.glob("f:\\work\\OwnCloud\\projects\\ImProCo\\data\\OpenNeuroDataset\\sub-02\\min-rot\\*.png")
#filelist1 = glob.glob("f:\\work\\OwnCloud\\projects\\ImProCo\\data\\OpenNeuroDataset\\sub-01\\anat\\png\\*.png")

for fichier in filelist1[:]: # filelist[:] makes a copy of filelist.
    if not(fichier.endswith(".png")):
        filelist1.remove(fichier)
ref_images = filelist1

for fichier in filelist2[:]: # filelist[:] makes a copy of filelist.
    if not(fichier.endswith(".png")):
        filelist2.remove(fichier)
test_images = filelist2

num_cores = multiprocessing.cpu_count()
start = time.time()
Parallel(n_jobs=2)(delayed(compute)(test_images,ref,3) for ref in ref_images)
end = time.time()
print("Time to compute all: " + str(end - start))


# 문제
# 자연수 과 정수 가 주어졌을 때 이항 계수 를 10,007로 나눈 나머지를 구하는 프로그램을 작성하시오.

# 입력
# 첫째 줄에 과 가 주어진다. (1 ≤  ≤ 1,000, 0 ≤  ≤ )

# 출력
#  를 10,007로 나눈 나머지를 출력한다.

from math import factorial

n, k = map(int, input().split())

x = factorial(n) // (factorial(n-k) * factorial(k))

print(int(x % 10007))


n = input()
s = {item: 0 for item in range(10)}
res = ''
for i in n:
    if i.isdigit():
        s[int(i)] += 1
tmp = ('' if s[0] % 2 == 0 else '0')
res_0 = '0' * (s[0] // 2)

for i in range(1, 10):
    res += str(i) * (s[i] // 2)

for j in range(10):
    if s[j] % 2 == 1:
        tmp = str(j)
        break

if len(res):
    res_tmp = res[0] + res_0 + (res[1:] if len(res) > 1 else '')
    res = res_tmp + tmp + res_tmp[::-1]
else:
    res = (tmp if s[0] == 0 else '0')

print(res)

Число-палиндром.py


from django.db import models

class employees(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100)
    address = models.TextField()
    phone = models.IntegerField()

    class Meta:
        db_table = "employe"


 #!/usr/bin/env python2
import traceback

from dataclay.api import init, finish

# Init dataClay session
init()

from CityNS.classes import City, EventsInCar

if __name__ == "__main__":

    try:

        # Check
        print("Checking if events in car are accessible")
        try:
            events_in_car = EventsInCar.get_by_alias("block1")
            print("Object with alias block1 found")
        except:
            print("Object with alias block1 not found")
        try:
            events_in_car = EventsInCar.get_by_alias("block2")
            print("Object with alias block2 found")
        except:
            print("Object with alias block2 not found")

        city = City.get_by_alias("my-pycity")

        # Print events
        for event in city.events:
            print(str(event))

        print("City aggregation: %s" % str(city.get_aggregation()))

    except:
        traceback.print_exc()

    # Close session
    finish()
    exit(0)


"""Metrics controller."""
import logging
from datetime import date
from datetime import timedelta as td
from functools import wraps

from sqlalchemy import func

from booking_microservice.constants import BlockChainStatus, BookingStatus
from booking_microservice.models import Booking

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

def isodate(x):
    try:
        return date.fromisoformat(x)
    except TypeError:
        return x

def pad(count, start_date: date, end_date: date):
    dates = [x.get("date") for x in count]

    current_date = start_date

    while current_date <= end_date:
        if current_date not in dates:
            count.append({"date": current_date, "value": 0.0})
        current_date += td(days=1)

    count = sorted(count, key=lambda x: x.get("date"))

    return count

def data_map(count):
    return [{"date": isodate(rdate), "value": rval} for rdate, rval in count]

def prepare_metric(name):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            count = f(*args, **kwargs)
            count = data_map(count)
            count = pad(count, *args)
            return {
                "name": name,
                "data": count,
            }

        return wrapper

    return decorator

@prepare_metric("revenue_per_day")
def revenue_per_day(start_date, end_date):
    count = (
        Booking.query.filter(
            (func.date(Booking.booking_date).between(start_date, end_date))
            & (Booking.booking_status == BookingStatus.ACCEPTED.value)
            & (Booking.blockchain_status == BlockChainStatus.CONFIRMED.value)
        )
        .with_entities(func.date(Booking.booking_date), func.sum(Booking.total_price),)
        .group_by(func.date(Booking.booking_date))
        .order_by(func.date(Booking.booking_date))
        .all()
    )
    return count

all_metrics = [revenue_per_day]


import tkinter
from tkinter.messagebox import showinfo as alert
from tkinter.messagebox import askyesno as question
from tkinter.simpledialog import askstring as prompt
import customtkinter

'''
Enunciado:

2.	El departamento de Construcción Rural requiere una herramienta que facilite el calculo de materiales necesarios a la hora de realizar un alambrado perimetral, se le solicita al usuario que ingrese el ancho y el largo del terreno.

    A. Informar los metros cuadrados del terreno y los metros lineales del perimetro
    B. Informar la cantidad de postes de quebracho Grueso de 2.4 mts (van cada 250 mts lineales y en las esquinas).
    C. Informar la cantidad de postes de quebracho Fino de 2.2 mts (van cada 12 mts lineales, si en es lugar no se encuentra el poste grueso).
    D. Informar la cantidad de varillas (van cada 2 mts lineales).
    E. Informar la cantidad de alambre alta resistencia 17/15 considerando 7 hilos.

    EJ 36 MTS X 24 MTS
    (G)Poste Quebracho Grueso de 2.4 mts
    (F)Poste Quebracho Fino de 2.2 mts
    (V)Varillas

    G V V V V V F V V V V V F V V V V V G
    V                                   V
    V                                   V
    V                                   V
    V                                   V
    V                                   V
    F                                   F
    V                                   V
    V                                   V
    V                                   V
    V                                   V
    V                                   V
    G V V V V V F V V V V V F V V V V V G

'''

class App(customtkinter.CTk):

    def __init__(self):
        super().__init__()

        # configure window
        self.title("UTN FRA")

        self.label_1 = customtkinter.CTkLabel(master=self, text="Largo")
        self.label_1.grid(row=0, column=0, padx=20, pady=10)

        self.txt_largo = customtkinter.CTkEntry(master=self)
        self.txt_largo.grid(row=0, column=1)

        self.label_2 = customtkinter.CTkLabel(master=self, text="Ancho")
        self.label_2.grid(row=1, column=0, padx=20, pady=10)

        self.txt_ancho = customtkinter.CTkEntry(master=self)
        self.txt_ancho.grid(row=1, column=1)
        self.btn_calcular = customtkinter.CTkButton(master=self, text="CALCULAR", command=self.btn_calcular_on_click)
        self.btn_calcular.grid(row=3, pady=10, columnspan=2, sticky="nsew")

    def btn_calcular_on_click(self):
        largo_guardado = float(self.txt_largo.get())
        ancho_guardado = float(self.txt_ancho.get())

        # PUNTO A
        area_terreno = largo_guardado * ancho_guardado
        perimetro_terreno = (largo_guardado + ancho_guardado)*2

        # PUNTO B
        cantidad_quebracho_grueso = (perimetro_terreno // 250) + 4

        # PUNTO C
        cantidad_quebracho_fino = (perimetro_terreno // 12) - cantidad_quebracho_grueso

        # PUNTO D
        cantidad_varillas = (perimetro_terreno // 2) - cantidad_quebracho_fino

        # PUNTO E
        cantidad_alambre = perimetro_terreno * 7

        mensaje_final = "El terreno tiene un total de {0}m2 y {1} metros de perímetro. Por lo tanto, se necesitarán: \n{2} postes de quebracho grueso \n{3} postes de quebracho fino \n{4} varillas \n{5}mts de alambre 17/15 considerando 7 hilos".format(area_terreno, perimetro_terreno, cantidad_quebracho_grueso, cantidad_quebracho_fino, cantidad_varillas, cantidad_alambre)

        alert("Lista de Materiales ;)", mensaje_final)

if __name__ == "__main__":
    app = App()
    app.mainloop()


import sqlite3
import contextlib
import datetime

class OperationalException(Exception): pass

class ShoppingListDB():
	def __init__(self, sqlite_dbfile):
		self._db = sqlite3.connect(sqlite_dbfile)
		self._cursor = self._db.cursor()

		with contextlib.suppress(sqlite3.OperationalError):
			self._cursor.execute("""
			CREATE TABLE items (
				itemid integer PRIMARY KEY AUTOINCREMENT,
				description varchar NOT NULL UNIQUE
			);
			""")

		with contextlib.suppress(sqlite3.OperationalError):
			self._cursor.execute("""
			CREATE TABLE item_alias_names (
				description varchar PRIMARY KEY,
				itemid integer NOT NULL,
				FOREIGN KEY(itemid) REFERENCES items(itemid)
			);
			""")

		with contextlib.suppress(sqlite3.OperationalError):
			self._cursor.execute("""
			CREATE TABLE shopping_list (
				itemid integer PRIMARY KEY,
				itemcount integer NOT NULL DEFAULT 0,
				last_edited_utc timestamp NOT NULL,
				CHECK(itemcount >= 0),
				FOREIGN KEY(itemid) REFERENCES items(itemid)
			);
			""")

		with contextlib.suppress(sqlite3.OperationalError):
			self._cursor.execute("""
			CREATE TABLE stores (
				storeid integer PRIMARY KEY AUTOINCREMENT,
				storename varchar NOT NULL UNIQUE
			);
			""")

		with contextlib.suppress(sqlite3.OperationalError):
			self._cursor.execute("""
			CREATE TABLE storeitemorder (
				storeid integer NOT NULL,
				itemid integer NOT NULL,
				orderno integer NOT NULL,
				PRIMARY KEY(storeid, itemid),
				FOREIGN KEY(storeid) REFERENCES stores(storeid),
				FOREIGN KEY(itemid) REFERENCES items(itemid)
			);
			""")

		with contextlib.suppress(sqlite3.OperationalError):
			self._cursor.execute("""
			CREATE TABLE history (
				transactionid uuid NOT NULL PRIMARY KEY,
				itemid integer NOT NULL,
				delta integer NOT NULL,
				user varchar NOT NULL,
				processed_utc timestamp NOT NULL,
				CHECK(delta != 0),
				FOREIGN KEY(itemid) REFERENCES items(itemid)
			);
			""")

	def get_shopping_list(self):
		return { itemid: itemcount for (itemid, itemcount) in self._cursor.execute("SELECT itemid, itemcount FROM shopping_list WHERE itemcount > 0;").fetchall() }

	def get_item_list(self):
		return { itemid: description for (itemid, description) in self._cursor.execute("SELECT itemid, description FROM items;").fetchall() }

	def get_item_aliases(self):
		return { description: itemid for (description, itemid) in self._cursor.execute("SELECT description, itemid FROM item_alias_names;").fetchall() }

	def _get_store_list(self):
		return { storeid: storename for (storeid, storename) in self._cursor.execute("SELECT storeid, storename FROM stores;").fetchall() }

	def _get_store_order(self, storeid):
		return { itemid: orderno for (itemid, orderno) in self._cursor.execute("SELECT itemid, orderno FROM storeitemorder WHERE storeid = ?;", (storeid, )).fetchall() }

	def get_stores(self):
		stores = { }
		for (storeid, storename) in self._get_store_list().items():
			store = {
				"storeid": storeid,
				"order": self._get_store_order(storeid),
			}
			stores[storename] = store
		return stores

	def get_all(self):
		return {
			"shopping_list":	self.get_shopping_list(),
			"items":			self.get_item_list(),
			"item_aliases":		self.get_item_aliases(),
			"stores":			self.get_stores(),
		}

	def add_store(self, store_name):
		with contextlib.suppress(sqlite3.IntegrityError):
			self._cursor.execute("INSERT INTO stores (storename) VALUES (?);", (store_name, ))
			self._db.commit()
		return self._cursor.execute("SELECT storeid FROM stores WHERE storename = ?;", (store_name, )).fetchone()[0]

	def reset_store_order(self, storeid):
		self._cursor.execute("DELETE FROM storeitemorder WHERE storeid = ?", (storeid, ))
		self._db.commit()

	def set_store_order(self, storeid, item_orders):
		for (itemid, orderno) in sorted(item_orders.items()):
			self._cursor.execute("INSERT INTO storeitemorder (storeid, itemid, orderno) VALUES (?, ?, ?);", (storeid, itemid, orderno))
		self._db.commit()

	def add_item(self, item_name, commit = True):
		with contextlib.suppress(sqlite3.IntegrityError):
			self._cursor.execute("INSERT INTO items (description) VALUES (?);", (item_name, ))
			if commit:
				self._db.commit()
		return self._cursor.execute("SELECT itemid FROM items WHERE description = ?;", (item_name, )).fetchone()[0]

	def add_items(self, item_names):
		item_ids = { }
		for item_name in item_names:
			item_ids[item_name] = self.add_item(item_name, commit = False)
		self._db.commit()
		return item_ids

	def add_item_alias(self, itemid, alias_name):
		(count, ) = self._cursor.execute("SELECT COUNT(*) FROM items WHERE description = ?;", (alias_name, )).fetchone()
		if count == 0:
			self._cursor.execute("INSERT INTO item_alias_names (itemid, description) VALUES (?, ?);", (itemid, alias_name))
			self._db.commit()
		else:
			raise OperationalException("Item with name '%s' already exists as a main item, cannot add alias by that same name.")

	def process_transaction(self, transactionid, itemid, delta, user):
		if delta == 0:
			# Discard
			return

		(count, ) = self._cursor.execute("SELECT COUNT(*) FROM history WHERE transactionid = ?;", (transactionid, )).fetchone()
		if count != 0:
			# Transaction already processed, discard.
			return

		# Transaction timestamp
		processed_utc = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")

		# Get current value
		itemcount = self._cursor.execute("SELECT itemcount FROM shopping_list WHERE itemid = ?;", (itemid, )).fetchone()
		if itemcount is None:
			# Value is not in table at all.
			itemcount = 0
			self._cursor.execute("INSERT INTO shopping_list (itemid, itemcount, last_edited_utc) VALUES (?, ?, ?);", (itemid, 0, processed_utc))
		else:
			itemcount = itemcount[0]

		# Update item count
		self._cursor.execute("UPDATE shopping_list SET itemcount = itemcount + ?, last_edited_utc = ? WHERE itemid = ?;", (delta, processed_utc, itemid))

		# Insert transaction history item
		self._cursor.execute("INSERT INTO history (transactionid, itemid, delta, user, processed_utc) VALUES (?, ?, ?, ?, ?);", (transactionid, itemid, delta, user, processed_utc))
		self._db.commit()

if __name__ == "__main__":
	import uuid
	db = ShoppingListDB("pyslist.sqlite3")
	foo_item = db.add_item("Foo Item")
	db.add_item_alias(100, "Second name for 100")
	db.process_transaction(str(uuid.uuid4()), itemid = foo_item, delta = 1, user = "joe")
	print(db.get_all())


import requests
import secrets
import json

def find_id(firstname, lastname, affil):
    url = f'http://api.elsevier.com/content/search/author?query=AUTHFIRST({firstname})+AND+AUTHLASTNAME({lastname})+AND+AFFIL({affil})&apiKey={secrets.key}'
    response = requests.get(url, headers={'Accept': 'application/json'})
    data = response.json()

    if data['search-results']['opensearch:totalResults'] == '0':
        return None
    else:
        author_id = data['search-results']['entry'][0]['dc:identifier'][data['search-results']['entry'][0]['dc:identifier'].index(':')+1:]

    return author_id

def retrieve_auth_detail(id):
    url = f'http://api.elsevier.com/content/search/scopus?query=AU-ID({id})&count=100&apiKey={secrets.key}'
    response = requests.get(url, headers={'Accept': 'application/json'})
    data = response.json()
    results = []
    try:
        for entry in data['search-results']['entry']:
            for link in entry['link']:
                if link['@ref'] == 'scopus':
                    ref = link['@href']
                    break
            results.append({
                'title': entry['dc:title'],
                'url': ref
            })
    except:
        results = []
    return results


from keras.applications.vgg16 import (
    VGG16, preprocess_input, decode_predictions)
from keras.preprocessing import image
from tensorflow.python.framework import ops
import keras.backend as K
import tensorflow as tf
import numpy as np
import keras
import cv2
import os

def normalize(x):
    # utility function to normalize a tensor by its L2 norm
    return x / (K.sqrt(K.mean(K.square(x))) + 1e-5)

def load_image(path):
    img_path = path
    img = image.load_img(img_path, target_size=(224, 224))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = preprocess_input(x)
    return x

def register_gradient():
    if "GuidedBackProp" not in ops._gradient_registry._registry:
        @ops.RegisterGradient("GuidedBackProp")
        def _GuidedBackProp(op, grad):
            dtype = op.inputs[0].dtype
            return grad * tf.cast(grad > 0., dtype) * \
                tf.cast(op.inputs[0] > 0., dtype)

def compile_saliency_function(model, activation_layer='block5_pool'):
    input_img = model.input
    layer_dict = dict([(layer.name, layer) for layer in model.layers[1:]])
    layer_output = layer_dict[activation_layer].output
    max_output = K.max(layer_output, axis=3)
    saliency = K.gradients(K.sum(max_output), input_img)[0]
    return K.function([input_img, K.learning_phase()], [saliency])

def modify_backprop(model, name):
    g = tf.get_default_graph()
    with g.gradient_override_map({'Relu': name}):

        # get layers that have an activation
        layer_dict = [layer for layer in model.layers[1:]
                      if hasattr(layer, 'activation')]

        # replace relu activation
        for layer in layer_dict:
            if layer.activation == keras.activations.relu:
                layer.activation = tf.nn.relu

        # re-instanciate a new model
        new_model = VGG16(weights='imagenet')
    return new_model

def deprocess_image(x):
    '''
    Same normalization as in:
    https://github.com/fchollet/keras/blob/master/examples/conv_filter_visualization.py
    '''
    if np.ndim(x) > 3:
        x = np.squeeze(x)
    # normalize tensor: center on 0., ensure std is 0.1
    x -= x.mean()
    x /= (x.std() + 1e-5)
    x *= 0.1

    # clip to [0, 1]
    x += 0.5
    x = np.clip(x, 0, 1)

    # convert to RGB array
    x *= 255
    if K.image_dim_ordering() == 'th':
        x = x.transpose((1, 2, 0))
    x = np.clip(x, 0, 255).astype('uint8')
    return x

def grad_cam(model, x, category_index, layer_name):
    """
    Args:
       model: model
       x: image input
       category_index: category index
       layer_name: last convolution layer name
    """
    # get category loss
    class_output = model.output[:, category_index]

    # layer output
    convolution_output = model.get_layer(layer_name).output
    # get gradients
    grads = K.gradients(class_output, convolution_output)[0]
    # get convolution output and gradients for input
    gradient_function = K.function([model.input], [convolution_output, grads])

    output, grads_val = gradient_function([x])
    output, grads_val = output[0], grads_val[0]

    # avg
    weights = np.mean(grads_val, axis=(0, 1))
    cam = np.dot(output, weights)

    # create heat map
    cam = cv2.resize(cam, (x.shape[1], x.shape[2]), cv2.INTER_LINEAR)
    cam = np.maximum(cam, 0)
    heatmap = cam / np.max(cam)

    # Return to BGR [0..255] from the preprocessed image
    image_rgb = x[0, :]
    image_rgb -= np.min(image_rgb)
    image_rgb = np.minimum(image_rgb, 255)

    cam = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET)
    cam = np.float32(cam) + np.float32(image_rgb)
    cam = 255 * cam / np.max(cam)
    return np.uint8(cam), heatmap

pic_folder = "./img/"
pic_cam_folder = "./img_grad_cam/"
model_vgg = VGG16(weights='imagenet')
model_vgg.summary()
list_name = os.listdir(pic_folder)

arr_images = []
for i, file_name in enumerate(list_name):
    img = load_image(pic_folder + file_name)
    predictions = model_vgg.predict(img)
    top_1 = decode_predictions(predictions)[0][0]
    print('Predicted class:')
    print('%s (%s) with probability %.2f' % (top_1[1], top_1[0], top_1[2]))

    predicted_class = np.argmax(predictions)
    cam_image, heat_map = grad_cam(model_vgg, img, predicted_class, "block5_pool")

    img_file = image.load_img(pic_folder + list_name[i])
    img_file = image.img_to_array(img_file)

    # guided grad_cam img
    register_gradient()
    guided_model = modify_backprop(model_vgg, 'GuidedBackProp')
    saliency_fn = compile_saliency_function(guided_model)

    saliency = saliency_fn([img, 0])
    grad_cam_img = saliency[0] * heat_map[..., np.newaxis]

    # save img
    cam_image = cv2.resize(cam_image, (img_file.shape[1], img_file.shape[0]), cv2.INTER_LINEAR)
    cv2.putText(cam_image,str(top_1[1]), (20, 20), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,(0, 0, 255))
    cv2.putText(cam_image,str(top_1[2]), (20, 50), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,(0, 0, 255))

    grad_cam_img = deprocess_image(grad_cam_img)
    grad_cam_img = cv2.resize(grad_cam_img, (img_file.shape[1], img_file.shape[0]), cv2.INTER_LINEAR)
    cv2.putText(grad_cam_img,str(top_1[1]), (20, 20), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,(0, 0, 255))
    cv2.putText(grad_cam_img,str(top_1[2]), (20, 50), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,(0, 0, 255))

    cam_image = cam_image.astype('float32')
    grad_cam_img = grad_cam_img.astype('float32')
    im_h = cv2.hconcat([img_file, cam_image, grad_cam_img])
    cv2.imwrite(pic_cam_folder + list_name[i], im_h)


#Discord bot to kick members without roles + kick specified member

#v2.0(20th Jan 2022)------------------------------------------------------------------------------------
#Bot logic: 0. Runs loop iterating over servers (list)
#           1. Runs loop iterating over server(guild) members, checks each for roles and 'joined_at' time
#           2. If joined_at <= allowed_time, continue, else kick if roles not present
#           3. Auto-kick loop repeats at 30s sleep intervals
#           4. async kick {@member} {reason}(optional) command always available if user has kick perms=true

#loading modules->
import discord
from discord.ext import commands
from discord.ext.commands import has_permissions
import asyncio
import time
import json

#loading config->
f = open('config.json',)
cfg = json.load(f)
admin_role = cfg["admin_role"] #role that can ask this bot to kick members directly
allowed_time = cfg["allowed_time"]#eg 3600 in seconds =6 hours
guild_ids = cfg["guild_ids"]
token = open('kickbot_token.txt','r').readline()
channel_ids = cfg["admin_channel_ids"] #id to which 'kick' updates will be posted.

#initiating client->
intents = discord.Intents.default()
intents.members = True #grabbing .members intent to retrieve guild members, member roles
client = commands.Bot(command_prefix='!', intents=intents)

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))
    print('---------------------------------------------------------------\n')
    print('DISCORD KICK BOT\n')
    print('---------------------------------------------------------------\n')

#@has_permissions(kick_members=True)
@client.command(pass_context=True)
async def kick(ctx, member: discord.Member, *, reason=None):
    commander = ctx.message.author
    print(f'Member {commander.name} tried to use !kick command.')
    j=1
    a_role = discord.utils.find(lambda r: r.name == admin_role, ctx.message.guild.roles)
    list = commander.roles
    for role in list:
        print(f'Role: {j} = {role}')
        j+=1
    if (a_role in list):
        print(f'Member {commander.name} has admin role {admin_role}. Kicking authorized. Kicking...')
        await member.kick(reason=reason)
        await ctx.send(f'User {member} has been kicked.')
        print (f'--------------\nUser {member} has been kicked directly\n-----------------')
    else:
        print(f'Member {commander.name} does not have admin role {admin_role}. Unauthorized. Not kicking.')
        await ctx.send(f'Error. {admin_role} role required to kick. {member} has not been kicked. ')
        print('-------------------------------------------------------\n')

@kick.error
async def kick_error(error, ctx):
   if isinstance(error, MissingPermissions):
        await ctx.send("You don't have permission to do that!")

async def auto_kick_iterator():
    await client.wait_until_ready()
    x = 1
    while not client.is_closed():
        i = 0
        print(f'-------------Iteration {x}----------------')
        for server in guild_ids:
            print(f'--------Checking Server ID: {server}--------')
            channel = client.get_channel(id=channel_ids[i])
            guild = client.get_guild(server)
            async for member in guild.fetch_members(limit=None):
                a=1
                joined_at = member.joined_at
                j_a_epoch = joined_at.timestamp()
                current_time = time.time()
                print(f'\nCurrent time(epoch): {current_time}')
                print(f'Member {member.name} (joined at {joined_at} UTC, Epoch at "{j_a_epoch}"")')
                print(f'Number of roles[] of member: {len(member.roles)-1}')
                i = 0
                for role in member.roles:
                    role_name = role.name
                    print(f'{i}. {role_name}')
                    i+=1
                if (len(member.roles)<=1):
                    if (current_time - j_a_epoch >= allowed_time):
                        print(f'Kicking member.')
                        reason = 'Member has no roles, been in server over allowed_time'
                        name = member.name
                        await member.kick(reason=reason)
                        await channel.send(f'User {name} has been kicked.')
                        print(f'User {name} has been kicked.')
                    else:
                        print('Member has no roles, but within allowed_time. Not kicking.')
                else:
                    print(f'Member has role/s, not kicking.')
            print('-----------------------------\n-------------------------\n')
        x+=1
        await asyncio.sleep(30)

client.loop.create_task(auto_kick_iterator())

client.run(token)