import itertools
import datetime
import operator
from django import test
from django.utils import translation, formats
from factories.indicators_models import RFIndicatorFactory
from factories.workflow_models import RFProgramFactory, SiteProfileFactory
from indicators.models import Indicator
from tola.test.utils import lang_context
from workflow.serializers_new import (
    ProgramPageProgramSerializer,
    ProgramPageIndicatorUpdateSerializer,
)

PROGRAM_PAGE_QUERIES = 7
PROGRAM_PAGE_UPDATE_QUERIES = PROGRAM_PAGE_QUERIES + 1

ENGLISH = 1
FRENCH = 2
SPANISH = 3

BY_TIER_CHAIN = {
    ENGLISH: 'by {} chain',
    FRENCH: 'par chaîne {}',
    SPANISH: 'por cadena de {}'
}
GOAL = {
    ENGLISH: 'Goal',
    FRENCH: 'But',
    SPANISH: 'Objetivo'
}
OUTCOME = {
    ENGLISH: 'Outcome',
    FRENCH: 'Résultat',
    SPANISH: 'Resultado'
}
OUTPUT = {
    ENGLISH: 'Output',
    FRENCH: 'Extrant',
    SPANISH: 'Salida'
}
ACTIVITY = {
    ENGLISH: 'Activity',
    FRENCH: 'Activité',
    SPANISH: 'Actividad'
}

class TestProgramPageProgramSerializer(test.TestCase):
    def get_serialized_data(self, program_pk, query_count=False):
        if not query_count:
            return ProgramPageProgramSerializer.load_for_pk(program_pk).data
        with self.assertNumQueries(PROGRAM_PAGE_QUERIES):
            return ProgramPageProgramSerializer.load_for_pk(program_pk).data

    def get_program_data(self, **kwargs):
        query_count = kwargs.pop('query_count', False)
        program = RFProgramFactory(**kwargs)
        return self.get_serialized_data(program.pk, query_count=query_count)

    def test_needs_additional_target_periods_false(self):
        p = RFProgramFactory()
        RFIndicatorFactory(program=p, target_frequency=Indicator.TRI_ANNUAL, targets=500)
        data = self.get_serialized_data(p.pk)
        self.assertFalse(data['needs_additional_target_periods'])

    def test_needs_additional_target_periods_true(self):
        p = RFProgramFactory()
        i = RFIndicatorFactory(program=p, target_frequency=Indicator.TRI_ANNUAL, targets=500)
        i.periodictargets.last().delete()
        data = self.get_serialized_data(p.pk)
        self.assertTrue(data['needs_additional_target_periods'])

    def test_needs_additional_target_periods_no_indicators(self):
        data = self.get_program_data()
        self.assertFalse(data['needs_additional_target_periods'])

    def test_needs_additional_target_periods_no_targets(self):
        p = RFProgramFactory()
        i = RFIndicatorFactory(program=p, target_frequency=Indicator.ANNUAL)
        i.periodictargets.all().delete()
        data = self.get_serialized_data(p.pk)
        self.assertFalse(data['needs_additional_target_periods'])

    def test_needs_additional_target_periods_no_target_frequency(self):
        p = RFProgramFactory()
        RFIndicatorFactory(program=p, target_frequency=None)
        data = self.get_serialized_data(p.pk)
        self.assertFalse(data['needs_additional_target_periods'])

    def test_needs_additional_target_periods_no_reporting_period_end(self):
        p = RFProgramFactory()
        RFIndicatorFactory(program=p, target_frequency=Indicator.TRI_ANNUAL, targets=1000)
        p.reporting_period_end = None
        p.save()
        data = self.get_serialized_data(p.pk)
        self.assertFalse(data['needs_additional_target_periods'])

    def test_site_count_zero(self):
        data = self.get_program_data()
        self.assertEqual(data['site_count'], 0)

    def test_site_count_non_zero(self):
        p = RFProgramFactory()
        i = RFIndicatorFactory(
            program=p, target_frequency=Indicator.LOP, targets=1000,
            results=800, results__count=10
        )
        for result in i.result_set.all():
            result.site.add(
                SiteProfileFactory()
            )
        i2 = RFIndicatorFactory(
            program=p, target_frequency=Indicator.ANNUAL, targets=50,
            results=80, results__count=3
        )
        for result in i2.result_set.all():
            result.site.add(
                SiteProfileFactory()
            )
        data = self.get_serialized_data(p.pk)
        self.assertEqual(data['site_count'], 13)

    def test_level_count_zero(self):
        data = self.get_program_data()
        self.assertFalse(data['has_levels'])

    def test_level_count_nonzero(self):
        data = self.get_program_data(tiers=['Tier1', 'Tier2'], levels=2)
        self.assertTrue(data['has_levels'])

    def test_time_period_info_non_time_aware(self):
        p = RFProgramFactory()
        for frequency in [Indicator.LOP, Indicator.MID_END]:
            RFIndicatorFactory(
                program=p, target_frequency=frequency, targets=100
            )
        data = self.get_serialized_data(p.pk, query_count=True)
        tp_data = data['target_period_info']
        self.assertTrue(tp_data['lop'])
        self.assertTrue(tp_data['midend'])
        self.assertFalse(tp_data['event'])
        self.assertFalse(tp_data['time_targets'])
        self.assertFalse(tp_data['annual'])
        self.assertFalse(tp_data['semi_annual'])
        self.assertFalse(tp_data['tri_annual'])
        self.assertFalse(tp_data['quarterly'])
        self.assertFalse(tp_data['monthly'])

    def test_time_period_info_time_aware(self):
        p = RFProgramFactory(
            reporting_period_start=datetime.date(2016, 1, 1),
            reporting_period_end=datetime.date(2024, 12, 31)
        )
        for frequency in Indicator.REGULAR_TARGET_FREQUENCIES:
            RFIndicatorFactory(
                program=p, target_frequency=frequency, targets=500,
            )
        data = self.get_serialized_data(p.pk)
        today = datetime.date.today()
        annual = datetime.date(today.year, 1, 1)-datetime.timedelta(days=1)
        semi_annual = datetime.date(
            today.year,
            7 if today.month > 6 else 1,
            1
        ) - datetime.timedelta(days=1)
        tri_annual = datetime.date(
            today.year,
            (today.month-1) // 4 * 4 + 1,
            1
        ) - datetime.timedelta(days=1)
        quarterly = datetime.date(
            today.year,
            (today.month-1) // 3 * 3 + 1,
            1
        ) - datetime.timedelta(days=1)
        monthly = datetime.date(
            today.year,
            today.month,
            1
        ) - datetime.timedelta(days=1)
        tp_data = data['target_period_info']
        date_format = lambda date_obj: formats.date_format(date_obj, "MEDIUM_DATE_FORMAT")
        self.assertFalse(tp_data['lop'])
        self.assertFalse(tp_data['midend'])
        self.assertFalse(tp_data['event'])
        self.assertTrue(tp_data['time_targets'])
        self.assertEqual(tp_data['annual'], date_format(annual))
        self.assertEqual(tp_data['semi_annual'], date_format(semi_annual))
        self.assertEqual(tp_data['tri_annual'], date_format(tri_annual))
        self.assertEqual(tp_data['quarterly'], date_format(quarterly))
        self.assertEqual(tp_data['monthly'], date_format(monthly))

class TestProgramPageSerializersFunctional(test.TestCase):
    def get_serialized_data(self, program_pk):
        return ProgramPageProgramSerializer.load_for_pk(program_pk).data

    def get_ordering_update_serialized_data(self, program_pk):
        return ProgramPageIndicatorUpdateSerializer.load_for_pk(program_pk).data

    def get_update_indicator_data(self, program_pk, indicator_pk):
        return ProgramPageIndicatorUpdateSerializer.load_for_indicator_and_program(indicator_pk, program_pk).data

    def test_rf_program_two_indicators(self):
        p = RFProgramFactory(
            tiers=['Tier1', 'Tier2'], levels=1,
            reporting_period_start=datetime.date(2014, 5, 1)
        )
        for level in p.levels.all():
            RFIndicatorFactory(program=p, level=level)
        data = self.get_serialized_data(p.pk)
        self.assertEqual(data['pk'], p.pk)
        self.assertEqual(data['name'], p.name)
        self.assertTrue(data['results_framework'])
        self.assertEqual(data['by_result_chain'], 'by Tier2 chain')
        self.assertEqual(data['reporting_period_start_iso'], '2014-05-01')
        self.assertEqual(data['site_count'], 0)
        self.assertTrue(data['has_levels'])
        self.assertEqual(data['indicator_pks_level_order'], data['indicator_pks_chain_order'])
        indicator_pks = data['indicator_pks_level_order']
        self.assertEqual(len(indicator_pks), 2)
        indicators_data = data['indicators']
        self.assertEqual(len(indicators_data), 2)
        goal_indicator_data = indicators_data[indicator_pks[0]]
        self.assertEqual(goal_indicator_data['number'], 'Tier1 a')
        output_indicator_data = indicators_data[indicator_pks[1]]
        self.assertEqual(output_indicator_data['number'], 'Tier2 1a')

    def test_unmigrated_program(self):
        p = RFProgramFactory(migrated=False)
        pks = []
        old_levels_numbers = [
            ('Activity', '5'),
            ('Activity', '3'),
            ('Outcome', '3.4'),
            ('Outcome', '2.8'),
            ('Outcome', '2.2')
        ]
        for old_level, number in old_levels_numbers:
            pks.append(
                RFIndicatorFactory(
                    program=p, old_level=old_level, number=number,
                    target_frequency=Indicator.SEMI_ANNUAL, targets=400, results=550
                ).pk
            )
        expected_pks = list(reversed(pks))
        data = self.get_serialized_data(p.pk)
        self.assertFalse(data['has_levels'])
        self.assertEqual(data['indicator_pks_level_order'], data['indicator_pks_chain_order'])
        indicator_pks = data['indicator_pks_level_order']
        self.assertEqual(expected_pks, indicator_pks)
        for (old_level, number), pk in zip(old_levels_numbers, pks):
            indicator_data = data['indicators'][pk]
            self.assertEqual(indicator_data['number'], u'{} {}'.format(old_level, number))
            self.assertEqual(indicator_data['old_level_name'], old_level)
            self.assertTrue(indicator_data['is_reporting'])
            self.assertEqual(indicator_data['over_under'], 1)
        self.assertEqual(data['indicators'][pks[0]]['level_pk'], 6)
        self.assertEqual(data['indicators'][pks[3]]['level_pk'], 3)
        with lang_context('fr'):
            french_data = self.get_serialized_data(p.pk)
        self.assertEqual(french_data['indicators'][pks[0]]['old_level_name'], ACTIVITY[FRENCH])
        self.assertEqual(french_data['indicators'][pks[4]]['old_level_name'], OUTCOME[FRENCH])

    def test_rf_program_many_indicators(self):
        p = RFProgramFactory(months=20, tiers=['Goal', 'Outcome', 'Output', 'Activity'], levels=3)
        p.levels.filter(parent__isnull=True, customsort__gt=1).delete()
        goal_level = p.levels.filter(parent__isnull=True).first()
        goal_pk_a = RFIndicatorFactory(
            program=p, level=goal_level,
            target_frequency=Indicator.LOP, targets=300, results=310
        ).pk
        goal_pk_b = RFIndicatorFactory(
            program=p, level=goal_level,
            target_frequency=Indicator.ANNUAL, targets=10, results=40,
            baseline="100", baseline_na=True
        ).pk
        pks = []
        pks.append(RFIndicatorFactory(program=p, level=None, number='A1').pk)
        pks.append(RFIndicatorFactory(program=p, level=None, old_level='Outcome', number='X21').pk)
        pks.append(RFIndicatorFactory(program=p, level=None, old_level='Outcome', number='C14').pk)
        pks.append(RFIndicatorFactory(program=p, level=None, old_level='Goal').pk)
        unassigned_pks = pks[::-1]
        all_levels = list(p.levels.all())
        levels_in_order = []
        parents = sorted([l for l in all_levels if l.parent is None], key=operator.attrgetter('customsort'))
        while parents:
            for parent in parents:
                children = sorted([l for l in all_levels if l.parent == parent], key=operator.attrgetter('customsort'))
                levels_in_order += children
                parents = children
        for level in list(reversed(levels_in_order)):
            pks.append(RFIndicatorFactory(program=p, level=level).pk)
        expected_pks = [goal_pk_a, goal_pk_b] + list(reversed(pks))
        data = self.get_serialized_data(p.pk)
        self.assertEqual(data['by_result_chain'], 'by Outcome chain')
        indicator_pks = data['indicator_pks_level_order']
        self.assertEqual(indicator_pks, expected_pks)
        chain_pks = [indicator.pk for indicator in goal_level.indicator_set.order_by('level_order')]
        for level in goal_level.get_children():
            chain_pks += [indicator.pk for indicator in level.indicator_set.order_by('level_order')]
        chain_pks += unassigned_pks
        self.assertEqual(data['indicator_pks_chain_order'], chain_pks)
        self.assertTrue(data['indicators'][goal_pk_a]['is_reporting'])
        self.assertEqual(data['indicators'][goal_pk_a]['over_under'], 0)
        self.assertEqual(data['indicators'][goal_pk_a]['lop_target'], 300)
        self.assertEqual(data['indicators'][goal_pk_a]['level_pk'], goal_level.pk)
        self.assertEqual(data['indicators'][goal_pk_b]['baseline'], None)
        self.assertEqual(data['indicators'][goal_pk_b]['over_under'], 1)
        self.assertEqual(data['indicators'][unassigned_pks[0]]['number'], None)
        self.assertEqual(data['indicators'][unassigned_pks[1]]['old_level_name'], None)
        self.assertEqual(data['indicators'][unassigned_pks[2]]['level_pk'], None)
        with lang_context('fr'):
            french_data = self.get_serialized_data(p.pk)
        self.assertEqual(french_data['by_result_chain'], BY_TIER_CHAIN[FRENCH].format(OUTCOME[FRENCH]))
        self.assertEqual(french_data['indicators'][goal_pk_b]['number'], '{} b'.format(GOAL[FRENCH]))
        self.assertEqual(french_data['indicators'][expected_pks[6]]['number'], '{} 1.2a'.format(OUTPUT[FRENCH]))
        self.assertEqual(french_data['indicators'][unassigned_pks[1]]['old_level_name'], None)

    def test_manual_numbering(self):
        p = RFProgramFactory(tiers=['Tier1', 'Tier2', 'Tier3'], levels=1, auto_number_indicators=False)
        levels = list(
            sorted(
                sorted(
                    [l for l in p.levels.all()],
                    key=lambda l: l.customsort
                ), key=lambda l: l.level_depth
            )
        )
        numbers = ['482', '28.C', '999']
        pks = []
        tiers = []
        for level, number in zip(list(reversed(levels)), numbers):
            pks.append(
                RFIndicatorFactory(
                    program=p,
                    level=level,
                    number=number
                ).pk
            )
            tiers.append(level.leveltier.name)
        expected_pks = list(reversed(pks))
        expected_numbers = list(reversed(numbers))
        expected_tiers = list(reversed(tiers))
        data = self.get_serialized_data(p.pk)
        self.assertEqual(len(data['indicators']), 3)
        self.assertEqual(data['indicator_pks_level_order'], expected_pks)
        self.assertEqual(data['indicator_pks_chain_order'], expected_pks)
        for pk, number, tier in zip(expected_pks, expected_numbers, expected_tiers):
            self.assertEqual(data['indicators'][pk]['number'], f"{tier} {number}")

    def test_rollups(self):
        p = RFProgramFactory()
        incomplete_i = RFIndicatorFactory(
            program=p, target_frequency=Indicator.MONTHLY, targets=300
        )
        incomplete_i.periodictargets.order_by('-end_date').first().delete()
        targets_i = RFIndicatorFactory(
            program=p, target_frequency=Indicator.QUARTERLY, targets=400
        )
        results_i = RFIndicatorFactory(
            program=p, target_frequency=Indicator.SEMI_ANNUAL, targets=400,
            results=200, results__count=10
        )
        sites = itertools.cycle([SiteProfileFactory() for _ in range(8)])
        for result in results_i.result_set.all():
            result.site.add(next(sites))
        evidence_i = RFIndicatorFactory(
            program=p, target_frequency=Indicator.ANNUAL, targets=40,
            results=100, results__count=12, results__evidence=8
        )
        for result in evidence_i.result_set.all():
            result.site.add(next(sites))
        evidence_i2 = RFIndicatorFactory(
            program=p, target_frequency=Indicator.ANNUAL, targets=40,
            results=10, results__count=4, results__evidence=4
        )
        data = self.get_serialized_data(p.pk)
        self.assertTrue(data['needs_additional_target_periods'])
        self.assertEqual(data['site_count'], 8)
        self.assertFalse(data['indicators'][incomplete_i.pk]['has_all_targets_defined'])
        self.assertTrue(data['indicators'][targets_i.pk]['has_all_targets_defined'])
        self.assertFalse(data['indicators'][targets_i.pk]['has_results'])
        self.assertEqual(data['indicators'][results_i.pk]['results_count'], 10)
        self.assertTrue(data['indicators'][results_i.pk]['has_results'])
        self.assertEqual(data['indicators'][evidence_i.pk]['results_with_evidence_count'], 8)
        self.assertTrue(data['indicators'][evidence_i.pk]['missing_evidence'])
        self.assertFalse(data['indicators'][evidence_i2.pk]['missing_evidence'])

    def test_rf_program_two_indicators_delete_only(self):
        p = RFProgramFactory(
            tiers=['Tier1', 'Tier2'], levels=1,
        )
        expected_pks = []
        levels = sorted(p.levels.all(), key=operator.attrgetter('level_depth'))
        for level in levels:
            expected_pks.append(RFIndicatorFactory(program=p, level=level).pk)
        indicator = RFIndicatorFactory(program=p, level=levels[1], name='Test Name')
        expected_pks.append(indicator.pk)
        full_data = self.get_serialized_data(p.pk)
        data = self.get_ordering_update_serialized_data(p.pk)
        self.assertEqual(data['pk'], p.pk)
        self.assertEqual(data['indicator_pks_level_order'], data['indicator_pks_chain_order'])
        indicator_pks = data['indicator_pks_level_order']
        self.assertEqual(indicator_pks, expected_pks)
        for indicator_pk in full_data['indicators']:
            self.assertIn(indicator_pk, data['indicators'])
            self.assertEqual(
                full_data['indicators'][indicator_pk]['number'],
                data['indicators'][indicator_pk]['number']
                )

    def test_rf_program_two_indicators_update_only(self):
        p = RFProgramFactory(
            tiers=['Tier1', 'Tier2'], levels=1,
        )
        expected_pks = []
        levels = sorted(p.levels.all(), key=operator.attrgetter('level_depth'))
        for level in levels:
            expected_pks.append(RFIndicatorFactory(program=p, level=level).pk)
        indicator = RFIndicatorFactory(program=p, level=levels[1], name='Test Name')
        expected_pks.append(indicator.pk)
        full_data = self.get_serialized_data(p.pk)
        data = self.get_update_indicator_data(p.pk, indicator.pk)
        self.assertEqual(data['pk'], p.pk)
        self.assertEqual(data['indicator_pks_level_order'], data['indicator_pks_chain_order'])
        indicator_pks = data['indicator_pks_level_order']
        self.assertEqual(indicator_pks, expected_pks)
        self.assertEqual(data['indicator']['name'], 'Test Name')
        for indicator_pk in full_data['indicators']:
            self.assertIn(indicator_pk, data['indicators'])
            self.assertEqual(
                full_data['indicators'][indicator_pk]['number'],
                data['indicators'][indicator_pk]['number']
                )

    def test_site_count_in_update(self):
        """Site count should be included in update serializer to supply reactive sites list with count"""
        p = RFProgramFactory()
        i = RFIndicatorFactory(program=p, targets=1000, results=True)
        data = self.get_update_indicator_data(p.pk, i.pk)
        self.assertEqual(data['site_count'], 0)
        r1 = i.result_set.first()
        r1.site.add(SiteProfileFactory())
        r1.save()
        data = self.get_update_indicator_data(p.pk, i.pk)
        self.assertEqual(data['site_count'], 1)


# 무조건 해시로 조져야하는 문제
# def solution(participant, completion):
#     answer = ''
#     parti = dict()
#     comple = dict()
#
#     for name in participant:
#         parti[name] = parti.get(name, 0) + 1
#         # try:
#         #     parti[name] += 1
#         # except KeyError:
#         #     parti[name] = 1
#
#     for name in completion:
#         comple[name] = comple.get(name, 0) + 1
#
#     for name in parti.keys():
#         if (parti[name] > 1 and parti[name] != comple[name]) or name not in comple:
#             answer = name
#             break
#     return answer

# get() 시간 복잡도가 시원찮네 => 효율성만 실패 => get() 이 문제가 아님 ㅎㅎ,, 위에 풀이 get()으로 고쳐도 ㄱ => get() dl try/except pattern 대신 사용하면 좋을
def solution(participant, completion):
    comple = dict()
    for name in completion:
        comple[name] = comple.get(name, 0) + 1
    for name in participant:
        if name not in comple:
            return name

        if participant.count(name) != comple[name]:
            return name

def solution(participant, completion):
    # 아니 최대 N 10만따리를 sort() 치는데도, 시간효율성 안터지네; O(NlogN)이라 그런가봄
    participant.sort()
    completion.sort()
    for parti, compl in zip(participant, completion):
        if parti != compl:
            return parti

import collections

def solution(participant, completion):
    return list(collections.Counter(participant) - collections.Counter(completion))[0]

participant = ["mislav", "stanko", "mislav", "ana"]
completion = ["stanko", "ana", "mislav"]
# participant =["marina", "josipa", "nikola", "vinko", "filipa"]
# completion = ["josipa", "filipa", "marina", "nikola"]
print(solution(participant, completion))
# 무조건 한명은 완주를 못했다는 명제를 잘 활용해야함


import openai
import os
import time
import streamlit as st

from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()

openai.api_key = os.environ["OPENAI_API_KEY"]

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
)

file_path = "docs/2023q3-alphabet-earnings-release.pdf"

file = client.files.create(
    file=open(file_path, "rb"),
    purpose='assistants'
)

st.header("GPT 4 Retriever Assistants")
user_message = st.text_input("Pls enter your question:")
submit = st.button("submit", type="primary")

if submit:

    # You can attach a maximum of 20 files per Assistant, and they can be at most 512 MB each.
    assistant = client.beta.assistants.create(
        name="RAG Assistant",
        description="You are great at extracting information from documents. You analyze data present in .pdf files, "
                    "understand trends, and come up with answers relevant to those documents. You also share a "
                    "brief text summary of the documents you analyze.",
        model="gpt-4-1106-preview",
        tools=[{"type": "code_interpreter"}],
        file_ids=[file.id]
    )

    thread = client.beta.threads.create(
        messages=[
            {
                "role": "user",
                "content": "Answer questions based on the content of the document.",
                "file_ids": [file.id]
            }
        ]
    )

    # Step 3: Add a Message to a Thread
    message = client.beta.threads.messages.create(
        thread_id=thread.id,
        role="user",
        content=user_message
    )

    run = client.beta.threads.runs.create(
        thread_id=thread.id,
        assistant_id=assistant.id,
        model="gpt-4-1106-preview",
        instructions="Please address the user as Jane Doe. The user has a premium account.",
        tools=[{"type": "code_interpreter"}, {"type": "retrieval"}]
    )

    run = client.beta.threads.runs.retrieve(
        thread_id=thread.id,
        run_id=run.id
    )

    time.sleep(20)

    messages = client.beta.threads.messages.list(
        thread_id=thread.id
    )

    run_steps = client.beta.threads.runs.steps.list(
        thread_id=thread.id,
        run_id=run.id
    )

    if run_steps.data[0].status == "completed":
        print("The run was successful!")
        messages = client.beta.threads.messages.list(
            thread_id=thread.id
        )
        for message in messages.data:
            print(message.role.upper(), message.content[0].text.value)
            role = message.role.upper()
            content = message.content[0].text.value
            st.write(role, " : ", content)


import sys
import os

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import unittest
from unittest.mock import Mock, patch, mock_open
from surprise import SVDpp, Dataset
from model_offline_evaluation import *

class TestEvaluation(unittest.TestCase):

# ---------------------------------------------------------------------------- #

    @patch('builtins.open', mock_open(read_data=b'mock_model_data'))
    @patch('pickle.load')
    def test_load_model(self, pickle_load_mock):
        model = SVDpp()
        pickle_load_mock.return_value = model

        loaded_model = load_model('test_model.pkl')
        self.assertEqual(loaded_model, model)

# ---------------------------------------------------------------------------- #

    def test_make_predictions(self):
        model = Mock()
        dataset = [1, 2, 3]
        expected_predictions = [4, 5, 6]

        model.test.return_value = expected_predictions
        predictions = make_predictions(model, dataset)

        self.assertEqual(predictions, expected_predictions)

# ---------------------------------------------------------------------------- #

    def test_compute_rmse(self):
        predictions = Mock()
        accuracy_mock = Mock(return_value=0.95)

        with patch('model_offline_evaluation.accuracy.rmse', accuracy_mock):
            performance = compute_rmse(predictions)

        accuracy_mock.assert_called_once_with(predictions)
        self.assertEqual(performance, 0.95)

# ---------------------------------------------------------------------------- #

    @patch('model_offline_evaluation.load_model')
    @patch('model_offline_evaluation.make_predictions')
    @patch('model_offline_evaluation.compute_rmse')
    def test_evaluate_model_pipeline(self, compute_rmse_mock, make_predictions_mock, load_model_mock):
        testset = Mock()
        model = SVDpp()

        load_model_mock.return_value = model
        make_predictions_mock.return_value = 'predictions'
        compute_rmse_mock.return_value = 0.95

        performance = evaluate_model_pipeline(testset)

        load_model_mock.assert_called_once_with('movie_recommender_model_final.pkl')
        make_predictions_mock.assert_called_once_with(model, testset)
        compute_rmse_mock.assert_called_once_with('predictions')

        self.assertEqual(performance, 0.95)

# ---------------------------------------------------------------------------- #

if __name__ == '__main__':
    unittest.main()


from typing import Union
import os
from transformers.configuration_utils import PretrainedConfig
from transformers.utils import logging
from transformers import BertConfig
logger = logging.get_logger(__name__)

class FusionConfig(PretrainedConfig):
    r"""
    [`FusionConfig`] is the configuration class to store the configuration of a
    [`FusionModel`]. It is used to instantiate [`FusionModel`] model according to the
    specified arguments, defining the text model, vision model, and fusion model configs.
    Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
    documentation from [`PretrainedConfig`] for more information.
    Args:
    """

    model_type = "fusion"

    def __init__(
        self,
        hidden_act = "quick_gelu",
        hidden_size = 512,
        initializer_range = 0.02,
        intermediate_size = 2048,
        layer_norm_eps = 1e-12,
        max_position_embeddings = 77,
        model_type = "fusion",
        num_attention_heads = 8,
        num_hidden_layers = 12,
        use_cache = True,
        dropout = 0.0,
        attention_dropout = 0.0,
        initializer_factor = 1.0,
        summary_type = 'mean',
        **kwargs
    ):
        super().__init__(fusion_model_type=None, **kwargs)

        self.hidden_size = hidden_size
        self.num_hidden_layers = num_hidden_layers
        self.num_attention_heads = num_attention_heads
        self.hidden_act = hidden_act
        self.intermediate_size = intermediate_size
        self.max_position_embeddings = max_position_embeddings
        self.initializer_range = initializer_range
        self.layer_norm_eps = layer_norm_eps
        self.use_cache = use_cache
        self.dropout = dropout
        self.attention_dropout = attention_dropout
        self.initializer_factor = initializer_factor
        self.summary_type = summary_type,

    @classmethod
    def from_pretrained(cls, pretrained_model_name_or_path: Union[str, os.PathLike], **kwargs) -> "PretrainedConfig":

        config_dict, kwargs = cls.get_config_dict(pretrained_model_name_or_path, **kwargs)
        if "model_type" in config_dict and hasattr(cls, "model_type") and config_dict["model_type"] != cls.model_type:
            logger.warning(
                f"You are using a model of type {config_dict['model_type']} to instantiate a model of type "
                f"{cls.model_type}. This is not supported for all configurations of models and can yield errors."
            )

        return cls.from_dict(config_dict, **kwargs)

    @classmethod
    def for_model(cls, model_type: str, *args, **kwargs):
        return FusionConfig()


from dgl.nn.functional import edge_softmax
from dgl import DGLError
import dgl.function as fn
import torch
import torch.nn as nn
import torch.nn.functional as F

class GATLayer(nn.Module):
    """Feature computation h => h'.

    **Linear transformation**:
        :math:`z_i=Wh_i`
    **Edge attention**:
        :math:`e_{ij}=LeakyReLU\ (a^T\cdot(z_i\ ||\ z_j\ ))`
    **Aggregation**:
        :math:`a_{ij}=\exp(e_{ij}\ )/(\sum_{k\in \mathcal{N}(i\ )}\exp(e_{ik}\ ))`

        :math:`h_i'=Relu\ (\sum_{j\in \mathcal{N}(i\ )} {a_{ij}\ z_j\ })`
    """
    def __init__(self, in_dim: int, out_dim: int,
                 feat_drop: float = 0., attn_drop: float = 0.,
                 negative_slope: float = 0.2):
        super(GATLayer, self).__init__()
        self.linear = nn.Linear(in_dim, out_dim, bias=False)
        self.attn_s = nn.Linear(out_dim, 1, bias=False)
        self.attn_d = nn.Linear(out_dim, 1, bias=False)
        self.feat_drop = nn.Dropout(feat_drop)
        self.attn_drop = nn.Dropout(attn_drop)
        self.leaky_relu = nn.LeakyReLU(negative_slope)
        self.reset_parameters()

    def reset_parameters(self):
        gain = nn.init.calculate_gain('relu')
        nn.init.xavier_normal_(self.linear.weight, gain=gain)
        nn.init.xavier_normal_(self.attn_s.weight, gain=gain)
        nn.init.xavier_normal_(self.attn_d.weight, gain=gain)

    def forward(self, graph, h):
        with graph.local_scope():
            h = self.feat_drop(h)
            z_s = self.linear(h)
            if graph.is_block:
                z_d = z_s[:graph.number_of_dst_nodes()]
            else:
                z_d = z_s

            # compute edge attention
            es = self.attn_s(z_s)
            ed = self.attn_d(z_d)
            graph.srcdata.update({'z': z_s, 'es': es})
            graph.dstdata.update({'ed': ed})
            graph.apply_edges(fn.u_add_v('es', 'ed', 'e'))
            e = self.leaky_relu(graph.edata.pop('e'))
            graph.edata['a'] = self.attn_drop(edge_softmax(graph, e))

            # message passing
            graph.update_all(fn.u_mul_e('z', 'a', 'm'), fn.sum('m', 'z'))

            return graph.dstdata['z']

class MultiHeadGATLayer(nn.Module):
    def __init__(self,
                 in_dim: int,
                 out_dim: int,
                 num_heads: int,
                 dropout: float = 0.2):
        super(MultiHeadGATLayer, self).__init__()
        self.heads = nn.ModuleList()
        for i in range(num_heads):
            self.heads.append(GATLayer(
                in_dim, out_dim, feat_drop=dropout, attn_drop=0.2))

    def forward(self, graph, h):
        batch = [head(graph, h) for head in self.heads]
        return torch.cat(batch, dim=-1)

class JKNLayer(nn.Module):
    """**Layer-level aggregation**
        :math:`\mathbf{h}_{final}=\phi(\mathbf{h}^1, \mathbf{h}^2, ...\ , \mathbf{h}^L\ )`

    * **Concatenation**: :math:`\phi = ||`

    * **Gated Recurrent Unit**:

        :math:`(\mathbf{f}^l,\mathbf{b}^l) = bidirectional\ GRU\ (\mathbf{h}^l\ )`

        Attention score for layers
        :math:`s^l = a^T\cdot(\mathbf{f}^l\ ||\ \mathbf{b}^l)`

        :math:`\mathbf{h}_{final} = softmax(\mathbf{s})\cdot(\mathbf{f}\ ||\ \mathbf{b})`

    Parameters
    ----------
    in_dim : int
        input feature size.
    out_dim : int
        output feature size.
    n_layers : int
        number of layers in multi-layer skip connection.
    aggregator_type : str
        the aggregation method. It supports "cat" and "gru". The default value is "cat".
    """
    def __init__(self, in_dim: int, out_dim: int,
                 n_layers: int,
                 aggregator_type='cat'):
        super(JKNLayer, self).__init__()
        if aggregator_type not in ['cat', 'gru']:
            raise KeyError('Aggregator type {} not supported.'.format(aggregator_type))
        self.__aggr_type = aggregator_type
        if aggregator_type == 'cat':
            self.linear = nn.Linear(in_dim * n_layers, out_dim, bias=False)
        if aggregator_type == 'gru':
            self.gru = nn.GRU(input_size=in_dim,
                              hidden_size=in_dim,
                              bidirectional=True)
            self.s = nn.Linear(in_dim * 2, 1, bias=False)
            self.linear = nn.Linear(in_dim * 2, out_dim, bias=False)

    def reset_parameters(self):
        gain = nn.init.calculate_gain('relu')
        nn.init.xavier_normal_(self.linear.weight, gain=gain)
        if self.__aggr_type == 'gru':
            nn.init.xavier_normal_(self.s.weight, gain=gain)

    def forward(self, h_list):
        if self.__aggr_type == 'cat':
            h_cat = torch.cat(h_list, dim=-1)
            return self.linear(h_cat)
        else:
            # gru
            h_seq, _ = self.gru(torch.stack(h_list, dim=0))
            w = self.s(h_seq)
            w = F.softmax(w, dim=-1)
            h_N = torch.einsum('lni,lnf->nf', w, h_seq)
            return self.linear(h_N)

class Model(nn.Module):
    def __init__(self, in_dim: int, h_dim: int, out_dim: int,
                 n_layers: int = 2, n_heads: int = 2,
                 dropout: float = 0.2, skip_connection='gru'):
        super(Model, self).__init__()
        self.input_layer = MultiHeadGATLayer(in_dim, h_dim, n_heads, dropout)
        if n_layers < 1:
            raise DGLError('Number of layers should be positive integer.')
        hid_dim = h_dim * n_heads
        n_h_layers = n_layers - 1
        self.layers = nn.ModuleList()
        for i in range(n_h_layers):
            self.layers.append(MultiHeadGATLayer(hid_dim, h_dim, n_heads, dropout))
        self.output_layer = JKNLayer(hid_dim, out_dim, n_layers, skip_connection)

    def forward(self, graph, in_feat):
        h = self.input_layer(graph, in_feat)
        h_list = [F.relu(h)]
        for layer in self.layers:
            h = layer(graph, F.relu(h))
            h_list.append(F.relu(h))
        return self.output_layer(h_list)


#!/usr/bin/env python

import sys
sys.setrecursionlimit(10000)

raw_input()
s = raw_input().strip()

def find_best(s1, s2):
    return s1 if len(s1) < len(s2) else s2

cache = {}

def fold(s):
    if s in cache:
        return cache[s]

    if len(s) == 1:
        cache[s] = (s, {s:1})
        return cache[s]

    ans = s
    ansr = {s: 1}

    for i in range(1, len(s)):
        p1, p2 = s[:i], s[i:]
        p1a, p1ar = fold(p1)
        p2a, p2ar = fold(p2)

        ans = find_best(ans, p1a + p2a)

        if p1 == p2:
            ansr[p1] = 2

        if p1 in p2ar:
            ansr[p1] = p2ar[p1]+1

        if p1 in ansr:
            ans = find_best(ans, "%d(%s)"%(ansr[p1], p1a))

    cache[s] = (ans, ansr)
    return cache[s]

print(fold(s)[0])


import numpy as np
import torch
import cv2
import argparse
from tqdm import tqdm

from RAVE.common.image_utils import (
    tensor_to_opencv_image,
    inverse_normalize,
    xyxy2xywh,
    opencv_image_to_tensor,
    scale_coords,
    scale_coords_landmarks,
)

from RAVE.face_detection.FaceDetectionDataset import FaceDetectionDataset
from RAVE.face_detection.FaceDetectionModel import FaceDetectionModel
from RAVE.face_detection.fpsHelper import FPS

CONFIDENCE_THRESHOLD = 0.5
INTERSECTION_OVER_UNION_THRESHOLD = 0.5

# Calibration
K_640 = np.array(
    [[376.96798, 0.0, 314.09011], [0.0, 374.08737, 250.37452], [0.0, 0.0, 1.0]]
)
D_640 = np.array([-0.321459, 0.073634, -0.005091, 0.001433, 0.000000])

K_1280 = np.array(
    [[688.98267, 0.0, 654.13648], [0.0, 687.22945, 487.61611], [0.0, 0.0, 1.0]]
)
D_1280 = np.array([-0.299440, 0.074629, 0.000560, -0.001228, 0.000000])

def main(
    TRAIN, NB_EPOCHS, CONTINUE_TRAINING, DISPLAY_VALIDATION, TEST, STREAM
):
    """main function of the module

    Args:
        TRAIN (bool): Whether to train the model or not
        NB_EPOCHS (int):
            Number of epochs for which to train the network(ignored if TRAIN is
            set to false)
        CONTINUE_TRAINING(bool):
            Whether to continue the training from the
            checkpoint on disk or not
        DISPLAY_VALIDATION (bool):
            Whether to display the predictions on the validation dataset or not
        TEST (bool):
            Whether to display the predictions on the test dataset or not
        STREAM (bool):
            Whether to display the predictions on a camera stream or not.
    """
    DEVICE = "cpu"
    if torch.cuda.is_available():
        DEVICE = "cuda"

    BATCH_SIZE = 32
    validation_sub_dataset = FaceDetectionDataset.get_validation_sub_dataset()

    validation_loader = torch.utils.data.DataLoader(
        validation_sub_dataset,
        batch_size=BATCH_SIZE,
        shuffle=True,
        num_workers=1,
        pin_memory=True,
        persistent_workers=True,
        collate_fn=collate_fn,
    )

    face_detection_model = FaceDetectionModel(DEVICE)
    face_detection_model.to(DEVICE)
    # print(face_detection_model)

    if TRAIN:
        # If one day we want to train the model
        print("Train")

    if DISPLAY_VALIDATION:
        visualize_predictions(face_detection_model, validation_loader, DEVICE)

    if TEST:
        # If one day we want to test the model for training
        print("Test validation")

    if STREAM:
        visualize_predictions_on_stream(face_detection_model, DEVICE, 0)

def collate_fn(batch):
    """
    Function to override the behavior of PyTorch Dataloader, so we can have
    variable label length (The number of faces varies between images)

    Args:
        batch (ndarray): Batch with the images, labels and labels shape
    """
    img, label, label_shape = zip(*batch)
    return torch.stack(img, 0), torch.cat(label, 0), label_shape

def visualize_predictions(model, data_loader, DEVICE):
    """
    Used to visualize the target and the predictions of the model on some
    input images

    Args:
        model (Module): The model used to perform the predictions
        data_loader (Dataloader):
            The dataloader that provides the images and the targets
        DEVICE (String): Device on which to perform the computations
    """
    with torch.no_grad():
        key_pressed = None
        for batch_images, _, _ in data_loader:
            batch_images = batch_images.to(DEVICE)
            batch_predictions = model(batch_images)
            for predictions, image in zip(batch_predictions, batch_images):
                image = inverse_normalize(
                    image,
                    FaceDetectionDataset.TRAINING_MEAN,
                    FaceDetectionDataset.TRAINING_STD,
                )
                image = tensor_to_opencv_image(image)
                # Convert RGB to BGR
                image = image[:, :, ::-1]

                for i in range(predictions.size()[0]):
                    # normalization gain whwh
                    gn = torch.tensor(image.shape)[[1, 0, 1, 0]].to(DEVICE)
                    # normalization gain landmarks
                    gn_lks = torch.tensor(image.shape)[
                        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
                    ].to(DEVICE)
                    face_box_xywh = (
                        (xyxy2xywh(predictions[i, :4].view(1, 4)) / gn)
                        .view(-1)
                        .tolist()
                    )
                    confidence = predictions[i, 4].cpu().numpy()
                    landmarks = (
                        (predictions[i, 5:15].view(1, 10) / gn_lks)
                        .view(-1)
                        .tolist()
                    )
                    image = show_results(
                        image, face_box_xywh, confidence, landmarks
                    )

                cv2.imshow("validation", image)

                # Stop if escape key is pressed
                key_pressed = cv2.waitKey(1500) & 0xFF
                if key_pressed == 27:
                    break
            if key_pressed == 27:
                break

def visualize_predictions_on_stream(
    model, DEVICE, opencv_device, fps=30, width=640, height=480
):
    """
    Used to visualize the target and the predictions of the model on some
    a camera stream

    Args:
        model (Module): The model used to perform the predictions
        DEVICE (String): Device on which to perform the computations
        opencv_device (int): Device number of the camera
        fps (int): At what framerate to capture from the camera
        width (int): Width of the image in pixels
        height (int): Height of the image in pixels
    """
    cap = cv2.VideoCapture(opencv_device)
    cap.set(cv2.CAP_PROP_FPS, fps)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)

    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

    fps = FPS()
    with torch.no_grad():
        while True:
            _, frame = cap.read()
            # Get predictions
            tensor = opencv_image_to_tensor(frame, DEVICE)
            tensor = torch.unsqueeze(tensor, 0)
            predictions = model(tensor)[0]

            # Scale coords
            predictions[:, 5:15] = scale_coords_landmarks(
                tensor.shape[2:], predictions[:, 5:15], frame.shape
            ).round()
            predictions[:, :4] = scale_coords(
                tensor.shape[2:], predictions[:, :4], frame.shape
            ).round()

            # Draw predictions
            for i in range(predictions.size()[0]):
                gn = torch.tensor(frame.shape)[[1, 0, 1, 0]].to(
                    DEVICE
                )  # normalization gain whwh
                gn_lks = torch.tensor(frame.shape)[
                    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
                ].to(
                    DEVICE
                )  # normalization gain landmarks
                xywh = (
                    (xyxy2xywh(predictions[i, :4].view(1, 4)) / gn)
                    .view(-1)
                    .tolist()
                )
                confidence = predictions[i, 4].cpu().item()
                landmarks = (
                    (predictions[i, 5:15].view(1, 10) / gn_lks)
                    .view(-1)
                    .tolist()
                )
                frame = show_results(frame, xywh, confidence, landmarks)

            fps.setFps()
            final_frame = fps.writeFpsToFrame(frame)

            cv2.imshow("Facial detection", final_frame)

            # Stop if escape key is pressed
            k = cv2.waitKey(30) & 0xFF
            if k == 27:
                break

    cap.release()
    cv2.destroyAllWindows()

def show_results(img, xywh, confidence, landmarks):
    """
    Writes the bounding box, the confidence score and the landmarks to the
    frame. For now, it only shows the result of one prediction.

    Args:
        img (ndarray):
            OpenCV image with shape (height, width, 3)
        xywh (ndarray):
            Normalized values to define the bounding box with shape
            (x, y, width height).
        confidence (float):
            Confidence score.
        landmarks (list):
            Normalized landmarks of length 10. The x and y alternate in the
            list like so: [x1, y1, x2, y2, ..., x5, y5]
    """
    height, width, _ = img.shape
    img = np.ascontiguousarray(img, dtype=np.uint8)
    line_thickness = 1 or round(0.002 * (height + width) / 2) + 1

    # Bounding box
    x1 = int(xywh[0] * width - 0.5 * xywh[2] * width)
    y1 = int(xywh[1] * height - 0.5 * xywh[3] * height)
    x2 = int(xywh[0] * width + 0.5 * xywh[2] * width)
    y2 = int(xywh[1] * height + 0.5 * xywh[3] * height)
    img = cv2.rectangle(
        img,
        (x1, y1),
        (x2, y2),
        (0, 255, 0),
        thickness=line_thickness,
        lineType=cv2.LINE_AA,
    )

    colors = [
        (255, 0, 0),
        (0, 255, 0),
        (0, 0, 255),
        (255, 255, 0),
        (0, 255, 255),
    ]

    # Landmarks
    for i in range(5):
        point_x = int(landmarks[2 * i] * width)
        point_y = int(landmarks[2 * i + 1] * height)
        img = cv2.circle(
            img, (point_x, point_y), line_thickness + 1, colors[i], -1
        )

    mouth_x = int(((landmarks[6] + landmarks[8]) * width) / 2)
    mouth_y = int(((landmarks[7] + landmarks[9]) * height) / 2)

    img = cv2.circle(
        img, (mouth_x, mouth_y), line_thickness + 1, (255, 0, 0), -1
    )

    # Confidence score
    font_thickness = max(line_thickness - 1, 1)  # font thickness
    label = f"{str(confidence)[:5]}"
    cv2.putText(
        img,
        label,
        (x1, y1 - 2),
        0,
        line_thickness / 3,
        [225, 255, 255],
        thickness=font_thickness,
        lineType=cv2.LINE_AA,
    )

    return img

def find_dataset_mean_and_std(loader):
    """
    Method to find the dataset mean and standard deviation.

    Args:
        loader (Dataloader): The Pytorch Dataloader.
    """
    nb_samples = 0
    mean = 0.0
    var = 0.0
    for data, _, _ in tqdm(loader, leave=False, desc="Mean and STD"):
        batch_samples = data.size(0)
        data = data.view(batch_samples, data.size(1), -1)
        mean += data.mean(2).sum(0)
        var += data.std(2).sum(0)
        nb_samples += batch_samples

    mean /= nb_samples
    var /= nb_samples
    std = torch.sqrt(var)

    print(f"Mean: {mean}")
    print(f"Std: {std}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-t", "--train", action="store_true", help="Train the neural network"
    )
    parser.add_argument(
        "-e",
        "--nb_epochs",
        action="store",
        type=int,
        default=20,
        help="Number of epoch for which to train the neural network",
    )
    parser.add_argument(
        "-c",
        "--continue_training_from_checkpoint",
        action="store_true",
        help="Continue training from checkpoint",
    )

    parser.add_argument(
        "-v",
        "--display_validation",
        action="store_true",
        help=(
            "Display the predictions of the neural network on the validation"
            "dataset"
        ),
    )
    parser.add_argument(
        "-p",
        "--predict",
        action="store_true",
        help=(
            "Display the predictions of the neural network on the test"
            "dataset"
        ),
    )
    parser.add_argument(
        "-s",
        "--stream",
        action="store_true",
        help=(
            "Display the predictions of the neural network on a video stream"
        ),
    )
    args = parser.parse_args()

    main(
        args.train,
        args.nb_epochs,
        args.continue_training_from_checkpoint,
        args.display_validation,
        args.predict,
        args.stream,
    )


from ...libs.io_lib import archive_object, unarchive_object

class AlphaSave():
    root    = None
    ext     = '.ast'

    @staticmethod
    def set_root(root):
        AlphaSave.root = root

    @staticmethod
    def get_file_path(filename):
        file_path = AlphaSave.root + os.sep + filename + '.ast'
        return file_path

    @staticmethod
    def save(object_to_save,filename):
        file_path = AlphaSave.get_file_path(filename)
        directory = os.path.dirname(file_path)
        os.makedirs(directory,exist_ok=True)
        archive_object(object_to_save,file_path)

    @staticmethod
    def load(filename):
        file_path = AlphaSave.get_file_path(filename)
        return unarchive_object(file_path)


from os.path import join

from urlnet.urltree import UrlTree
from urlnet.urlutils import GetConfigValue
import urlnet.log

workingDir = GetConfigValue('workingDir')

# turn on logging
urlnet.log.logging=True

# the following line causes lots of output to be generated!
urlnet.log.trace=True

# the following line says to flag functions that take more than five
# seconds to complete.
urlnet.log.limit = 5.0

# the following line causes output to be tee'd off to
# the file we open for writing.
urlnet.log.altfd = open(join(workingDir,'logging3.log.txt'),'w')

# The following line tells the log facility to write only to
# the altfd file descriptor and not to stderr.
urlnet.log.file_only = True

net = UrlTree(_maxLevel=2, _workingDir=workingDir)
net.SetProperty('getTitles',True)
net.BuildUrlTree('http://www.southwindpress.com')
net.WritePajekFile('logging3', 'logging3',useTitles=True)

# clean up
urlnet.log.altfd.close()
urlnet.log.altfd = None


from __future__ import unicode_literals
import webnotes
from webnotes.model.doc import addchild, Document
from webnotes import msgprint, _
from webnotes.model.bean import getlist
from webnotes.utils import cint, cstr, flt, now, nowdate, get_first_day, get_last_day, add_to_date, getdate

class DocType:
	def __init__(self, d, dl):
		self.doc, self.doclist = d, dl

	#def on_update(self):

	def on_submit(self):
		self.update_sample_status()
		self.update_sample_allocation_to_lab()
		self.update_test_log()

	#Select test from sample allocation to lab & also from the test log where we kept rejected test
	def get_sample_no(self):

		samples=webnotes.conn.sql("""select f.sample_no from `tabFinal Sample Allocation To Lab` f
		where
				f.parent='%(parent)s'
				and find_in_set('%(test_name)s',f.test)
		union
			select sample_no from `tabTest Log` tl
		where
			test = '%(test_name)s' and docstatus in ('0','1')""" %{'parent':self.doc.sample_allocation_lab, 'test_name':self.doc.test_name },as_list=1)
		if samples:
			for sample_no in samples:
				flag = False
				sample_detail=webnotes.conn.sql("""select barcode,priority from `tabSample`
					where name='%s'"""%(sample_no[0]),as_list=1)
				for d in getlist(self.doclist, 'sample_allocation_detail'):
					if d.sample_no==sample_no[0]:
						if d.test:
							if not self.doc.test_name in d.test:
								d.test = d.test + ',' +self.doc.test_name
						else:
							d.test = self.doc.test_name
						flag = True
				if not flag:
					self.create_child_record(sample_no[0], sample_detail)
		else:
			webnotes.msgprint("There is no any Sample Number allocated against the test='"+self.doc.test_name+"'",raise_exception=1)
			return{
				"test_name":''
			}
		return{
			"test_name": ''
		}

	#To add entries in child table according to the selected test.
	def create_child_record(self, sample_no, sample_detail):
		ch = addchild(self.doc, 'sample_allocation_detail',
					'Sample Allocation Detail', self.doclist)
		ch.sample_no=sample_no
		ch.test=self.doc.test_name
		ch.bottle_no=sample_detail[0][0]
		ch.priority=sample_detail[0][1]
		ch.save(new=1)

	def update_test_log(self):
		for i in getlist(self.doclist,'sample_allocation_detail'):
			#webnotes.errprint(i.sample_no)
			webnotes.conn.sql("""update `tabTest Log` set docstatus = 2
					   where sample_no ='%s'""" %(i.sample_no),as_list=1)
			webnotes.conn.sql("commit")

	#To change status of sample to 'Assigned' after completing the sample allocation
	def update_sample_status(self):
		samples, dic = {}, {}
		for sample in getlist(self.doclist, 'sample_allocation_detail'):
			#samples[sample.get('sample_no')] = ''
			self.test_allocation(sample, dic)

		self.prepare_escape_test(dic)

		#for updation of status in Sample Doctype
		for sample in getlist(self.doclist,'sample_allocation_detail'):
			webnotes.conn.sql("update tabSample set status = 'Assigned' where name ='"+sample.sample_no+"'")
			webnotes.conn.sql("commit")

	#To disable link from sample allocation to lab to sample allocation to tester after completing sample allocation to tester process corresponding to the perticular sample allocation to lab form.
	def update_sample_allocation_to_lab(self):
		webnotes.conn.sql("update `tabSample Allocation To Lab` set sample_allocation_name='"+self.doc.name+"' where name ='"+self.doc.sample_allocation_lab+"'")
		webnotes.conn.sql("commit")

	#To create document for each test present in sample allocation detail table.
	def test_allocation(self, sample, dic):
		self.create_test(sample, dic)

	def create_test(self,sample, dic):
		tests=sample.get("test").split(',')
		length=len(tests)
		if length==1:
			single_sample =[]
			self.ckeck_test(tests[0],sample, dic, single_sample)
		else:
			for test in tests:
				test_id = self.ckeck_test(test,sample,dic)

	#Test which involve basic step as Test Preparation
	def ckeck_test(self, test_name, sample, dic, sample_nos=None):
		escape_tests=['Neutralization Value', 'Sediment','Furan Content','Corrossive Sulphur','Oxidation Stability','Accelerated Aging']
		if test_name not in escape_tests:
			test_id=self.create_doc(test_name, sample)
			self.create_todo(sample, test_name,  test_id)
		else:
			if dic.get(test_name):
				dic[test_name].append(sample.get('sample_no'))
			else:
				dic[test_name] = [sample.get('sample_no')]
			# webnotes.errprint(dic[test_name])

	#create document for escape test.
	def prepare_escape_test(self, dic):
			# dic = {'Test Name':['sample numbers']}
			for test_name in dic:
				parent=self.create_test_preparation(test_name)
				self.create_child_test_preparation(dic[test_name], test_name, parent)
				self.create_todo_preparation(parent,self.doc.tester, test_name)

	#Create Document for escape test i.e document for Test Preparation Form
	def create_test_preparation(self,test_name):
		if test_name == 'Neutralization Value':
			test_preparation = Document("Neutralization Value")
			test_preparation.tested_by = self.doc.tester
			test_preparation.save()

		else :
			test_preparation=Document("Test Preparation")
			test_preparation.test=test_name
			test_preparation.save()

		return test_preparation.name

	#add child records in the test preparation form child table.
	def create_child_test_preparation(self, samples, test_name, parent):
		temp = 0
		childtab = {'Neutralization Value':['neutralisation_test_details', 'Neutralization Test Details']}
		from webnotes.model.doc import get
		if parent and samples:
			doc = get('Neutralization Value' if test_name=='Neutralization Value' else 'Test Preparation', parent)
			doclist = get('Neutralization Value' if test_name=='Neutralization Value' else 'Test Preparation', parent, with_children=1)
			for sample in samples:
				ch = addchild(doc[0], childtab.get(test_name)[0] if childtab.get(test_name) else 'sample_details', childtab.get(test_name)[1] if childtab.get(test_name) else 'Sample Preparation Details', doclist)
				ch.sample_no = sample
				ch.bottle_no= webnotes.conn.get_value("Sample", sample, "barcode")
				if test_name != 'Neutralization Value':
					ch.tester=self.doc.tester
				ch.save()
				temp = get_temp(sample)

			d = Document('Neutralization Value' if test_name=='Neutralization Value' else 'Test Preparation', parent)
			d.temperature = temp
			d.save()

	#Create Document for Test which are not involve in the escape test.
	def create_doc(self, test_name, sample):
		test_method, specification = self.get_test_method(sample)
		test = Document(test_name)
		test.sample_no = sample.get("sample_no")
		test.specification = specification
		test.temperature = get_temp(sample.get("sample_no"))
		test.tested_by = self.doc.tester
		test.save()
		self.update_test_id(sample,test.name)
		return test.name

	def get_test_method(self, sample):
		specification = webnotes.conn.get_value("Sample", self.doc.sample_no, 'specification')
		test_method = webnotes.conn.sql("""select test_method from `tabTest Specification`
			where specification = '%s' and test = '%s'"""%(specification, sample.get("test")))
		return test_method[0][0] if test_method else '', specification

	def update_test_id(self, sample, test_name):
		webnotes.conn.sql("update `tabSample Allocation Detail` set test_id='"+test_name+"' where test='"+sample.get("test")+"' and parent='"+self.doc.name+"'")
		webnotes.conn.commit()

	# Create TODO Notification for tester.
	def create_todo(self, sample, test_name, test_id):
		# webnotes.errprint("in create to do")
		userid = webnotes.conn.sql("select user_id from tabEmployee where name = '%s'"%(self.doc.tester),as_list=1)
		# webnotes.errprint([userid , sample, sample.get("tester")])
		if userid:
			d = Document("ToDo")
			d.owner = userid[0][0]
			d.reference_type = test_name
			d.reference_name = test_id
			d.priority =  'Medium'
			d.date = nowdate()
			d.assigned_by = webnotes.user.name
			d.save(1)
			# webnotes.errprint(d.name)

	#Create TODO Notification Of Test Preparation for tester.
	def create_todo_preparation(self, parent, tester, test_name):
		# webnotes.errprint("in create to do test preparation")
		d = Document("ToDo")
		d.owner = webnotes.conn.get_value("Employee",tester,'user_id')
		d.reference_type = 'Neutralization Value' if test_name == 'Neutralization Value' else 'Test Preparation'
		d.reference_name = parent
		d.priority =  'Medium'
		d.date = nowdate()
		d.assigned_by = webnotes.user.name
		d.save(1)

def get_test_name(doctype, txt, searchfield, start, page_len, filters):
	return get_test(filters)

def get_test(filters):
	lst = []

	lab_test = webnotes.conn.sql("""select test from `tabFinal Sample Allocation To Lab`
			where parent = '%s'"""%(filters.get('sample_allocation_id')), as_list=1)

	for test in lab_test:
		for i in test[0].split(','):
			lst.insert(len(lst), [i])

	log_test = webnotes.conn.sql("""select distinct test from `tabTest Log`
		where docstatus in (0,1) and test is not null""",as_list=1)

	for test in log_test:
		lst.insert(len(lst), [test[0]])

	return map(list, set(map(tuple, lst)))

def get_sample_no(doctype, txt, searchfield, start, page_len, filters):
	return 	webnotes.conn.sql(""" select  name from tabSample where status = 'Lab Entry'
		union select distinct sample_no from`tabTest Log` tl""")

def get_employee(doctype, txt, searchfield, start, page_len, filters):
	#webnotes.errprint("hi")
	return webnotes.conn.sql(""" select name, employee_name, date_of_birth from tabEmployee
		where (%(key)s like "%(txt)s" or employee_name like "%(txt)s")"""%{'key':searchfield, 'txt': "%%%s%%" % txt})

def get_temp(sample_no):
	ret = webnotes.conn.sql("""select se.temperature from `tabSample Entry` se, `tabSample` s
			where se.name = s.sample_entry and s.name = '%s'"""%(sample_no),as_list=1)

	return ((len(ret[0]) > 1) and ret[0] or ret[0][0]) if ret else None


'''
Precondition: If g[i] is greater than s[i], then g[i+1] must be greater than s[i].

1. Ascend a unsorted lists
2. 현재 주려는 쿠키가 아이가 원하는 쿠키 사이즈보다 크거나 같다면
    아이에게 쿠키를 주고, 다음 아이와 다음 쿠키를 가져옵니다.
3. 현재 주려는 쿠키가 아이가 원하는 쿠키 사이즈보다 작다면
    다음 쿠키를 가져옵니다. (precondition)
4. 쿠키를 받은 아이의 수를 반환합니다.
'''

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:

        # Ascend lists
        g.sort()
        s.sort()

        # Declare variable
        '''
        i:  The minimum size of a cookie a child wants
        j:  cookie size
        '''
        i = j = 0

        # Find the maximum number of children who received cookies
        while i < len(g) and j < len(s):
            if g[i] <= s[j]:
                i += 1
            j += 1

        return i

'''
Time complexity: O(n)
Space complexity: O(n^2)
'''


# Databricks notebook source
dbutils.widgets.text("subscription_id", "")
dbutils.widgets.text("resource_group", "")
dbutils.widgets.text("azure_ml_workspace_name", "")
dbutils.widgets.text("model_project_name", "")
dbutils.widgets.text("path_to_mlflow_experiment", "")

# COMMAND ----------

# MAGIC %md
# MAGIC ### Deploy Model as a Web Service in AML
# MAGIC
# MAGIC

# MAGIC The MLFlow model will conainerized and deployed as a web service with AML and Azure Container Instances

# COMMAND ----------

from pyspark.sql.types import *
from pyspark.sql.functions import *
import mlflow
import mlflow.spark
import mlflow.sklearn
import mlflow.azureml
from mlflow.exceptions import RestException
import azureml
import azureml.core

# COMMAND ----------

# MAGIC %md
# MAGIC ## Step 1: Upload and Read Sensor Dataset
# MAGIC
# MAGIC For the training dataset, you will need to upload some data to the Databricks File System (DBFS). Go to File > Upload Data and click "Browse" in the middle box to bring up your file explorer for your local computer. Navigate to the place where you downloaded the artifacts for this workshop and go into the `/Datasets` folder and choose `sensordata.csv`. Once you see a green checkmark, then you just need to press **Next** and then **Done** on the next screen.

# COMMAND ----------

# MAGIC %md
# MAGIC Here we will be creating a database to store some of the tables that we will create during this workshop. The first table will be a Delta Lake table that will hold our uploaded sensor data.

# COMMAND ----------

MODEL_PROJECT_NAME = dbutils.widgets.get("model_project_name")
spark.sql(f"CREATE DATABASE IF NOT EXISTS {MODEL_PROJECT_NAME}")
username = spark.sql("SELECT current_user()").collect()[0][0]
sensorData = spark.read.csv(f"dbfs:/FileStore/shared_uploads/{username}/sensordata.csv", header=True, inferSchema=True)
sensorData.write.saveAsTable(f"{DB_NAME}.sensor", format="delta", mode="overwrite")
dataDf = spark.table("sensor").where(col('Device') == 'Device001')

# COMMAND ----------

# MAGIC %md
# MAGIC With our sensor data table saved, we can create an MLFlow Experiment to house the metrics that we log during our training runs.
# MAGIC
# MAGIC First, within our workspace, we need to create a location for the experiment to be created. Go to a location and create a folder to hold the experiment. Copy the path to the newly-created folder into the `PATH_TO_MLFLOW_EXPERIMENT` variable.
# MAGIC
# MAGIC Next, we first establish a `MlflowClient()` which gives us a connection to the MLFlow Tracking Server and allows us to issue commands via the MLFlow API to do things like create experiments, which we do using `client.create_experiment()`.

# COMMAND ----------

from mlflow.tracking import MlflowClient
PATH_TO_MLFLOW_EXPERIMENT = "ENTER PATH HERE"
client = MlflowClient()
try:
  experiment_id = client.create_experiment(PATH_TO_MLFLOW_EXPERIMENT)
except RestException as r:
  print("Experiment Already Exists, loading experiment...")
except Exception as e:
  print(e)
mlflow.set_experiment(PATH_TO_MLFLOW_EXPERIMENT)

# COMMAND ----------

# MAGIC %md
# MAGIC In this next cell, we take the sensor data and create test and training datasets by splitting up the table using a randomized distribution of data.

# COMMAND ----------

import pandas as pd
import random

#Setup Test/Train datasets
data = dataDf.toPandas()
x = data.drop(["Device", "Time", "Sensor5"], axis=1)
y = data[["Sensor5"]]
train_x, test_x, train_y, test_y = train_test_split(x,y,test_size=0.20, random_state=30)

# COMMAND ----------

# MAGIC %md
# MAGIC With our training and test dataset ready, we are able to run a few training runs for our model.
# MAGIC
# MAGIC We are going to run three runs of the `RandomForestClassifier` from sklearn using the following parameters:
# MAGIC ```python
# MAGIC numEstimators = [10, 15, 20]
# MAGIC maxDepths = [15, 20, 25]
# MAGIC ```
# MAGIC
# MAGIC We will also be leveraging the sklearn autologger to log the parameters for each run, as well as key metrics and the trained model itself. The autologging capabilities of MLFlow make it even easier to get started with training your models and tracking your model performance over various training runs.

# COMMAND ----------

from sklearn.linear_model import LinearRegression, Lasso
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.ensemble import RandomForestRegressor

def fetch_logged_data(run_id):
    client = mlflow.tracking.MlflowClient()
    data = client.get_run(run_id).data
    tags = {k: v for k, v in data.tags.items() if not k.startswith("mlflow.")}
    artifacts = [f.path for f in client.list_artifacts(run_id, "model")]
    return data.params, data.metrics, tags, artifacts

numEstimators = [10, 15, 20]
maxDepths = [15, 20, 25]

mlflow.sklearn.autolog()

for (numEstimator, maxDepth) in [(numTree, maxDepth) for numEstimator in numEstimators for maxDepth in maxDepths]:
  with mlflow.start_run(run_name="Sensor Regression") as run:
    # Fit, train, and score the model
    model = RandomForestRegressor(max_depth = maxDepth, n_estimators = numEstimator)
    model.fit(train_x, train_y)
    preds = model.predict(test_x)

# COMMAND ----------

params, metrics, tags, artifacts = fetch_logged_data(run.info.run_id)

# COMMAND ----------

# MAGIC %md
# MAGIC ## Step 2: Deploy Model to a Azure Container Instance via MLFlow + AzureML
# MAGIC
# MAGIC The next few steps will walk you through the deployment of the model to Azure Machine Leaning Service.

# COMMAND ----------

from azureml.core import Workspace
from azureml.core.webservice import AciWebservice, AksWebservice
from datetime import datetime

# COMMAND ----------

# MAGIC %md
# MAGIC In this cell, we grab the latest run ID, which is needed to know what model from what run to deploy to AzureML.

# COMMAND ----------

expId = mlflow.get_experiment_by_name(PATH_TO_MLFLOW_EXPERIMENT).experiment_id
last_run_id = spark.read.format("mlflow-experiment").load(expId).orderBy(col("end_time").desc()).select("run_id").limit(1).collect()[0][0]
model_uri = "runs:/"+last_run_id+"/model"

# COMMAND ----------

# MAGIC %md
# MAGIC Here we establish a connection to the AzureML workspace so that we can deploy the model that is logged in MLFlow.

# COMMAND ----------

workspace_name = dbutils.widgets.get("azure_ml_workspace_name")
subscription_id = dbutils.widgets.get("subscription_id")
resource_group = dbutils.widgets.get("resource_group")

ws = Workspace.get(name=workspace_name,
               subscription_id=subscription_id,
               resource_group=resource_group)

# COMMAND ----------

# MAGIC %md
# MAGIC In this cell, we establish a `Deployment Configuration` in which we enable logging to Application Insights to ensure that we can capture and query model response and trace information for monitoring purposes.

# COMMAND ----------

service_config = AciWebservice.deploy_configuration(cpu_cores=1, memory_gb=1, enable_app_insights=True, collect_model_data=True)

# COMMAND ----------

# MAGIC %md
# MAGIC In this last cell, the model from MLFlow and the Deployment Configuration are packaged together, sent to Azure ML, and deployed as an endpoint hosted on an Azure Container Instance.

# COMMAND ----------

azure_service, azure_model = mlflow.azureml.deploy(model_uri=model_uri,
                                                   service_name=endpointName,
                                                   workspace=ws,
                                                   deployment_config=service_config,
                                                   synchronous=True,
                                                   tags={"mlflowExperiment":PATH_TO_MLFLOW_EXPERIMENT, "modelProjectName": MODEL_PROJECT_NAME})


# [num. channel, height, width], [num, size]
import numpy as np
from config import N, W, LESS_N
import torch

def seqMappingCost(tasks, schedule, flexable=False):
    time = 0
    cost = 0
    for i in range(0, len(schedule)):
        t_idx = int(schedule[i])
        if t_idx >= LESS_N and flexable:
            continue
        tk = tasks[:, t_idx]
        exe_time = max(tk[0], time)
        time = (exe_time + tk[2]) * (exe_time <= (tk[0] + tk[1])) + time * (exe_time > (tk[0] + tk[1]))
        cost = cost + (exe_time - tk[0]) * tk[3] * (exe_time <= (tk[0] + tk[1]))
        cost = cost + tk[4] * (exe_time > (tk[0] + tk[1]))

    return cost

# [height, width], [size] ([0 1 ..0, 1 0 ..., ])
def predictCost(tasks, predict, _N=N, flexable=False):
    # num = tasks.shape[0]
    schedule = np.zeros([_N])
    predict = np.reshape(predict, [_N, _N + 1])
    indices = set(i for i in range(0, _N))
    for i in range(0, _N):
        srt = np.argsort(predict[:, i])[::-1]
        while srt[0] not in indices:
            srt = srt[1::]
        schedule[i] = srt[0]
        indices.remove(srt[0])

    return seqMappingCost(tasks, schedule, flexable=flexable)

def capedActivation(cap=W):
    def f(tensor):
        c = torch.ones(tensor.size()) * cap
        c = c.to('cuda')
        return torch.fmin(tensor, c)

    return f

# outputs and labels shape: [1,110]
def cost_stat(LOADER, _model, flexable=False):
    L = len(LOADER)
    out_cost = np.zeros([L])
    optimal_cost = np.zeros([L])
    for _i, _data in enumerate(LOADER, 0):
        if _i % 500 == 0:
            print(_i)
        _inputs, _labels = _data
        tasks = _inputs[0, 0, :, :].cpu().detach().numpy()
        _outputs = _model(_inputs.to('cuda').float())
        out_cost[_i] = predictCost(tasks, _outputs[0, :].cpu().detach().numpy(), flexable=flexable)
        optimal_cost[_i] = predictCost(tasks, _labels[0, :].cpu().detach().numpy(), _N=LESS_N)

    return out_cost, optimal_cost


import tkinter as tk
import os
from tkinter import ttk
from tkinter.constants import NSEW, NW, TOP

class TkinterApp:
    def __init__(self, appname="TkinterApp", width=400, height=400):
        self.appname = appname
        self.width = width
        self.height = height

        self.root = tk.Tk()
        self.root.geometry(f"{self.width}x{self.height}")

        self.root.title(self.appname)
        if os.name == "nt":
            self.root.wm_iconbitmap(bitmap="python3.ico")
        else:
            self.root.wm_iconbitmap(bitmap="@python3.xbm")
        self.root.iconphoto(self.root._w, tk.PhotoImage(file="python3.png"))

        self.root.resizable(width=True, height=True)

        self.root.pack_propagate(False)

        self.frame = tk.Frame(
            self.root, width=self.width, height=self.height, background="green"
        )
        self.frame.pack(padx=5, pady=5)
        self.frame.pack_propagate(False)
        self.frame.grid_propagate(False)
        self.frame.grid_rowconfigure(0, weight=1)
        self.frame.grid_columnconfigure(0, weight=1)
        self.frame.grid_columnconfigure(1, weight=1)

        self.frame_grid = tk.Frame(
            self.frame, highlightbackground="black", highlightthickness=1
        )
        self.frame_grid.grid(row=0, column=0, sticky=NSEW)
        self.frame_grid.grid_columnconfigure(0, weight=1)
        self.frame_grid.grid_rowconfigure(0, weight=1)
        self.frame_grid.grid_rowconfigure(1, weight=1)

        self.frame_pack = tk.Frame(
            self.frame, highlightbackground="red", highlightthickness=1
        )
        self.frame_pack.grid(row=0, column=1, sticky=NSEW)

        # Using grid
        self.label_grid = tk.Label(self.frame_grid, text="Hello World")
        self.label_grid.grid(row=0, column=0)
        self.sizegrip_grid = ttk.Sizegrip(self.frame_grid)
        self.sizegrip_grid.grid(row=1, sticky=NW)

        # Using pack
        self.label_pack = tk.Label(self.frame_pack, text="Hello World")
        self.label_pack.pack(padx=5, pady=5)
        self.sizegrip_pack = ttk.Sizegrip(self.frame_pack)
        self.sizegrip_pack.pack(side=TOP, anchor=NW)

    def start(self):
        self.center_window()
        self.root.mainloop()

    def center_window(self):
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        self.root.geometry(
            f"{self.width}x{self.height}+{screen_width//2-self.width//2}+{screen_height//2-self.height//2}"
        )

def main():
    app = TkinterApp("Sizegrip", 700, 500)
    app.start()

if __name__ == "__main__":
    main()


import typing
from abc import ABCMeta, abstractmethod as abstract_method
from collections import defaultdict as default_dict

from data_providers.exceptions import with_context

__all__ = [
    'BaseDataProvider',
    'DataProvider',
    'MutableDataProviderMixin',
]

TKey = typing.TypeVar('TKey', bound=typing.Hashable)
TVal = typing.TypeVar('TVal')

class BaseDataProvider(typing.Generic[TKey, TVal], metaclass=ABCMeta):
    """
    Implementation of the flywheel pattern.  Bulk-loads data from a backend
    and parcels them out on an as-needed basis.
    """

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

        self._cache = self._create_cache()
        """
        Caches data loaded from the backend so that it can be accessed easily.
        """

        self._pending_load_keys: typing.Set[typing.Hashable] = set()
        """
        Stores lookup keys for values that haven't been loaded yet.

        Note: This value should be a set; if you find yourself wanting to use a
        dict here, :py:class:`BaseDataProviderDelegate` is probably a better
        fit for your use case.
        """

        self._pending_cache_keys: typing.Dict[
            typing.Hashable,
            typing.Set[typing.Hashable]
        ] = default_dict(set)
        """
        Stores cache keys for values that haven't been loaded yet.

        This is used to gracefully handle cases where the backend doesn't
        return data for one or more load keys.
        """

    def __getitem__(self, value: TKey) -> TVal:
        """
        Returns data for the specified value.

        :param value:
            The lookup key.

        :raise:
            - :py:class:`ValueError` if the value wasn't registered first.
        """
        # Determine the key we will use to look up the value in the cache.
        cache_key = self.gen_cache_key(value)
        if cache_key is None:
            return self.gen_empty_result()

        try:
            cached = self._get_from_cache(cache_key)
        except KeyError:
            # The value has not been cached yet.
            # Determine which data we need to load from the backend.
            load_key = self.gen_load_key(value)
            if load_key is None:
                cached = self.gen_empty_result()
            else:
                # If the key hasn't been registered, we cannot continue.
                # If we were to allow loading without registering, we would
                # undermine the whole point of using a flywheel in the first
                # place!
                if load_key not in self._pending_load_keys:
                    raise with_context(
                        ValueError(
                            f'Attempting to get data for '
                            'unregistered value {value!r}.',
                        ),

                        context={
                            'cacheKey': cache_key,
                            'loadKey': load_key,
                            'value': value,
                        },
                    )

                # Load data from the backend and populate/extend the cache.
                self._load_data(load_key)

                # Try loading from cache again, this time without a safety net.
                cached = self._get_from_cache(cache_key)

        return cached

    @abstract_method
    def fetch_from_backend(self, load_keys: typing.Set[typing.Hashable]) -> \
            typing.Union[
                typing.Mapping[typing.Hashable, TVal],
                typing.Iterable[typing.Tuple[typing.Hashable, TVal]],
            ]:
        """
        Fetches data from the backend for the specified load keys.

        :return:
            A mapping, or a generator that yields (key, value) pairs.

            The keys in the resulting mapping should correspond to the data
            provider's cache keys (from :py:meth:`gen_cache_key`).
        """
        raise NotImplementedError(
            'Not implemented in {cls}.'.format(cls=type(self).__name__),
        )

    def gen_load_key(self, key: TKey) -> typing.Optional[typing.Hashable]:
        """
        Extracts the value that will be used by the backend to load
        data for the specified value.

        If this method returns ``None``, then the data provider will
        never attempt to return data for that value; if that value is
        passed to :py:meth:`__getitem__`, the data provider will return
        an empty result instead (see :py:meth:`gen_empty_result`).

        :param key:
            The key passed to :py:meth:`__getitem__`.
        """
        return key

    def gen_cache_key(self, key: TKey) -> typing.Optional[typing.Hashable]:
        """
        Generates a lookup key for the data provider's cached data.

        If this method returns ``None``, then the data provider will never
        attempt to return data for that value; if that value is passed to
        :py:meth:`__getitem__`, the data provider will return an empty result
        instead (see :py:meth:`gen_empty_result`).

        :param key:
            The key value passed to ``__getitem__``.
        """
        return self.gen_load_key(key)

    def gen_empty_result(self) -> typing.Optional[TVal]:
        """
        Generates an empty result that is returned if the backend cannot (or
        will not) return data for a particular key.

        You may override this method in a subclass if desired.  This method may
        return any value, or even raise an exception, depending on the use
        case.
        """
        return None

    def register(self, values: typing.Iterable[TKey]) -> None:
        """
        Registers a set of values so that the data provider can plan out the
        bulk queries it needs to execute against the backend.
        """
        for v in values:
            self._add_to_key_registry(v)

    def warm_cache(self):
        """
        Warms the cache, fetching data for any keys that haven't been loaded
        yet.

        Note: the data provider will automatically load data from the backend
        as needed.  In general, you shouldn't have to invoke this method,
        though it can be useful in particular during debugging.
        """
        if self._pending_load_keys:
            self._load_batch(self._pending_load_keys)

    # noinspection PyMethodMayBeStatic
    def _create_cache(self) -> typing.MutableMapping[typing.Hashable, TVal]:
        """
        Initializes the cache that the data provider will use.

        You may override this method in a subclass if desired; the only
        restriction is that it must return some kind of mutable mapping.
        """
        return {}

    def _add_to_cache(self,
            cache_key: typing.Hashable,
            cache_value: TVal,
    ) -> None:
        """
        Adds a value to the cache.

        If there is an existing value with the same key, it is overwritten.

        You may override this method in a subclass if desired.
        """
        self._cache[cache_key] = cache_value

    def _get_from_cache(self, cache_key: typing.Hashable) -> TVal:
        """
        Attempts to retrieve the data from the cache for the specified key.

        You may override this method in a subclass if desired.

        :raise:
          - :py:class:`KeyError` in the event of a cache miss.
        """
        return self._cache[cache_key]

    def _add_to_key_registry(self, key: TKey) -> None:
        """
        Adds the specified value to the registry of unloaded keys.

        :param key:
            The key that was passed to :py:meth:`register`.
        """
        # If we can't load data for a value, then there's no point in
        # registering it.
        load_key = self.gen_load_key(key)
        if load_key is not None:
            # If we can't cache data for a value, then there would be no point
            # in loading data for it.
            # Also, we don't need to register a value if we already have cached
            # data for it.
            cache_key = self.gen_cache_key(key)
            if (cache_key is not None) and (cache_key not in self._cache):
                # Queue the load key for the next time we call
                # :py:meth:`_load_data`.
                self._pending_load_keys.add(load_key)

                # Queue the corresponding cache key so that we can ensure that
                # *some* kind of value is cached, even if the backend doesn't
                # return any data for it.
                self._pending_cache_keys[load_key].add(cache_key)

    # noinspection PyUnusedLocal
    def _get_keys_to_load(self,
            hint: typing.Hashable,
    ) -> typing.Set[typing.Hashable]:
        """
        Used by :py:meth:`_load_data` to decide which values to send to the
        backend.

        By default, this method returns all pending load keys, but you may
        override this method in a subclass if you want to use a more selective
        strategy.

        :param hint:
            The requested load key (based on the key passed to
            :py:meth:`__getitem__`).  This can be useful if the data provider
            only needs to load a subset of the data depending on which key the
            caller requested data for.
        """
        return self._pending_load_keys

    def _load_data(self, hint: typing.Hashable) -> None:
        """
        Bulk-loads data from the backend in the event of a cache miss.

        :param hint:
            The requested load key (based on the key passed to
            :py:meth:`__getitem__`).  Passed to :py:meth:`_get_keys_to_load`,
            in case only a subset of the data should be loaded depending on
            which key the caller requested data for.
        """
        batched_load_keys = self._get_keys_to_load(hint)
        if batched_load_keys:
            self._load_batch(batched_load_keys)

    def _load_batch(self, load_keys: typing.Set[typing.Hashable]) -> None:
        """
        Bulk-loads data from the backend, only for the specified keys.
        """
        loaded = self.fetch_from_backend(load_keys)

        # :py:meth:`fetch_from_backend` is expected to return a mapping, or at
        # least a value that quacks like one.
        if isinstance(loaded, typing.Generator):
            iterator = loaded
        else:
            if not isinstance(loaded, typing.Mapping):
                loaded = dict(loaded)

            iterator = loaded.items()

        for cache_key, cache_value in iterator:
            # The backend can overwrite any existing cached values.
            # You may override :py:meth:`_add_to_cache` in a subclass if this
            # is not desirable behavior.
            self._add_to_cache(cache_key, cache_value)

        # Fill in any missing cache keys that weren't included in the result
        # from the backend.
        for lk in load_keys:
            for pck in self._pending_cache_keys[lk]:
                if pck not in self._cache:
                    self._add_to_cache(pck, self.gen_empty_result())
            self._pending_cache_keys.pop(lk, None)

        self._pending_load_keys -= load_keys

class MutableDataProviderMixin(
    BaseDataProvider[TKey, TVal],
    metaclass=ABCMeta,
):
    """
    A mixin for data provider classes that allow external code to modify the
    contents of the cache.

    Any values set this way will override values returned by the backend.
    """

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

        self._override_cache_keys: typing.Set[typing.Hashable] = set()

    def __setitem__(self, key: TKey, cache_value: TVal) -> None:
        """
        Sets the cached value for the specified object.

        :param key:
            Same as :py:meth:`__getitem__`.

        :param cache_value:
            The value that should be put in the cache.
        """
        load_key = self.gen_load_key(key)
        if load_key is not None:

            cache_key = self.gen_cache_key(key)
            if cache_key is not None:

                # Since we are setting the cached value explicitly, we do not
                # need to backfill it when :py:meth:`_load_data` runs.
                pending_cache_keys = self._pending_cache_keys[load_key]
                pending_cache_keys.discard(cache_key)

                # If there are no [other] registered cache keys associated with
                # this load key, then we won't have to load any data for that
                # key (i.e., we can drop it).
                if not pending_cache_keys:
                    self._pending_load_keys.discard(load_key)

                # Allow :py:meth:`__setitem__` to override values more than
                # once.
                self._override_cache_keys.discard(cache_key)

                self._replace_cached_value(cache_key, cache_value)
                self._override_cache_keys.add(cache_key)

    def _replace_cached_value(self,
            cache_key: typing.Hashable,
            cache_value: TVal,
    ) -> None:
        """
        Replaces a value in the cache.

        You may override this method in a subclass if desired.

        Note: this method must *not* raise an exception.
        """
        self._add_to_cache(cache_key, cache_value)

    def _add_to_cache(self,
            cache_key: typing.Hashable,
            cache_value: TVal,
    ) -> None:
        """
        Adds a value to the cache, if it has not been overridden by
        :py:meth:`__setitem__`.
        """
        if cache_key not in self._override_cache_keys:
            super(MutableDataProviderMixin, self) \
                ._add_to_cache(cache_key, cache_value)

class DataProvider(MutableDataProviderMixin[TKey, TVal]):
    """
    Basic data provider implementation.
    """

    def __init__(self,
            loader: typing.Callable[
                [typing.Set[TKey]],
                typing.Union[
                    typing.Mapping[TKey, TVal],
                    typing.Iterable[typing.Tuple[TKey, TVal]],
                ],
            ],
    ) -> None:
        """
        :param loader:
            The function that will be used to load the values from the backend.

            The function must accept a set of load keys and return a dict or
            tuple of key/value pairs, so that it can associate each load key
            with the corresponding data from the backend.

        Example:

        .. code-block:: python

           def get_users_by_id(user_ids: Set[int]) -> Dict[int, dict]:
               '''
               Load user records for the specified IDs and return the
               corresponding rows.
               '''
               # ...

           dp = DataProvider(get_users_by_id)
           dp.register(user_ids)

           for user_id in user_ids:
               # ``dp[user_id]`` will be the row the bulk-query returned
               # for the that user ID.
               do_something_with(dp[user_id])

        Refer to the unit test for more examples.
        """
        super().__init__()

        self.loader = loader

    def fetch_from_backend(self,
            load_keys: typing.Set[TKey]
    ) -> typing.Union[
        typing.Mapping[TKey, TVal],
        typing.Iterable[typing.Tuple[TKey, TVal]],
    ]:
        """
        Execute the loader function to bulk-load data from the backend.
        """
        return self.loader(load_keys)


from django.shortcuts import render
from django.db import models
from FamiliApp.models import Familiar
from django.template import Template, loader
from django.http import HttpResponse
# Create your views here.

def familiapp_inicio(request):
    familiar1 = Familiar(nombre = "Jorge", apellido="Rojas", edad=50, ultimo_asado = "01/01/2000")
    familiar1.save()
    familiar2 = Familiar(nombre = "Marcelo", apellido="Miraglia", edad=57, ultimo_asado = "17/05/2017")
    familiar2.save()
    familiar3 = Familiar(nombre = "Juan", apellido="Moreira", edad=37, ultimo_asado = "24/02/1995")
    familiar3.save()
    diccionario = {
        "f1nombre": familiar1.nombre, "f1apellido":familiar1.apellido, "f1edad":familiar1.edad, "f1ultimo_asado":familiar1.ultimo_asado,
        "f2nombre": familiar2.nombre, "f2apellido":familiar2.apellido, "f2edad":familiar2.edad, "f2ultimo_asado":familiar2.ultimo_asado,
        "f3nombre": familiar3.nombre, "f3apellido":familiar3.apellido, "f3edad":familiar1.edad, "f3ultimo_asado":familiar3.ultimo_asado
    }
    plantilla = loader.get_template('FamiliApp/familiapp_inicio.html')
    documento= plantilla.render(diccionario)
    return HttpResponse(documento)


from base import *
from matplotlib import pyplot as plt
from filters.spatialFilters import spatialFilterClass
from filters.frequencyFilters import frequencyFilterClass

class dataLoader:
    def __init__(self, cfg):
        self.cfg = cfg
        self.spatial = cfg["spatial"]
        self.frequency = cfg["frequency"]
        self.objS = spatialFilterClass(cfg)
        self.objF = frequencyFilterClass(cfg)

    def loadImage(self):
        if self.cfg["type"] == "image":
            imagePath = Image.open(self.cfg["path"]) #Loads Image
            imgResize = imagePath.resize((self.cfg["height"],self.cfg["width"])) #Resizes Image
            self.img = np.array(imgResize) #Converts to numpy array
            self.imgPadded = np.pad(self.img,((1,1),(1,1),(0,0)),'constant')
        else:
            file = open(self.cfg["path"], "r")
            matrix = []
            for row in file:
                matrix.append([int(x) for x in row.split()])

            self.img = np.array(matrix)
            self.imgPadded = np.pad(self.img, [(1, 1), (1, 1)], mode='constant')

    def save(self,ans):
        save_path = "outputs/result"
        if self.cfg["type"] == "image":
            plt.imshow(ans)
            plt.savefig(save_path +".jpg")

        else:
            f  = open(save_path, "w")
            f.write(str(ans))
            f.close()

    def execute(self):
        self.loadImage()
        if self.spatial:
            for i in self.spatial:
                if self.spatial[i] is True:
                    try:
                        method = getattr(self.objS,i)
                        ans = method(self.imgPadded)
                    except AttributeError:
                        ans = None

        if self.frequency:
            for i in self.frequency:
                if self.frequency[i] is True:
                    ans = self.objF.start(self.img,i)

        if ans is None:
            print("Incorrect Domain / Filter not found ")
        else:
            if self.cfg["save"]:
                self.save(ans)
            else:
                display(self.cfg["type"], ans)


import paho.mqtt.client as mqtt
import ssl
import json
import _thread
import time
from datetime import datetime

broker = "a1vs29u7y7oh8s-ats.iot.eu-west-1.amazonaws.com"
caPath = "./AmazonRootCA1.pem"
certPath = "./certificate.pem.crt"
keyPath = "./private.pem.key"
topic = "sesnor/temp"

def on_connect(client, userdata, flags, rc):
    print("Connected to AWS IoT: " + str(rc))

client = mqtt.Client()
client.on_connect = on_connect
client.tls_set(ca_certs=caPath, certfile=certPath,
               keyfile=keyPath, tls_version=ssl.PROTOCOL_SSLv23)
client.tls_insecure_set(True)
client.connect(broker, 8883, 60)

def publishData():

    while (True):
        timestamp = datetime.now().strftime("%m/%d/%Y, %H:%M:%S")
        data = json.dumps({"timestamp": timestamp,
                           "device_id":"sensor-1",
                           "tempC": 10})
        client.publish(topic, payload=data,qos=0, retain=False)
        print("published")
        time.sleep(5)

_thread.start_new_thread(publishData,())

client.loop_forever()