import time
from typing import Optional, List
import warnings

# IBM Qiskit imports
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile
from qiskit_ibm_provider.job.exceptions import (
    IBMJobApiError,
    IBMJobInvalidStateError,
    IBMJobFailureError,
    IBMJobTimeoutError,
)
from qiskit.circuit import Parameter

from .devices import DeviceQiskit
from .gates_qiskit import QiskitGateApplicator
from openqaoa.backends.basebackend import (
    QAOABaseBackendShotBased,
    QAOABaseBackendCloud,
    QAOABaseBackendParametric,
)
from openqaoa.qaoa_components import QAOADescriptor
from openqaoa.qaoa_components.variational_parameters.variational_baseparams import (
    QAOAVariationalBaseParams,
)
from openqaoa.utilities import flip_counts

class QAOAQiskitQPUBackend(
    QAOABaseBackendParametric, QAOABaseBackendCloud, QAOABaseBackendShotBased
):
    """
    A QAOA simulator as well as for real QPU using qiskit as the backend

    Parameters
    ----------
    device: `DeviceQiskit`
        An object of the class ``DeviceQiskit`` which contains the credentials
        for accessing the QPU via cloud and the name of the device.
    qaoa_descriptor: `QAOADescriptor`
        An object of the class ``QAOADescriptor`` which contains information on
        circuit construction and depth of the circuit.
    n_shots: `int`
        The number of shots to be taken for each circuit.
    prepend_state: `QuantumCircuit`
        The state prepended to the circuit.
    append_state: `QuantumCircuit`
        The state appended to the circuit.
    init_hadamard: `bool`
        Whether to apply a Hadamard gate to the beginning of the
        QAOA part of the circuit.
    cvar_alpha: `float`
        The value of alpha for the CVaR method.
    """

    def __init__(
        self,
        qaoa_descriptor: QAOADescriptor,
        device: DeviceQiskit,
        n_shots: int,
        prepend_state: Optional[QuantumCircuit],
        append_state: Optional[QuantumCircuit],
        init_hadamard: bool,
        initial_qubit_mapping: Optional[List[int]] = None,
        qiskit_optimization_level: int = 1,
        cvar_alpha: float = 1,
    ):
        QAOABaseBackendShotBased.__init__(
            self,
            qaoa_descriptor,
            n_shots,
            prepend_state,
            append_state,
            init_hadamard,
            cvar_alpha,
        )
        QAOABaseBackendCloud.__init__(self, device)

        self.qureg = QuantumRegister(self.n_qubits)
        self.problem_reg = self.qureg[0 : self.problem_qubits]
        self.creg = ClassicalRegister(len(self.problem_reg))

        if qiskit_optimization_level in [0, 1, 2, 3]:
            self.qiskit_optimziation_level = qiskit_optimization_level
        else:
            raise ValueError(
                f"qiskit_optimization_level cannot be {qiskit_optimization_level}. Choose between 0 to 3"
            )
        self.gate_applicator = QiskitGateApplicator()

        if self.initial_qubit_mapping is None:
            self.initial_qubit_mapping = (
                initial_qubit_mapping
                if initial_qubit_mapping is not None
                else list(range(self.n_qubits))
            )
        else:
            if isinstance(initial_qubit_mapping, list):
                warnings.warn(
                    "Ignoring the initial_qubit_mapping since the routing algorithm chose one"
                )

        if self.prepend_state:
            assert self.n_qubits >= len(prepend_state.qubits), (
                "Cannot attach a bigger circuit" "to the QAOA routine"
            )

        # if self.device.provider_connected and self.device.qpu_connected:
        #     self.backend_qpu = self.device.backend_device
        if self.device.provider_connected and self.device.qpu_connected in [
            False,
            None,
        ]:
            raise Exception(
                "Connection to {} was made. Error connecting to the specified backend.".format(
                    self.device.device_location.upper()
                )
            )

        elif not (self.device.provider_connected and self.device.qpu_connected):
            raise Exception(
                "Error connecting to {}.".format(self.device.device_location.upper())
            )

        if self.device.n_qubits < self.n_qubits:
            raise Exception(
                "There are lesser qubits on the device than the number of qubits required for the circuit."
            )
        # For parametric circuits
        self.parametric_circuit = self.parametric_qaoa_circuit

    def qaoa_circuit(self, params: QAOAVariationalBaseParams) -> QuantumCircuit:
        """
        The final QAOA circuit to be executed on the QPU.

        Parameters
        ----------
        params: `QAOAVariationalBaseParams`

        Returns
        -------
        qaoa_circuit: `QuantumCircuit`
            The final QAOA circuit after binding angles from variational parameters.
        """
        angles_list = self.obtain_angles_for_pauli_list(self.abstract_circuit, params)
        memory_map = dict(zip(self.qiskit_parameter_list, angles_list))
        circuit_with_angles = self.parametric_circuit.bind_parameters(memory_map)

        if self.append_state:
            circuit_with_angles = circuit_with_angles.compose(self.append_state)

        # only measure the problem qubits
        if self.final_mapping is None:
            circuit_with_angles.measure(self.problem_reg, self.creg)
        else:
            for idx, qubit in enumerate(self.final_mapping[0 : len(self.problem_reg)]):
                cbit = self.creg[idx]
                circuit_with_angles.measure(qubit, cbit)

        if self.qaoa_descriptor.routed is True:
            transpiled_circuit = transpile(
                circuit_with_angles,
                self.device.backend_device,
                initial_layout=self.initial_qubit_mapping,
                optimization_level=self.qiskit_optimziation_level,
                routing_method="none",
            )
        else:
            transpiled_circuit = transpile(
                circuit_with_angles,
                self.device.backend_device,
                initial_layout=self.initial_qubit_mapping,
                optimization_level=self.qiskit_optimziation_level,
            )

        return transpiled_circuit

    @property
    def parametric_qaoa_circuit(self) -> QuantumCircuit:
        """
        Creates a parametric QAOA circuit, given the qubit pairs, single qubits with biases,
        and a set of circuit angles. Note that this function does not actually run
        the circuit. To do this, you will need to subsequently execute the command self.eng.flush().

        Parameters
        ----------
            params:
                Object of type QAOAVariationalBaseParams
        """
        # self.reset_circuit()
        parametric_circuit = QuantumCircuit(self.qureg, self.creg)

        if self.prepend_state:
            parametric_circuit = parametric_circuit.compose(self.prepend_state)
        # Initial state is all |+>
        if self.init_hadamard:
            parametric_circuit.h(self.problem_reg)

        self.qiskit_parameter_list = []
        for each_gate in self.abstract_circuit:
            # if gate is of type mixer or cost gate, assign parameter to it
            if each_gate.gate_label.type.value in ["MIXER", "COST"]:
                angle_param = Parameter(each_gate.gate_label.__repr__())
                self.qiskit_parameter_list.append(angle_param)
                each_gate.angle_value = angle_param
            decomposition = each_gate.decomposition("standard")
            # using the list above, construct the circuit
            for each_tuple in decomposition:
                gate = each_tuple[0](self.gate_applicator, *each_tuple[1])
                gate.apply_gate(parametric_circuit)

        return parametric_circuit

    def get_counts(self, params: QAOAVariationalBaseParams, n_shots=None) -> dict:
        """
        Execute the circuit and obtain the counts

        Parameters
        ----------
        params: QAOAVariationalBaseParams
            The QAOA parameters - an object of one of the parameter classes, containing
            variable parameters.
        n_shots: int
            The number of times to run the circuit. If None, n_shots is set to the default: self.n_shots

        Returns
        -------
            A dictionary with the bitstring as the key and the number of counts
            as its value.
        """

        n_shots = self.n_shots if n_shots is None else n_shots

        circuit = self.qaoa_circuit(params)

        job_state = False
        no_of_job_retries = 0
        max_job_retries = 5

        while job_state is False:
            # initial_layout only passed if not azure device
            # if type(self.device).__name__ == "DeviceAzure":
            # job = self.backend_qpu.run(circuit, **input_items)
            job = self.device.backend_device.run(circuit, shots=n_shots)

            api_contact = False
            no_of_api_retries = 0
            max_api_retries = 5

            while api_contact is False:
                try:
                    self.job_id = job.job_id()
                    counts = job.result().get_counts()
                    api_contact = True
                    job_state = True
                except (IBMJobApiError, IBMJobTimeoutError):
                    print("There was an error when trying to contact the IBMQ API.")
                    job_state = True
                    no_of_api_retries += 1
                    time.sleep(5)
                except (IBMJobFailureError, IBMJobInvalidStateError):
                    print("There was an error with the state of the Job in IBMQ.")
                    no_of_job_retries += 1
                    break

                if no_of_api_retries >= max_api_retries:
                    raise ConnectionError(
                        "Number of API Retries exceeded Maximum allowed."
                    )

            if no_of_job_retries >= max_job_retries:
                raise ConnectionError("An Error Occurred with the Job(s) sent to IBMQ.")

        # Expose counts
        final_counts = flip_counts(counts)
        self.measurement_outcomes = final_counts
        return final_counts

    def circuit_to_qasm(self, params: QAOAVariationalBaseParams) -> str:
        """
        A method to convert the entire QAOA `QuantumCircuit` object into
        a OpenQASM string
        """
        raise NotImplementedError()
        # qasm_string = self.qaoa_circuit(params).qasm(formatted=True)
        # return qasm_string

    def reset_circuit(self):
        """
        Reset self.circuit after performing a computation
        """
        raise NotImplementedError()


# Standard Library
from builtins import str
from datetime import datetime
import collections
# Third Party Stuff
from django.core.exceptions import PermissionDenied,ObjectDoesNotExist
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Count, Min, Q, Sum
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.template.defaultfilters import slugify
from django.utils.timezone import now

# Spoken Tutorial Stuff
from cms.sortable import *
from events.filters import AcademicCenterFilter, TestFilter, TrainingRequestFilter, EventStatsFilter
from events.models import *
from training.models import *
from creation.models import TutorialResource
from creation.filters import CreationStatisticsFilter
from events.views import get_page
from .forms import LearnerForm
from django.core.cache import cache

# Create your views here.
def maphome(request):
    states = State.objects.filter(has_map=1)

    counts = TrainingRequest.objects.filter(
        participants__gt=0,
        sem_start_date__lte=datetime.now()
    ).aggregate(Count('id'), Sum('participants'))

    institution_count = AcademicCenter.objects.filter(
        id__in=TrainingRequest.objects.filter(
            participants__gt=0,
            sem_start_date__lte=datetime.now()
        ).values_list('training_planner__academic_id').distinct()
    ).aggregate(Count('id'))

    context = {
        'states': states,
        'participant_count': counts['participants__sum'],
        'training_count': counts['id__count'],
        'institution_count': institution_count['id__count'],
    }
    return render(request, 'statistics/templates/maphome.html', context)

def get_state_info(request, code):
    state = None
    try:
        state = State.objects.get(code=code)
        # academic_list = AcademicCenter.objects.filter(state = state).values_list('id')

        academic_centers = AcademicCenter.objects.filter(
            state=state,
            id__in=TrainingRequest.objects.filter(
                participants__gt=0,
                sem_start_date__lte=datetime.now()
            ).values_list('training_planner__academic_id').distinct()
        ).count()
        # workshop_details = Training.objects.filter(academic_id__in = academic_list, status = 4).aggregate(Sum('participant_count'), Count('id'), Min('tdate'))
        workshop_details = TrainingRequest.objects.filter(
            participants__gt=0,
            sem_start_date__lte=datetime.now(),
            training_planner__academic__state_id=state.id
        ).aggregate(Sum('participants'), Count('id'), Min('sem_start_date'))
        context = {
            'state': state,
            'workshops': workshop_details['id__count'],
            'participants': workshop_details['participants__sum'],
            'academic_centers': academic_centers,
            'from_date': workshop_details['sem_start_date__min']
        }
        return render(request, 'statistics/templates/get_state_info.html', context)
    except Exception as e:
        print(e)
        return HttpResponse('
Permission Denied!
')

def training(request):
    """ Organiser index page """
    collectionSet = TrainingRequest.objects.filter(
            sem_start_date__lte=datetime.now()
        ).order_by('-sem_start_date')
    state = None
    TRAINING_COMPLETED = '1'
    TRAINING_PENDING = '0'
    if request.method == 'GET':
        status = request.GET.get('status')
        print('###################', status)
        if status not in [TRAINING_COMPLETED, TRAINING_PENDING]:
            status = TRAINING_COMPLETED

        lang= request.GET.get('lang')
        if status == TRAINING_COMPLETED:
            if lang and '---------' not in lang:
                training_attend_lang = TrainingAttend.objects.filter(language__name=lang).values_list('training_id').distinct()
                collectionSet= collectionSet.filter(id__in=training_attend_lang)

    if status == TRAINING_PENDING:
        collectionSet = collectionSet.filter(participants=0, status=TRAINING_COMPLETED)

    else:
        collectionSet = collectionSet.filter(participants__gt=0)
    header = {
        1: SortableHeader('#', False),
        2: SortableHeader('training_planner__academic__state__name', True, 'State'),
        3: SortableHeader('training_planner__academic__city__name', True, 'City'),
        4: SortableHeader('training_planner__academic__institution_name', True, 'Institution'),
        5: SortableHeader('course__foss__foss', True, 'FOSS'),
        6: SortableHeader('department', True, 'Department'),
        7: SortableHeader('course__category', True, 'Type'),
        8: SortableHeader('training_planner__organiser__user__first_name', True, 'Organiser'),
        9: SortableHeader('sem_start_date', True, 'Date'),
        10: SortableHeader('participants', 'True', 'Participants'),
        11: SortableHeader('Action', False)
    }

    raw_get_data = request.GET.get('o', None)
    collection = get_sorted_list(request, collectionSet, header, raw_get_data)
    ordering = get_field_index(raw_get_data)

    # find state id
    if 'training_planner__academic__state' in request.GET and request.GET['training_planner__academic__state']:
        state = State.objects.get(id=request.GET['training_planner__academic__state'])
    collection = TrainingRequestFilter(request.GET, queryset=collection, state=state)
    # find participants count

    participants = collection.qs.aggregate(Sum('participants'))

    if lang == 'English':
        participants = participants['participants__sum']+294593

    else:
        participants = participants['participants__sum']

    chart_query_set = collection.qs.extra(select={'year': "EXTRACT(year FROM sem_start_date)"}).values('year').order_by(
            '-year').annotate(total_training=Count('sem_start_date'), total_participant=Sum('participants'))
    chart_data = ''

    get_year = []
    pending_attendance_participant_count = 0
    key = ''.join('None' if i == '' or i == '---------' else str(i).replace(" ", "") for i in request.GET.values())
    key = key if key else 'NoneNoneNoneNoneNoneNoneNoneNoneNoneNone1'
    female_key = key + 'female'
    male_key = key + 'male'
    femalecount = cache.get(female_key)
    malecount = cache.get(male_key)
    if status != 0:
        if not femalecount or not malecount:
            female_list=list(Student.objects.filter(trainingattend__training_id__in=[col.id for col in collection.qs], gender='Female').values_list('id'))
            femalecount= len([i[0] for i in female_list])
            male_list=list(Student.objects.filter(trainingattend__training_id__in=[col.id for col in collection.qs], gender='Male').values_list('id'))
            malecount= len([i[0] for i in male_list])
            try:
                cache.set(female_key, femalecount)
                cache.set(male_key, malecount)
            except Exception:
                print('Error setting cache key values')

    year_data_all=dict()
    visited=dict()
    if status == TRAINING_PENDING:

        pending_attendance_student_batches = StudentBatch.objects.filter(
            id__in=(collection.qs.filter(status=TRAINING_COMPLETED,participants=0,batch_id__gt=0).values('batch_id'))
            )
        pending_attendance_training = collection.qs.filter(batch_id__in = pending_attendance_student_batches.filter().values('id')).distinct()

        for batch in pending_attendance_student_batches:
            pending_attendance_participant_count += batch.stcount
        for a_traning in pending_attendance_training:
            if a_traning.batch_id not in visited:
                if a_traning.sem_start_date.year in year_data_all:
                    visited[a_traning.batch_id] = [a_traning.batch_id]
                    year_data_all[a_traning.sem_start_date.year] +=  a_traning.batch.stcount
                else:
                    visited[a_traning.batch_id] = [a_traning.batch_id]
                    year_data_all[a_traning.sem_start_date.year] =  a_traning.batch.stcount

    if status == TRAINING_COMPLETED:
        for data in chart_query_set:
            chart_data += "['" + str(data['year']) + "', " + str(data['total_participant']) + "],"
    else:
        for year,count in list(year_data_all.items()):
            chart_data += "['" + str(year) + "', " + str(count) + "],"

    no_of_colleges=collection.qs.filter().values('training_planner__academic_id').distinct().count()
    print(" ********************** no of colleges: ", no_of_colleges)

    context = {}
    context['form'] = collection.form
    context['chart_data'] = chart_data
    page = request.GET.get('page')
    collection = get_page(collection.qs, page )
    context['collection'] = collection
    context['header'] = header
    context['ordering'] = ordering
    if status == TRAINING_PENDING:
        context['participants'] = pending_attendance_participant_count
    else:
        context['participants'] = participants
    context['model'] = 'Workshop/Training'
    context['status']=status
    context['femalecount'] = femalecount
    context['malecount'] = malecount
    context['no_of_colleges'] = no_of_colleges

    context['language'] = Language.objects.values('id','name')
    return render(request, 'statistics/templates/training.html', context)

def fdp_training(request):
    """ Organiser index page """
    collectionSet = None
    state = None

    collectionSet = TrainingRequest.objects.filter(
        participants__gt=0,
        department=169,
        sem_start_date__lte=datetime.now()
    ).order_by('-sem_start_date')
    header = {
        1: SortableHeader('#', False),
        2: SortableHeader('training_planner__academic__state__name', True, 'State'),
        3: SortableHeader('training_planner__academic__city__name', True, 'City'),
        4: SortableHeader('training_planner__academic__institution_name', True, 'Institution'),
        5: SortableHeader('course__foss__foss', True, 'FOSS'),
        6: SortableHeader('department', True, 'Department'),
        7: SortableHeader('course__category', True, 'Type'),
        8: SortableHeader('training_planner__organiser__user__first_name', True, 'Organiser'),
        9: SortableHeader('sem_start_date', True, 'Date'),
        10: SortableHeader('participants', 'True', 'Participants'),
        11: SortableHeader('Action', False)
    }

    raw_get_data = request.GET.get('o', None)
    collection = get_sorted_list(request, collectionSet, header, raw_get_data)
    ordering = get_field_index(raw_get_data)

    # find state id
    if 'training_planner__academic__state' in request.GET and request.GET['training_planner__academic__state']:
        state = State.objects.get(id=request.GET['training_planner__academic__state'])

    collection = TrainingRequestFilter(request.GET, queryset=collection, state=state)
    # find participants count
    participants = collection.qs.aggregate(Sum('participants'))

    femalecount =0
    female_list=list(Student.objects.filter(trainingattend__training_id__in=[col.id for col in collection.qs], gender='Female').values_list('id'))
    femalecount= len([i[0] for i in female_list])

    malecount =0
    male_list=list(Student.objects.filter(trainingattend__training_id__in=[col.id for col in collection.qs], gender='Male').values_list('id'))
    malecount= len([i[0] for i in male_list])

    chart_query_set = collection.qs.extra(select={'year': "EXTRACT(year FROM sem_start_date)"}).values('year').order_by(
        '-year').annotate(total_training=Count('sem_start_date'), total_participant=Sum('participants'))
    chart_data = ''
    for data in chart_query_set:
        chart_data += "['" + str(data['year']) + "', " + str(data['total_participant']) + "],"

    no_of_colleges=collection.qs.filter().values('training_planner__academic_id').distinct().count()
    print(" ********************** no of colleges: ", no_of_colleges)

    context = {}
    context['form'] = collection.form
    context['chart_data'] = chart_data
    page = request.GET.get('page')
    collection = get_page(collection.qs, page)
    context['collection'] = collection
    context['header'] = header
    context['ordering'] = ordering
    context['participants'] = participants
    context['model'] = 'Workshop/Training'
    context['femalecount'] = femalecount
    context['malecount'] = malecount
    context['no_of_colleges'] = no_of_colleges
    return render(request, 'statistics/templates/pmmm_stats.html', context)

def training_participant(request, rid):
    context = {}
    try:
        context['model_label'] = 'Workshop / Training'
        context['model'] = TrainingRequest.objects.get(id=rid)
        context['collection'] = TrainingAttend.objects.filter(training_id=rid)
    except Exception as e:
        print(e)
        raise PermissionDenied()
    return render(request, 'statistics/templates/training_participant.html', context)

def studentmaster_ongoing(request, rid):

    context = {}
    try:
        context['model_label'] = 'Workshop / Training'
        context['model'] = TrainingRequest.objects.get(id=rid)
        current_batch = TrainingRequest.objects.filter(id=rid)
        for ab in current_batch:
            row_data = StudentMaster.objects.filter(batch_id=ab.batch_id)
        context['collection'] = row_data

    except Exception as e:
        print(e)
        raise ObjectDoesNotExist()
    return render(request, 'statistics/templates/training_participant.html', context)

def online_test(request):
    """ Organiser index page """
    collectionSet = None
    participant_count = 0

    collectionSet = Test.objects.filter(status=4, participant_count__gt=0).order_by('-tdate')
    header = {
        1: SortableHeader('#', False),
        2: SortableHeader('academic__state__name', True, 'State'),
        3: SortableHeader('academic__city__name', True, 'City'),
        4: SortableHeader('academic__institution_name', True, 'Institution'),
        5: SortableHeader('foss__foss', True, 'FOSS'),
        6: SortableHeader('organiser__user__first_name', True, 'Organiser'),
        7: SortableHeader('tdate', True, 'Date'),
        8: SortableHeader('participant_count', 'True', 'Participants'),
        9: SortableHeader('Action', False)
    }

    raw_get_data = request.GET.get('o', None)
    collection = get_sorted_list(request, collectionSet, header, raw_get_data)
    ordering = get_field_index(raw_get_data)

    # find state id
    state = None
    if 'academic__state' in request.GET and request.GET['academic__state']:
        state = State.objects.get(id=request.GET['academic__state'])

    collection = TestFilter(request.GET, queryset=collection, state=state)
    # find participants count
    participant_count = collection.qs.aggregate(Sum('participant_count'))
    #
    chart_query_set = collection.qs.extra(select={'year': "EXTRACT(year FROM tdate)"}).values('year').order_by(
        '-year').annotate(total_training=Count('tdate'), total_participant=Sum('participant_count'))
    chart_data = ''
    for data in chart_query_set:
        chart_data += "['" + str(data['year']) + "', " + str(data['total_participant']) + "],"

    no_of_colleges=collection.qs.filter().values('academic_id').distinct().count()
    print(" ********************** no of colleges: ", no_of_colleges)

    context = {}
    context['form'] = collection.form
    context['chart_data'] = chart_data
    page = request.GET.get('page')
    collection = get_page(collection.qs, page)
    context['collection'] = collection
    context['header'] = header
    context['ordering'] = ordering
    context['participant_count'] = participant_count
    context['model'] = 'Online-Test'
    context['no_of_colleges'] = no_of_colleges
    return render(request, 'statistics/templates/online_test.html', context)

def test_participant(request, rid):
    context = {}
    if not rid:
        raise PermissionDenied()
    try:
        context['model_label'] = 'Online-Test'
        context['model'] = Test.objects.get(id=rid)
        test_mdlusers = TestAttendance.objects.using('default').filter(
            test_id=rid, status__gte=2).values_list('mdluser_id')
        ids = []
        for wp in test_mdlusers:
            ids.append(wp[0])
        context['collection'] = MdlUser.objects.using('moodle').filter(id__in=ids)
    except Exception:
        raise PermissionDenied()
    return render(request, 'statistics/templates/participant.html', context)

def academic_center(request, slug=None):
    context = {}
    header = {
        1: SortableHeader('#', False),
        2: SortableHeader('State', False),
        3: SortableHeader('institution_name', True, 'Institution Name'),
        4: SortableHeader('Training', False),
        5: SortableHeader('Participants', True),
        6: SortableHeader('Action', False)
    }

    collection = None
    start_date = request.GET.get('training__tdate_0', 0)
    end_date = request.GET.get('training__tdate_1', 0)
    lookup = None
    training_query = TrainingRequest.objects.filter(
        participants__gt=0,
        sem_start_date__lte=datetime.now()
    )
    if start_date or end_date:
        if start_date and end_date:
            lookup = [start_date, end_date]
        elif start_date:
            lookup = [start_date, now()]
        else:
            lookup = [datetime.strptime('1970-01-01', '%Y-%m-%d'), end_date]
    if slug:
        collection = AcademicCenter.objects.filter(
            id__in=training_query.values_list(
                'training_planner__academic_id'
            ).distinct(),
            state__slug=slug
        ).order_by('state__name', 'institution_name')
    else:
        if lookup:
            training_query = TrainingRequest.objects.filter(
                Q(sem_start_date__range=lookup) & Q(sem_start_date__lte=datetime.now()),
                participants__gt=0
            )
            collection = AcademicCenter.objects.filter(
                id__in=training_query.values_list(
                    'training_planner__academic_id'
                ).distinct()
            ).order_by('state__name', 'institution_name')
        else:
            collection = AcademicCenter.objects.filter(
                id__in=training_query.values_list(
                    'training_planner__academic_id'
                ).distinct()
            ).order_by('state__name', 'institution_name')

    raw_get_data = request.GET.get('o', None)
    collection = get_sorted_list(request, collection, header, raw_get_data)
    ordering = get_field_index(raw_get_data)

    collection = AcademicCenterFilter(request.GET, queryset=collection)
    context['form'] = collection.form
    context['total_training'] = training_query.count()
    participant_count = training_query.aggregate(Sum('participants'))
    print(participant_count)
    context['total_participant'] = participant_count['participants__sum']

    page = request.GET.get('page')
    collection = get_page(collection.qs, page)
    context['collection'] = collection
    context['header'] = header
    context['ordering'] = ordering

    return render(request, 'statistics/templates/academic-center.html', context)

def academic_center_view(request, academic_id=None, slug=None):
    collection = get_object_or_404(AcademicCenter, id=academic_id)
    slug_title = slugify(collection.institution_name)
    if slug != slug_title:
        return HttpResponseRedirect('/statistics/academic-center/' + str(collection.id) + '/' + slug_title)
    context = {
        'collection': collection
    }
    return render(request, 'statistics/templates/view-academic-center.html', context)

def motion_chart(request):
    collection = TrainingRequest.objects.filter(
        participants__gt=0, sem_start_date__lte=datetime.now()
    ).values(
        'training_planner__academic__state__name', 'sem_start_date'
    ).annotate(tcount=Count('sem_start_date'), pcount=Sum('participants'))

    interactive_workshop_data = ""
    static_workshop_data = ""
    states = {}
    for row in collection:
        curr_state = str(row['training_planner__academic__state__name'])
        if curr_state in states:
            states[curr_state]['tcount'] += int(row['tcount'])
            states[curr_state]['pcount'] += int(row['pcount'])
        else:
            states[curr_state] = {}
            states[curr_state]['tcount'] = int(row['tcount'])
            states[curr_state]['pcount'] = int(row['pcount'])
        js_date = 'new Date(' + str(row['sem_start_date'].year) + ', ' + \
            str(int(row['sem_start_date'].month) - 1) + ', ' + str(row['sem_start_date'].day) + ')'
        interactive_workshop_data += "['" + curr_state + "', " + js_date + \
            ", " + str(row['tcount']) + ", " + str(row['pcount']) + "],"

    for key, value in list(states.items()):
        curr_year = str(datetime.now().year)
        static_workshop_data += "['" + key + "', " + curr_year + ", " + \
            str(value['tcount']) + ", " + str(value['pcount']) + "],"

    context = {
        'interactive_workshop_data': interactive_workshop_data,
        'static_workshop_data': static_workshop_data,
    }

    return render(request, 'statistics/templates/motion_charts.html', context)

def learners(request):
    context = {}
    form = LearnerForm()
    if request.method == 'POST':
        form = LearnerForm(request.POST)
        if form.is_valid():
            try:
                form.save()
                messages.success(
                    request, "Thank you for submitting your details. You can choose your course and then continue..")
                return HttpResponseRedirect('/tutorial-search/?search_foss=&search_language=')
            except Exception as e:
                print(e)
                messages.success(request, "Sorry, something went wrong, Please try again!")
    context['form'] = form
    return render(request, 'statistics/templates/learners.html', context)

def tutorial_content(request, template='statistics/templates/statistics_content.html'):
    header = {
        1: SortableHeader('# ', False),
        2: SortableHeader('tutorial_detail__tutorial', True, 'Tutorial'),
        3: SortableHeader('tutorial_detail__foss__foss', True, 'FOSS Course'),
        4: SortableHeader('tutorial_detail__level', True, 'Level'),
        5: SortableHeader('language__name', True, 'Language'),
        6: SortableHeader('publish_at', True, 'Date Published')
    }

    published_tutorials_set = TutorialResource.objects.filter(Q(status=1) | Q(status=2))

    raw_get_data = request.GET.get('o', None)
    tutorials = get_sorted_list(request, published_tutorials_set, header, raw_get_data)
    ordering = get_field_index(raw_get_data)

    tutorials_filter = CreationStatisticsFilter(request.GET, queryset=tutorials)
    # whenever publish date filter is applied there is a table join, resulting a duplicate entry for tutorials
    # because single tutorial might have multiple pushish objects
    qs = tutorials_filter.qs.distinct()
    no_of_foss = qs.filter().values('tutorial_detail__foss_id').distinct().count()
    print('************ no of foss: ',no_of_foss)

    context = {}

    context['form'] = tutorials_filter.form

    # display information table across multiple pages
    paginator = Paginator(qs, 100)
    page = request.GET.get('page')
    try:
        tutorials = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        tutorials = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        tutorials = paginator.page(paginator.num_pages)
    context['tutorials'] = tutorials
    context['tutorial_num'] = tutorials.paginator.count
    context['header'] = header
    context['ordering'] = ordering
    context['no_of_foss'] = no_of_foss

    return render(request, template, context)

def ilw_stats(request):
    queryset =TrainingEvents.objects.filter(training_status=2).order_by('-event_start_date')
    context = {}

    REG_COMPLETED = '1'
    CLOSED_TRAINING = '2'

    if request.method == 'GET':
        status = request.GET.get('status')
        if status not in [REG_COMPLETED, CLOSED_TRAINING]:
            status = CLOSED_TRAINING
    if status == REG_COMPLETED:
        queryset = TrainingEvents.objects.filter(training_status=1).order_by('-event_start_date')
    elif status == CLOSED_TRAINING:
        queryset = TrainingEvents.objects.filter(training_status=2).order_by('-event_start_date')

    header = {
        1: SortableHeader('#', False),
        2: SortableHeader(
          'state__name',
          True,
          'State'
        ),
        3: SortableHeader(
          'host_college__academic_code',
          True,
          'Code'
        ),
        4: SortableHeader(
          'host_college__institution_name',
          True,
          'Institution'
        ),
        5: SortableHeader('foss__foss', True, 'Foss Name'),
        6: SortableHeader(
          'event_coordinator_name',
          True,
          'Coordinator'
        ),
        7: SortableHeader(
          'registartion_end_date',
          True,
          'Registration Period'
        ),
        8: SortableHeader(
          'event_start_date',
          True,
          'Event Start Date'
        ),
        9: SortableHeader(
          'event_end_date',
          True,
          'Event End Date'
        ),
        10: SortableHeader('Participant Count', True),
        11: SortableHeader('Action', False)
        }

    raw_get_data = request.GET.get('o', None)

    queryset = get_sorted_list(
        request,
        queryset,
        header,
        raw_get_data
    )
    collection= EventStatsFilter(request.GET, queryset=queryset)

    femalecount =0
    malecount =0

    if status == REG_COMPLETED:
        participants = Participant.objects.filter(event_id__in=collection.qs, reg_approval_status=1)
        pcount = participants.count()
        female_list=list(participants.filter(gender__in=('f','F','female','Female','FEMALE')).values_list('id'))
        male_list=list(participants.filter(gender__in=('m','M','male','Male','MALE')).values_list('id'))

    elif status == CLOSED_TRAINING:
        participants = EventAttendance.objects.filter(event_id__in=collection.qs)
        pcount=participants.count()
        female_list = list(participants.filter(participant__gender__in=('f','F','female','Female','FEMALE')).values_list('id'))
        male_list=list(participants.filter(participant__gender__in=('m','M','male','Male','MALE')).values_list('id'))

    femalecount= len([i[0] for i in female_list])

    malecount= len([i[0] for i in male_list])

    context['form'] = collection.form
    page = request.GET.get('page')
    collection = get_page(collection.qs, page)
    context['collection'] = collection
    context['header'] = header
    context['participants'] = pcount
    context['femalecount'] = femalecount
    context['malecount'] = malecount
    context['status'] = status
    return render(request, 'statistics/templates/ilw_stats.html', context)


from itertools import chain

from notifications_python_client.errors import HTTPError

from app.extensions import redis_client
from app.notify_client import NotifyAdminAPIClient, cache

class OrganisationsClient(NotifyAdminAPIClient):

    @cache.set('organisations')
    def get_organisations(self):
        return self.get(url='/organisations')

    @cache.set('domains')
    def get_domains(self):
        return list(chain.from_iterable(
            organisation['domains']
            for organisation in self.get_organisations()
        ))

    def get_organisation(self, org_id):
        return self.get(url='/organisations/{}'.format(org_id))

    @cache.set('organisation-{org_id}-name')
    def get_organisation_name(self, org_id):
        return self.get_organisation(org_id)['name']

    def get_organisation_by_domain(self, domain):
        try:
            return self.get(
                url='/organisations/by-domain?domain={}'.format(domain),
            )
        except HTTPError as error:
            if error.status_code == 404:
                return None
            raise error

    @cache.delete('organisations')
    def create_organisation(self, name, crown, organisation_type, agreement_signed):
        return self.post(
            url="/organisations",
            data={
                "name": name,
                "crown": crown,
                "organisation_type": organisation_type,
                "agreement_signed": agreement_signed,
            }
        )

    @cache.delete('domains')
    @cache.delete('organisations')
    def update_organisation(self, org_id, cached_service_ids=None, **kwargs):
        api_response = self.post(url="/organisations/{}".format(org_id), data=kwargs)

        if cached_service_ids:
            redis_client.delete(*map('service-{}'.format, cached_service_ids))

        if 'name' in kwargs:
            redis_client.delete(f'organisation-{org_id}-name')

        if 'email_branding_id' in kwargs and kwargs['email_branding_id']:
            redis_client.delete(f'organisation-{org_id}-email-branding-pool')

        return api_response

    @cache.delete('organisation-{org_id}-email-branding-pool')
    def add_brandings_to_email_branding_pool(self, org_id, branding_ids):
        return self.post(
            url=f"/organisations/{org_id}/email-branding-pool",
            data={'branding_ids': branding_ids}
        )

    @cache.delete('service-{service_id}')
    @cache.delete('live-service-and-organisation-counts')
    @cache.delete('organisations')
    def update_service_organisation(self, service_id, org_id):
        data = {
            'service_id': service_id
        }
        return self.post(
            url="/organisations/{}/service".format(org_id),
            data=data
        )

    def get_organisation_services(self, org_id):
        return self.get(url="/organisations/{}/services".format(org_id))

    @cache.delete('user-{user_id}')
    def remove_user_from_organisation(self, org_id, user_id):
        return self.delete(f'/organisations/{org_id}/users/{user_id}')

    def get_services_and_usage(self, org_id, year):
        return self.get(
            url=f"/organisations/{org_id}/services-with-usage",
            params={"year": str(year)}
        )

    @cache.delete('organisations')
    @cache.delete('domains')
    def archive_organisation(self, org_id):
        redis_client.delete(f'organisation-{org_id}-name')

        return self.post(
            url=f"/organisations/{org_id}/archive",
            data=None,
        )

    @cache.set('organisation-{org_id}-email-branding-pool')
    def get_email_branding_pool(self, org_id):
        branding = self.get(
            url=f"/organisations/{org_id}/email-branding-pool",

        )
        return branding["data"]

    @cache.delete('organisation-{org_id}-email-branding-pool')
    def remove_email_branding_from_pool(self, org_id, branding_id):
        self.delete(f"/organisations/{org_id}/email-branding-pool/{branding_id}")

organisations_client = OrganisationsClient()


import unittest

import zope.component
import zope.interface

from Zope2.App import zcml
from Products.Five import fiveconfigure
from Products.PloneTestCase import PloneTestCase as ptc

from pmr2.users.interfaces import IEmailManager
from pmr2.users.browser import UserEmailForm

from pmr2.testing.base import TestRequest
from pmr2.users.tests import base

class EmailEditorTestCase(ptc.PloneTestCase):
    """
    For the browser side of things.
    """

    def afterSetUp(self):
        self.portal.acl_users._doAddUser('user1', 'secret', ['Member'], [])
        self.portal.acl_users._doAddUser('user2', 'secret', ['Member'], [])
        self.email_manager = zope.component.getAdapter(
            self.portal, IEmailManager)

    def test_user_email_form_render(self):
        context = self.portal
        request = TestRequest()
        form = UserEmailForm(context, request)
        result = form()
        self.assertTrue('<textarea' in result)

    def test_user_email_set(self):
        self.login('user1')
        context = self.portal
        request = TestRequest(form={
            'form.widgets.addresses': 'user1@example.com\nuser11@example.com',
            'form.buttons.apply': 1,
        })
        form = UserEmailForm(context, request)
        result = form()
        self.assertEqual(self.email_manager.get_emails_for('user1'), [
            u'user11@example.com',
            u'user1@example.com',
        ])

        self.login('user2')
        context = self.portal
        request = TestRequest(form={
            'form.widgets.addresses': 'user1@example.com\nuser22@example.com',
            'form.buttons.apply': 1,
        })
        form = UserEmailForm(context, request)
        result = form()
        self.assertEqual(self.email_manager.get_emails_for('user2'), [
            u'user22@example.com',
        ])


from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
from rest_framework import status
from .serializers import FileSerializer
import subprocess
# from .fanar_cv import find_face

class FileView(APIView):
  parser_classes = (MultiPartParser, FormParser)
  def post(self, request, *args, **kwargs):
    file_serializer = FileSerializer(data=request.data)
    if file_serializer.is_valid():
      file_serializer.save()
      # print(file_serializer.data['file'])
      # cv_status = find_face(file_serializer.data['file'])
      # cv_status_json = {"status":"{0}".format(cv_status)}
      completed = subprocess.run(
        ['python', 'face-find.py', "."+file_serializer.data['file']],
        stdout=subprocess.PIPE,
      )
      result = completed.stdout.decode('ascii').strip()
      print(result)

      if result != "Found encodings":
        completed2 = subprocess.run(
        ['python', 'face-add.py', "."+file_serializer.data['file']],
        stdout=subprocess.PIPE,
        )
        result = completed2.stdout.decode('ascii').strip()
        print(result)

      # completed = subprocess.run(
      #   ['pwd'],
      #   stdout=subprocess.PIPE,
      # )
      # file_serializer.data['cv_result'] = completed.stdout.decode('utf-8')
      # return Response(cv_status_json, status=status.HTTP_201_CREATED)
      return Response(result, status=status.HTTP_201_CREATED)
    else:
      return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# Data Preprocessing

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('50_startups.csv')
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, 4].values

#categorising the data
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
labelencoder_X = LabelEncoder()
X[:, 3]= labelencoder_X.fit_transform(X[:, 3])
onehotencoder = OneHotEncoder(categorical_features=[3])
X = onehotencoder.fit_transform(X).toarray()

#Escape the dummy variable trap
X = X[:, 1:]

#splitting test set and data set
from sklearn.cross_validation import train_test_split
X_train , X_test , y_train , y_test = train_test_split(X , y , test_size = 0.2 , random_state = 0)

'''#feature Scalling
from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)'''

#perform multiple linear regression
from sklearn.linear_model import LinearRegression
Regressor = LinearRegression()
Regressor = Regressor.fit(X_train , y_train)

#predicting the result
y_train_pred = Regressor.predict(X_train)
y_test_pred = Regressor.predict(X_test)

#Building optical model using backward elimination
import statsmodels.formula.api as sm
X = np.append(arr = np.ones([50 ,1]).astype(int) , values = X , axis=1)
X_opt = X[: , [0,1,2,3,4,5]]
regressor_ols = sm.OLS(endog = y , exog = X_opt).fit()
regressor_ols.summary()
X_opt = X[: , [0,1,3,4,5]]
regressor_ols = sm.OLS(endog = y , exog = X_opt).fit()
regressor_ols.summary()
X_opt = X[: , [0,3,4,5]]
regressor_ols = sm.OLS(endog = y , exog = X_opt).fit()
regressor_ols.summary()
X_opt = X[: , [0,3,4,5]]
regressor_ols = sm.OLS(endog = y , exog = X_opt).fit()
regressor_ols.summary()
X_opt = X[: , [0,3,5]]
regressor_ols = sm.OLS(endog = y , exog = X_opt).fit()
regressor_ols.summary()
X_opt = X[: , [0,3]]
regressor_ols = sm.OLS(endog = y , exog = X_opt).fit()
regressor_ols.summary()

Regressor_2 = LinearRegression()
Regressor_2.fit(X_train[:,2:3] , y_train)
#showing the result of X train dataset
X_grid = np.arange(min(X_train[:,2:3]), max(X_train[:,2:3]), 0.01)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(X_train[:, 2] , y_train , color='red')
plt.plot(X_grid , Regressor_2.predict(X_grid) , color='blue')
plt.title('R&D Spend vs Profit')
plt.xlabel('R&D Spend')
plt.ylabel('Profit')
plt.show()

#showing the result of Y train dataset
plt.scatter(X_test[:,2] , y_test , color='red')
plt.plot(X_test[:,2] , Regressor_2.predict(X_test[:,2:3]) , color='blue')
plt.title('R&D Spend vs Profit')
plt.xlabel('R&D Spend')
plt.ylabel('Profit')
plt.show()

Regression/Multiple Linear Regression/Multiple linear regression.py


import sys
from turtle import position
sys.path.append('..')
from functions import read_file
from typing import Iterable

def preprocess_file(file: Iterable[str]) -> Iterable[int]:
    return list(map(int, file[0].split(',')))

def cost_formula(cost: int) -> int:
    """ Sum of first n natural numbers

    Sum = N(N+1) / 2
    """
    return (cost * (cost + 1)) / 2

def simulate_moves(starting_positions: Iterable[int], part: int = 1) -> Iterable[int]:
    """Simulate all possible moves and return the index that leads to least fuel cost"""

    cost_dict = {}
    for index, _ in enumerate(starting_positions):
        position_copy = starting_positions.copy()
        # We remove the position unders consideration from the list copy
        position_copy.pop(index)
        # Find the total fuel cost by subtracting the current position with all the other positions
        if part == 1:
            position_wise_cost = [abs(positions - starting_positions[index]) for positions in position_copy]
        else:
            position_wise_cost = [abs(positions - starting_positions[index]) for positions in position_copy]
            position_wise_cost = [cost_formula(cost_val) for cost_val in position_wise_cost]

        cost = sum(position_wise_cost)
        cost_dict[starting_positions[index]] = cost
    return min(cost_dict, key=cost_dict.get), cost_dict[min(cost_dict, key=cost_dict.get)]

if __name__ == '__main__':
    # reading and preprocessing input
    file = read_file(sys.argv[1])
    pp_file = preprocess_file(file)
    # part 1 and 2 simulations
    part_1 = simulate_moves(pp_file, part=1)
    part_2 = simulate_moves(pp_file, part=2)

    # print answers
    print(f'Part 1 solution: \n\tBest position: {part_1[0]}\n\tFuel to spend: {part_1[1]}')
    print(f'Part 2 solution: \n\tBest position: {part_2[0]}\n\tFuel to spend: {part_2[1]}')


import pygame

class SudokuSquare:
    """A sudoku square class."""
    def __init__(self, number=None, offsetX=0, offsetY=0, edit="Y", xLoc=0, yLoc=0):
        if number != None:
            number = str(number)
        else:
            number = ""

        self.font = pygame.font.Font(None, 30)
        self.text = self.font.render(number, 1, (0, 0, 0))
        self.textpos = self.text.get_rect()
        self.textpos = self.textpos.move(offsetX + 12, offsetY + 6)

        self.collide = pygame.Surface((40, 40))
        self.collide = self.collide.convert()
        self.collide.fill((255, 255, 255, 255))
        self.collideRect = self.collide.get_rect()
        self.collideRect = self.collideRect.move(offsetX + 1, offsetY + 1)
        # The rect around the text is 11 x 28

        self.edit = edit
        self.xLoc = xLoc
        self.yLoc = yLoc

    def draw(self):
        screen = pygame.display.get_surface()
        screen.blit(self.collide, self.collideRect)
        screen.blit(self.text, self.textpos)

    def checkCollide(self, collision):
        if len(collision) == 2:
            return self.collideRect.collidepoint(collision)
        elif len(collision) == 4:
            return self.collideRect.colliderect(collision)
        else:
            return False

    def highlight(self):
        self.collide.fill((190, 190, 255))
        self.draw()

    def unhighlight(self):
        self.collide.fill((255, 255, 255, 255))
        self.draw()

    def highlight_wrong(self):
        self.collide.fill((255, 0, 0))
        self.draw()

    def change(self, number):
        if number != None:
            number = str(number)
        else:
            number = ""

        if self.edit == "Y":
            self.text = self.font.render(number, 1, (0, 0, 0))
            self.draw()
            return 0
        else:
            return 1

    def currentLoc(self):
        return self.xLoc, self.yLoc


import requests
from bs4 import BeautifulSoup
# 컨테이너 div.lst_thum_wrap li
# 저자   div.lst_thum_wrap li span.writer
# 제목   div.lst_thum_wrap li a strong
for i in range (1,5): #range도 함수 -> 괄호가 꼭 필요함
    print("<",(i-1)*20+1,"위~",i*20,"위>")  #순위를 나타내고 싶음 1~10위/ 11~20위 이런식으로
    raw = requests.get("https://series.naver.com/ebook/top100List.nhn?page=",str(i),
                       headers={"User-Agent":"Mozilla/5.0"})
    html = BeautifulSoup(raw.text, 'html.parser')
    container = html.select("div.lst_thum_wrap li")
    for j,cont in enumerate(container): #enumerate-> 앞에 따로 숫자 따로 인덱싱해줌
        print(str((i-1)*20+1+j),"위 서적") #여기서 i는 위에 i임 -> 페이지를 나타내기 위함/ j는 아래 for문에서 새로운 순서
        title = cont.select_one("div.lst_thum_wrap li a strong").text
        writer = cont.select_one("div.lst_thum_wrap li span.writer").text
        print("제목:",title)
        print("     ",writer)


from ast import Return
from asyncio import SendfileNotAvailableError
from socket import *
import time
import gestorPaquetes
import threading
import sender_server

class StopWait(threading.Thread,sender_server.Sender_Server):

    def __init__(self,receiver_ip,receiver_port,filename,filePath,logger):
        threading.Thread.__init__(self)
        self.sender_socekt = socket(AF_INET,SOCK_DGRAM)
        self.sender_socekt.setblocking(False)
        self.receiver_ip = receiver_ip
        self.receiver_port = receiver_port
        self.gestorPaquetes = gestorPaquetes.Gestor_Paquete()
        self.cola = []
        self.filename = filename
        self.hay_data = False
        self.Termino = False
        self.filePath = filePath
        self.MAX_TRIES = 3
        self.MAX_WAIT = 3
        self.MSJ_SIZE = 2000
        self.logger = logger
        self.conexion_activa = True

    def run(self):
        self.enviar_archivo(self.logger)

    def enviar(self,mensaje):
        pck = self.gestorPaquetes.crearPaquete(mensaje)
        pckBytes = self.gestorPaquetes.pasarPaqueteABytes(pck)
        try:
            self.sender_socekt.sendto(pckBytes ,(self.receiver_ip,self.receiver_port))
        except SendfileNotAvailableError:
            self.logger.error("✗ El archivo no esta disponible ")
        cantidad_intentos = 1
        paqueteRecibido = self.recibirPaquete()

        while(paqueteRecibido == None and cantidad_intentos <= self.MAX_TRIES):
            try:
                self.sender_socekt.sendto(pckBytes ,(self.receiver_ip,self.receiver_port))
            except SendfileNotAvailableError:
                self.logger.error("✗ El archivo no esta disponible ")
            paqueteRecibido = self.recibirPaquete()
            cantidad_intentos += 1
            if(paqueteRecibido != None):
                return (True,paqueteRecibido)

        if(cantidad_intentos > self.MAX_TRIES):
            self.Termino = True
            return (False,None)

        return (True,paqueteRecibido)

    def terminar_ejecucion(self, nuevo_estado):
        self.Termino = nuevo_estado

    def recibir_y_esperar(self, pckBytes):
        cantidad_intentos = 1
        paqueteRecibido = self.recibirPaquete()

        while(paqueteRecibido == None and cantidad_intentos <= self.MAX_TRIES):
            try:
                self.sender_socekt.sendto(pckBytes,(self.receiver_ip,self.receiver_port))
            except SendfileNotAvailableError:
                self.logger.error("✗ El archivo no esta disponible ")
            paqueteRecibido = self.recibirPaquete()
            if(paqueteRecibido != None):
                break
            cantidad_intentos += 1

        return paqueteRecibido, cantidad_intentos

    def enviarPaquetes(self, file):

        mensaje = file.read(self.MSJ_SIZE)
        while(len(mensaje) > 0):
            if(self.conexion_activa == False):
                return
            intentar_mandar,paquete_recibido = self.enviar(mensaje)

            if (intentar_mandar == False):
                self.Termino =  True
                return
            verificar_ack = self.gestorPaquetes.actualizarACK(paquete_recibido)
            intentar_mandar_ack = True
            if(verificar_ack == False): #EXTREMA SEGURIDAD --> ACK CORRUPTO
                cant_max_envios = 0
                while (cant_max_envios <= self.MAX_TRIES):
                    intentar_mandar_ack,paquete_recibido = self.enviar(mensaje)
                    cant_max_envios += 1
            if (intentar_mandar_ack == False):
                self.Termino =  True
                return
            mensaje = file.read(self.MSJ_SIZE)
        conexion_cerrada,pck_recibido = self.enviar_fin()
        if(conexion_cerrada == True):
            self.logger.info("Se ha cerrado la conexion con el protocolo StopAndWait con exito")
            self.Termino = True
        return


from flask_restplus import Namespace, Resource, fields
from core import db
from functools import wraps
from flask import request
from core import api_vars
import sys
from datetime import datetime
import json

api = Namespace('Public', description='The public side of the Lokaalbezetting API')

def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):

        token = None

        if 'X-API-KEY' in request.headers:
            token = request.headers['X-API-KEY']

        if not token:
            return {'status': 'failed', 'error': 'This endpoint requires an access token'}, 401

        database = db.Database()
        matchedTokens = database.readToken(token=token, namespace='public')
        database.close()
        if matchedTokens == False:
            return {'status': 'failed', 'error': 'Could not check if token exists in database'}
        else:
            if len(matchedTokens) == 0:
                return {'status': 'failed', 'error': 'Incorrect token'}, 401

        return f(*args, **kwargs)

    return decorated

@api.route('/classrooms')
class Classrooms(Resource):

    @api.doc(security=['Token'])
    @token_required
    @api.response(200, 'Success')
    @api.response(401, 'Unauthorized')
    def get(self):

        classrooms = []

        database = db.Database()
        classroomsQuery = database.query('''SELECT classcode FROM classrooms;''')
        database.close()

        if classroomsQuery == False:
            return {'status': 'failed', 'error': 'Could not get classrooms from database.'}

        if len(classroomsQuery) < 1:
            return {'status': 'failed', 'error': 'There are no classrooms.'}

        for classroom in classroomsQuery:
            classroomdict = dict()
            classroomdict['classcode'] = classroom[0]
            classrooms.append(classroomdict)

        return {'status': 'ok', 'classrooms': classrooms}

@api.route('/occupation/buildings')
class Buildings(Resource):

    @api.doc(security=['Token'])
    @token_required
    @api.response(200, 'Success')
    @api.response(401, 'Unauthorized')
    def get(self):

        totalObject = []

        database = db.Database()
        buildings = database.query('''SELECT * FROM buildings ORDER BY name;''')

        if buildings == False:
            return {'status': 'failed', 'error': 'Could not get buildings from database'}

        if len(buildings) < 1:
            return {'status': 'failed', 'error': 'There are no buildings.'}

        for building in buildings:
            buildingdict = dict()
            buildingdict['id'] = building[0]
            buildingdict['name'] = building[1]
            buildingdict['streetname'] = building[2]
            buildingdict['buildingnumber'] = building[3]
            buildingdict['floors'] = []
            totalObject.append(buildingdict)

        floors = database.query('''SELECT * FROM floors ORDER BY floornumber;''')

        if floors == False:
            return {'status': 'failed', 'error': 'Could not get floors from database'}

        for floor in floors:
            floordict = dict()
            floordict['id'] = floor[0]
            floordict['floornumber'] = int(floor[1])
            floordict['classrooms'] = []

            for building in totalObject:
                if building['id'] == floor[2]:
                    building['floors'].append(floordict)

        classrooms = database.query('''SELECT * FROM classrooms;''')

        if classrooms == False:
            return {'status': 'failed', 'error': 'Could not get classrooms from database'}

        for classroom in classrooms:
            classroomdict = dict()
            classroomdict['classcode'] = classroom[0]

            free = "Unknown"

            try:
                freeQuery = database.query('''select count(*) from occupation WHERE classcode = '{}' AND time > now() - interval '60 seconds';'''.format(classroomdict['classcode']))

                if freeQuery[0][0] >= int(api_vars.MOTION_THRESHOLD):
                    free = False
                elif freeQuery[0][0] < int(api_vars.MOTION_THRESHOLD):
                    free = True
            except:
                free = "Unknown"

            classroomdict['free'] = free

            for buildings in totalObject:
                for floor in buildings['floors']:
                    if floor['id'] == classroom[1]:
                        floor['classrooms'].append(classroomdict)

        database.close()

        return {'status': 'ok', 'buildings': totalObject}

@api.route('/occupation/building/<string:building_id>')
class Building(Resource):

    @api.doc(security=['Token'])
    @token_required
    @api.response(200, 'Success')
    @api.response(401, 'Unauthorized')

    def get(self, building_id):

        totalObject = []

        database = db.Database()
        buildings = database.query('''SELECT * FROM buildings WHERE id = '{}' ORDER BY name;'''.format(building_id))

        if buildings == False:
            return {'status': 'failed', 'error': '{} is not a valid UUID.'.format(building_id)}

        if len(buildings) < 1:
            return {'status': 'failed', 'error': 'Building with id {} does not exist.'.format(building_id)}

        for building in buildings:
            buildingdict = dict()
            buildingdict['id'] = building[0]
            buildingdict['name'] = building[1]
            buildingdict['streetname'] = building[2]
            buildingdict['buildingnumber'] = building[3]
            buildingdict['floors'] = []
            totalObject.append(buildingdict)

        floors = database.query('''SELECT * FROM floors ORDER BY floornumber;''')

        if floors == False:
            return {'status': 'failed', 'error': 'Could not get floors from database'}

        for floor in floors:
            floordict = dict()
            floordict['id'] = floor[0]
            floordict['floornumber'] = int(floor[1])
            floordict['classrooms'] = []

            for building in totalObject:
                if building['id'] == floor[2]:
                    building['floors'].append(floordict)

        classrooms = database.query('''SELECT * FROM classrooms;''')

        if classrooms == False:
            return {'status': 'failed', 'error': 'Could not get classrooms from database'}

        for classroom in classrooms:
            classroomdict = dict()
            classroomdict['classcode'] = classroom[0]

            free = "Unknown"

            try:
                freeQuery = database.query('''select count(*) from occupation WHERE classcode = '{}' AND time > now() - interval '60 seconds';'''.format(classroomdict['classcode']))
                if freeQuery[0][0] >= int(api_vars.MOTION_THRESHOLD):
                    free = False
                elif freeQuery[0][0] < int(api_vars.MOTION_THRESHOLD):
                    free = True
            except:
                free = "Unknown"

            classroomdict['free'] = free

            for buildings in totalObject:
                for floor in buildings['floors']:
                    if floor['id'] == classroom[1]:
                        floor['classrooms'].append(classroomdict)

        building = totalObject[0]

        database.close()

        return {'status': 'ok', 'id': building['id'], 'name': building['name'], 'streetname': building['streetname'], 'buildingnumber': building['buildingnumber'], 'floors': building['floors']}

@api.route('/occupation/floor/<string:floor_id>')
class Floor(Resource):

    @api.doc(security=['Token'])
    @token_required
    @api.response(200, 'Success')
    @api.response(401, 'Unauthorized')

    def get(self, floor_id):

        database = db.Database()

        floors = database.query('''SELECT * FROM floors WHERE id = '{}';'''.format(floor_id))

        if floors == False:
            return {'status': 'failed', 'error': 'Could not get floors from database'}

        if len(floors) < 1:
            return {'status': 'failed', 'error': 'Floor with id {} does not exist'.format(floor_id)}

        floor_id = floors[0][0]
        floor_number = int(floors[0][1])
        classrooms_object = []

        classrooms = database.query('''SELECT * FROM classrooms WHERE id_floors = '{}';'''.format(floor_id))

        if classrooms == False:
            return {'status': 'failed', 'error': 'Could not get classrooms from database'}

        if len(classrooms) < 1:
            return {'status': 'failed', 'error': 'Floor with id {} has no classrooms'.format(floor_id)}

        for classroom in classrooms:
            classroomdict = dict()
            classroomdict['classcode'] = classroom[0]

            free = "Unknown"

            try:
                freeQuery = database.query('''select count(*) from occupation WHERE classcode = '{}' AND time > now() - interval '60 seconds';'''.format(classroomdict['classcode']))
                if freeQuery[0][0] >= int(api_vars.MOTION_THRESHOLD):
                    free = False
                elif freeQuery[0][0] < int(api_vars.MOTION_THRESHOLD):
                    free = True
            except:
                free = "Unknown"

            classroomdict['free'] = free

            classrooms_object.append(classroomdict)

        database.close()

        return {'status': 'ok', 'id': floor_id, 'classrooms': classrooms_object}

@api.route('/occupation/classroom/<string:classcode>')
class Classroom(Resource):

    @api.doc(security=['Token'])
    @token_required
    @api.response(200, 'Success')
    @api.response(401, 'Unauthorized')

    def get(self, classcode):

        database = db.Database()

        classrooms = database.query('''SELECT * FROM classrooms WHERE classcode = '{}';'''.format(classcode))

        if classrooms == False:
            return {'status': 'failed', 'error': 'Could not get classrooms from database'}

        if len(classrooms) < 1:
            return {'status': 'failed', 'error': 'Classroom with classcode {} does not exist'.format(classcode)}

        classcode = classrooms[0][0]

        free = "Unknown"

        try:
            freeQuery = database.query('''select count(*) from occupation WHERE classcode = '{}' AND time > now() - interval '60 seconds';'''.format(classcode))
            if freeQuery[0][0] >= int(api_vars.MOTION_THRESHOLD):
                free = False
            elif freeQuery[0][0] < int(api_vars.MOTION_THRESHOLD):
                free = True
        except:
            free = "Unknown"

        database.close()

        return {'status': 'ok', 'classcode': classcode, 'free': free}

@api.route('/floorplan/<string:floor_id>')
class Floorplan(Resource):

    @api.doc(security=['Token'])
    @token_required
    @api.response(200, 'Success')
    @api.response(401, 'Unauthorized')

    def get(self, floor_id):

        database = db.Database()

        try:
            result = database.query('''SELECT * FROM floorplans WHERE id_floors = '{}';'''.format(floor_id))
            if len(result) < 1:
                return {'status': 'failed', 'error': 'There is no floorplan for floor with UUID {}.'.format(floor_id)}
        except:
            return {'status': 'failed', 'error': 'Floor with UUID {} does not exist'.format(floor_id)}

        database.close()

        return {'status': 'ok', 'floorplan': str(result[0][0])}

@api.route('/export')
class Export(Resource):

    @api.doc(security=['Token'])
    @token_required
    @api.response(200, 'Success')
    @api.response(401, 'Unauthorized')

    def get(self):

        database = db.Database()
        classrooms = dict()

        result = database.query('''SELECT DISTINCT(classcode) FROM occupation;''')
        if len(result) < 1:
            return {'status': 'failed', 'error': 'There is no occupation data.'}

        for classroom in result:
            classrooms[classroom[0]] = []

        for classroom in classrooms.keys():
            detections = database.query('''SELECT time FROM occupation WHERE classcode = '{}';'''.format(classroom))
            detections_formatted = []
            for detection in detections:
                detections_formatted.append(detection[0].strftime("%x %X"))

            classrooms[classroom] = detections_formatted

        database.close()

        return {'status': 'ok', 'export': classrooms}


"""
This is the main entry point to our Python application from PythonSkill.cpp,
where 'robot' is defined so 'import robot' does not fail with ImportError.

The `import robot` bridge from C++ to Python is defined by various Python
wrappers, run once at import time. Please see the `tick` function below for a
bridge from C++ to Python and back to C++ which is run many times at run time.

For example, for the implementation of `robot.TOP_IMAGE_ROWS`,
see the file `VisionDefinitions_wrap.cpp` in the following directory:
@see
https://github.com/UNSWComputing/rUNSWift/tree/master/robot/perception/behaviour/python/wrappers

For info, the following contains the C++ definition of `TOP_IMAGE_ROWS`:
@see
https://github.com/UNSWComputing/rUNSWift/blob/master/robot/perception/vision/VisionDefinitions.hpp
"""
import Simulation  # noqa

from pkgutil import iter_modules
from traceback import format_exc
from importlib import import_module
from os import getenv
from os.path import join
from util import Log
from robot import BehaviourRequest, All
from util.world import World
from util.Global import update_global
from util.TeamStatus import update_team_status
from util.FieldGeometry import update_field_geometry
from util.Timer import update_timer
from util.Sonar import update_sonar
from util.GameStatus import update_game_status
from util.NetworkEar import update_network_ear, get_ear_colour
from util.RemoteStiffener import update_remote_stiffener, get_stiffen_command
from util.ObstacleAvoidance import update_obstacle_avoidance
from util.LedOverride import override_request, reset_led_override
from util.Constants import LEDColour

skill_instance = None
headskill_instance = None

def catch_all(tick):
    def catcher(blackboard):
        try:
            return tick(blackboard)
        except Exception:
            Log.error("Behaviour exception:", exc_info=True)
            raise

    return catcher

def skill_instance_factory(blackboard, skill, behaviour_packages):
    # Load the module and the class we're going to use.
    found_skill = False
    SkillClass = None
    behaviour_root = getenv("BEHAVIOUR_ROOT", "/home/nao/data/behaviours")
    for package in behaviour_packages:
        look_in = join(behaviour_root, "/".join(package))
        seen_modules = [name for _, name, _ in iter_modules([look_in])]
        if skill not in seen_modules:
            Log.info("%s.py was not in %s, skipping import attempt.", skill, look_in)
            continue
        skill_path = "%s.%s" % (".".join(package), skill)
        try:
            skill_module = import_module(skill_path)
            # Access the class so we can do some reflection.
            SkillClass = getattr(skill_module, skill)
            found_skill = True
            Log.info("Successfully imported %s from %s", skill, skill_path)
            break
        except ImportError as e:
            Log.error("%s %s", package, e)
            Log.error(format_exc())

    if not found_skill:
        raise ImportError("Skill: %s not found in behaviour packages %s" % (skill, behaviour_packages))

    new_world = World(blackboard)  # It's a whole new world.
    _skill_instance = SkillClass(world=new_world)

    return _skill_instance

@catch_all
def tick(blackboard):
    """
    This is the main entry point from C++ into our Python behaviours and back.

    More specifically it is the bridge from which C++ calls Python inside
    the runswift executable, and receives a BehaviourRequest back.

    Currently called in `robot/perception/behaviour/python/PythonSkill.cpp`,
    the `PythonSkill::execute()` C++ function, and explicitly the line
    `behaviour_tick(bb)`.

    :param blackboard: The runswift Blackboard, a bunch of things
        stored in global memory.
    :return: A `robot.BehaviourRequest()` instance, defined in C++ inside
        `robot/types/BehaviourRequest.hpp`.
    """
    # Update all blackboard dependent helper modules.
    update_timer(blackboard)
    update_global(blackboard)
    update_team_status(blackboard)
    update_field_geometry(blackboard)
    update_sonar(blackboard)
    update_network_ear(blackboard)
    update_remote_stiffener(blackboard)
    update_game_status(blackboard)
    update_obstacle_avoidance(blackboard)

    reset_led_override()

    global skill_instance
    if not skill_instance:
        behaviour_packages = [["body", "roles"], ["body", "skills"], ["body", "test"]]
        skill_name = blackboard.behaviour.skill
        skill_instance = skill_instance_factory(blackboard, skill_name, behaviour_packages)

    global headskill_instance
    if not headskill_instance:
        head_packages = [["head"]]
        headskill_name = blackboard.behaviour.headskill
        headskill_instance = skill_instance_factory(blackboard, headskill_name, head_packages)

    # On every tick of the perception thread, we update the blackboard,
    # tick the skill, and then return the resulting behaviour request.
    skill_instance.world.update(blackboard)
    skill_instance.world.b_request = BehaviourRequest()
    skill_instance.world.b_request.actions = All()
    skill_instance.tick()
    request = skill_instance.world.b_request

    headskill_instance.world.update(blackboard)
    headskill_instance.world.b_request = request
    headskill_instance.tick()
    request = headskill_instance.world.b_request

    # LED colouring for ball detection
    if len(blackboard.vision.balls) > 0:
        request.actions.leds.rightEye = LEDColour.red
    else:
        request.actions.leds.rightEye = LEDColour.off

    # Override leds as requested by skills
    override_request(request)

    # Get right ear colour depending on network activity
    request.actions.leds.rightEar = get_ear_colour()

    # Remotely stiffen
    request.actions.stiffen = get_stiffen_command()

    # Obtain behaviour hierarchies of current skill
    request.behaviourDebugInfo.bodyBehaviourHierarchy = skill_instance.world.behaviour_hierarchy
    skill_instance.world.behaviour_hierarchy = ""
    request.behaviourDebugInfo.headBehaviourHierarchy = headskill_instance.world.behaviour_hierarchy
    headskill_instance.world.behaviour_hierarchy = ""

    return request


import unittest
import trio
import os
import subprocess

from minio import Minio
from util.test_base import ApolloTest
from util import skvbc as kvbc
from util import eliot_logging as log
from util.object_store import ObjectStore, start_replica_cmd_prefix
from util.bft import KEY_FILE_PREFIX, with_trio, with_bft_network

def start_replica_cmd(builddir, replica_id, config):
    """
    There are two test s3 config files. The one used here hasn't got s3-prefix parameter
    set its value will be an empty string.
    The effect of this is that on each RO replica start we have got empty S3 storage.
    This is the default behaviour for most of the tests.
    """
    return start_replica_cmd_prefix(builddir, replica_id, config)

class SkvbcS3IntegrityCheckTest(ApolloTest):
    """
    Integrity Check has got two modes of operation:
        - validate all
        - validate key
    """

    @classmethod
    def setUpClass(cls):
        cls.object_store = ObjectStore()

    @classmethod
    def tearDownClass(cls):
        pass

    @with_trio
    @unittest.skip("unstable scenario")
    @with_bft_network(start_replica_cmd=start_replica_cmd_prefix, num_ro_replicas=1, selected_configs=lambda n, f, c: n == 7)
    async def test_integrity_check_validate_all(self, bft_network):
        """
        Start all replicas including ROR
        Generate a checkpoint
        start integrity
        check that integrity was verified
        This test is executed only in S3 mode.
        """
        bft_network.start_all_replicas()
        ro_replica_id = bft_network.config.n

        bft_network.start_replica(ro_replica_id)
        skvbc = kvbc.SimpleKVBCProtocol(bft_network)

        await skvbc.fill_and_wait_for_checkpoint(
            initial_nodes=bft_network.all_replicas(),
            num_of_checkpoints_to_add=1,
            verify_checkpoint_persistency=False,
            assert_state_transfer_not_started=False
        )

        await self._wait_for_st(bft_network, ro_replica_id)

        keys_config = f"{KEY_FILE_PREFIX}{ro_replica_id}"
        s3_config = "test_s3_config_prefix.txt"
        self._start_integrity_check(bft_network, keys_config, s3_config)

    @with_trio
    @unittest.skip("unstable scenario")
    @with_bft_network(start_replica_cmd=start_replica_cmd_prefix, num_ro_replicas=1, selected_configs=lambda n, f, c: n == 7)
    async def test_integrity_check_validate_all_with_missing_block(self, bft_network):
        """
        Start all replicas including ROR
        Generate a checkpoint
        start integrity
        delete block
        verify that integrity check failed
        This test is executed only in S3 mode.
        """
        bft_network.start_all_replicas()
        ro_replica_id = bft_network.config.n

        bft_network.start_replica(ro_replica_id)
        skvbc = kvbc.SimpleKVBCProtocol(bft_network)

        await skvbc.fill_and_wait_for_checkpoint(
            initial_nodes=bft_network.all_replicas(),
            num_of_checkpoints_to_add=1,
            verify_checkpoint_persistency=False,
            assert_state_transfer_not_started=False
        )

        await self._wait_for_st(bft_network, ro_replica_id)
        self._delete_block()
        keys_config = f"{KEY_FILE_PREFIX}{ro_replica_id}"
        s3_config = "test_s3_config_prefix.txt"
        try:
            self._start_integrity_check(bft_network, keys_config, s3_config)
            assert False
        except AssertionError as e:
            pass

    def _start_integrity_check(self, bft_network, keys_file, s3_config_file, key_to_validate=None):
        """
        Start integrity check
        """
        with log.start_action(action_type="start_integrity_check"):
            stdout_file = None
            stderr_file = None

            if os.environ.get('KEEP_APOLLO_LOGS', "").lower() in ["true", "on"]:
                test_name = os.environ.get('TEST_NAME')

                if not test_name:
                    now = datetime.now().strftime("%y-%m-%d_%H:%M:%S")
                    test_name = f"{now}_{bft_network.current_test}"

                test_dir = f"{bft_network.builddir}/tests/apollo/logs/{test_name}/{bft_network.current_test}/"
                test_log = f"{test_dir}stdout_integrity_check.log"
                log.log_message(message_type=f"test log is: {test_log}")
                os.makedirs(test_dir, exist_ok=True)

                stdout_file = open(test_log, 'w+')
                stderr_file = open(test_log, 'w+')

                stdout_file.write("############################################\n")
                stdout_file.flush()
                stderr_file.write("############################################\n")
                stderr_file.flush()

                s3_config_path = os.path.join(bft_network.builddir, s3_config_file)
                integrity_check_fds = (stdout_file, stderr_file)
                integrity_check_exe = os.path.join(bft_network.builddir, "kvbc", "tools", "object_store_utility", "object_store_utility")
                integrity_check_cmd = [integrity_check_exe,
                                       "--keys-file", keys_file,
                                       "--s3-config-file", s3_config_path]
                integrity_check_cmd.append("validate")
                if key_to_validate is not None:
                    integrity_check_cmd.append("--key")
                    integrity_check_cmd.append(key_to_validate)
                else:
                    integrity_check_cmd.append("--all")
                log.log_message(message_type="starting the subprocess")
                integrity_check_pid = subprocess.Popen(
                    integrity_check_cmd,
                    stdout=stdout_file,
                    stderr=stderr_file,
                    close_fds=True)
                try:
                    exit_code = integrity_check_pid.wait()
                    assert exit_code == 0
                except Exception as e:
                    assert False
                finally:
                    for fd in integrity_check_fds:
                        fd.close()

    def _delete_block(self):
        client = Minio("127.0.0.1:9000", access_key="concordbft", secret_key="concordbft", secure=False)
        buckets = client.list_buckets()
        bucketName = buckets[0].name
        try:
            client.remove_object(bucketName, 'concord/blocks/1')
        except ResponseError as err:
            assert False

    async def _wait_for_st(self, bft_network, ro_replica_id, seqnum_threshold=150):
        with trio.fail_after(seconds=70):
            # the ro replica should be able to survive these failures
            while True:
                with trio.move_on_after(seconds=.5):
                    try:
                        key = ['replica', 'Gauges', 'lastExecutedSeqNum']
                        lastExecutedSeqNum = await bft_network.metrics.get(ro_replica_id, *key)
                    except KeyError:
                        continue
                    else:
                        # success!
                        if lastExecutedSeqNum >= seqnum_threshold:
                            log.log_message(message_type="Replica" + str(ro_replica_id) + " : lastExecutedSeqNum:" + str(lastExecutedSeqNum))
                            break


from django.shortcuts import render
import requests

def Home(request):
    """ Api From Weatherbit.io """

    key = 'Your Api'
    url = 'https://api.weatherbit.io/v2.0/current?lat={}&lon={}&key={}'

    if request.method == "POST":
        latitude = request.POST['latitude']
        longitude = request.POST['longitude']

        try:
            result = requests.get(url.format(latitude,longitude,key)).json()

        except:
            print('try again')

        context ={
            "latitude": latitude,
            "longitude": longitude,
            'temp':result['data'][0]['temp']

        }
    else:
        context = {}
    return render(request,'index.html',context)


import jwt
from functools import wraps

## Validation layer check incoming requests to see if they are valid before handling with the rest controller layer.

def auth_token_required(f): #Wrapping function to check and decode JWT token
	@wraps(f)
	def decorated_function(*args, **kwargs):
		try:
			if not request.headers.get("JWT-Auth"): #Check for token
				response = json_message("Missing auth token")
				return Response(response=response, status=401, mimetype='application/json')
			else:
				token = request.headers.get("JWT-Auth")
				str_token = str(token)
				payload = jwt.decode(str_token, signkey, algorithms=['HS512']) #Decoding token
				uuid = payload['uuid']

				return f(*args, **kwargs) #Returning function

		except jwt.DecodeError: #If JWT token doesnt decode ie isnt created with same secret
			response = json_message("Token is invalid")
			return Response(response=response, status=401, mimetype='application/json')

		except jwt.ExpiredSignature: #If JWT token has expired
			response = json_message("Token has expired, please sign in again")
			return Response(response=response, status=401, mimetype='application/json')

		return f(*args, **kwargs)
	return decorated_function

def json_included_authtoken(f):
	@wraps(f)
	def decorated_function(*args, **kwargs):
		data = request.get_json()
		if data:
			try:
				data['username']
				data['password']

				if len(username) > 20:
					response = json_message("Username is too long")
					return Response(response=response, status=400, mimetype='application/json')

				return f(*args, **kwargs)
			except KeyError:
				response = json_message("You are missing some JSON fields")
				return Response(response=response, status=400, mimetype='application/json')

		else:
			response = json_message("You are missing JSON")
			return Response(response=response, status=400, mimetype='application/json')

		return f(*args, **kwargs)
	return decorated_function

def json_included_user(f):
	@wraps(f)
	def decorated_function(*args, **kwargs):
		return f(*args, **kwargs)

	return decorated_function


import sys
import time
import os
import tkinter as tk
from tkinter import messagebox
import numpy as np
import h5py
import pandas as pd
import matplotlib
matplotlib.use("TkAgg")
from tkinter.filedialog import askopenfilename
from matplotlib.widgets import RectangleSelector
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from h5_menu_options import H5MenuOptions
from graph_window import GraphWindow

class ControlPanel(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.root = parent
        self.root.title("Set Up")
        self.show_graph_button = tk.Button(self, text='Show Graph',
                                           command=self.show_graph)
        self.show_graph_button.grid(row=0)
        self.add_data_button = tk.Button(self, text='Add Data Set', command=self.add_data_set)
        self.remove_data_button = tk.Button(self, text='Remove Data Set', command=self.remove_data_set)
        self.add_data_button.grid(row=0, column=1)
        self.remove_data_button.grid(row=0, column=2)
        self.data_sets = []
        self.data_row = 1

    def show_graph(self):
        if self.data_sets:
            summary_data = pd.DataFrame()
            raw_data = []
            for menu_option in self.data_sets:
                if os.path.exists(menu_option.h5_directory):
                    h5_file = h5py.File(menu_option.h5_directory, 'r')
                    new_summary = pd.read_hdf(menu_option.h5_directory, key='summary')
                    if isinstance(new_summary['channel'][0], str):
                        new_summary['channel'] = new_summary['channel'].map(lambda s: int(s[8:]))
                    summary_data = summary_data.append(new_summary)
                    raw_group = h5_file['raw']
                    new_raw_data = [raw_group[str(i)][()] for i in range(len(raw_group.keys()))]
                    raw_data.extend(new_raw_data)
                else:
                    messagebox.showinfo("No File Found",
                            "Could not find data files\n    given summary: "
                            + menu_option.summary_directory +
                            "\n    given raw: " + menu_option.raw_directory)
                    return
            summary_data = summary_data.reset_index(drop=True)
            GraphWindow(self, summary_data, np.asarray(raw_data))

    def add_data_set(self):
        new_menu_option = H5MenuOptions(self)
        new_menu_option.grid(row=self.data_row, columnspan=3)
        self.data_row += 1
        self.data_sets.append(new_menu_option)

    def remove_data_set(self):
        if self.data_sets:
            old_menu_option = self.data_sets.pop()
            old_menu_option.grid_forget()
            old_menu_option.destroy()
            self.data_row -= 1