from unittest import mock
import os
import sys
import unittest

from cgf_utils.data_utils import Data

class UnitTest_CloudGemFramework_LambdaSettings(unittest.TestCase):

    def setUp(self):

        if 'cgf_lambda_settings' in sys.modules:
            del sys.modules['cgf_lambda_settings']

        if 'CloudCanvas' in sys.modules:
            del sys.modules['CloudCanvas']

    @mock.patch('cgf_lambda_settings._LambdaSettingsModule__load_settings')
    def test_settings_loaded_when_imported(self, mock_load_settings):
        import cgf_lambda_settings
        self.assertIs(cgf_lambda_settings.settings, mock_load_settings.return_value)
        self.assertIs(cgf_lambda_settings.settings, mock_load_settings.return_value)
        mock_load_settings.assert_called_once_with()

    @mock.patch('cgf_lambda_settings._LambdaSettingsModule__load_settings', return_value = Data({'Test': 'Settings'}))
    def test_get_settings_returns_setting_value(self, mock_load_settings):
        import CloudCanvas
        import cgf_lambda_settings
        self.assertEquals(cgf_lambda_settings.settings.Test, 'Settings')
        self.assertEquals(cgf_lambda_settings.get_setting('Test'), 'Settings')
        self.assertEquals(CloudCanvas.get_setting('Test'), 'Settings')

    @mock.patch('os.path.isfile', return_value = True)
    @mock.patch('json.load', return_value = { 'Test': 'Setting' })
    def test_load_settings_loads_settings_file(self, mock_json_load, mock_isfile):
        import cgf_lambda_settings
        mock_open = mock.mock_open()
        with mock.patch('builtins.open', mock_open, create = True):
            expected_path = os.path.abspath(os.path.join(__file__, '..', '..', 'cgf_lambda_settings', 'settings.json'))
            result = cgf_lambda_settings._LambdaSettingsModule__load_settings()
            self.assertEquals(result.DATA, mock_json_load.return_value)
            mock_isfile.assert_called_once_with(expected_path)
            mock_open.assert_called_once_with(expected_path, 'r')
            mock_handle = mock_open()
            mock_json_load.assert_called_once_with(mock_handle)


from pathlib import Path
import time
from typing import List

import cv2
from loguru import logger
import numpy as np

from actions.action import Action
from actions.converter import Converter
from actions.indexer import GraspIndexer, ShiftIndexer, GraspShiftIndexer
from data.loader import Loader
from config import Config
from inference.planar import InferencePlanarPose
from picking.epoch import Epoch
from picking.image import clone, draw_around_box, draw_pose, get_area_of_interest, patch_image_at
from picking.param import SelectionMethod
from picking.planning_tree import PlanningTree
from orthographical import OrthographicImage

class Agent:
    def __init__(self, prediction_model):
        self.grasp_model = Config.grasp_model
        self.shift_model = Config.shift_model

        self.with_types = 'types' in self.grasp_model[1]

        self.output_layer = 'prob' if not self.with_types else ['prob', 'type']
        self.grasp_inference = InferencePlanarPose(
            Loader.get_model(self.grasp_model, output_layer=self.output_layer),
            box=Config.box,
            lower_random_pose=Config.lower_random_pose,
            upper_random_pose=Config.upper_random_pose,
            with_types=self.with_types,
            input_uncertainty=True,
        )
        self.grasp_inference.keep_indixes = [0, 1]
        self.grasp_indexer = GraspIndexer(gripper_classes=Config.gripper_classes)

        self.shift_inference = InferencePlanarPose(
            Loader.get_model(self.shift_model, output_layer='prob'),
            box=Config.box,
            lower_random_pose=Config.lower_random_pose,
            upper_random_pose=Config.upper_random_pose,
            with_types=False,
        )
        self.shift_inference.a_space = np.linspace(-3.0, 3.0, 26)  # [rad] # Don't use a=0.0
        self.shift_inference.size_original_cropped = (240, 240)
        self.shift_indexer = ShiftIndexer(shift_distance=Config.shift_distance)

        self.grasp_shift_indexer = GraspShiftIndexer(
            gripper_classes=Config.gripper_classes,
            shift_distance=Config.shift_distance,
        )

        self.converter = Converter(grasp_z_offset=Config.grasp_z_offset, shift_z_offset=0.007, box=Config.box)  # [m]

        self.prediction_model = prediction_model
        self.monte_carlo = 20

        self.actions_since_last_inference = 0
        self.actions: List[Action] = []

        self.output_path = Path.home() / 'Desktop'

        self.reinfer_next_time = True

        # First inference is slower
        self.prediction_model.predict([np.zeros((1, 64, 64, 1)), np.zeros((1, 1, 1, 1)), np.zeros((1, 1, 1)), np.zeros((1, 1, 1, 8))])

    def predict_images_after_action(
            self,
            images: List[OrthographicImage],
            action: Action,
            reward: float,
            action_type: int,
            uncertainty_images=None,
        ) -> List[OrthographicImage]:
        image = images[0]
        uncertainty_image = uncertainty_images[0]

        start = time.time()
        draw_around_box(image, box=Config.box)
        area = get_area_of_interest(image, action.pose, size_cropped=(256, 256), size_result=(64, 64))

        area_input = np.expand_dims(area.mat, axis=2).astype(np.float32) / np.iinfo(np.uint16).max * 2 - 1
        reward = np.expand_dims(np.expand_dims(np.expand_dims(reward, axis=1), axis=1), axis=1).astype(np.float32)
        action_type = np.expand_dims(np.expand_dims(action_type, axis=1), axis=1)

        use_monte_carlo = self.monte_carlo and self.monte_carlo > 1

        if not use_monte_carlo:
            area_result = self.prediction_model.predict([[area_input], [reward], [action_type], np.zeros((1, 1, 1, 8))])[0]
            area_result = np.array(np.iinfo(np.uint16).max * (area_result + 1) / 2, dtype=np.uint16)

        else:
            latent = np.random.normal(scale=0.05, size=(self.monte_carlo, 1, 1, 8))
            if self.monte_carlo > 3:
                latent[0, :, :, :] = 0.0

            predictions = self.prediction_model.predict([
                [area_input for _ in range(self.monte_carlo)],
                [reward for _ in range(self.monte_carlo)],
                [action_type for _ in range(self.monte_carlo)],
                latent,
            ])
            predictions = (predictions + 1) / 2

            predictions = np.array(predictions, dtype=np.float32)
            area_result = predictions[0]
            area_result = np.array(np.iinfo(np.uint16).max * area_result, dtype=np.uint16)

            predictions[predictions < 0.1] = np.nan
            area_uncertainty = np.nanvar(predictions, axis=0)
            area_uncertainty *= 7e3
            area_uncertainty[area_uncertainty > 1] = 1
            area_uncertainty = np.array(np.iinfo(np.uint16).max * area_uncertainty, dtype=np.uint16)

            uncertainty_image = patch_image_at(
                uncertainty_image,
                area_uncertainty,
                action.pose,
                size_cropped=(256, 256),
                operation='add',
            )

        result = patch_image_at(image, area_result, action.pose, size_cropped=(256, 256))

        logger.info(f'Predicted image [s]: {time.time() - start:0.3f}')

        if use_monte_carlo:
            return [result], [uncertainty_image]
        return [result]

    def plan_actions(
            self,
            images: List[OrthographicImage],
            method: SelectionMethod,
            depth=1,
            leaves=1,
            verbose=False,
        ) -> List[Action]:

        uncertainty_images = [OrthographicImage(
            np.zeros(i.mat.shape, dtype=np.uint16),
            i.pixel_size,
            i.min_depth,
            i.max_depth,
            i.camera,
            i.pose
        ) for i in images]

        tree = PlanningTree(images, uncertainty_images)

        for node, i in tree.fill_nodes(leaves=leaves, depth=depth):
            # Visited actions: node.actions

            for image in node.images:
                draw_around_box(image, box=Config.box)

            grasp = self.grasp_inference.infer(node.images, method, uncertainty_images=node.uncertainty_images)
            self.grasp_indexer.to_action(grasp)

            # Shift actions
            if Config.shift_objects and grasp.estimated_reward < Config.grasp_shift_threshold:
                shift = self.shift_inference.infer(node.images, method)
                self.shift_indexer.to_action(shift)

                bin_empty = shift.estimated_reward < Config.shift_empty_threshold

                if bin_empty:
                    action = Action('bin_empty', safe=1)
                else:
                    self.converter.calculate_pose(shift, node.images)
                    action = shift

            # Grasp actions
            else:
                estimated_reward_lower_than_threshold = grasp.estimated_reward < Config.bin_empty_at_max_probability
                bin_empty = estimated_reward_lower_than_threshold and Epoch.selection_method_should_be_high(method)
                new_image = False

                if bin_empty:
                    action = Action('bin_empty', safe=1)
                elif grasp.estimated_reward_std > 0.9:  # default=0.25
                    action = Action('new_image', safe=1)
                else:
                    self.converter.calculate_pose(grasp, node.images)
                    action = grasp
            logger.info(f'{i}: {action}')

            if verbose:
                image_copy = clone(images[0])
                uncertainty_image_copy = clone(uncertainty_images[0])

                draw_pose(image_copy, action.pose, convert_to_rgb=True)
                draw_pose(uncertainty_image_copy, action.pose, convert_to_rgb=True)

                cv2.imwrite(str(self.output_path / f'result-{i}.png'), image_copy.mat)
                cv2.imwrite(str(self.output_path / f'uncertainty-{i}.png'), uncertainty_image_copy.mat)

            if action.type == 'bin_empty' or action.type == 'new_image':
                break

            # Predict next image
            reward = action.estimated_reward > Config.bin_empty_at_max_probability if action.type == 'grasp' else action.estimated_reward
            action_type = self.grasp_shift_indexer.from_action(action)
            images = self.predict_images_after_action(
                node.images,
                action,
                reward=reward,
                action_type=action_type,
                uncertainty_images=node.uncertainty_images,
            )

            if isinstance(images, tuple):
                images, uncertainty_images = images
            else:
                uncertainty_images = None

            node.add_action(action, images, uncertainty_images)

        if verbose:
            cv2.imwrite(str(self.output_path / f'result-{i+1}.png'), node.images[0].mat)
            cv2.imwrite(str(self.output_path / f'uncertainty-{i+1}.png'), node.uncertainty_images[0].mat)

        actions, max_reward, mean_reward = tree.get_actions_maximize_reward(max_depth=depth)
        print(f'Max reward: {max_reward:0.3f}, Mean reward: {mean_reward:0.3f}, Length: {len(actions)}')

        # actions, max_steps, mean_steps = tree.get_actions_minimize_steps()
        return actions

    def predict_actions(
            self,
            images: List[OrthographicImage],
            method: SelectionMethod,
            N=1,
            verbose=True,
        ) -> List[Action]:

        actions: List[Action] = []

        uncertainty_images = [OrthographicImage(
            np.zeros(i.mat.shape, dtype=np.uint16),
            i.pixel_size,
            i.min_depth,
            i.max_depth,
            i.camera,
            i.pose
        ) for i in images]

        for i in range(N):
            for image in images:
                draw_around_box(image, box=Config.box)

            grasp = self.grasp_inference.infer(images, method, uncertainty_images=uncertainty_images)
            self.grasp_indexer.to_action(grasp)

            # Shift actions
            if Config.shift_objects and grasp.estimated_reward < Config.grasp_shift_threshold:
                shift = self.shift_inference.infer(images, method)
                self.shift_indexer.to_action(shift)

                bin_empty = shift.estimated_reward < Config.shift_empty_threshold

                if bin_empty:
                    actions.append(Action('bin_empty', safe=1))
                else:
                    self.converter.calculate_pose(shift, images)
                    actions.append(shift)

            # Grasp actions
            else:
                estimated_reward_lower_than_threshold = grasp.estimated_reward < Config.bin_empty_at_max_probability
                bin_empty = estimated_reward_lower_than_threshold and Epoch.selection_method_should_be_high(method)
                new_image = False

                if bin_empty:
                    actions.append(Action('bin_empty', safe=1))
                elif grasp.estimated_reward_std > 0.9:  # default=0.25
                    actions.append(Action('new_image', safe=1))
                else:
                    self.converter.calculate_pose(grasp, images)
                    actions.append(grasp)

            actions[-1].step = i
            action = actions[-1]
            logger.info(f'{i}: {action}')

            if verbose:
                image_copy = clone(images[0])
                uncertainty_image_copy = clone(uncertainty_images[0])

                draw_pose(image_copy, action.pose, convert_to_rgb=True)
                draw_pose(uncertainty_image_copy, action.pose, convert_to_rgb=True)

                cv2.imwrite(str(self.output_path / f'result-{i}.png'), image_copy.mat)
                cv2.imwrite(str(self.output_path / f'uncertainty-{i}.png'), uncertainty_image_copy.mat)

            if action.type == 'bin_empty' or action.type == 'new_image':
                break

            # Predict next image
            reward = action.estimated_reward > Config.bin_empty_at_max_probability if action.type == 'grasp' else action.estimated_reward
            action_type = self.grasp_shift_indexer.from_action(action)
            images = self.predict_images_after_action(
                images,
                action,
                reward=reward,
                action_type=action_type,
                uncertainty_images=uncertainty_images,
            )

            if isinstance(images, tuple):
                images, uncertainty_images = images
            else:
                uncertainty_images = None

        if verbose:
            cv2.imwrite(str(self.output_path / f'result-{i+1}.png'), images[0].mat)
            cv2.imwrite(str(self.output_path / f'uncertainty-{i+1}.png'), uncertainty_images[0].mat)

        return actions

    def infer(self, images: List[OrthographicImage], method: SelectionMethod, N=5, reinfer=False):
        if self.actions_since_last_inference == 0 or self.actions_since_last_inference >= N or self.reinfer_next_time or reinfer:
            logger.warning(f'Calculate {N} predictions.')

            # self.actions = self.predict_actions(images, method, N=(N+1))
            self.actions = self.plan_actions(images, method, depth=N, leaves=1)
            self.actions_since_last_inference = 0
            self.reinfer_next_time = False
        else:
            logger.warning(f'Saved action, last inference {self.actions_since_last_inference} actions ago.')
            if self.actions_since_last_inference == len(self.actions) - 2:
                self.reinfer_next_time = True

        self.actions_since_last_inference += 1
        return self.actions[self.actions_since_last_inference - 1]


from typing import Union
import shutil
from typing import Dict
import charactors as c
from wish import EventWish

# COST = 2     #    60 /    120 yen
# COST = 1.85  #   330 /    610 yen
# COST = 1.69  # 1,090 /  1,840 yen
# COST = 1.64  # 2,240 /  3,680 yen
# COST = 1.57  # 3,880 /  6,100 yen
COST = 1.49  # 8,080 / 12,000 yen

def main(cell_width=12, width: Union[int, None] = None):
    from eastasianwidth import ljust2, width2

    if width is None:
        width = shutil.get_terminal_size().columns

    pu5 = [c.Raiden_Shogun]
    pu4 = [c.Kujou_Sara, c.Sayu, c.Rosaria]
    wish = EventWish(pu5, pu4)  # type: ignore
    gems = 0

    hit_chars: Dict[c.Charactor, int] = {}
    while True:
        carsole = 0
        pu4count = 0
        pu5count = 0
        gems += 1600
        print(f"¥{gems * COST:,.0f} / {gems:,} gems")
        for i in range(10):
            result = wish.wish()
            if result.rarity == 5:
                if result in pu5:
                    pu5count += 1
                    print('\033[38;5;220m', end='')
                else:
                    print('\033[38;5;130m', end='')
            elif result.rarity == 4:
                if result in pu4:
                    pu4count += 1
                    print('\033[38;5;045m', end='')
                else:
                    print('\033[38;5;053m', end='')
            cell = ljust2(result.name, cell_width) + ' '
            print(ljust2(result.name, cell_width), end='')
            carsole += width2(cell)
            if carsole + cell_width > width:
                carsole = 0
                print('')
            print('\033[0m', end='')

            if isinstance(result, c.Charactor):
                if result not in hit_chars:
                    hit_chars[result] = -1
                hit_chars[result] += 1

        # for _ in range(pu4count):
        #     print('\033[38;5;045m*4PU\033[0m ', end='')
        # for _ in range(pu5count):ß
        #     print('\033[38;5;220m*5PU!\033[0m ', end='')

        carsole = 0

        print('')
        for k, v in hit_chars.items():
            if k.rarity == 5:
                if k in pu5:
                    pu5count += 1
                    print('\033[38;5;220m', end='')
                else:
                    print('\033[38;5;130m', end='')
            elif k.rarity == 4:
                if k in pu4:
                    pu4count += 1
                    print('\033[38;5;045m', end='')
                else:
                    print('\033[38;5;053m', end='')

            cell = k.name + ':' + ('無' if v == 0 else str(v) if v < 6 else f'完({v})') + '凸 '
            print(ljust2(cell, cell_width), end='')
            print('\033[0m', end='')

            carsole += width2(cell)
            if carsole + cell_width > width:
                carsole = 0
                print('')

        if not input('\n') == '':
            break

if __name__ == "__main__":
    main()


from collections import deque

T = int(input())

for _ in range(T):

    p = list(input()) # 명령어를 한글자씩 분리하기
    n = int(input())
    txt = input()[1:-1].split(',')
    r_flag = False
    error_flag = False
    if txt == ['']:
        dq = deque()
    else:
        dq = deque(list(map(int, txt)))

    for i in p:
        if i == 'R':
            r_flag = not r_flag
            #dq.reverse()
        elif i == 'D':
            if dq:
                if r_flag:
                    dq.pop()
                else:
                    dq.popleft()
            else:
                print('error')
                error_flag = True
                break

    if not error_flag:
        if r_flag:
            dq.reverse()
            print(str(list(dq)).replace(' ', ''))
        else:
            print(str(list(dq)).replace(' ', ''))


from binvec import BV
from part import (PackageDIP14, Pin, PinType)
from test import TestLogic

class Part74LS51(PackageDIP14):
    name = "74LS51"
    desc = "Invert Gates"
    pin_cfg = {
        1: Pin("1A", PinType.IN),
        2: Pin("2A", PinType.IN),
        3: Pin("2B", PinType.IN),
        4: Pin("2C", PinType.IN),
        5: Pin("2D", PinType.IN),
        6: Pin("2Y", PinType.OUT),
        8: Pin("1Y", PinType.OUT),
        9: Pin("1D", PinType.IN),
        10: Pin("1E", PinType.IN),
        11: Pin("1F", PinType.IN),
        12: Pin("1B", PinType.IN),
        13: Pin("1C", PinType.IN),
    }

    test_gate1 = TestLogic("Gate 1",
        inputs=[1, 12, 13,  9, 10, 11],
        outputs=[8],
        body=[
            [[*abc, *_def],  [not (abc.vand() or _def.vand())]]
            for abc in BV.range(0, 8)
            for _def in BV.range(0, 8)
        ]
    )

    test_gate2 = TestLogic("Gate 2",
        inputs=[2, 3,  4, 5],
        outputs=[6],
        body=[
            [[*ab, *cd],  [not (ab.vand() or cd.vand())]]
            for ab in BV.range(0, 4)
            for cd in BV.range(0, 4)
        ]
    )

    tests = [test_gate1, test_gate2]


from __future__ import print_function
import random
import time
#checker True = happy, false == sad

from jokes import joke
from motivationQuotes import quotes

# --------------- Helpers that build all of the responses ----------------------

def build_speechlet_response(title, output, reprompt_text, should_end_session):
    return {
        'outputSpeech': {
            'type': 'PlainText',
            'text': output
        },
        'card': {
            'type': 'Simple',
            'title': "SessionSpeechlet - " + title,
            'content': "SessionSpeechlet - " + output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }

def build_response(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }

# --------------- Functions that control the skill's behavior ------------------------------------------
def get_sad_response():
        session_attributes = {}
        card_title = "sad"
        speech_output = "Would you like to talk about your day or do you want to hear a joke?"
        reprompt_text = "Hey! if you are still there, would you like to hear a joke?"
        should_end_session = False
        return build_response(session_attributes, build_speechlet_response(
            card_title, speech_output, reprompt_text, should_end_session))

def get_stressed_response():
        session_attributes = {}
        card_title = "stressed"
        speech_output = "You seem to be stressed, you should try the CAPS session. Say start CAPS to begin"
        reprompt_text = "Hey! are you still there?"
        should_end_session = False
        return build_response(session_attributes, build_speechlet_response(
            card_title, speech_output, reprompt_text, should_end_session))

def get_help_response():
        session_attributes = {}
        card_title = "help"
        speech_output = "You can ask for jokes, meditation session, motivational quotes and uplifing news or you can talk to me about your day"
        reprompt_text = "Do you still need help"
        should_end_session = False
        return build_response(session_attributes, build_speechlet_response(
            card_title, speech_output, reprompt_text, should_end_session))

def get_happy_response():
        session_attributes = {}
        card_title = "day"
        speech_output = "That is awesome to hear? Would you like to uplifing news to brighten your day?"
        reprompt_text = "Hey! if you are still there, would you like to listen to uplifiting news?"
        should_end_session = False
        return build_response(session_attributes, build_speechlet_response(
            card_title, speech_output, reprompt_text, should_end_session))

def get_unmotivated_response():
        session_attributes = {}
        card_title = "unmotivated"
        speech_output = "You seem to be feeling unmotivated. " +  quotes()
        reprompt_text = "Hey! if you are still there, would you like to listen to uplifiting news?"
        should_end_session = False
        return build_response(session_attributes, build_speechlet_response(
            card_title, speech_output, reprompt_text, should_end_session))

def get_joke_response():
    session_attributes = {}
    card_title = "joke"
    speech_output = joke()
    reprompt_text = "Hey! if you are still there, would you like to listen to a joke?"
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

def get_day_response():
    session_attributes = {}
    card_title = "day"

    speech_output = "I am here to listen!"
    reprompt_text = "hmmmm, I see"
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

def get_caps_response():
    session_attributes = {}
    card_title = "caps"

    speech_output = "Slow down. Take a deep breath.                            Now list what you see"
    reprompt_text = ""
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

def get_welcome_response():
    """ If we wanted to initialize the session to have some attributes we could
    add those here
    """

    session_attributes = {}
    card_title = "Welcome"
    speech_output = "Hi! How are you feeling today? I am here to help"
    # If the user either does not reply to the welcome message or says something
    # that is not understood, they will be prompted again with this text.
    reprompt_text = "Are you there? How are you feeling?"
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

#-----------------------------------------------------------------------Add responses above-----------------------
def handle_session_end_request():
    card_title = "Session Ended"
    speech_output = "I hope you have a good day!" \
                    "Call me if you need me!!"
    # Setting this to true ends the session and exits the skill.
    should_end_session = True
    return build_response({}, build_speechlet_response(
        card_title, speech_output, None, should_end_session))

# --------------- Events ------------------

def on_session_started(session_started_request, session):
    """ Called when the session starts.
        One possible use of this function is to initialize specific
        variables from a previous state stored in an external database
    """
    # Add additional code here as needed
    pass

def on_launch(launch_request, session):
    """ Called when the user launches the skill without specifying what they
    want
    """
    # Dispatch to your skill's launch message
    return get_welcome_response()

def on_intent(intent_request, session):
    """ Called when the user specifies an intent for this skill """

    intent = intent_request['intent']
    intent_name = intent_request['intent']['name']

    # Dispatch to your skill's intent handlers using simple
    if intent_name == "sad":
        return get_sad_response()
    elif intent_name == "joke":
        return get_joke_response()
    elif intent_name == "day":
        return get_day_response()
    elif intent_name == "happy":
        return get_happy_response()
    elif intent_name == "unmotivated":
        return get_unmotivated_response()
    elif intent_name == "stressed":
        return get_stressed_response()
    elif intent_name == "AMAZON.HelpIntent":
        return get_help_response()
    elif intent_name == "AMAZON.CancelIntent" or intent_name == "AMAZON.StopIntent":
        return handle_session_end_request()
    elif intent_name == 'caps':
        return get_caps_response()
    else:
        raise ValueError("Invalid intent")

def on_session_ended(session_ended_request, session):
    """ Called when the user ends the session.
    Is not called when the skill returns should_end_session=true
    """
    print("on_session_ended requestId=" + session_ended_request['requestId'] +
          ", sessionId=" + session['sessionId'])
    # add cleanup logic here

# --------------- Main handler ------------------

def lambda_handler(event, context):
    """ Route the incoming request based on type (LaunchRequest, IntentRequest,
    etc.) The JSON body of the request is provided in the event parameter.
    """
    print("Incoming request...")
    """
    Uncomment this if statement and populate with your skill's application ID to
    prevent someone else from configuring a skill that sends requests to this
    function.
    """
    # if (event['session']['application']['applicationId'] !=
    #         "amzn1.echo-sdk-ams.app.[unique-value-here]"):
    #     raise ValueError("Invalid Application ID")

    if event['session']['new']:
        on_session_started({'requestId': event['request']['requestId']},
                           event['session'])

    if event['request']['type'] == "LaunchRequest":
        return on_launch(event['request'], event['session'])
    elif event['request']['type'] == "IntentRequest":
        return on_intent(event['request'], event['session'])
    elif event['request']['type'] == "SessionEndedRequest":
        return on_session_ended(event['request'], event['session'])


from flask import Flask, request, render_template, flash, redirect, url_for
from werkzeug.utils import secure_filename
from sklearn.externals import joblib
import urllib.request
import rdflib
import json
import re
import validators
import numpy as np
from nltk.corpus import stopwords

#%% Functions for the ML model

# Tokenizer (the pipeline cannot be loaded otherwise)
def Tokenizer(str_input):
    words = re.sub(r"[^A-Za-z0-9\-]", " ", str_input).lower().split()
    words = [word for word in words if word not in stopwords.words('english')]
    return words

# Load model and mlb transformer
clf = joblib.load("clf.pkl")
mlb = joblib.load("mlb.pkl")

# Return the label with the highest value from the probability label vector
def getBestLabel(y_pred_proba):
    # Get one tag for each prediction by the highest value in the predicted vector
    row_maxs = y_pred_proba.max(axis=1, keepdims=True)
    # Indices of maximum value for each row
    ybest = np.where(y_pred_proba == row_maxs, 1, 0)
    # Decode vector
    ybestLabel = mlb.inverse_transform(ybest)
    return ybestLabel

# From a rdflib graph, concatenate all rdfs:comments in a string
def process(rdflib_graph):
    TEXT_SUFFIXES = ["comment", "description", "label", "definition"]
    full_text = ""

    for s,p,o in rdflib_graph:
        # remove literals
        #if type(o) != rdflib.term.Literal:
        suf = rdflib_graph.compute_qname(p)[2]
        if suf in TEXT_SUFFIXES:
            text = str(o)
            if len(text) > 0 and text[-1] != ".":
                text += "."
            full_text += text
            full_text += " "

        #print(str(o))
        #print(text)

    return full_text

# Transform a string of graph file (nt) into the text describing the graph
def vocab_to_text(string):
    print("first char : ", string[0])
    if string[0] == "<":
        form = "xml"
    else:
        form = "n3"
    g = rdflib.Graph()
    g.parse(data = string, format=form)
    text = process(g)
    return text

#%% Flask API

UPLOAD_FOLDER = "/uploads/"
ALLOWED_EXTENSIONS = set(["n3", "owl", "ttl"])

app = Flask(__name__)
app.config["UPLOAD_FOLDER"] = UPLOAD_FOLDER

# Return true is the filename is accepted for upload
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

"""
@app.route("/", methods=['GET'])
@app.route("/index")
def index():
    return "
Hello, World !
"
"""

@app.route("/", methods=['GET', "POST"])
@app.route("/index", methods=['GET', "POST"])
def form():
    if request.method == "POST":
        print("getting text")

        # If input come from text area form
        if "text" in request.form.keys():
            text = request.form["text"]
        # If inut comes from an uploaded file
        elif "file" in request.files.keys():
            file = request.files["file"]
            if allowed_file(file.filename):
                text = file.read().decode("utf-8")
            else:
                return redirect(request.url)
        # If input comes from uri
        elif "uri" in request.form.keys():
            uri = request.form["uri"]
            if not(validators.url(uri)):
                return redirect(request.url)
            else:
                data = urllib.request.urlopen(uri)
                text = data.read().decode("utf-8")
        # If POST request is sent without good data
        else:
            return redirect(request.url)

        print(type(text))

        # Process text
        processed_text = vocab_to_text(text)

        # Make prediction from text
        print("before pred")
        pred = clf.predict([processed_text])
        pred_prob = clf.predict_proba([processed_text])

        # Get results
        pred_labels = mlb.inverse_transform(pred)
        pred_best_label =  getBestLabel(pred_prob)

        json_results = json.dumps({"tags":pred_labels, "best_tag":pred_best_label})
        print("after pred")
        return json_results
    else:
        return render_template("form.html")

if __name__ == "__main__":
    app.run(debug=True, port=5002)

#%%


#! /usr/bin/env python3

import rospy
from std_msgs.msg import Bool, Empty
import rospkg
import subprocess
import os

#### DEFINE NEEDED CALLBACK FUNCTIONS

def callback_vizualization_map_building(msg):

	global proc_map_run, proc_viz_run, proc_map, proc_viz, last_viz_map_value, map_destination_path

	#on rising edge
	if(msg.data and not last_viz_map_value):

		command_slam = "exec roslaunch  {0} {1}".format(slam_algorithm_launchfile_package, slam_algorithm_launchfile_name)

		command_viz = "exec roslaunch  {0} {1}".format("slam_algorithms", "launch_map_visualization.launch")

		if(not proc_viz_run):
			proc_viz = subprocess.Popen(command_viz, shell=True)
			proc_viz_run = True

			state = proc_viz.poll()
			if state is None:
				rospy.loginfo("Process is running fine")
			elif state < 0:
				rospy.loginfo("Process terminated with error")
				proc_viz_run = False
			elif state > 0:
				rospy.loginfo("Process terminated without error")

		rospy.sleep(2.0)	#give some time to start visualization

		if(not proc_map_run):
			proc_map = subprocess.Popen(command_slam, shell=True)
			proc_map_run = True

			state = proc_map.poll()
			if state is None:
				rospy.loginfo("Process is running fine")
			elif state < 0:
				rospy.loginfo("Process terminated with error")
				proc_map_run = False
			elif state > 0:
				rospy.loginfo("Process terminated without error")

	#on falling edge
	if(not msg.data and last_viz_map_value):

		if(proc_viz_run):
			proc_viz.terminate()
			rospy.sleep(2.5)	#give time to close process
			proc_viz.kill()
			proc_viz_run = False

			state = proc_viz.poll()
			if state is None:
				rospy.loginfo("process is running fine, but should been terminated!")
				proc_viz_run = True
			elif state < 0:
				rospy.loginfo("Process terminated with error")
			elif state > 0:
				rospy.loginfo("Process terminated without error")

		if(proc_map_run):

			#the following code saves the generated map
			command_save = "rosrun  map_server map_saver -f {0} map:={1} __name:=map_saver_gui".format("initial_gui_generated_map", used_map_topic)

			proc_save = subprocess.Popen(command_save, shell=True, cwd=map_destination_path)

			state = proc_save.poll()
			if state is None:
				rospy.loginfo("Process is running fine")
			elif state < 0:
				rospy.loginfo("Process terminated with error")
			elif state > 0:
				rospy.loginfo("Process terminated without error")

			rospy.sleep(1.5)	#time to save map

			proc_map.terminate()
			rospy.sleep(2.5)	#give time to close process
			proc_map.kill()
			proc_map_run = False

			state = proc_map.poll()
			if state is None:
				rospy.loginfo("process is running fine, but should been terminated!")
				proc_map_run = True
			elif state < 0:
				rospy.loginfo("Process terminated with error")
			elif state > 0:
				rospy.loginfo("Process terminated without error")

			rospy.sleep(1.5)	#again time to process

	last_viz_map_value = msg.data

def callback_stop_map_generation(msg):

	global proc_map, proc_map_run, map_destination_path

	if(proc_map_run):

		#the following code saves the generated map
		command_save = "rosrun  map_server map_saver -f {0} map:={1} __name:=map_saver_gui".format("initial_gui_generated_map", used_map_topic)

		proc_save = subprocess.Popen(command_save, shell=True, cwd=map_destination_path)

		state = proc_save.poll()
		if state is None:
			rospy.loginfo("Process is running fine")
		elif state < 0:
			rospy.loginfo("Process terminated with error")
		elif state > 0:
			rospy.loginfo("Process terminated without error")

		rospy.sleep(1.5)	#time to save map

		#now we kill the running mapping process

		proc_map.terminate()
		rospy.sleep(2.5)	#give time to close process
		proc_map.kill()
		rospy.sleep(1.0)	#give time to close process
		proc_map_run = False

		state = proc_map.poll()
		if state is None:
			rospy.loginfo("process is running fine, but should been terminated!")
			proc_map_run = True
		elif state < 0:
			rospy.loginfo("Process terminated with error")
		elif state > 0:
			rospy.loginfo("Process terminated without error")

#### DEFINE GENERAL FUNCTIONS WHICH ARE NEEDED
def directory_check_and_generate(path):
	if(not (os.path.isdir(path))):
		os.mkdir(path)
		print("Created directory ", path, " because it was not present! (Is needed for filehandling!)")

#### FOLLOWING THE MAIN CODE

if __name__ == '__main__':

	#initate node
	rospy.init_node('map_builder_start')

	#get the name of the node if started from a .launch file
	node_name = rospy.get_name()

	#get params started from a .launch file
	map_destination_package = rospy.get_param(node_name + "/map_destination_package", "navigation")
	map_destination_folder = rospy.get_param(node_name + "/map_destination_folder", "/maps/test")
	slam_algorithm_launchfile_package = rospy.get_param(node_name + "/slam_algorithm_launchfile_package", "slam_algorithms")
	slam_algorithm_launchfile_name = rospy.get_param(node_name + "/slam_algorithm_launchfile_name", "karto_slam_real_robot.launch")
	used_map_topic = rospy.get_param(node_name + "/used_map_topic", "/map_karto")

	#get full paths to directories with the help of RosPack
	rospack = rospkg.RosPack()
	global map_destination_path
	map_destination_path = rospack.get_path(map_destination_package)
	map_destination_path = (map_destination_path + map_destination_folder)

	#checking if needed directory exists, otherwise we generate it
	directory_check_and_generate(map_destination_path)

	#definde global needed variables
	global proc_viz_run		#variable to see if subprocess for visualization is running
	global proc_map_run	#variable to see if subprocess for mapping is running

	proc_viz_run = False	#visualiuation process not running
	proc_map_run = False	#mapping process not running

	global last_viz_map_value	#safe last value on to vizualise_map topic for edge detection
	last_viz_map_value = False	#set to false

	#define a subscriber to a boolean msg which tells us if we should start the mapping phase
	sub_right_loc = rospy.Subscriber("vizualise_map", Bool, callback_vizualization_map_building)

	#define a subscriber which tells us if the
	sub_right_loc = rospy.Subscriber("end_mapping", Empty, callback_stop_map_generation)

	rospy.spin()


#!/usr/bin/env python
# coding: utf-8

#
# # Projet: Investiguer la Base de Données des Films "The Movies Database"
#
# ## Table des Matières
#

#
Introduction

#
Traitement des Données

#
Analyse Exploratoire des Données

#
Conclusions

#

#
# ## Introduction
#
# L'ensemble de données sur les films contient des informations sur 10 000 films recueillies auprès de The Movie Database (TMDb). Cet ensemble de données comprend les avis des utilisateurs, les revenus, les acteurs, le genre, le directeur et la boîte de production comme principales variables à étudier.
#
# Compte tenu de tout cela, la principale question à se poser est la suivante : **Quels sont les critères de succès d'un film?**
#
# Comme il n'existe pas de définition précise d'un film à succès, nous pouvons citer deux variables cruciales à cet égard :
# 1. Le film est un succès commercial en termes de profits.
# 2. le film est hautement noté par le public - Populairité.
#
# Pour cela, nous allons étudier les différents critères qui font le succès d'un film du point de vue commercial et du point de vue du public.
#
# Nous pouvons décomposer cette question générale en questions spécifiques afin d'orienter notre analyse et d'obtenir la réponse précise:
# 1. Success Commerciale: Quels critères sont associés aux films qui ont des revenus élevés?
# 2. Popularité: Quels critères sont associés aux films qui ont des votes élevés?
# 3. Un film populaire signifie-t-il directement un film commercialement réussi?
#
# Enfin, il est particulièrement intéressant d'étudier l'évolution des bénéfices au fil des ans.
#
# La conclusion de toutes les analyses sera détaillée à la fin de ce rapport et répond à la question principale.

# ## Importation des Paquets et La Base de Données
# Dans cette premiere section du rapport, nous allons charger les pqauets necessaires aisni que la base de données des films.

# In[1]:

# Importing necessary packages
import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

#Importing the database we will work on
df = pd.read_csv('tmdb-movies.csv')

#
# ## Traitement des Données
# Dans cette section du rapport, nous allons charger les données, vérifier leur propreté, puis découper et nettoyer notre ensemble de données pour l'analyse.
# ### Propriétés Générales

# In[2]:

# Load the database
df.head()

# In[3]:

print(df.shape)
df.info()

# #### Insight
# Les informations sur les données indiquent que certaines colonnes ne seront pas utilisées dans notre analyse car elles ne sont pas directement liées à notre problématique, et que certaines valeurs manquantes doivent être corrigées pour garantir une analyse précise.
#
# Nous vérifierons également les lignes dupliquées et les types de données inexactes pour les corriger.

# ### Data Cleaning

# In[4]:

# Dropping unecessary columns
df.drop(['id', 'imdb_id','homepage','tagline', 'overview',  'keywords'], axis=1, inplace=True)
df.info()

# In[5]:

# Checking and removing duplicated rows
sum(df.duplicated())

# In[6]:

df.drop_duplicates(inplace=True)

# In[7]:

sum(df.duplicated())

# In[8]:

# Checking and fixing missing values
df.isnull().sum()

# In[9]:

df.fillna(0, inplace = True)

# In[10]:

df.isnull().sum()

# In[11]:

# Correcting the release date data type
df['release_date'] = pd.to_datetime(df['release_date'])

# Maintenant que nous avons nettoyé notre base de données des colonnes non essentielles, des valeurs manquantes, des lignes redondantes et des types de données erronés, nous allons créer trois nouvelles colonnes:
#
#
# 1. **profit**: ou la colonne de bénéfices: cette colonne est nécessaire pour comparer les bénéfices de chaque film afin de pouvoir extraire le critère du succès commercial (bénéfices élevés)
#
#
# 2. **profit_rate**: ou le taux_de_profits : Même si les bénéfices peuvent donner un aperçu des films qui font des profits, le taux de profits sera un indicateur plus précis car il souligne à quel point un film multiplie ses revenus par rapport au budget investi.
#
#
# 3. **release_month**: dans cette colonne, nous ne considérerons que le mois car le mois de sortie peut affecter le succès du film. Pour cela, nous allons supprimer la colonne release_date.

# In[12]:

df['profits'] = df['revenue_adj'] - df['budget_adj']
df['profits_rate'] = df['revenue_adj'] / df['budget_adj']
df.drop(['revenue_adj', 'budget_adj'], axis=1, inplace=True)

# In[13]:

df['release_month'] = df['release_date'].dt.month
df.drop(['release_date'], axis=1, inplace=True)

# In[14]:

print(df.shape)
df.head()

#
# ## Analyse Exploratoire des Données
# Dans cette section, nous analyserons nos données pour répondre à nos principales questions en détail. À la fin de cette section, nous comprendrons les facteurs critiques d'un succès commercial et d'un film populaire (point de vue du public).
#
# Une analyse de corrélation sera effectuée pour découvrir la dépendance entre les deux principales variables en question : le succès commercial et la popularité d'un film. En d'autres termes, nous aimerions savoir si un film très bien noté fera plus de bénéfices.
#
#
# ### Question de Recherche 1: Success Commerciale: Quels critères sont associés aux films qui ont des revenus élevés?
#
# #### Critère 1: Genres
# Nous allons étudier si le genre d'un film est un facteur de succès commercial. En d'autres termes, nous chercherons à savoir s'il existe un ou plusieurs genres spécifiques d'un film qui contribuent à faire plus de profits. Si ce n'est pas le cas, alors il existe d'autres facteurs de succès commercial différents des genres.
# Nous étudierons deux échantillons : un échantillon de top 50 films et un second échantillon de top 1000 films.
#

# In[48]:

def stat(sortBy, headCount, column):
    df_stat = df.sort_values(by=sortBy, ascending = False).head(headCount)
    df_stat.loc[:, column].head()
    df_stat[column] = df_stat[column].astype(str)
    df_stat_sep = df_stat[column].str.cat(sep='|')
    df_stat_sep = pd.Series(df_stat_sep.split('|'))
    df_stat_sep = df_stat_sep.value_counts(ascending = False).to_frame()
    return df_stat_sep

data = stat('profits', 50, 'genres')
data.head()

# In[49]:

data = stat('profits', 1000, 'genres')
data.head()

# #### Insight
# Sur la base des bénéfices et de deux échantillons différents, nous n'avons pas pu prendre une décision claire sur les genres qui contribuent à des bénéfices élevés, car lorsque la taille de l'échantillon a changé, les valeurs ont changé, ce qui est logique. Pour cela, nous utiliserons le taux de profits pour une étude plus approfondie.

# In[50]:

data = stat('profits_rate', 50, 'genres')
data.head()

# In[53]:

data = stat('profits_rate', 1000, 'genres')
data.head()

# #### Insight
# L'utilisation du taux de profits donne de meilleurs résultats car il met l'accent sur les profits, c'est-à-dire sur les revenus qu'un film génère par rapport au budget investi.
#
# Cette analyse montre que les genres Drame et Comédie contribuent le plus à la réalisation de bénéfices, et donc à un succès commercial.

# #### Critère 2: Cast
# Nous allons étudier si le cast d'un film est un facteur de succès commercial. En d'autres termes, nous chercherons à savoir s'il un acteur ou plusieurs acteurs spécifiques contribuent à faire plus de profits.
# data = stat('profits_rate', 1000, 'genres')
# data.head()
#
# Nous étudierons deux échantillons : un échantillon de top 50 films et un second échantillon de top 1000 films.

# In[56]:

data = stat('profits', 50, 'cast')
data.head()

# In[59]:

data = stat('profits', 1000, 'cast')
data.head()

# In[61]:

data = stat('profits_rate', 50, 'cast')
data.head()

# In[63]:

data = stat('profits_rate', 1000, 'cast')
data.head()

# #### Insight
# Sur la base de cette analyse, nous pouvons conclure deux points majeurs:
# 1. Si l'on considère quels sont les acteurs qui contribuent à faire plus de recettes, il s'agirait de Tom Cruise et Tom Hanks, ce qui est logique puisqu'ils sont principalement choisis pour leur notoriété.
#
# 2. Si l'on considère les films qui font plus de recettes tout en investissant moins de budget, ce qui signifie un taux de profit plus élevé, ce sont d'autres acteurs comme Clint Eastwood et John Cusack. Dans le même temps, Tom Cruise et Tom Hanks n'apparaissent pas dans la liste des 10 acteurs ayant les taux de profit les plus élevés. Cela peut refléter le fait que ces deux acteurs sont payés très cher et qu'ils contribuent effectivement à la réalisation de bénéfices, mais pas au taux de profit.

# #### Critère 3: Production Company
# Nous chercherons à savoir si la société de production peut être un facteur de succès commercial pour les réalisateurs de films. Y a-t-il vraiment une différence dans les revenus lorsqu'on travaille avec une société de production et pas une autre?

# In[65]:

data = stat('profits', 50, 'production_companies')
data.head()

# In[66]:

data = stat('profits', 1000, 'production_companies')
data.head()

# In[68]:

data = stat('profits_rate', 50, 'production_companies')
data.head()

# In[69]:

data = stat('profits_rate', 1000, 'production_companies')
data.head()

# #### Insight
# Qu'il s'agisse de profits purs ou de taux de profits, il y a trois grandes sociétés de production qui contribuent le plus aux revenus élevés des films : Warner Bros, Universal Pictures et Paramount Pictures.
# Par conséquent, travailler avec l'une de ces sociétés garantira les profits les plus élevés.

# #### Critère 4: Release Month
# Nous chercherons à savoir si le mois de diffusion de film peut être un facteur de succès commercial pour les réalisateurs de films. Y a-t-il vraiment une différence dans les revenus lorsqu'on diffuse le film dans un mois et pas un autre?

# In[70]:

data = stat('profits', 50, 'release_month')
data.head()

# In[71]:

data = stat('profits_rate', 100, 'release_month')
data.head()

# #### Insight
# Le 6e mois, qui est Juin, s'est avéré être le mois le plus rentable pour la diffusion des films, ce qui est logique puisque c'est le début des vacances d'été où les gens souhaitent profiter au maximum de leur temps.

# ### Question de Recherche 2: Popularité: Quels critères sont associés aux films qui ont des votes élevés?
# Dans cette section, nous allons d'abord étudier la corrélation entre la popularité et les films bien notés. En d'autres termes, nous aimerions savoir si un film populaire est nécessairement bien noté par le public.
#
# Ensuite, nous étudierons les facteurs qui motivent le public à donner de bonnes critiques à un film. Cela aidera les réalisateurs de films à se concentrer sur ces facteurs pour obtenir l'appréciation du public.

# In[29]:

df_loved_movies = df
df_loved_movies.drop(df_loved_movies[df_loved_movies['vote_count'] < 1000].index, inplace=True)
df_loved_movies = df_loved_movies.sort_values(by='vote_average', ascending = False).head(1000)
df_loved_movies.drop(df_loved_movies[df_loved_movies['production_companies'] == 'nan'].index, inplace=True)

# In[30]:

print(df_loved_movies.shape)
df_loved_movies.head()

# #### Correlation between Popularity and Reviews

# In[72]:

# Defining our plotting function that will be used for all plots
def plotting (title, x, y, x_label, y_label):
    plt.scatter(x, y, alpha = 0.5)
    plt.xlabel(x_label)
    plt.ylabel(y_label)
    plt.title(title)
    plt.show()

plotting ('Correlation Between Average Vote and Popularity',df_loved_movies['vote_average'], df_loved_movies['popularity'],"Average Vote","Popularity")

# #### Insight
# Sur la base du Scratter plot ci-dessus, nous pouvons conclure qu'il n'y a pas de corrélation entre la popularité et les notes moyennes. Cela nous amène à conclure que le vote moyen du public n'affecte pas la popularité du film et que ce sont des variables indépendantes.
#
# Ceci étant dit, nous pouvons travailler sur les avis des utilisateurs et détecter les facteurs qui conduisent à un plus grand nombre d'avis des utilisateurs.

# #### Criteria 1: Production Companies

# In[32]:

df_loved_movies['production_companies'] = df_loved_movies['production_companies'].astype(str)
df_loved_movies_companies = df_loved_movies['production_companies'].str.cat(sep='|')
companies = pd.Series(df_loved_movies_companies.split('|'))
count_loved_movies_campanies = companies.value_counts(ascending = False).to_frame()
count_loved_movies_campanies.head(10)

# #### Insight
# Les films réalisés par Warner Bros. sont remarquablement mieux notés par le public que les autres films.

# #### Criteria 2: Cast

# In[33]:

df_loved_movies['cast'] = df_loved_movies['cast'].astype(str)
df_loved_movies_companies = df_loved_movies['cast'].str.cat(sep='|')
companies = pd.Series(df_loved_movies_companies.split('|'))
count_loved_movies_campanies = companies.value_counts(ascending = False).to_frame()
count_loved_movies_campanies.head(50)

# #### Insight
# Sur la base de cette analyse, nous pouvons conclure qu'il n'y a pas de grande différence dans le score en fonction des acteurs. Par conséquent, le casting n'est pas un facteur de popularité du film du point de vue du public.

# #### Criteria 3: Genres

# In[34]:

df_loved_movies['genres'] = df_loved_movies['genres'].astype(str)
df_loved_movies_companies = df_loved_movies['genres'].str.cat(sep='|')
companies = pd.Series(df_loved_movies_companies.split('|'))
count_loved_movies_campanies = companies.value_counts(ascending = False).to_frame()
count_loved_movies_campanies.head(10)

# #### Insight
# Sur la base de cet aperçu, nous pouvons conclure que les films d'action et d'aventure sont les plus appréciés par le public.

# ### Research Question 3: Un film populaire signifie-t-il directement un film commercialement réussi?

# In[35]:

df.corr()

# In[44]:

plotting ('Correlation Between Profits Rate and Popularity',df_loved_movies['profits'], df_loved_movies['popularity'],"Average Vote","Popularity")

#

# In[73]:

plotting ('Correlation Between Profits Rate and Popularity',df_loved_movies['profits_rate'], df_loved_movies['popularity'],"Profits","Popularity")

# In[74]:

plotting ('Correlation Between Profits and Average Vote',df_loved_movies['vote_average'], df_loved_movies['profits'],"Average Vote","Profits")

# In[75]:

plotting ('Correlation Between Profits Rate and Average Vote',df_loved_movies['vote_average'], df_loved_movies['profits_rate'],"Average Vote","Profits Rate")

# #### Insight
# Le succès commercial ( plus de bénéfices) s'est avéré indépendant de la moyenne des votes et de la popularité du film.

# ### Evolution du Bénéfice par Année

# In[40]:

df['prft'] = df['revenue'] - df['budget']
plt.figure(figsize=(10,8))
sns.lineplot(x = df['release_year'], y = df['prft'])
plt.title('Evolution du Bénéfice par Année')
plt.xlabel("Year")
plt.ylabel("Bénéfice")
plt.xlim(1955,2025)
plt.show()

# #### Insight
# L'évolution des bénéfices au fil des ans ne suit pas un schéma clair : elle est marquée par de nombreux hauts et bas, avec un pic significatif dans les années 70. Pour comprendre cette tendance, nous devons soit examiner en profondeur l'histoire de l'industrie cinématographique, soit étendre nos recherches et essayer de comprendre quels sont les facteurs qui ont contribué à ce pic à cette période.

#
# ## Conclusions
#
# Tout au long de notre travail, nous avons conservé deux définitions principales du **succès**: Le succès commercial (bénéfices) et la popularité ( avis élevés des utilisateurs). Sur la base de ces deux définitions, nous avons travaillé à la détection des facteurs contribuant au succès global d'un film.
#
# L'analyse a montré que :
#
# 1. **Succès commercial** : Les critères affectant le succès commercial d'un film sont principalement le genre du film et la société de production. Par exemple, les genres **Drame et Comédie** ont prouvé qu'ils généraient des taux de profit significativement plus élevés que les autres genres. De même, le bénéfice dépend de la société de production, puisque **Warner Bros., Universal Pictures et Paramount Pictures** sont les sociétés de production qui produisent les films les plus rentables.
# En plus, le 6ème mois s'est avéré être le mois le plus rentable pour la sortie des films, les producteurs doivent donc en tenir compte pour viser des bénéfices plus substantiels.
# En ce qui concerne le facteur "cast", il n'y a pas eu d'acteur ou de casting particulier pour contribuer à faire plus de profits. Pourtant, gagner plus d'argent dans un film dépend du salaire de chaque acteur. En d'autres termes, l'intégration d'une figure célèbre dans un film coûtera plus cher que celle d'une figure moins célèbre, et rapportera sûrement plus de recettes, mais en ce qui concerne les bénéfices, il est plus efficace de travailler avec une figure moins célèbre pour que le taux de profit soit plus élevé.
#
#
# 2. **Popularité** : La popularité et les avis des utilisateurs moyens se sont avérés être indépendants. Pour cela, nous reflétons la popularité par des films très bien notés par le public. Les facteurs qui affectent les avis des utilisateurs sont les genres des films et les sociétés de production. Sur la base de notre analyse, nous concluons que le fait de travailler avec **Warner Bros** contribuera de manière significative à l'obtention de meilleures critiques. De même, les genres **Action et Aventure** sont les plus appréciés par le public. Le casting n'a pas été présenté comme un facteur important contribuant à des critiques plus élevées.
# Sur cette base, nous pouvons conclure que pour faire un film plaisant pour le public, nous devons nous concentrer sur la société de production et les genres.
#
#
# 3. Comme nous voulions démontrer une **relation entre la popularité (les critiques des utilisateurs) et le succès commercial d'un film**, la corrélation était proche de zéro, ce qui prouve qu'un film très bien noté ne signifie pas nécessairement un succès commercial et vice versa.
#
#
# 4. **Evolution des bénéfice au fil des ans**:  L'évolution du bénéfice au cours de l'année ne présente pas un schéma clair : elle comporte de nombreux hauts et bas avec quelques pics. Nous pouvons étendre notre recherche pour étudier en profondeur les facteurs qui contribuent à ce modèle instable et déterminer comment optimiser les profits.
#
# En conclusion, dans l'industrie cinématographique, les réalisateurs s'efforcent de faire le plus de profits possible et d'attirer le public. Pour cela, afin de réaliser un film populaire et à succès sur le plan commercial, ils doivent se concentrer sur deux facteurs principaux : **les genres et les sociétés de production**.
#
# Les acteurs peuvent être un facteur important pour le film et peuvent générer plus de revenus, mais ils ne contribuent pas à générer plus de bénéfices (car pour générer plus de revenus, il faut plus de budget dans le cas des acteurs). Pour cela, le choix du cast dépend vraiment de la perspective du décideur.
#
# ### Limitations
# Bien que ces données aient contribué à la compréhension de nombreux facteurs et relations, il leur manque encore certaines données qui pourraient rendre notre analyse et notre interprétation plus précises, comme l'importante quantité de données manquantes trouvées dans cette base de données. Plus important encore, il n'y avait pas de données claires pouvant être utilisées pour recueillir des informations sur l'évolution instable des bénéfices au fil des ans. Ce type de données aurait beaucoup aidé à conclure les facteurs et critères importants sur lesquels se concentrer dans l'industrie cinématographique et contribuerait énormément à sa croissance.
#
# En outre, il serait plus efficace de construire un algorithme d'apprentissage automatique qui automatisera le processus de prédiction des films susceptibles d'avoir du succès commerciale et/ou popularité.

# In[ ]:


from pyglet.gl import *
import pyglet
from pyglet import app, graphics
from pyglet.window import Window, key
import numpy as np
from pyglet import clock
import math

#dx, dy = 25, 15 # Размеры прямоугольника
#dx2 = dx / 2
#dy2 = dy / 2
size = 20
a = int(size/2) #ширина
wx, wy = 1.5 * size, 1.5 * size # Параметры области визуализации
w, h = int(20 * wx), int(20 * wy) # Размеры окна вывода
#----------------------------------------------------
window = Window(visible = True, width = w, height = h,
                resizable = True, caption = 'А-05-19 Лабораторная работа № 4 Абросимова')
window.set_location(0, 50)
glClearColor(0.15, 0.15, 0.15, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
#----------------------------------------------------

angle = -3*math.pi/4
alfa = math.pi/4

tc = 1 # Число повторов текстуры
t_coords = ((0, 0), (0, tc), (tc, tc), (tc, 0)) # Координаты текстуры
n_rot = 0
color = 0

def texInit():
    r = GL_RGB
    p = GL_TEXTURE_2D
    vp = np.full((w, w, 3), 0, dtype='uint8')
    k = w // 4
    vp[:w, :k, 0] = 255
    vp[:w, k:2*k, :] = 255
    vp[:w, 2*k:3 * k, 1] = 255

    vp = vp.flatten()
    vp = (GLubyte * (w * w * 3))(*vp)

    gl.glTexParameterf(p, GL_TEXTURE_WRAP_S, GL_REPEAT)
    gl.glTexParameterf(p, GL_TEXTURE_WRAP_T, GL_REPEAT)
    gl.glTexParameterf(p, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    gl.glTexParameterf(p, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    gl.glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
    gl.glTexImage2D(p, 0, r, w, w, 0, r, GL_UNSIGNED_BYTE, vp)
    gl.glEnable(p)

param1 = 1
param2 = 1

def update(dt):
    global n_rot, color, tc, param1, param2
    if n_rot >= 360:
        n_rot = 0
    if tc > 4 or tc < 1:
        param1 *= -1
    tc += param1 * 0.1
    n_rot += 1
    if color < 0 or color > 1:
        param2 *=-1
    color += param2 * 0.009

clock.schedule_interval(update, 0.01)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST)
texInit()

@window.event
def on_draw():
    global n_rot, angle, alfa, color
    window.clear()

    glEnable(GL_CULL_FACE)
    glCullFace(GL_BACK)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glRotatef(angle * 180 / math.pi, 1, 0, 0)
    glRotatef(-alfa * 180 / math.pi, 0, 1, 0)
    glRotatef(angle, 0, 1, 0)
    glOrtho(-wx, wx, -wx, wx, -wx, wx)

    glMatrixMode(gl.GL_MODELVIEW)
    glLoadIdentity()
    glRotatef(n_rot, 0, 1, 0)

    glDisable(GL_TEXTURE_2D)

    glBegin(GL_QUADS)
    glColor3f(color, 0, 1-color)

    glVertex3f(0, -a, 0)
    glVertex3f(-a, -a, -a)
    glVertex3f(-a, a, -a)
    glVertex3f(0, a, 0)

    glVertex3f(a, -a, -a)
    glVertex3f(0, -a, 0)
    glVertex3f(0, a, 0)
    glVertex3f(a, a, -a)
    glEnd()
    glEnable(GL_TEXTURE_2D)  # Включение текстуры

    glBegin(GL_QUADS)
    glTexCoord2f(0, 0)
    glVertex3f(-a, -a, -a)
    glTexCoord2f(tc * 0.75, 0)
    glVertex3f(0, -a, 0)
    glTexCoord2f(tc * 0.75, tc)
    glVertex3f(0, a, 0)
    glTexCoord2f(0, tc)
    glVertex3f(-a, a, -a)

    glTexCoord2f(0, 0)
    glVertex3f(0, -a, 0)
    glTexCoord2f(tc * 0.75, 0)
    glVertex3f(a, -a, -a)
    glTexCoord2f(tc * 0.75, tc)
    glVertex3f(a, a, -a)
    glTexCoord2f(0, tc)
    glVertex3f(0, a, 0)
    glEnd()

app.run()


from cogs.core import core
from discord.ext import commands

class on_ready(core):

    @commands.Cog.listener()
    async def on_ready(self):
        print(">>>Bot ready<<<")

def setup(client):
    client.add_cog(on_ready(client))


import math

a=int(input("Coeficiente cuadratico: "))
b=int(input("Coeficiente lineal: "))
c=int(input("Ordenada al origen: "))

if a==0:
    print("Es una funcion lineal")
if a!=0:
    x=-b/(2*a)
    y= a*x**2+b*x+c
    if x==-0:
         x=0
    if a>0:
        print(f"El minimo es {y} y esta en {x}")
    if a<0:
        print(f"El maximo es {y} y esta en {x}")


"""Embedding utils for queries."""
import heapq
import math
from typing import Any, Callable, List, Optional, Tuple

import numpy as np

from llama_index.embeddings.base import similarity as default_similarity_fn
from llama_index.vector_stores.types import VectorStoreQueryMode

def get_top_k_embeddings(
    query_embedding: List[float],
    embeddings: List[List[float]],
    similarity_fn: Optional[Callable[..., float]] = None,
    similarity_top_k: Optional[int] = None,
    embedding_ids: Optional[List] = None,
    similarity_cutoff: Optional[float] = None,
) -> Tuple[List[float], List]:
    """Get top nodes by similarity to the query."""
    if embedding_ids is None:
        embedding_ids = list(range(len(embeddings)))

    similarity_fn = similarity_fn or default_similarity_fn

    embeddings_np = np.array(embeddings)
    query_embedding_np = np.array(query_embedding)

    similarity_heap: List[Tuple[float, Any]] = []
    for i, emb in enumerate(embeddings_np):
        similarity = similarity_fn(query_embedding_np, emb)
        if similarity_cutoff is None or similarity > similarity_cutoff:
            heapq.heappush(similarity_heap, (similarity, embedding_ids[i]))
            if similarity_top_k and len(similarity_heap) > similarity_top_k:
                heapq.heappop(similarity_heap)
    result_tups = sorted(similarity_heap, key=lambda x: x[0], reverse=True)

    result_similarities = [s for s, _ in result_tups]
    result_ids = [n for _, n in result_tups]

    return result_similarities, result_ids

def get_top_k_embeddings_learner(
    query_embedding: List[float],
    embeddings: List[List[float]],
    similarity_top_k: Optional[int] = None,
    embedding_ids: Optional[List] = None,
    query_mode: VectorStoreQueryMode = VectorStoreQueryMode.SVM,
) -> Tuple[List[float], List]:
    """Get top embeddings by fitting a learner against query.

    Inspired by Karpathy's SVM demo:
    https://github.com/karpathy/randomfun/blob/master/knn_vs_svm.ipynb

    Can fit SVM, linear regression, and more.

    """
    try:
        from sklearn import linear_model, svm
    except ImportError:
        raise ImportError("Please install scikit-learn to use this feature.")

    if embedding_ids is None:
        embedding_ids = list(range(len(embeddings)))
    query_embedding_np = np.array(query_embedding)
    embeddings_np = np.array(embeddings)
    # create dataset
    dataset_len = len(embeddings) + 1
    dataset = np.concatenate([query_embedding_np[None, ...], embeddings_np])
    y = np.zeros(dataset_len)
    y[0] = 1

    if query_mode == VectorStoreQueryMode.SVM:
        # train our SVM
        # TODO: make params configurable
        clf = svm.LinearSVC(
            class_weight="balanced", verbose=False, max_iter=10000, tol=1e-6, C=0.1
        )
    elif query_mode == VectorStoreQueryMode.LINEAR_REGRESSION:
        clf = linear_model.LinearRegression()
    elif query_mode == VectorStoreQueryMode.LOGISTIC_REGRESSION:
        clf = linear_model.LogisticRegression(class_weight="balanced")
    else:
        raise ValueError(f"Unknown query mode: {query_mode}")

    clf.fit(dataset, y)  # train

    # infer on whatever data you wish, e.g. the original data
    similarities = clf.decision_function(dataset[1:])
    sorted_ix = np.argsort(-similarities)
    top_sorted_ix = sorted_ix[:similarity_top_k]

    result_similarities = similarities[top_sorted_ix]
    result_ids = [embedding_ids[ix] for ix in top_sorted_ix]

    return result_similarities, result_ids

def get_top_k_mmr_embeddings(
    query_embedding: List[float],
    embeddings: List[List[float]],
    similarity_fn: Optional[Callable[..., float]] = None,
    similarity_top_k: Optional[int] = None,
    embedding_ids: Optional[List] = None,
    similarity_cutoff: Optional[float] = None,
    mmr_threshold: Optional[float] = None,
) -> Tuple[List[float], List]:
    """Get top nodes by similarity to the query,
    discount by their similarity to previous results.

    A mmr_threshold of 0 will strongly avoid similarity to previous results.
    A mmr_threshold of 1 will check similarity the query and ignore previous results.

    """
    threshold = mmr_threshold or 0.5
    similarity_fn = similarity_fn or default_similarity_fn

    if embedding_ids is None or embedding_ids == []:
        embedding_ids = list(range(len(embeddings)))
    full_embed_map = dict(zip(embedding_ids, range(len(embedding_ids))))
    embed_map = full_embed_map.copy()
    embed_similarity = {}
    score: float = -math.inf
    high_score_id = None

    for i, emb in enumerate(embeddings):
        similarity = similarity_fn(query_embedding, emb)
        embed_similarity[embedding_ids[i]] = similarity
        if similarity * threshold > score:
            high_score_id = embedding_ids[i]
            score = similarity * threshold

    results: List[Tuple[Any, Any]] = []

    embedding_length = len(embeddings or [])
    similarity_top_k_count = similarity_top_k or embedding_length
    while len(results) < min(similarity_top_k_count, embedding_length):
        # Calculate the similarity score the for the leading one.
        results.append((score, high_score_id))

        # Reset so a new high scoring result can be found
        del embed_map[high_score_id]
        recent_embedding_id = high_score_id
        score = -math.inf

        # Iterate through results to find high score
        for embed_id in embed_map:
            overlap_with_recent = similarity_fn(
                embeddings[embed_map[embed_id]],
                embeddings[full_embed_map[recent_embedding_id]],
            )
            if (
                threshold * embed_similarity[embed_id]
                - ((1 - threshold) * overlap_with_recent)
                > score
            ):
                score = threshold * embed_similarity[embed_id] - (
                    (1 - threshold) * overlap_with_recent
                )
                high_score_id = embed_id

    result_similarities = [s for s, _ in results]
    result_ids = [n for _, n in results]

    return result_similarities, result_ids


def fun(s):
    for i in range(len(s)):
        for j in range(len(s)):
            if s[i]*s[j]==n:
                return s[i],s[j]
    return "-1"
def primt(i):
    for j in range(2,i):
        if i%j==0:
            return False
    return True
n=int(input())
s=[]
for i in range(2,n):
    if primt(i):
        s.append(i)
if fun(s)=="-1":
    print("-1")
else:
    a,b=fun(s)
    print(a,b)