from functools import partial
import asyncio
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.uix.colorpicker import ColorPicker
from phone.client import connect, send_command
from server.kb_io import parse_json_kb, save_kb
from server.utils import split_list

class Kboard(GridLayout, Screen):
    last_used_kb = ''
    def __init__(self, name, layout: dict, **kwargs):
        GridLayout.__init__(self, cols=int(layout['cols']), **kwargs)
        Screen.__init__(self, name=name)
        self.kb_name = name
        self.layout = layout
        self.commands_list = []
        self.buttons_list = []
        self.objects_per_screen = int(layout['cols']) * int(layout['rows']) - 2
        self.reload_layout()

    def reload_layout(self):
        self.clear_widgets()
        self.commands_list = self.layout['Buttons']
        self.buttons_list = []
        if len(self.commands_list) > self.objects_per_screen:
            print(f'KB size incorrect in "{self.kb_name}"') #TODO, add pagination
            raise ValueError

        for new_button in self.commands_list:
            self.add_button(new_button)
            self.button_bind(new_button['hotkeys'])

        if len(self.commands_list) < self.objects_per_screen:
            button = Button(text='Add new Button')
            self.add_widget(button)
            button.bind(on_press=self.button_add_event)

        self.settings_button = Button(text='Settings')
        self.kb_selection_button = Button(text='Select KB')
        self.add_widget(self.settings_button)
        self.add_widget(self.kb_selection_button)
        self.kb_selection_button.bind(on_press=self.kb_selection_button_press_event)
        self.settings_button.bind(on_press=self.open_setting_menu)

    def add_button(self, new_button):
        self.button = Button(
            text=new_button['name'],
            color=self.layout['def_text_color'] if not\
                    new_button['text_color'] else new_button['text_color'],
        )
        if self.layout['def_background_color'] != [1, 1, 1, 1]:
            self.button.background_normal = ''
            self.button.background_color=self.layout['def_background_color'] \
                    if not new_button['button_color'] else new_button['button_color']
        self.add_widget(self.button)
        self.buttons_list.append(self.button)
        return self.button

    def button_bind(self, hotkeys):
        self.button.bind(on_press=partial(self.button_press_event, hotkeys))

    def button_press_event(self, hotkeys, _):
        print('Command:', hotkeys)
        if not MainApp.sock is None:
            send_command(MainApp.sock, hotkeys)

    def kb_selection_button_press_event(self, _):
        MainApp.sm.current = KbSelection.last_used_page

    def button_add_event(self, _):
        Kboard.last_used_kb = self.kb_name
        MainApp.sm.current = 'ButtonAddScreen'

    def open_setting_menu(self, _):
        Kboard.last_used_kb = self.kb_name
        MainApp.sm.current = 'ButtonSettingsScreen'

    def chroma_light_mode(self):
        ... # TODO add light (profiles) transitions

class ButtonSettingsScreen(GridLayout, Screen):
    editable_button = Button(text='Dummy')
    def __init__(self, **kwargs):
        GridLayout.__init__(self, cols=4, **kwargs)
        Screen.__init__(self, name='ButtonSettingsScreen')

        self.back_button = Button(text='Back')
        self.quit_button = Button(text='Quit')
        self.edit_button = Button(text='Edit Button')

        self.add_widget(self.back_button)
        self.add_widget(self.edit_button)
        self.add_widget(self.quit_button)

        self.back_button.bind(on_press=self.back_to_last_kb)
        self.quit_button.bind(on_press=self.close_app)
        self.edit_button.bind(on_press=self.select_button)

    def back_to_last_kb(self, _):
        MainApp.sm.current = Kboard.last_used_kb

    def close_app(self, _):
        quit()

    def edit_button_event(self, instance):
        MainApp.kb_dict[Kboard.last_used_kb].buttons_list = self.save_buttons_list
        MainApp.kb_dict[Kboard.last_used_kb].reload_layout()
        ButtonSettingsScreen.editable_button = instance
        MainApp.sm.current = 'ButtonEditScreen'
        MainApp.editor.run_editor()

    def select_button(self, _):
        self.save_buttons_list = MainApp.kb_dict[Kboard.last_used_kb].buttons_list.copy()
        MainApp.kb_dict[Kboard.last_used_kb].clear_widgets()
        for new_button in MainApp.kb_dict[Kboard.last_used_kb].commands_list:
            button = MainApp.kb_dict[Kboard.last_used_kb].add_button(new_button)
            button.bind(on_press=self.edit_button_event)
        MainApp.sm.current = Kboard.last_used_kb

class ButtonAddScreen(Screen):
    def __init__(self, name='ButtonAddScreen', **kwargs):
        # FloatLayout.__init__(self, **kwargs)
        Screen.__init__(self, name=name, **kwargs)

        self.button = Button(text='Hello world', size_hint=(.3, .3),
                        pos_hint={'center_x':0.5, 'center_y':0.5})

        self.button_back_color_button = Button(text='Select Background color', size_hint=(.3, .3),
                                            pos_hint={'x':0.7, 'y':0.7})
        self.button_back_color_button.bind(on_press=self.bg_color_select_event)
        self.button_font_color_button = Button(text='Select Font color', size_hint=(.3, .3),
                                            pos_hint={'x':0.7, 'y':0.4})
        self.button_font_color_button.bind(on_press=self.ft_color_select_event)

        self.button_name = TextInput(
            multiline=False,
            hint_text='Name',
            size_hint=(.3, .5),
            pos_hint={'x':0, 'y':0.5}
        )
        self.button_name.bind(text=self.on_text_event)
        self.button_keys = TextInput(
            multiline=False,
            hint_text='Hotkey Combination',
            size_hint=(.3, .5),
            pos_hint={'x':0, 'y':0}
        )
        self.button_save = Button(text='Save', size_hint=(.15, .3),
                            pos_hint={'x':0.7, 'y':0})
        self.button_save.bind(on_press=self.save_event)
        self.button_back = Button(text='Back', size_hint=(.15, .3),
                            pos_hint={'x':0.85, 'y':0})
        self.button_back.bind(on_press=self.back)

        self.add_widget(self.button)
        self.add_widget(self.button_keys)
        self.add_widget(self.button_name)
        self.add_widget(self.button_back_color_button)
        self.add_widget(self.button_font_color_button)
        self.add_widget(self.button_save)
        self.add_widget(self.button_back)

    def bg_color_select_event(self, _, name='ButtonAddScreen'):
        MainApp.sm.current = 'ColorScreen'
        ColorScreen.requester = name
        asyncio.ensure_future(self.wait_for_switchback(True, name))

    def ft_color_select_event(self, _,  name='ButtonAddScreen'):
        MainApp.sm.current = 'ColorScreen'
        ColorScreen.requester = name
        asyncio.ensure_future(self.wait_for_switchback(False, name))

    async def wait_for_switchback(self, change_bg: bool, name='ButtonAddScreen'):
        while MainApp.sm.current != name:
            await asyncio.sleep(0.1)
        self.update_color(change_bg)

    def update_color(self, change_bg):
        if change_bg:
            self.button.background_normal = ''
            self.button.background_color = ColorScreen.last_color_selected
        else:
            self.button.color = ColorScreen.last_color_selected

    def on_text_event(self, _, value):
        self.button.text = value

    def back(self, _):
        MainApp.sm.current = Kboard.last_used_kb

    def save_event(self, _):
        MainApp.sm.current = Kboard.last_used_kb
        text_color = [] if self.button.color == [1, 1, 1, 1] else self.button.color
        background_color = [] if self.button.background_color\
              == [1, 1, 1, 1] else self.button.background_color
        new_button = {
            'name': self.button.text,
            'hotkeys': self.button_keys.text,
            'text_color': text_color,
            'button_color': background_color
        }
        MainApp.kb_dict[Kboard.last_used_kb].layout['Buttons'].append(new_button)
        MainApp.kb_dict[Kboard.last_used_kb].reload_layout()
        self.button_name.text = ''
        self.button_keys.text = ''
        self.button.text = 'Hello World!'
        save_kb("layouts.json", MainApp.kb_json)

class ButtonEditScreen(ButtonAddScreen):
    def __init__(self, **kwargs):
        super().__init__(name='ButtonEditScreen', **kwargs)
        self.remove_button = Button(text='Remove Button', size_hint=(.3, .2),
                                            pos_hint={'center_x':0.5, 'center_y':.1})
        self.button_back_color_button.unbind(on_press=self.bg_color_select_event)
        self.button_font_color_button.unbind(on_press=self.ft_color_select_event)
        self.button_back_color_button.bind(
            on_press=partial(self.bg_color_select_event, name='ButtonEditScreen')
        )
        self.button_font_color_button.bind(
            on_press=partial(self.ft_color_select_event, name='ButtonEditScreen')
        )
        self.remove_button.bind(on_press=self.del_button)
        self.add_widget(self.remove_button)

    def run_editor(self):
        editable_button = ButtonSettingsScreen.editable_button
        self.button.background_normal = ''
        self.button.text = editable_button.text
        self.button.background_color = editable_button.background_color
        self.button.color = editable_button.color
        self.button_name.text = editable_button.text
        # self.button_keys =

    def save_event(self, _):
        ...

    def del_button(self, _):
        ...

class ColorScreen(BoxLayout, Screen):
    last_color_selected = [1, 1, 1, 1]
    requester = ''
    def __init__(self, **kwargs):
        BoxLayout.__init__(self, **kwargs)
        Screen.__init__(self, name='ColorScreen')
        self.clr_picker = ColorPicker()
        self.clr_picker.bind(color=self.on_color)
        self.add_widget(self.clr_picker)
        self.button = Button(text='Select Color')
        self.add_widget(self.button)
        self.button.bind(on_press=self.on_button)

    def on_color(self, _, value):
        self.button.background_normal = ''
        self.button.color = [1 - i for i in value[:3]]
        self.button.background_color = value

    def on_button(self, _):
        print('Color selected')
        ColorScreen.last_color_selected = self.button.background_color
        MainApp.sm.current = ColorScreen.requester

class LayoutSettings(GridLayout, Screen):
    def __init__(self, **kwargs):
        GridLayout.__init__(self, cols=4)
        Screen.__init__(self, name='LayoutSettings', **kwargs)
        self.button_quit = Button(text='Quit')
        self.button_quit.bind(on_press=quit)
        self.button_back = Button(text='Back')
        self.button_back.bind(on_press=self.back)
        self.button_create_new_layout = Button(text='Create new Layout')
        self.button_create_new_layout.bind(on_press=self.switch_layout_creator)

        self.add_widget(self.button_create_new_layout)
        self.add_widget(self.button_back)
        self.add_widget(self.button_quit)

    def back(self, _):
        MainApp.sm.current = KbSelection.last_used_page

    def switch_layout_creator(self, _):
        MainApp.sm.current = 'NewLayoutCreator'

class NewLayoutCreator(Screen):
    def __init__(self, **kwargs):
        super().__init__(name='NewLayoutCreator', **kwargs)
        self.layout_name = TextInput(
            multiline=False,
            hint_text='Name',
            size_hint=(.33333, .5),
            pos_hint={'x':0, 'y':0.5}
        )
        self.cols_count = TextInput(
            multiline=False,
            hint_text='Cols, default = 4',
            size_hint=(.33333, .5),
            pos_hint={'x':0.33333, 'y':0.5}
        )
        self.rows_count = TextInput(
            multiline=False,
            hint_text='Rows, default = 3',
            size_hint=(.33333, .5),
            pos_hint={'x':0.66666, 'y':0.5}
        )
        self.button_save = Button(text='Save', size_hint=(.16666, .5),
                            pos_hint={'x':0.6666, 'y':0})
        self.button_back = Button(text='Back', size_hint=(.16666, .5),
                            pos_hint={'x':0.83333, 'y':0})
        self.color_select = Button(text='Select Button Color', size_hint=(.33333, .5),
                            pos_hint={'x':0, 'y':0})
        self.text_color_select = Button(text='Select Text Color', size_hint=(.33333, .5),
                            pos_hint={'x':.33333, 'y':0})

        self.button_save.bind(on_press=self.save_event)
        self.button_back.bind(on_press=self.back)
        self.color_select.bind(on_press=partial(self.select_color, True))
        self.text_color_select.bind(on_press=partial(self.select_color, False))

        self.add_widget(self.button_save)
        self.add_widget(self.button_back)
        self.add_widget(self.color_select)
        self.add_widget(self.text_color_select)
        self.add_widget(self.layout_name)
        self.add_widget(self.cols_count)
        self.add_widget(self.rows_count)

    def select_color(self, change_bg, _):
        MainApp.sm.current = 'ColorScreen'
        ColorScreen.requester = 'NewLayoutCreator'
        asyncio.ensure_future(self.wait_for_switchback(change_bg))

    async def wait_for_switchback(self, change_bg):
        while MainApp.sm.current != 'NewLayoutCreator':
            await asyncio.sleep(0.1)
        self.update_color(change_bg)

    def update_color(self, change_bg):
        if change_bg:
            self.color_select.background_normal = ''
            self.color_select.background_color = ColorScreen.last_color_selected
            self.text_color_select.background_normal = ''
            self.text_color_select.background_color = ColorScreen.last_color_selected
        else:
            self.text_color_select.color = ColorScreen.last_color_selected
            self.color_select.color = ColorScreen.last_color_selected

    def save_event(self, _):
        if self.layout_name.text == '':
            print('No name specified')
        else:
            new_layout = {
                'cols': 4 if not self.cols_count.text else self.cols_count.text,
                'rows': 3 if not self.cols_count.text else self.cols_count.text,
                'def_background_color': self.color_select.background_color,
                'def_text_color': self.text_color_select.color,
                'Buttons': []
            }
            name = self.layout_name.text
            MainApp.kb_json[name] = new_layout
            new_kb = Kboard(name, new_layout)
            MainApp.sm.add_widget(new_kb)
            MainApp.kb_dict[name] = new_kb
            last_page = KbSelection.all_pages[-1]
            if len(last_page.buttons_list) < 4:
                counter = len(last_page.buttons_list)
                new_button = Button(text=str(name), size_hint=(.18, 1),\
                                        pos_hint={'x':0.14+counter%4*0.18, 'y':0})
                new_button.bind(on_press=self.kb_selection)
                if self.color_select.background_color != [1, 1, 1, 1]:
                    new_button.background_normal = ''
                new_button.background_color = self.color_select.background_color
                new_button.color = self.text_color_select.color
                last_page.buttons_list.append(new_button)
                last_page.add_widget(new_button)
            else:
                new_page = KbSelectionPage(len(KbSelection.all_pages), [name])
                KbSelection.all_pages.append(new_page)
                KbSelection.max_screen_counter += 1
                MainApp.sm.add_widget(new_page)

            save_kb("layouts.json", MainApp.kb_json)
            MainApp.sm.current = KbSelection.last_used_page

    def kb_selection(self, _):
        MainApp.sm.current = self.layout_name.text

    def back(self, _):
        MainApp.sm.current = 'LayoutSettings'

class KbSelection(Screen):
    last_used_page = 'layoutScreen0'
    max_screen_counter = -1
    all_pages = []
    def __init__(self, **kwargs):
        Screen.__init__(self, name='KbSelection', **kwargs)
        kb_names_list = ['LayoutSettings']
        kb_names_list += list(MainApp.kb_dict.keys())
        splited_lists = split_list(kb_names_list, 4)
        for i, each_list in enumerate(splited_lists):
            page = KbSelectionPage(i, kb_name_list=each_list)
            KbSelection.all_pages.append(page)
            MainApp.sm.add_widget(page)

class KbSelectionPage(Screen):
    def __init__(self, kb_id: int, kb_name_list: list[str], **kwargs):
        super().__init__(name='layoutScreen'+str(kb_id), **kwargs)
        KbSelection.max_screen_counter += 1
        self.buttons_list = []
        for i, name in enumerate(kb_name_list):
            self.buttons_list.append(
                Button(text=str(name),
                size_hint=(.18, 1),
                pos_hint={'x':0.14+i%4*0.18, 'y':0})
            )
            if name != 'LayoutSettings':
                color = MainApp.kb_json[name]['def_background_color']
                if color != [1, 1, 1, 1]:
                    self.buttons_list[-1].background_normal = ''
                    self.buttons_list[-1].background_color = color
            self.buttons_list[-1].bind(on_press=partial(self.button_press_event, str(name)))
            self.add_widget(self.buttons_list[-1])

        self.perv_button = (Button(text='<', size_hint=(.14, 1), pos_hint={'x':0, 'y':0}))
        self.next_button = (Button(text='>', size_hint=(.14, 1), pos_hint={'x':0.86, 'y':0}))
        self.perv_button.bind(on_press=partial(self.switch_next_screen, kb_id-1, transition='right'))
        self.next_button.bind(on_press=partial(self.switch_next_screen, kb_id+1, transition='left'))
        self.add_widget(self.perv_button)
        self.add_widget(self.next_button)
        # self.layout_settings_button = Button(text='Settings')
        # self.add_widget(self.layout_settings_button)

    def switch_next_screen(self, screen_id: int, _, transition: str):
        MainApp.sm.transition.direction = transition
        if screen_id > KbSelection.max_screen_counter or screen_id < 0:
            print('Screen not found')
        else:
            KbSelection.last_used_page = 'layoutScreen'+str(screen_id)
            MainApp.sm.current = 'layoutScreen'+str(screen_id)

    def button_press_event(self, name: str, _):
        MainApp.sm.current = name
        print(f'Kb swtiched to {name}')

class ConnectScreen(Screen):
    def __init__(self, **kwargs):
        Screen.__init__(self, name='ConnectScreen', **kwargs)
        self.connect_ip = TextInput(multiline=False, hint_text='IP', size_hint=(.3333, 1), pos_hint={'x':0, 'y':0})
        self.connect_port = TextInput(multiline=False, hint_text='Port', size_hint=(.3333, 1), pos_hint={'x':0.3333, 'y':0})
        self.connect_button = Button(text='Connect', size_hint=(.3333, 0.5), pos_hint={'x':0.6666, 'y':0.5})
        self.run_button = Button(text='Run without connection', size_hint=(.3333, 0.5), pos_hint={'x':0.6666, 'y':0})
        self.connect_button.bind(on_press=self.connect_button_press_event)
        self.run_button.bind(on_press=self.run_without_connection)
        self.add_widget(self.connect_port)
        self.add_widget(self.connect_ip)
        self.add_widget(self.connect_button)
        self.add_widget(self.run_button)

    def connect_button_press_event(self, _):
        try:
            MainApp.sock = connect((self.connect_ip.text, int(self.connect_port.text)))
            MainApp.sm.current = KbSelection.last_used_page
        except ValueError:
            print('Connection Failed')

    def run_without_connection(self, _):
        MainApp.sm.current = KbSelection.last_used_page

class MainApp(App):
    sock = None
    sm = ScreenManager()
    editor = ButtonEditScreen()
    kb_dict = {}
    kb_json = {}

    def build(self):
        MainApp.sm.add_widget(ConnectScreen())

        MainApp.kb_json = parse_json_kb("layouts.json")
        for kb_name, kb_value in MainApp.kb_json.items():
            MainApp.kb_dict[kb_name] = Kboard(kb_name, kb_value)
            MainApp.sm.add_widget(MainApp.kb_dict[kb_name])

        MainApp.sm.add_widget(KbSelection())
        MainApp.sm.add_widget(ButtonAddScreen())
        MainApp.sm.add_widget(ColorScreen())
        MainApp.sm.add_widget(ButtonSettingsScreen())
        MainApp.sm.add_widget(LayoutSettings())
        MainApp.sm.add_widget(NewLayoutCreator())
        MainApp.sm.add_widget(MainApp.editor)

        return MainApp.sm

if __name__ == '__main__':
    app=MainApp()
    asyncio.run(app.async_run())


from relegy.embeddings import GraphWave
from relegy.graphs.examples import examplesDict
import numpy as np

def test_graph_wave_fast_embeds_without_error():
    for graph in examplesDict.values():
        Z = GraphWave.fast_embed(graph)
        assert isinstance(Z, np.ndarray)

def test_graph_wave_result_has_expected_shape():
    for graph in examplesDict.values():
        d = 4
        Z = GraphWave.fast_embed(graph, d=d)
        n = len(graph.nodes)
        assert Z.shape == (n, 2*d)

def test_graph_wave_parameter_verification():
    graph = None
    try:
        m = GraphWave(graph)
        assert False
    except Exception:
        assert True
# def test_graph_wave_consistent_embedding_with_identical_random_state():
#     for graph in examplesDict.values():
#         model1 = GraphWave(graph, random_state=2137)
#         Z1 = model1.embed()
#         model2 = GraphWave(graph, random_state=2137)
#         Z2 = model2.embed()
#         assert (Z1 == Z2).all()
#
# def test_graph_wave_different_embedding_with_different_random_state():
#     for graph in examplesDict.values():
#         model1 = GraphWave(graph, random_state=2137)
#         Z1 = model1.embed()
#         model2 = GraphWave(graph, random_state=80085)
#         Z2 = model2.embed()
#         assert not (Z1 == Z2).all()


from django.core.management.base import BaseCommand
import pandas as pd

from playerevals.models import *

class Command(BaseCommand):
    help = __doc__

    def handle(self, *args, **options):

        df_reviewers = pd.read_csv('playerevals/reviewers.csv')
        CODES = df_reviewers['code'].values
        PLAYERS = df_reviewers['players'].values
        REVIEWERS = df_reviewers['reviewer'].values

        for p in REVIEWERS:
            obj, created = Players.objects.get_or_create(name=p)
            if created:
                self.stdout.write(self.style.SUCCESS(f'Created Player {p}'))

        for r, c, pp in zip(REVIEWERS, CODES, PLAYERS):
            obj, created = Reviewer.objects.get_or_create(
                name=r,
                code=c,
                assigned_players=pp,
                completed_reviews='')
            if created:
                self.stdout.write(self.style.SUCCESS(
                    f'Created Reviewer {r} with code {c} and players:{pp}'))

        df = pd.read_csv('playerevals/skills.csv')
        for k, row in df.iterrows():
            obj, created = Skills.objects.get_or_create(
                                slug=row['skill'].replace(' ', '_'),
                                name=row['skill'],
                                description=row['description'],
                                ref_value=row['ref'])
            if not created:
                continue
            obj.save()
            self.stdout.write(self.style.SUCCESS(f'Created Skill-Question {row["skill"]}'))


from datetime import datetime
# from django.utils import timezone
import hashlib
import pyexcel
import json

from tincan import (
    Statement,
    Agent,
    Verb,
    Activity,
    Context,
    LanguageMap,
    ActivityDefinition,
)

from xapi_client.utils import XAPI_PLATFORM
from xapi_client.utils import get_activity_choices,  get_verb_choices, make_uri
from xapi_client.xapi_vocabularies import xapi_verbs_by_id, xapi_activities_by_type
from xapi_client.track.xapi_statements import send_statement

from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views import View
from django.contrib.auth.decorators import login_required
from django.conf import settings

from .forms import SelfRecordForm

@method_decorator(login_required, name='post')
class SelfRecord(View):
    form_class = SelfRecordForm
    template_name = 'self_record.html'

    def get(self, request, *args, **kwargs):
        context_activity_type = request.GET.get('ca_type', None)
        context_object_name = project_title = request.GET.get('ca_name', None)
        context_object_id = project_url = request.GET.get('ca_id', None)
        context_activity_relationship = request.GET.get('ca_rel', None)
        try:
            recipe_ids = settings.XAPI_DEFAULT_RECIPES
        except:
            recipe_ids = []
        user = request.user
        actor_name = user.get_display_name()
        actor_email = user.email
        # initial = { 'actor_name': actor_name, 'actor_email': actor_email, 'endpoint': settings.LRS_ENDPOINT, 'platform': XAPI_PLATFORM, 'authority_name': actor_name, 'authority_email': actor_email, }
        initial = { 'actor_name': actor_name, 'actor_email': actor_email, 'endpoint': settings.LRS_ENDPOINT, 'platform': XAPI_PLATFORM, 'timestamp': datetime.now(),}
        if context_activity_type and context_object_name and context_object_id and context_activity_relationship:
            initial.update({ 'context_activity_type': context_activity_type, 'context_object_name': context_object_name, 'context_object_id': context_object_id, 'context_activity_relationship': context_activity_relationship, })
        if recipe_ids:
            initial['recipe_ids'] = recipe_ids
        form = self.form_class(initial=initial)
        form.fields['verb_id'].choices = get_verb_choices(recipe_ids)
        form.fields['activity_type'].choices = get_activity_choices(recipe_ids)
        return render(request, self.template_name, {'form': form, 'project_title': project_title, 'project_url': project_url})

    def post(self, request, *args, **kwargs):
        result = None
        project_title = request.GET.get('ca_name', None)
        project_url = request.GET.get('ca_id', None)
        form = self.form_class(request.POST)
        date_time = request.POST.get('timestamp', '')
        print('date_time:', date_time)
        if form.is_valid():
            # <process form cleaned data>
            data = form.cleaned_data
            if form.data.get('send', ''):
                actor = Agent(
                    name=data['actor_name'],
                    mbox='mailto:{}'.format(data['actor_email'])
                )
                verb_id = data['verb_id']
                verb = Verb(
                    id=verb_id,
                    display=LanguageMap(**xapi_verbs_by_id[verb_id]['display']),
                )
                object_language = data['object_language']
                activity_definition = ActivityDefinition(
                     name=LanguageMap(**{object_language: data['object_name']}),
                     type=data['activity_type'],
                )
                if data['object_description']:
                    activity_definition.description = LanguageMap(**{object_language: data['object_description']})
                object = Activity(
                    id=make_uri(data['object_id']),
                    definition=activity_definition,
                )
                context = {'platform': data['platform']}
                if data['context_object_name'] and data['context_object_id']:
                    context_activity_definition = ActivityDefinition(
                        name=LanguageMap(**{object_language: data['context_object_name']}),
                        type=data['context_activity_type'],
                    )
                    context_activity_object = Activity(
                        id=make_uri(data['context_object_id']),
                        definition=context_activity_definition,
                    )
                    context_activities = {
                        data['context_activity_relationship']: context_activity_object
                    }
                    context['context_activities'] = context_activities
                """
                authority = Agent(
                    name=data['authority_name'],
                    mbox='mailto:{}'.format(data['authority_email'])
                )
                """
                timestamp = data['timestamp']
                print('timestamp 1:', timestamp)
                """
                timestamp = datetime.strptime(date_time, "%d/%m/%Y %H:%M")
                print('timestamp 2:', timestamp)
                """
                statement = Statement(
                    actor=actor,
                    verb=verb,
                    object=object,
                    context=context,
                    timestamp=timestamp
                )
                result = send_statement(statement)
        recipe_ids = request.POST.getlist('recipe_ids')
        if recipe_ids:
            form.fields['verb_id'].choices = get_verb_choices(recipe_ids)
            form.fields['activity_type'].choices = get_activity_choices(recipe_ids)
        if result:
            try:
                result = json.dumps(json.loads(result.to_json()), indent=2)
            except:
                pass
        return render(request, self.template_name, {'form': form, 'result': result, 'project_title': project_title, 'project_url': project_url})


svalue=input("what is the starting value of odometer?")
svalue=int(svalue)
evalue=input("what is the end value of odometer?")
evalue=int(evalue)
fuel=input("how much fuel used?")
fuel=int(fuel)
tankcap=input("what is the tank capacity of the car?")
tankcap=int(tankcap)
mil=(evalue-svalue)/fuel
print("mileage is ",mil)
totdis=mil*tankcap
count=0
distrav=560
while(distrav>totdis ):
    count=count+1
    distrav=distrav-totdis
print("the no of stops req is",count)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jun  6 13:44:02 2019

@author: florianpgn

This function applies the association rules on the actions and estimates tasks. For
a detailed analysis and comparison with the proposed method, check main_proposed,
which implements not only the Bayesian approach but also the benchmark method
and provides comparison.

"""

import numpy as np

import time

import tools_dic as dtools
import tools_file as ftools
import tools_rule as rtools
import tools_presentation as ptools

from prettytable import PrettyTable

from importlib import reload
import params
reload(params)

if __name__ == "__main__":

    start_time = time.time()

    """
    Load activity data and set the definitions
    """
    exes = ftools.load(params.PATH_EXE+params.DAT_FILE_PREFIX+params.EXE_MAT)
    windows = ftools.load(params.PATH_TITLE+params.DAT_FILE_PREFIX+params.TITLE_MAT)
    tasks = ftools.load(params.PATH_TASK+params.DAT_FILE_PREFIX+params.TASK_MAT)
    keystrokes_quan = ftools.load(params.PATH_KSTROKES+params.DAT_FILE_PREFIX+params.KSTROKE_MAT)
    lunch = ftools.load(params.PATH_LUNCH+params.DAT_FILE_PREFIX+params.LUNCH_MAT)
    l_clicks = ftools.load(params.PATH_CLICKS+params.NEW_DAT+params.LCLICK_MAT)
    r_clicks = ftools.load(params.PATH_CLICKS+params.NEW_DAT+params.RCLICK_MAT)
    duration = ftools.load(params.PATH_DURATION+params.NEW_DAT+params.DURATION_MAT)

    (exe_names, window_names, time_names, level_of_assoc) = dtools.define_names()

    title_combinations = np.unique([ftools.joinTitles(t) for t in windows])
    title_codes = np.array([ftools.joinTitles(t) for t in windows])

    n_actions = len(exes) #  or any other matrix

    """
    In est_by_rules_direct, I use use 1 column for line number,  4 columns for
    estimations. But actually number of maximum estimations is no more than 3.
    """
    est_by_rules_direct = []

    for i in range(n_actions):

        """
        Estimation by applying the rules directly
        """
        (exe_only_rules, title_only_rules, exe_and_title_rules, exe_and_keyst_rules, exe_and_lunch_rules) = rtools.define_rules()
        est_task = np.array(rtools.apply_rules_to_action( exes[i],
                                                  windows[i],
                                                  keystrokes_quan[i],
                                                  lunch[i],
                                                  exe_only_rules,
                                                  title_only_rules,
                                                  exe_and_title_rules,
                                                  exe_and_keyst_rules,
                                                  exe_and_lunch_rules), dtype='<U14')

        # Pad with unknowns
        pad = est_task.tolist().copy()
        pad += [params.UNKNOWN] * (params.N_MAX_EST-len(est_task))
        est_by_rules_direct.append(pad)

    """
    Analyze results obtained by the benchmark method
    """
    print('==========================================')
    print('Applying the rules directly')
    nest_count = rtools.analyze_rule_based_estimations(tasks, est_by_rules_direct)

    x = time.time() - start_time
    print('Time elapsed {} sec'.format(x))


import mediapipe as mp
import math
import numpy as np
import cv2

class Detector:
    def __init__(self):
        self.mp_face_mesh = mp.solutions.face_mesh
        self.mp_drawing = mp.solutions.drawing_utils
        self.mp_drawing_styles = mp.solutions.drawing_styles

        # 눈동자의 중앙 특징점 인덱스(좌)
        self.IRIS_L_IDX = 468
        # 눈동자의 중앙 특징점 인덱스(우)
        self.IRIS_R_IDX = 473

        # 좌측 눈 주변 특징점 리스트
        self.EYE_L_IDX = [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385, 384, 398, 473]
        # 우측 눈 주변 특징점 리스트
        self.EYE_R_IDX = [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161, 246, 468]

        # 좌측 눈 각도 계산을 위한 눈 특징점 리스트(눈물샘, 위측, 아래측)
        self.EYE_L_SETA_IDX = [133, 158, 153]
        # 우측 눈 각도 계산을 위한 눈 특징점 리스트(눈물샘, 위측, 아래측)
        self.EYE_R_SETA_IDX = [362, 385, 380]

        # 좌측 입 벌어짐 각도(왼쪽 끝, 위측, 아래측)
        self.MOUTH_L_SETA_IDX = [78, 13, 14]
        # 우측 입 벌어짐 각도(오른쪽 끝, 위측, 아래측)
        self.MOUTH_R_SETA_IDX = [308, 13, 14]

        # Mediapipe 모델 가져오기(FaceMesh)
        self.face_mesh = self.mp_face_mesh.FaceMesh(
            #
            static_image_mode=True,
            #
            refine_landmarks=True,
            # 최대 얼굴 인식 개수
            max_num_faces=1,
            #
            min_detection_confidence=0.5
        )

        # 이미지 높이
        self.img_height = 0
        # 이미지 너비
        self.img_width = 0
        # 인식된 얼굴 정보 리스트
        self.face_landmarks = None

        self.GREEN = [0, 255, 0]
        self.RED = [0, 0, 255]

    def processImg(self, img):
        self.img_height, self.img_width, _ = img.shape
        results = self.face_mesh.process(img)
        self.face_landmarks = results.multi_face_landmarks

    def isFaceDetected(self):
        if self.face_landmarks is None:
            return False
        else:
            return True

    def getCoordinateByIDX(self, idx, face_idx):
        if self.face_landmarks is None:
            return None
        else:
            coordinate = self.face_landmarks[face_idx].landmark[idx]
            x, y, z = coordinate.x, coordinate.y, coordinate.z
            x *= self.img_width
            y *= self.img_height
            return int(x), int(y)

    def getIrisCoordinates(self, face_idx):
        eye_l_coordinate = self.getCoordinateByIDX(self.IRIS_L_IDX, face_idx)
        eye_r_coordinate = self.getCoordinateByIDX(self.IRIS_R_IDX, face_idx)
        return eye_l_coordinate, eye_r_coordinate

    def getEyeCenter(self, face_idx):
        var_l_x = 0
        var_l_y = 0
        for l_idx in self.EYE_L_IDX:
            x, y = self.getCoordinateByIDX(l_idx, face_idx)
            var_l_x += x
            var_l_y += y
        var_l_x /= len(self.EYE_L_IDX)
        var_l_y /= len(self.EYE_L_IDX)

        var_r_x = 0
        var_r_y = 0
        for r_idx in self.EYE_R_IDX:
            x, y = self.getCoordinateByIDX(r_idx, face_idx)
            var_r_x += x
            var_r_y += y
        var_r_x /= len(self.EYE_R_IDX)
        var_r_y /= len(self.EYE_R_IDX)

        return (var_l_x, var_l_y), (var_r_x, var_r_y)

    def getDist(self, x1, y1, x2, y2):
        return ((x1 - x2)**2 + (y1 - y2)**2)**0.5

    def getSeta(self, x_s, y_s, x1, y1, x2, y2):
        hypot1 = self.getDist(x_s, y_s, x1, y1)
        base1 = self.getDist(x_s, 0, x1, 0)
        seta1 = math.acos(base1 / hypot1)
        hypot2 = self.getDist(x_s, y_s, x2, y2)
        base2 = self.getDist(x_s, 0, x2, 0)
        seta2 = math.acos(base2 / hypot2)
        return np.rad2deg(seta1 + seta2)

    def getEyeSeta(self, eye_seta_idx):
        x_s, y_s = self.getCoordinateByIDX(eye_seta_idx[0], 0)
        x1, y1 = self.getCoordinateByIDX(eye_seta_idx[1], 0)
        x2, y2 = self.getCoordinateByIDX(eye_seta_idx[2], 0)
        return self.getSeta(x_s, y_s, x1, y1, x2, y2)

    def getEyeSetas(self):
        eye_l_seta = self.getEyeSeta(self.EYE_L_SETA_IDX)
        eye_r_seta = self.getEyeSeta(self.EYE_R_SETA_IDX)
        return eye_l_seta, eye_r_seta

    def getMouthSeta(self, mouth_seta_idx):
        x_s, y_s = self.getCoordinateByIDX(mouth_seta_idx[0], 0)
        x1, y1 = self.getCoordinateByIDX(mouth_seta_idx[1], 0)
        x2, y2 = self.getCoordinateByIDX(mouth_seta_idx[2], 0)
        return self.getSeta(x_s, y_s, x1, y1, x2, y2)

    def getMouthSetas(self):
        mouth_l_seta = self.getMouthSeta(self.MOUTH_L_SETA_IDX)
        mouth_r_seta = self.getMouthSeta(self.MOUTH_R_SETA_IDX)
        return mouth_l_seta, mouth_r_seta

    def getDiff(self, xy1, xy2):
        x1, y1 = xy1
        x2, y2 = xy2
        return (x2 - x1), (y2 - y1)

    def getGazeTarget(self):
        eye_l, eye_r = self.getEyeCenter(0)
        iris_l, iris_r = self.getIrisCoordinates(0)
        diff_l = self.getDiff(eye_l, iris_l)
        diff_r = self.getDiff(eye_r, iris_r)
        return (eye_l + diff_l * 3), (eye_r + diff_r * 3)

    def getFaceMaskedIMG(self, img, face_idx):
        self.mp_drawing.draw_landmarks(
            image=img,
            landmark_list=self.face_landmarks[face_idx],
            connections=self.mp_face_mesh.FACEMESH_TESSELATION,
            landmark_drawing_spec=None,
            connection_drawing_spec=self.mp_drawing_styles
            .get_default_face_mesh_tesselation_style())
        return img

    def getEyeMaskedIMG(self, img, face_idx):
        self.mp_drawing.draw_landmarks(
            image=img,
            landmark_list=self.face_landmarks[face_idx],
            connections=self.mp_face_mesh.FACEMESH_CONTOURS,
            landmark_drawing_spec=None,
            connection_drawing_spec=self.mp_drawing_styles
            .get_default_face_mesh_contours_style())
        return img

    def getIrisMaskedIMG(self, img, face_idx):
        self.mp_drawing.draw_landmarks(
            # 그릴 배경 이미지
            image=img,
            # 그릴 얼굴 데이터
            landmark_list=self.face_landmarks[face_idx],
            # 그릴 부위
            connections=self.mp_face_mesh.FACEMESH_IRISES,
            #
            landmark_drawing_spec=None,
            # 그릴 마스크 스타일
            connection_drawing_spec=self.mp_drawing_styles
            .get_default_face_mesh_iris_connections_style())
        return img

    def getMaskedIMG(self, img):
        if not self.isFaceDetected():
            return img
        img = self.getFaceMaskedIMG(img, 0)
        img = self.getEyeMaskedIMG(img, 0)
        img = self.getIrisMaskedIMG(img, 0)
        return img

    def getEyeResultIMG(self, img):
        if not self.isFaceDetected():
            return img

        eye_l_xy = []
        for idx in self.EYE_L_SETA_IDX:
            x, y = self.getCoordinateByIDX(idx, 0)
            eye_l_xy.append((x, y))
            cv2.circle(img, (x, y), 4, self.GREEN, -1)
        cv2.line(img, eye_l_xy[0], eye_l_xy[1], self.GREEN, 2)
        cv2.line(img, eye_l_xy[0], eye_l_xy[2], self.GREEN, 2)

        eye_r_xy = []
        for idx in self.EYE_R_SETA_IDX:
            x, y = self.getCoordinateByIDX(idx, 0)
            eye_r_xy.append((x, y))
            cv2.circle(img, (x, y), 4, self.GREEN, -1)

        cv2.line(img, eye_r_xy[0], eye_r_xy[1], self.GREEN, 2)
        cv2.line(img, eye_r_xy[0], eye_r_xy[2], self.GREEN, 2)

        return img

    def getMouthResultIMG(self, img):
        if not self.isFaceDetected():
            return img

        mouth_l_seta = []
        for idx in self.MOUTH_L_SETA_IDX:
            x, y = self.getCoordinateByIDX(idx, 0)
            mouth_l_seta.append((x, y))
            cv2.circle(img, (x, y), 4, self.RED, -1)
        cv2.line(img, mouth_l_seta[0], mouth_l_seta[1], self.RED, 2)
        cv2.line(img, mouth_l_seta[0], mouth_l_seta[2], self.RED, 2)

        mouth_r_seta = []
        for idx in self.MOUTH_R_SETA_IDX:
            x, y = self.getCoordinateByIDX(idx, 0)
            mouth_r_seta.append((x, y))
            cv2.circle(img, (x, y), 4, self.RED, -1)

        cv2.line(img, mouth_r_seta[0], mouth_r_seta[1], self.RED, 2)
        cv2.line(img, mouth_r_seta[0], mouth_r_seta[2], self.RED, 2)

        return img


from pathlib import Path
from typing import Literal

from jtcmake import SELF, GroupsGroup, Rule, RulesGroup, StaticGroupBase, VFile

def func1(a: Path):
    ...

def func2(a: Path, b: Path):
    ...

class Static1(StaticGroupBase):
    r1: Rule[str]
    r2: Rule[Literal["a", "b"]]
    g1: GroupsGroup[RulesGroup]

    def __init__(self):
        self.r1.init({"a": "a.txt", "b": "b.txt"}, func2)(SELF.a, b=SELF[1])
        self.r1.init(["a.txt", "b.txt"], func2)(SELF[0], SELF[1])
        self.r1.init("a.txt", func1)(SELF)
        self.r1.init(VFile("a.txt"), func1)(SELF)
        self.r2.init({"a": "a.txt", "b": "b.txt"}, func2)(SELF.a, b=SELF[1])
        self.r2.init(Path("x"), func2)(SELF.a, b=SELF[1])

        gr = self.g1.init(RulesGroup)
        gr.add_group("a")


interfaces = {
    "员工列表": {
        "uri": "/es/workOrderStaffStatistics/queryStaff",
        "method": "post",
        "be_from_data": {
            "data_type": "json",
            "deptIds": [],
            "name": "PJPJ",
            "current": 1,
            "size": 20
        }
    },
    "客户列表": {
        "uri": "/es/customer/list2",
        "method": "post",
        "be_from_data": {
            "data_type": "json",
            "customerNumber": "",
            "fullName": "",
            "contactName": "",
            "employeeId": {
                "data_from": {
                    "interface_name": "员工列表",
                    "value_path": ["data", "records", 0, "employeeId"]
                }
            },
            "customerManagerId": "",
            "organizationIds": [],
            "labelIds": [],
            "current": 1,
            "size": 100
        }
    },
    "test": {
        "uri": "",
        "name": "",
        "method": "",
        "data_type": "json",
        "json": {
            "interface_data": {"data_from": {
                "interface_name": "客户列表",
                "value_path": ["data", "records", 0, "id"]
            }},
            "list_data": [{
                "list_mark": "list_data_1",
                "is_dict": 1,
                "str": {"data_length": 10, "data_type": "str"},
                "int": {"data_range": [0, 1000], "data_type": "int"},
                "float": {"data_range": [0, 1000], "decimal_range": [0, 999], "data_type": "float"},
            }, {"list_mark": "list_data_2", "data_length": 10, "data_type": "str"},
                {"list_mark": "list_data_3", "data_range": [0, 1000], "data_type": "int"}],
            "str": {"data_length": 10, "data_type": "str"},
            "int": {"data_range": [0, 1000], "data_type": "int"},
            "float": {"data_range": [0, 1000], "decimal_range": [0, 999], "data_type": "float"},
            "dict_data": {
                "is_dict": 1,
                "str": {"data_length": 10, "data_type": "str"},
                "int": {"data_range": [0, 1000], "data_type": "int"},
                "float": {"data_range": [0, 1000], "decimal_range": [0, 999], "data_type": "float"},
            }
        }
    },
    "新增产品类别": {
        "uri": "/es/sparePartsType/saveOrUpdate",
        "name": "新增产品类别",
        "method": "post",
        "data_type": "json",
        "json": {
            "typeName": {"data_length": 20, "data_type": "str"},
            "typeCode": {"data_length": 8, "data_type": "str"},
            "remark": {"data_length": 100, "data_type": "str"},
            "parentName": "",
            "parentId": 0,
        }
    }
}


from transformers import AutoTokenizer, AutoModelForCausalLM
import transformers
import torch
import time

model = "tiiuae/falcon-7b-instruct"

tokenizer = AutoTokenizer.from_pretrained(model)
pipeline = transformers.pipeline(
    "text-generation",
    model=model,
    tokenizer=tokenizer,
    torch_dtype=torch.bfloat16,
    trust_remote_code=True,
    device_map="auto",
)

while (True):
  mem = input('')
  starttime = time.time()
  with open('preprompt.txt', 'r') as file:
    prompt = file.read()
  sequences = pipeline(
    prompt,
    max_length=400,
    do_sample=True,
    top_k=1,
    num_return_sequences=1,
    eos_token_id=tokenizer.eos_token_id,
  )
  for seq in sequences:
    print(f"Result: {seq['generated_text']}")
  print(f'time: ${time.time() - starttime}')


#Simple pong game
import turtle
import winsound

win = turtle.Screen()               #the actual window
win.title('Pong by Sanchit')
win.bgcolor('Black')
win.setup(width=800, height=600)
win.tracer(0)                       #prevents auto-update

#Score A
score_a = 0
score_b = 0

#Paddle L
paddle_l = turtle.Turtle()
paddle_l.speed(0)
paddle_l.shape('square')            #20pix x 20pix size
paddle_l.shapesize(stretch_wid=5, stretch_len=1)
paddle_l.color('White')
paddle_l.penup()
paddle_l.goto(-350,0)

#Paddle R
paddle_r = turtle.Turtle()
paddle_r.speed(0)
paddle_r.shape('square')            #20pix x 20pix size
paddle_r.shapesize(stretch_wid=5, stretch_len=1)
paddle_r.color('White')
paddle_r.penup()
paddle_r.goto(350,0)

#Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape('circle')            #20pix x 20pix size
ball.color('white')
ball.penup()
ball.goto(0,0)
ball.dx = 0.35
ball.dy = -0.35

#UI ans Scoreboard
pen = turtle.Turtle()
pen.speed(0)
pen.color('white')
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write('Player A: 0 & Player B: 0', align='center', font=("Segoe UI", 24, "bold"))

#Functions to move paddles
def paddle_l_up():
    y = paddle_l.ycor()
    y += 20
    paddle_l.sety(y)

def paddle_l_down():
    y = paddle_l.ycor()
    y -= 20
    paddle_l.sety(y)

def paddle_r_up():
    y = paddle_r.ycor()
    y += 20
    paddle_r.sety(y)

def paddle_r_down():
    y = paddle_r.ycor()
    y -= 20
    paddle_r.sety(y)

#Keybinds
win.listen()
win.onkeypress(paddle_l_up, 'w')
win.onkeypress(paddle_l_down, 's')

win.onkeypress(paddle_r_up, 'Up')
win.onkeypress(paddle_r_down, 'Down')

#Game Loop
while True:
    win.update()
    #Move the ball
    ball.setx(ball.xcor() + ball.dx)
    ball.sety(ball.ycor() + ball.dy)

    #Border Checking
    if ball.ycor() > 290:
        ball.sety(290)
        ball.dy *= -1
        winsound.PlaySound("bounce.wav", winsound.SND_ASYNC)

    if ball.ycor() < -285:
        ball.sety(-285)
        ball.dy *= -1
        winsound.PlaySound("bounce.wav", winsound.SND_ASYNC)

    if paddle_l.ycor() > 248:
        paddle_l.sety(248)

    if paddle_l.ycor() < -248:
        paddle_l.sety(-248)

    if paddle_r.ycor() > 248:
        paddle_r.sety(248)

    if paddle_r.ycor() < -248:
        paddle_r.sety(-248)

    if ball.xcor() > 390:
        ball.goto(0,0)
        ball.dx *= -1
        score_a += 1
        pen.clear()
        pen.write('Player A: {} & Player B: {}'.format(score_a, score_b), align='center', font=("Segoe UI", 24, "bold"))

    if ball.xcor() < -390:
        ball.goto(0,0)
        ball.dx *= -1
        score_b += 1
        pen.clear()
        pen.write('Player A: {} & Player B: {}'.format(score_a, score_b), align='center', font=("Segoe UI", 24, "bold"))

    #Can-Collide to On
    if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_r.ycor() + 40 and ball.ycor() > paddle_r.ycor() - 40):
        ball.setx(340)
        ball.dx *= -1
        winsound.PlaySound("bounce.wav", winsound.SND_ASYNC)

    if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_l.ycor() + 40 and ball.ycor() > paddle_l.ycor() - 40):
        ball.setx(-340)
        ball.dx *= -1
        winsound.PlaySound("bounce.wav", winsound.SND_ASYNC)


# 같은 숫자는 싫어 : https://programmers.co.kr/learn/courses/30/lessons/12906

def solution(arr):
    answer = []
    answer.append(arr[0])

    for j in range(1, len(arr)):
        if answer[-1] == arr[j]:
            continue
        answer.append(arr[j])

    return answer

# 슬라이싱으로 조금 더 깔끔하게. 근데 조금 느림

def solution1(arr):
    answer = []

    for j in range(len(arr)):
        if answer[-1:] == [arr[j]]:
            continue
        answer.append(arr[j])

    return answer


import pandas as pd
import numpy as np
import torch
import torch.autograd as autograd
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

def save_checkpoint(state, filename='checkpoint.pth.tar'):
    torch.save(state, filename)

def en_cuda(tensor):
    if torch.cuda.is_available():
        return tensor.cuda()
    else:
        return tensor

def diff_axis_0(a):
    ret = a[1:] - a[:-1]
    ret = torch.cat([torch.zeros(1, a.size()[1], a.size()[2]).cuda(), ret])
    return ret

def compute_speeds(a):
    ret = a[1:] - a[:-1]
    ret = torch.cat([en_cuda(torch.zeros(1, a.size()[1])), ret])
    return ret

def get_coef(mux, muy, sx, sy, corr):
    # eq 20 -> 22 of Graves (2013)

    # The output must be exponentiated for the std devs
    o_sx = torch.exp(sx)
    o_sy = torch.exp(sy)
    # Tanh applied to keep it in the range [-1, 1]
    o_corr = torch.tanh(corr)
    return [mux, muy, o_sx, o_sy, o_corr]

def import_data(scene, batch_size, factor=10, rotate_=True):
    '''Import Data file for training'''
    # Read data and group by frame
    selector = en_cuda(torch.LongTensor([2, 3]))
    df_positions = pd.read_table(scene, delim_whitespace=True, header=None)
    df_positions.loc[:, [2, 3]] = df_positions.loc[:, [2, 3]] * factor
    df_positions_by_frame = []

    map_frame_index = {}
    index = 0
    for _, x in df_positions.groupby(df_positions[0]):
        df_positions_by_frame.append(en_cuda(torch.Tensor(x.as_matrix())))
        map_frame_index[x.iloc[0, 0]] = index
        index += 1

    df = []

    map_ped_index = {}

    first_positions = []
    # Group by ped_id
    index = 0
    for _, x in df_positions.groupby(df_positions[1]):
        first_positions.append(x.iloc[8, :])
        map_ped_index[x.iloc[0, 1]] = (
            int(index / batch_size), index % batch_size)
        index += 1
        tmp = en_cuda(torch.Tensor(x.as_matrix()))
        df.append(tmp.unsqueeze(0))

    # Get_first positions so that we can recover the position from the velocity
    first_positions = en_cuda(torch.Tensor(
        pd.concat(first_positions, axis=1).as_matrix().T)).split(batch_size, 0)

    # creates Batches
    tmp = torch.cat(df, 0).transpose(1, 0)
    count = tmp.size()[1]

    # Apply rotations
    rotations = None
    result_speeds = tmp.clone()
    result_speeds[:, :, selector] = diff_axis_0(result_speeds[:, :, selector])
    if rotate_:
        rotations = create_rotation_matrices(torch.atan2(
            result_speeds[1, :, 3], result_speeds[1, :, 2]))
        result_speeds[:, :, selector] = rotate(
            rotations, result_speeds[:, :, selector])
        for i in range(rotations.size()[0]):
            rotations[i, :, :] = torch.mul(
                rotations[i, :, :], en_cuda(torch.Tensor([[1, -1], [-1, 1]])))
    result_speeds = Variable(result_speeds)
    result_pts = tmp.split(batch_size, 1)
    result_speeds = result_speeds.split(batch_size, 1)
    rotations = rotations.split(batch_size, 0) if rotate_ else None
    return map_ped_index, result_speeds, rotations, result_pts, first_positions, df_positions_by_frame, map_frame_index, count

def sample_gaussian_2d(mux, muy, sx, sy, rho):
    '''
    Function to sample a point from a given 2D normal distribution
    params:
    mux : mean of the distribution in x
    muy : mean of the distribution in y
    sx : std dev of the distribution in x
    sy : std dev of the distribution in y
    rho : Correlation factor of the distribution
    '''
    # Extract mean
    mean = [mux, muy]
    # Extract covariance matrix
    cov = [[sx * sx, rho * sx * sy], [rho * sx * sy, sy * sy]]
    # Sample a point from the multivariate normal distribution
    x = np.random.multivariate_normal(mean, cov, 1)
    return x[0][0], x[0][1]

def tf_2d_normal(x, y, mux, muy, sx, sy, rho):
    # PDF normal
    normx = x.sub(mux)
    normy = y.sub(muy)
    # Calculate sx*sy
    sxsy = torch.mul(sx, sy)
    # Calculate the exponential factor
    z = (torch.div(normx, sx))**2 + (torch.div(normy, sy))**2 - 2 * \
        torch.div(torch.mul(rho, torch.mul(normx, normy)), sxsy)
    negRho = 1 - rho**2
    # exp part
    result = torch.exp(torch.div(-z, 2 * negRho))
    # Normalization constant
    denom = 2 * np.pi * torch.mul(sxsy, torch.sqrt(negRho))
    # Final PDF calculation
    result = torch.div(result, denom)

    return result

def get_lossfunc(z_mux, z_muy, z_sx, z_sy, z_corr, x_data, y_data):
    '''
    Function to calculate given a 2D distribution over x and y, and target data
    of observed x and y points
    params:
    z_mux : mean of the distribution in x
    z_muy : mean of the distribution in y
    z_sx : std dev of the distribution in x
    z_sy : std dev of the distribution in y
    z_rho : Correlation factor of the distribution
    x_data : target x points
    y_data : target y points
    '''
    # Calculate the PDF of the data w.r.t to the distribution
    result = tf_2d_normal(x_data, y_data, z_mux, z_muy, z_sx, z_sy, z_corr)
    epsilon = 1e-20

    # Apply the log operation
    result1 = -torch.log(torch.clamp(result, min=epsilon)
                         )  # Numerical stability
    print(result1.size())
    return torch.sum(result1).div(result1.size()[0])

def get_avg_displacement(true, pred):
    # Compute MSE
    result = pred.sub(true)**2
    result = torch.sum(result, 2)
    norm = result.size()[0]
    result = torch.sum(result, 0)
    result = torch.div(result, norm)
    return result

def get_accuracy(true, pred):
    # Compute L2 distance and Final displacement error
    result = torch.sqrt(pred.sub(true)**2)
    result = torch.sum(result, 2)
    norm = result.size()[0]
    result_ = torch.sum(result, 0)
    result_ = torch.div(result_, norm)
    return result_, result[-1, :]

def plot_trajectory(true, pred, neighbs, n_paths, name, obs=8, xlim=None, ylim=None, debug=False):
    plt.figure()
    # Plot predicted and true trajectories
    true_ = true.cpu().numpy()
    x1, y1, x2, y2 = pred[:, 0].cpu().numpy(), pred[:, 1].cpu().numpy(), true_[
        :, 2], true_[:, 3]
    plt.plot(x1, y1, 'ro-', x2, y2, 'go-')
    plt.plot([x2[7], x1[0]], [y2[7], y1[0]], 'ro-')
    red_patch = mpatches.Patch(color='red', label='predicted trajectory')
    # Add timestamps
    for i in range(x1.shape[0]):
        plt.text(x1[i], y1[i], str(i))
        plt.text(x2[i + 8], y2[i + 8], str(i))

    map_ped_index = {}
    min_frame_all, step = true[0, 0], (true[1, 0] - true[0, 0])
    if step == 0:
        step = 1
    # Group neighbors by ped_id
    pedestrians = []
    idx = 0
    for frame in neighbs:
        for entry in frame:
            if entry[1] in map_ped_index:
                pedestrians[map_ped_index[entry[1]]].append(
                    np.expand_dims(entry.cpu().numpy(), axis=0))
            else:
                map_ped_index[entry[1]] = idx
                pedestrians.append([])
                pedestrians[idx].append(
                    np.expand_dims(entry.cpu().numpy(), axis=0))
                idx += 1

    if len(pedestrians):
        pedestrians = [np.concatenate(x, axis=0) for x in pedestrians]
        # Find closest neighbors
        dists = []
        for x in pedestrians:
            min_frame = np.min(x[:, 0])
            max_frame = np.max(x[:, 0])
            sub_traj = true_[
                (true_[:, 0] >= min_frame) & (true_[:, 0] <= max_frame), :]
            dist = np.mean(
                np.sum((sub_traj[:, [2, 3]] - x[:, [2, 3]])**2, 1))
            dists.append(dist)

        idxs = np.argsort(np.array(dists))[:n_paths]
        pedestrians = [pedestrians[i] for i in idxs]
        # print(pedestrians[0])
        # Plot neighbors
        for path in pedestrians:
            plt.plot(path[:, 2], path[:, 3], 'bo-')
            plt.text(path[0, 2], path[0, 3], int(
                (path[0, 0] - min_frame_all) / step))
            plt.text(path[-1, 2], path[-1, 3],
                     int((path[-1, 0] - min_frame_all) / step))

    green_patch = mpatches.Patch(color='green', label='true trajectory')
    blue_patch = mpatches.Patch(color='blue', label='neighboring trajectories')
    plt.legend(handles=[red_patch, green_patch, blue_patch])
    if xlim is not None:
        plt.xlim(xlim)
    if ylim is not None:
        plt.ylim(ylim)
    plt.savefig(name + '.png')

    plt.close()
    return


#!/usr/bin/env python
import rospy
import rostopic
from rostopic import ROSTopicHz
from diagnostic_updater import *
import diagnostic_msgs
from std_msgs.msg import Float32, Int32, Int16
from geometry_msgs.msg import Twist

class FrequencyStatus(DiagnosticTask):
    """A diagnostic task that monitors the frequency of an event.

    This diagnostic task monitors the frequency of calls to its tick method,
    and creates corresponding diagnostics. It will report a warning if the
    frequency is outside acceptable bounds, and report an error if there have
    been no events in the latest window.
    """

    def __init__(self, name, params, topic, sensor_id):
        """Constructs a FrequencyStatus class with the given parameters."""
        DiagnosticTask.__init__(self, name)
        self.params = params
        self.lock = threading.Lock()
        self.clear()
        self.sub = rospy.Subscriber(topic, rospy.AnyMsg, self.tick)
        self.state = 2
        self.id = sensor_id

    def clear(self):
        """Resets the statistics."""
        with self.lock:
            self.count = 0
            curtime = rospy.Time.now()
            self.times = [curtime for i in range(self.params.window_size)]
            self.seq_nums = [0 for i in range(self.params.window_size)]
            self.hist_indx = 0

    def tick(self, msg):
        """Signals that an event has occurred."""
        with self.lock:
            self.count += 1

    def run(self, stat):
        with self.lock:
            curtime = rospy.Time.now()
            curseq = self.count
            events = curseq - self.seq_nums[self.hist_indx]
            window = (curtime - self.times[self.hist_indx]).to_sec() + 0.0001
            freq = events / window
            self.seq_nums[self.hist_indx] = curseq
            self.times[self.hist_indx] = curtime
            self.hist_indx = (self.hist_indx + 1) % self.params.window_size

            if events == 0:
                stat.summary(2, "No events recorded.")
                self.state = 2
            elif freq < self.params.freq_bound['min'] * (1 - self.params.tolerance):
                stat.summary(1, "Frequency too low.")
                self.state = 1
            elif self.params.freq_bound.has_key('max') and freq > self.params.freq_bound['max'] * (1 + self.params.tolerance):
                stat.summary(1, "Frequency too high.")
                self.state = 1
            else:
                stat.summary(0, "Desired frequency met")
                self.state = 0

            stat.add("Events in window", "%d" % events)
            stat.add("Events since startup", "%d" % self.count)
            stat.add("Duration of window (s)", "%f" % window)
            stat.add("Actual frequency (Hz)", "%f" % freq)
            if self.params.freq_bound.has_key('max') and self.params.freq_bound['min'] == self.params.freq_bound['max']:
                stat.add("Target frequency (Hz)", "%f" % self.params.freq_bound['min'])
            if self.params.freq_bound['min'] > 0:
                stat.add("Minimum acceptable frequency (Hz)", "%f" % (self.params.freq_bound['min'] * (1 - self.params.tolerance)))
            if self.params.freq_bound.has_key('max'):
                stat.add("Maximum acceptable frequency (Hz)", "%f" % (self.params.freq_bound['max'] * (1 + self.params.tolerance)))

        return stat

class Emergency_stop:

    def __init__(self, freq_check_list):
        self.freq_check = freq_check_list

        #Subscribed to move command topic
        self.Move_sub = rospy.Subscriber('/mux_cmd_vel', Twist, self.E_STOP_CB, queue_size=1 )
        self.Move_pub = rospy.Publisher('/watchdog/cmd_vel', Twist, queue_size=1)

    def E_STOP_CB(self, data):
        self.stop = 0

        for i in self.freq_check:
            if i.state != 0:
                self.stop = 1

        if self.stop == 0:
            self.Move_pub.publish(data)
        else :
            # Publish a 0 velocity message for safety
            self.Move_pub.publish(Twist())

if __name__ == '__main__':
    rospy.init_node("sensor_check")
    # Wait for the ROS clock to be initialized

    r = rospy.Rate(100)
    while not rospy.Time.now().to_sec() > 0:
        r.sleep

    nb_sensors = int(rospy.get_param("~nb_sensors", 0))
    updaters = []
    pkg_name = rospy.get_name()
    freq_check_list = []

    for i in range(1, nb_sensors + 1):
        name = ('~' + pkg_name + '/sensor_' + str(i))

        # sensor parameters
        path = str(rospy.get_param((name + '/name'), ''))
        sensor_id = str(rospy.get_param((name + '/sensor_id'), ''))
        topic = str(rospy.get_param((name + '/topic'), ''))
        min_freq = float(rospy.get_param((name + '/min_freq'), ''))
        max_freq = float(rospy.get_param((name + '/max_freq'), ''))

        updater = Updater()
        updater.setHardwareID(sensor_id)

        # Diagnostic tasks are added to the Updater. They will later be run when
        # the updater decides to update.
        param = FrequencyStatusParam({'min': min_freq, 'max': max_freq}, tolerance=0, window_size=20)
        freq_check = FrequencyStatus(path, param, topic, sensor_id)
        updater.add(freq_check)
        freq_check_list.append(freq_check)
        # If we know that the state of the node just changed, we can force an
        # immediate update.
        updater.force_update()
        updaters.append(updater)

    E_stop = Emergency_stop(freq_check_list)

    while not rospy.is_shutdown():
        rospy.sleep(0.1)
        # We can call updater.update whenever is convenient. It will take care
        # of rate-limiting the updates.
        for u in updaters:

            u.force_update()


from sqlalchemy.orm import Session, joinedload, lazyload
from typing_extensions import get_args

from constants import DATASET_ESTIMATORS, DATASET_TYPE_NAMES, DETAIL_LEVEL, METRICS, RUN_DESCRIPTORS

from db.models import Experiment, Run, CompletenessCurve
from utils.completeness_curve import get_experiment_completeness_curve
from utils.file_helpers import load_results
from utils.numpy_encoder import NumpyEncoder

def get_or_create(session, db_model, **kwargs):
    instance = session.query(db_model).filter_by(**kwargs).first()
    if instance:
        return instance
    else:
        instance = db_model(**kwargs)
        session.add(instance)
        session.commit()
        return instance

def reset_db(db: Session):

    db.query(Experiment).delete()
    db.query(Run).delete()
    db.query(CompletenessCurve).delete()

def load_runs_csvs(db: Session, dataset_type: DATASET_TYPE_NAMES):
    runs_df = load_results(dataset_type)
    group_by_descriptors = ['dataset_type', 'dataset', 'model'] + DATASET_ESTIMATORS
    db_experiments = []
    db_runs = []

    for group_by_values, values in runs_df.groupby(group_by_descriptors):
        grouped_in_dict = NumpyEncoder(dict(zip(group_by_descriptors, group_by_values)))

        experiment = get_or_create(db, Experiment, **grouped_in_dict)
        db_experiments.append(experiment)

        for index, value in values.iterrows():
            db_runs.append(Run(**{i: value[i] for i in RUN_DESCRIPTORS}, experiment=experiment))

    db.add_all(db_experiments)
    db.commit()

    return db_experiments

def load_completeness_curves(db: Session, load_only_missing: bool = True):
    experiments_to_load_query = db.query(Experiment).options(lazyload(Experiment.completeness_curves))

    if load_only_missing:
        experiments_to_load_query = experiments_to_load_query.filter(Experiment.completeness_curves == None)

    db_completeness_curves = []
    for experiment in experiments_to_load_query:
        for metric in get_args(METRICS):
            experiment_completeness_curve = get_experiment_completeness_curve(experiment, metric)
            db_completeness_curves.append(CompletenessCurve(experiment=experiment, **experiment_completeness_curve))

    db.add_all(db_completeness_curves)
    db.commit()

    return db_completeness_curves

def get_experiment(db: Session, dataset_name: str, model_name: str, detail_level: DETAIL_LEVEL = "0"):
    basic_query = db.query(Experiment).filter_by(
        dataset=dataset_name,
        model=model_name
    )

    if detail_level == "1":
        basic_query =  basic_query.options(
            joinedload(Experiment.completeness_curves)
        )
    if detail_level == "2":
        basic_query =  basic_query.options(
            joinedload(Experiment.runs)
        )
    return basic_query.first()

def get_experiments(db: Session, detail_level: DETAIL_LEVEL = "0", dataset_type: DATASET_TYPE_NAMES | None = None):
    basic_query = db.query(Experiment)
    if dataset_type is not None:
        basic_query = basic_query.filter_by(dataset_type = dataset_type)
    if detail_level == "1":
        basic_query = basic_query.options(
            joinedload(Experiment.completeness_curves)
        )
    if detail_level == "2":
        basic_query = basic_query.options(
            joinedload(Experiment.runs)
        )
    return basic_query.all()

def get_runs(db: Session, dataset_type: DATASET_TYPE_NAMES | None = None, dataset_name: str | None = None, model_name: str | None = None):

    experiment_kwargs = {'dataset_type': dataset_type, 'dataset': dataset_name, 'model': model_name}
    experiment_kwargs = {k: v for k, v in experiment_kwargs.items() if v is not None}

    return db.query(Run).options(
        lazyload(Run.experiment)).filter(
        Run.experiment.has(**experiment_kwargs)).all()


# A Dictionary is a changeable unordered collection of unique key:value  pairs
countries = {
    "Nigeria": "Abuja",
    "USA": "Washington DC",
    "Ghana": "Accra",
    "India": "New Dheli",
    "China": "Beijing",
    "Russia": "Moscow",
}
countries["Japan"] = "Tokyo"
countries.update({"USA": "Los Angeles"})
countries.pop("Russia")
# countries.clear()
# print(countries["USA"])
# print(countries["Nigeria"])

for key, value in countries.items():
    # print(value)
    # print(key)
    print(key, ":", value)
    # print(countries.items())
    # print(countries.keys())
    # print(countries.values())

# class work
# Create a dictionary name students with names = Hermione, Harry, Ron aand Draco
# Their corresponding houses are                Griffyndor, Griffyndor, Griffyndor and Slytherin
name = {
    "email": "ekenehanson@gmail.com",
    "age": 12,
    "is_human": True,
    "height": 23.45,
    "has_bad_credit": False,
}


import torch.nn as nn

class MyLeNet_5(nn.Module):
    def __init__(self):
        super(MyLeNet_5,self).__init__()
        self.conv1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5,padding=2)
        self.Sigmoid = nn.Sigmoid()
        self.pool1 = nn.AvgPool2d(kernel_size=2,stride=2)
        self.conv2 = nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5)
        self.pool2 = nn.AvgPool2d(kernel_size=2,stride=2)
        self.conv3 = nn.Conv2d(in_channels=16,out_channels=120,kernel_size=5)
        self.flatten = nn.Flatten()
        self.fc1 = nn.Linear(120,84)
        self.output = nn.Linear(84,10)

    def forward(self, x):
        x = self.Sigmoid(self.conv1(x))
        x = self.pool1(x)
        x = self.Sigmoid(self.conv2(x))
        x = self.pool2(x)
        x = self.conv3(x)
        x = self.flatten(x)
        x = self.fc1(x)
        x = self.output(x)
        return x

#model=MyLeNet_5
#print(model)


# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

from astropy.time import Time
import astropy.units as u
import os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from scipy import optimize

__all__ = ['LightCurve', 'split_light_curve_at_gaps',
           'concatenate_light_curves']

class LightCurve(object):
    """
    Container object for light curves
    """
    def __init__(self, times=None, fluxes=None, errors=None, name=None,
                 meta=None, raw_fluxes=None, raw_errors=None, xcentroids=None,
                 ycentroids=None, weights=None):

        if isinstance(times[0], Time) and isinstance(times, np.ndarray):
            times = Time(times)
        elif not isinstance(times, Time):
            times = Time(times, format='jd')

        self.times = times
        self.fluxes = fluxes
        self.errors = errors
        self.name = name
        self.meta = meta
        self.raw_fluxes = raw_fluxes
        self.raw_errors = raw_errors
        self.xcentroids = xcentroids
        self.ycentroids = ycentroids
        self.weights = weights
        self.cached_light_curves = {}
        self.meta = meta

    def plot(self, ax=None, show=True,
             plot_kwargs={'color':'b', 'marker':'o', 'lw':0}):
        """
        Plot light curve
        """
        if ax is None:
            ax = plt.gca()

        ax.plot(self.times.jd, self.fluxes, **plot_kwargs)
        ax.set(xlabel='Time', ylabel='Flux', title=self.name)

        def format_coord(x, y):
            return 'x=%1.8f, y=%1.8f' % (x, y)
        ax.format_coord = format_coord

        if show:
            plt.show()

    def megaplot(self, show=True,
             plot_kwargs={'color':'b', 'marker':'o', 'lw':0}):
        """
        Plot light curve and other data
        """
        plt.figure(figsize=(15, 15))
        gs = GridSpec(3, 3)
        ax_lc = plt.subplot(gs[0, :])
        ax_rawflux = plt.subplot(gs[1, :], sharex=ax_lc)
        ax_centroids = plt.subplot(gs[2, 0])
        ax_x = plt.subplot(gs[2, 1])
        ax_y = plt.subplot(gs[2, 2])

        ax_lc.plot(self.times.jd, self.fluxes, **plot_kwargs)
        ax_lc.set(ylabel='Flux', title=self.name)

        ax_rawflux.plot(self.times.jd, self.raw_fluxes[:, 1:, 0])
        ax_rawflux.plot(self.times.jd, self.raw_fluxes[:, 0, 0], 'k.')
        ax_rawflux.set(xlabel='Time', ylabel='Flux')

        ax_centroids.plot(self.xcentroids[:, 1:], self.ycentroids[:, 1:], '.')
        ax_centroids.plot(self.xcentroids[:, 0], self.ycentroids[:, 0], 'ks')
        ax_centroids.set(xlabel='x', ylabel='y')

        ax_x.plot(self.times.jd, self.xcentroids[:, 1:])
        ax_x.plot(self.times.jd, self.xcentroids[:, 0], 'k.')
        ax_x.set(xlabel='Time', ylabel='x')

        ax_y.plot(self.times.jd, self.ycentroids[:, 1:])
        ax_y.plot(self.times.jd, self.ycentroids[:, 0], 'k.')
        ax_y.set(xlabel='Time', ylabel='y')

        if show:
            plt.show()

    def __repr__(self):
        """Repr string should be 'LightCurve: name' """
        return "<{0}: {1}>".format(self.__class__.__name__, self.name)

    @property
    def times_jd(self):
        return self.times.jd

    def save_to(self, path, overwrite=True):
        """
        Save times, fluxes, errors to ``path``.txt
        """
        if not path.endswith('.npz'):
            path += '.npz'

        if not os.path.exists(path) or overwrite:
            # attrs = ['times_jd', 'fluxes', 'errors']
            # output_array = np.zeros((len(self.fluxes), len(attrs)), dtype=float)
            # for i, attr in enumerate(attrs):
            #     output_array[:, i] = getattr(self, attr)
            # np.savetxt(os.path.join(path), output_array)
            save_attrs = ['times_jd', 'fluxes', 'errors', 'raw_fluxes',
                          'raw_errors', 'xcentroids', 'ycentroids']
            save_dict = {}
            for attr in save_attrs:
                save_dict[attr] = getattr(self, attr)
            np.savez_compressed(os.path.join(path), **save_dict)

    @classmethod
    def load_from(cls, path, name=None):
        """
        Load times, fluxes, errors to ``path``.txt
        """
        if not path.endswith('.npz'):
            path += '.npz'

        in_file = np.load(os.path.join(path))

        # times, fluxes, errors = np.loadtxt(os.path.join(path), unpack=True)
        # name = path.split(os.sep)[-1].split('.')[0]
        # return cls(times=times, fluxes=fluxes, errors=errors, name=name)
        return cls(times=in_file['times_jd'], fluxes=in_file['fluxes'],
                   errors=in_file['errors'], raw_fluxes=in_file['raw_fluxes'],
                   raw_errors=in_file['raw_errors'],
                   xcentroids=in_file['xcentroids'],
                   ycentroids=in_file['ycentroids'], name=name)

    def fit_linear_baseline(self, plots=False, sigma=5):
        """
        Find linear baseline trend with `~numpy.polyfit`. Do sigma clipping
        outlier rejection before fitting for the trend.
        """
        # Remove linear baseline trend
        if len(self.fluxes) > 1:
            order = 1
            print()
            non_outliers = (np.abs(self.fluxes - self.fluxes.mean()) <
                            sigma*np.std(self.fluxes) + (self.fluxes <
                            self.fluxes.mean()))

            linear_baseline = np.polyfit(self.times.jd[non_outliers],
                                         self.fluxes[non_outliers], order)
            linear_baseline_fit = np.polyval(linear_baseline, self.times.jd)

            if plots:
                fig, ax = plt.subplots(1, figsize=(8, 6))
                ax.axhline(1, ls='--', color='k')
                ax.plot(self.times.jd[non_outliers], self.fluxes[non_outliers], 'bo', label='data')
                ax.plot(self.times.jd[-non_outliers], self.fluxes[-non_outliers],'ro', label='outliers')
                ax.plot(self.times.jd, linear_baseline_fit, 'r', label='fit')
                ax.set(title='Linear trend fit', xlabel='JD', ylabel='Flux')
                ax.legend()
                plt.show()
        else:
            linear_baseline = None

        return linear_baseline

    def remove_linear_baseline(self, plots=False):
        """
        Find and remove linear baseline trend
        """
        linear_baseline = self.fit_linear_baseline(plots=plots)
        if linear_baseline is not None:
            linear_baseline_fit = np.polyval(linear_baseline, self.times.jd)
            self.fluxes =  self.fluxes/linear_baseline_fit
            self.errors = self.errors/linear_baseline_fit

    # def generate_light_curve(self, star_index=0):
    #
    #     for aperture_radius_index in range(self.fluxes.shape[2]):
    #         light_curve_key = (star_index, aperture_radius_index)
    #
    #         if light_curve_key in self.cached_light_curves:
    #             return self.cached_light_curves[light_curve_key]
    #         else:
    #             comp_stars = np.arange(self.fluxes.shape[1]) != star_index
    #             target_fluxes = self.fluxes[:, star_index, aperture_radius_index]
    #             comp_star_fluxes = self.fluxes[:, comp_stars, aperture_radius_index]
    #
    #             n_comp_stars = comp_star_fluxes.shape[1]
    #             initP = np.zeros([n_comp_stars])+ 1./n_comp_stars
    #             ########################################################
    #
    #             def errfunc(p,target):
    #                 if all(p >=0.0):
    #                     return np.dot(p, comp_star_fluxes.T) - target_fluxes ## Find only positive coefficients
    #
    #             #return np.dot(p,compStarsOOT.T) - target
    #             best_p = optimize.leastsq(errfunc, initP[:],
    #                                       args=(target_fluxes.astype(np.float64)),
    #                                             maxfev=10000000,
    #                                             epsfcn=np.finfo(np.float32).eps)[0]
    #             #print '\nDefault weight:',1./numCompStars
    #             #print 'Best fit regression coefficients:',bestFitP
    #
    #             #self.comparisonStarWeights = np.vstack([compStarKeys,bestFitP])
    #             meanComparisonStar = np.dot(best_p, comp_star_fluxes.T)
    #
    #             meanCompError = np.zeros_like(meanComparisonStar)
    #             comp_star_indices = np.arange(self.fluxes.shape[1])[comp_stars]
    #             for i in comp_star_indices:
    #                 meanCompError += ((best_p[i-1]*self.fluxes[:, i, aperture_radius_index] /
    #                                    np.sum(best_p[i-1]*self.fluxes[:, i, aperture_radius_index]))**2 *
    #                                    (self.errors[:, i, aperture_radius_index] /
    #                                    self.fluxes[:, i, aperture_radius_index])**2)
    #             meanCompError = meanComparisonStar*np.sqrt(meanCompError)
    #
    #             lc = self.fluxes[:, star_index, aperture_radius_index] / meanComparisonStar
    #             lc /= np.median(lc)
    #             lc_err = (lc*np.sqrt((self.errors[:, star_index, aperture_radius_index] /
    #                       self.fluxes[:, star_index, aperture_radius_index])**2 +
    #                       (meanCompError/meanComparisonStar)**2))
    #             self.cached_light_curves[light_curve_key] = (lc, lc_err)
    #
    #             lc_name = ("{0}\n target={1}, aprad={2}"
    #                        .format(self.target_name,
    #                                star_index,
    #                                self.aperture_radii[aperture_radius_index]))
    #
    #             # metadata = {}
    #             # metadata_attrs = ['xcentroids', 'ycentroids', 'fluxes', 'errors']
    #             # for attr in metadata_attrs:
    #             #     metadata[attr] = getattr(self, attr)
    #             return self.__class__.__init__(times=self.times, fluxes=lc,
    #                                            errors=lc_err, name=lc_name,
    #                                            raw_fluxes=self.fluxes,
    #                                            raw_errors=self.errors,
    #                                            xcentroids=self.xcentroids,
    #                                            ycentroids=self.ycentroids,
    #                                            weights=best_p)

def split_light_curve_at_gaps(light_curve, gap_median_factor=3):
    """
    Split a light curve by time gaps, into smaller light curves.
    """
    sort_by_time = np.argsort(light_curve.times.jd)
    dt = np.diff(light_curve.times.jd[sort_by_time])
    split_indices = np.argwhere(dt > gap_median_factor*np.median(dt)).T[0]
    split_times = [np.mean(light_curve.times.jd[sort_by_time][[split_index-1,
                                                               split_index+1]])
                   for split_index in split_indices]
    split_times = np.concatenate([[light_curve.times.jd.min()],
                                  split_times,
                                  [light_curve.times.jd.max()]])

    # # Visualize breaks in time
    # plt.plot(light_curve.times.jd)
    # [plt.axhline(splittime) for splittime in split_times]
    # plt.show()

    chunks = []

    for i in range(len(split_times) - 1):
        start_jd, end_jd = split_times[i], split_times[i+1]
        chunk = ((start_jd < light_curve.times.jd) &
                 (light_curve.times.jd < end_jd))
        chunks.append(LightCurve(times=light_curve.times.jd[chunk],
                                 fluxes=light_curve.fluxes[chunk],
                                 errors=light_curve.errors[chunk],
                                 name=light_curve.name+'_chunk{0}'.format(i)))
    return chunks

def concatenate_light_curves(light_curve_list, name=None):
    """
    Combine multiple light curves into one `LightCurve` object
    """
    times = []
    fluxes = []
    errors = []
    for light_curve in light_curve_list:
        times.append(light_curve.times.jd)
        fluxes.append(light_curve.fluxes)
        errors.append(light_curve.errors)
    times, fluxes, errors = [np.concatenate(i)
                             for i in [times, fluxes, errors]]

    times = Time(times, format='jd')
    return LightCurve(times=times, fluxes=fluxes, errors=errors,
                      name=name)


#!/usr/bin/python
'''<Author=Omar Faruk>
<Simple Fb Chat Bot.
\*Disclaimer:Simple Chat bot.You can Convert Your Id as a bot. Its Very usefull when you are doing some important task and can't attend your frzs or thers messages.
You can configure qus and ans  in your way.*/
Version:[1.0v]
'''
from fbchat import Client
from fbchat.models import *
import  logging
from time import sleep
from getpass import getpass
print('Please Wait Some Time It Take Some Time to Learn Conversation....\n')
#qustion and anwser file open and create a dictionary
Q=open('qus.txt','r').readlines()#create a ques file
A=open('ans.txt','r').readlines()#create a anwser file
#in that files Qus and Ans must be in same line
QA={}
for q,a in zip(Q,A):
	"""here this loop set the Qus as a key and Ans as a value of QA dictionary"""
	QA[q.replace('\n','').lower()]=a.replace('\n','')

sleep(5)
class Main_Client(Client):
	QA=QA
	bool=False #it's just for a frist messg when this bot is start frist time'
	color={'Lite_purple':ThreadColor.BILOBA_FLOWER,'Pink':ThreadColor.BRILLIANT_ROSE,'Brown_shade':ThreadColor.CAMEO,'Sky_blue':ThreadColor.DEEP_SKY_BLUE,'Farn':ThreadColor.FERN,'Lite_green':ThreadColor.FREE_SPEECH_GREEN,'Golden_poppy':ThreadColor.GOLDEN_POPPY,'Lite_coral':ThreadColor.LIGHT_CORAL,'Medium_slate_blue':ThreadColor.MEDIUM_SLATE_BLUE,'Messenger_blue':ThreadColor.MESSENGER_BLUE,'Picton_blue':ThreadColor.PICTON_BLUE,'Pumpkin':ThreadColor.PUMPKIN,'Red':ThreadColor.RADICAL_RED,'Shocking':ThreadColor.SHOCKING,'Viking':ThreadColor.VIKING}#It's for change the conversition color
	help="Here You Find a list of commands\n1.Change Colour To [colour name]\n2.Show ChatColours\n3.Change Emoji To [emoji]\n4.Change Nickname To [Name]"#help menu
	def onMessage(self,author_id,message_object,thread_id=None,thread_type=ThreadType.USER,**kwargs):
		self.markAsRead(author_id)
		print(message_object)
		if message_object.text==None and len(message_object.attachments)>0:
			self.send(Message(text='''Sorry!I can't read photo.'''),thread_id=thread_id,thread_type=thread_type)
		else:
			self.msg=message_object.text
			self.msg=self.msg.lower()
			print(self.msg)

		if author_id!=self.uid:
			if Main_Client.bool==False:
				'''its for send a message for 1 time when this bot run for frist time'''
				self.messge_send=self.send(Message(text='''How Can I Help You Sir.I am a FbBot.Created By Omar Faruk with Python\nYou Found Some Help by send  help message.'''),thread_id=thread_id,thread_type=thread_type)
			if 'change colour to' in self.msg:
				'''find that text in message if exeist then find the color name from the class dict if found then change with that color else show a another message'''
				text=message_object.text
				text=text.split()
				print(text)
				self.colorname=text[-1].capitalize()
				print(self.colorname)
				if self.colorname in Main_Client.color.keys():

					Main_Client.bool=True
					t_c=Main_Client.color.get(self.colorname)
					print(t_c)
					self.changeThreadColor(t_c,thread_id=thread_id)
					self.send(Message(text="Chat Colour Is Changed Successfully!🔍🔎"),thread_id=thread_id,thread_type=thread_type)
				else:
					self.send(Message(text=f'''Colour Is unavailable 😓'''),thread_id=thread_id,thread_type=thread_type)
			elif 'Show ChatColours'.lower() in message_object.text.lower():
				'''It's send a messge of a list of colors name which is avabile'''
				Main_Client.bool=True
				colors=''.join(f'{p+1}.'+i+"\n" for p,i in enumerate(Main_Client.color.keys()))
				showmsg=f'This Colours is available\n{colors}'
				self.send(Message(text=showmsg),thread_id=thread_id,thread_type=thread_type)
			elif message_object.text=='help' or message_object.text=='Help':
				'''send the help menu'''
				self.send(Message(text=Main_Client.help),thread_id=thread_id,thread_type=thread_type)
				Main_Client.bool=True
			elif 'Change Emoji To'.lower() in message_object.text.lower():
				'''its change emoji of this conversation'''
				text=message_object.text
				text=text.split()
				emoj=text[-1]
				try:
					self.changeThreadEmoji(emoji=emoj,thread_id=thread_id)
					self.send(Message(text=f'''Changed the emoji to {emoj}'''),thread_id=thread_id,thread_type=thread_type)
					Main_Client.bool=True
				except Exception as ex:
					self.send(Message(text='Something is wrong!😟'),thread_id=thread_id,thread_type=thread_type)
			elif 'Change Nickname To'.lower() in message_object.text.lower():
				'''Set nickname by bot'''
				text=message_object.text
				text=text.split()
				nick=text[-1].capitalize()
				self.changeThreadTitle(nick,thread_id=thread_id,thread_type=thread_type)
				self.send(Message(text=f'Your Nickname  in changed to {nick} 😎'),thread_id=thread_id,thread_type=thread_type)
				Main_Client.boot=True
			elif self.msg in Main_Client.QA.keys():
				'''Nothing special it's just for match of another person's message if that message is match with built-in questions(in a question file) then send a specific anwser of that ques or messge which is also built-in anwser(in a anwser file)'''
				getans=Main_Client.QA.get(self.msg)
				self.messge_send=self.send(Message(text=getans),thread_id=thread_id,thread_type=thread_type)
				Main_Client.bool=True
			else:
				Main_Client.bool=True
				'''if recived messg is not in you file then send a another messge'''
				self.messge_send=self.send(Message(text='''Sorry!! Sir.\nI Don't understand.😞'''),thread_id=thread_id,thread_type=thread_type)
		self.markAsDelivered(author_id,self.messge_send)

email=input('Enter Your email or username:')
passs=getpass('Enter Your Password:')
client=Main_Client(email,passs,logging_level=logging.DEBUG)
client.listen()


import numpy as np
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import tempfile
import pandas as pd
from tensorflow.contrib.keras.python.keras.preprocessing.image import ImageDataGenerator

def trans_to_array(label):
    test = np.zeros((label.shape[0],10))
    for i in range(test.shape[0]):
        test[i,int(label[i,0])] = 1
    return test

def scale(images):
    return np.multiply(images.astype(np.float32), 1.0 / 255.0)

data = np.load('data.npz')
num_classes = 10
nchannels,rows,cols = 1,64,64
rawfeature = data['train_X']
features = scale(rawfeature)
labels = trans_to_array(data['train_y'][:,np.newaxis])
x_test = scale(data['test_X'])

def next_batch(index,feature,label,batch_size):
    """Return the next `batch_size` examples from this data set."""
    epochs_completed = 0
    examples = feature.shape[0]
    start = index*batch_size
    index_in_epoch =index*batch_size+batch_size-1
    if index_in_epoch > examples:
      # Finished epoch
      epochs_completed += 1
      # Shuffle the data
      perm = np.arange(examples)
      np.random.shuffle(perm)
      feature = feature[perm]
      label = label[perm]
      # Start next epoch
      start = 0
      index_in_epoch = batch_size
      assert batch_size <= examples
    end = index_in_epoch
    return feature[start:end], label[start:end]

DEPTH   = 3                 # Depth of a tree
N_LEAF  = 2 ** (DEPTH + 1)  # Number of leaf node
N_LABEL = 10                # Number of classes
N_TREE  = 5                 # Number of trees (ensemble)
N_BATCH = 50               # Number of data points per mini-batch

def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

def init_bias(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

def init_prob_weights(shape, minval=-5, maxval=5):
    return tf.Variable(tf.random_uniform(shape, minval, maxval))

def model(X, w, w2, w3, w4_e, b, b2, b3, b4_e, w_d_e, w_l_e, p_keep_conv, p_keep_hidden):
    """
    Create a forest and return the neural decision forest outputs:
        decision_p_e: decision node routing probability for all ensemble
            If we number all nodes in the tree sequentially from top to bottom,
            left to right, decision_p contains
            [d(0), d(1), d(2), ..., d(2^n - 2)] where d(1) is the probability
            of going left at the root node, d(2) is that of the left child of
            the root node.
            decision_p_e is the concatenation of all tree decision_p's
        leaf_p_e: terminal node probability distributions for all ensemble. The
            indexing is the same as that of decision_p_e.
    """
    assert(len(w4_e) == len(w_d_e))
    assert(len(w4_e) == len(w_l_e))

    l1a = tf.nn.relu(tf.nn.conv2d(X, w, [1, 1, 1, 1], 'SAME')+b)
    l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

    l2a = tf.nn.relu(tf.nn.conv2d(l1, w2, [1, 1, 1, 1], 'SAME')+b2)
    l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

    l3a = tf.nn.relu(tf.nn.conv2d(l2, w3, [1, 1, 1, 1], 'SAME')+b3)
    l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

    l3 = tf.reshape(l3, [-1, w4_e[0].get_shape().as_list()[0]])

    decision_p_e = []
    leaf_p_e = []
    for w4, b4, w_d, w_l in zip(w4_e, b4_e, w_d_e, w_l_e):
        l4 = tf.nn.relu(tf.matmul(l3, w4)+b4)
        l4 = tf.nn.dropout(l4, p_keep_hidden)

        decision_p = tf.nn.sigmoid(tf.matmul(l4, w_d))
        leaf_p = tf.nn.softmax(w_l)

        decision_p_e.append(decision_p)
        leaf_p_e.append(leaf_p)

    return decision_p_e, leaf_p_e

##################################################
# Initialize network weights
##################################################
w = init_weights([3, 3, 1, 32])
w2 = init_weights([3, 3, 32, 64])
w3 = init_weights([3, 3, 64, 128])
b = init_bias([32])
b2 = init_bias([64])
b3 = init_bias([128])

w4_ensemble = []
b4_ensemble = []
w_d_ensemble = []
w_l_ensemble = []
for i in range(N_TREE):
    w4_ensemble.append(init_weights([128 * 8 * 8, 1024]))
    b4_ensemble.append(init_bias([1024]))
    w_d_ensemble.append(init_prob_weights([1024, N_LEAF], -1, 1))
    w_l_ensemble.append(init_prob_weights([N_LEAF, N_LABEL], -2, 2))

p_keep_conv = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")

##################################################
# Define a fully differentiable deep-ndf
##################################################
# With the probability decision_p, route a sample to the right branch
X = tf.placeholder(tf.float32, [N_BATCH, 64, 64, 1])
Y = tf.placeholder(tf.float32, [N_BATCH, N_LABEL])
decision_p_e, leaf_p_e = model(X, w, w2, w3, w4_ensemble, b, b2, b3, b4_ensemble, w_d_ensemble,
                               w_l_ensemble, p_keep_conv, p_keep_hidden)

flat_decision_p_e = []

# iterate over each tree
for decision_p in decision_p_e:
    # Compute the complement of d, which is 1 - d
    # where d is the sigmoid of fully connected output
    decision_p_comp = tf.subtract(tf.ones_like(decision_p), decision_p)

    # Concatenate both d, 1-d
    decision_p_pack = tf.stack([decision_p, decision_p_comp])

    # Flatten/vectorize the decision probabilities for efficient indexing
    flat_decision_p = tf.reshape(decision_p_pack, [-1])
    flat_decision_p_e.append(flat_decision_p)

# 0 index of each data instance in a mini-batch
batch_0_indices = \
    tf.tile(tf.expand_dims(tf.range(0, N_BATCH * N_LEAF, N_LEAF), 1),
            [1, N_LEAF])

###############################################################################
# The routing probability computation
#
# We will create a routing probability matrix \mu. First, we will initialize
# \mu using the root node d, 1-d. To efficiently implement this routing, we
# will create a giant vector (matrix) that contains all d and 1-d from all
# decision nodes. The matrix version of that is decision_p_pack and vectorized
# version is flat_decision_p.
#
# The suffix `_e` indicates an ensemble. i.e. concatenation of all responsens
# from trees.
#
# For depth = 2 tree, the routing probability for each leaf node can be easily
# compute by multiplying the following vectors elementwise.
# \mu =       [d_0,   d_0,   d_0,   d_0, 1-d_0, 1-d_0, 1-d_0, 1-d_0]
# \mu = \mu * [d_1,   d_1, 1-d_1, 1-d_1,   d_2,   d_2, 1-d_2, 1-d_2]
# \mu = \mu * [d_3, 1-d_3,   d_4, 1-d_4,   d_5, 1-d_5,   d_6, 1-d_6]
#
# Tree indexing
#      0
#    1   2
#   3 4 5 6
##############################################################################
in_repeat = N_LEAF / 2
out_repeat = N_BATCH

# Let N_BATCH * N_LEAF be N_D. flat_decision_p[N_D] will return 1-d of the
# first root node in the first tree.
batch_complement_indices = \
    np.array([[0] * int(in_repeat), [N_BATCH * N_LEAF] * int(in_repeat)]
             * out_repeat).reshape(N_BATCH, N_LEAF)

# First define the routing probabilities d for root nodes
mu_e = []

# iterate over each tree
for i, flat_decision_p in enumerate(flat_decision_p_e):
    mu = tf.gather(flat_decision_p,
                   tf.add(batch_0_indices, batch_complement_indices))
    mu_e.append(mu)

# from the second layer to the last layer, we make the decision nodes
for d in range(1, DEPTH + 1):
    indices = tf.range(2 ** d, 2 ** (d + 1)) - 1
    tile_indices = tf.reshape(tf.tile(tf.expand_dims(indices, 1),
                                      [1, 2 ** (DEPTH - d + 1)]), [1, -1])
    batch_indices = tf.add(batch_0_indices, tf.tile(tile_indices, [N_BATCH, 1]))

    in_repeat = in_repeat / 2
    out_repeat = out_repeat * 2

    # Again define the indices that picks d and 1-d for the node
    batch_complement_indices = \
        np.array([[0] * int(in_repeat), [N_BATCH * N_LEAF] * int(in_repeat)]
                 * int(out_repeat)).reshape(N_BATCH, N_LEAF)

    mu_e_update = []
    for mu, flat_decision_p in zip(mu_e, flat_decision_p_e):
        mu = tf.multiply(mu, tf.gather(flat_decision_p,
                                  tf.add(batch_indices, batch_complement_indices)))
        mu_e_update.append(mu)

    mu_e = mu_e_update

##################################################
# Define p(y|x)
##################################################
py_x_e = []
for mu, leaf_p in zip(mu_e, leaf_p_e):
    # average all the leaf p
    py_x_tree = tf.reduce_mean(
        tf.multiply(tf.tile(tf.expand_dims(mu, 2), [1, 1, N_LABEL]),
               tf.tile(tf.expand_dims(leaf_p, 0), [N_BATCH, 1, 1])), 1)
    py_x_e.append(py_x_tree)

py_x_e = tf.stack(py_x_e)
py_x = tf.reduce_mean(py_x_e, 0)

features_new = features.reshape(-1, 64, 64, 1)
test_new = x_test.reshape(-1, 64, 64, 1)
# cross entropy loss
cost = tf.reduce_mean(-tf.multiply(tf.log(py_x), Y))

# cost = tf.reduce_mean(tf.nn.cross_entropy_with_logits(py_x, Y))
train_step = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
predict = tf.argmax(py_x, 1)

sess = tf.Session()
sess.run(tf.initialize_all_variables())

for i in range(50):
    # One epoch
    for start, end in zip(range(0, len(features_new)+1, N_BATCH), range(N_BATCH, len(features_new)+1, N_BATCH)):
        sess.run(train_step, feed_dict={X: features_new[start:end], Y: labels[start:end],
                                        p_keep_conv: 0.8, p_keep_hidden: 0.5})
    print(i)

result = []
for start_t, end_t in zip(range(0, len(test_new)+1, N_BATCH), range(N_BATCH, len(test_new)+1, N_BATCH)):
        result.extend(sess.run(predict, feed_dict={X: test_new[start_t:end_t],p_keep_conv: 1.0,
                                         p_keep_hidden: 1.0}))

print(result)
new_result = []
for i in range(len(result)):
    new_result.append((i+1,result[i]))
lab = ['Id','Label']
df = pd.DataFrame.from_records(new_result, columns=lab)
print(new_result)
df.to_csv('out2.csv',index=False,header=True)