import datetime

import boto3
from django.shortcuts import render

from django.http import HttpResponse, JsonResponse
from django.template import loader
from django.views.decorators.clickjacking import xframe_options_exempt

from phishing.forms import CreateTemplate
from phishing.models import Submission, MTurkUser, Rating

# import the logging library
import logging

# Get an instance of a logger
logger = logging.getLogger(__name__)

create_hits_in_live = False

environments = {
        "live": {
            "endpoint": "https://mturk-requester.us-east-1.amazonaws.com",
            "preview": "https://www.mturk.com/mturk/preview",
            "manage": "https://requester.mturk.com/mturk/manageHITs",
            "reward": "0.00"
        },
        "sandbox": {
            "endpoint": "https://mturk-requester-sandbox.us-east-1.amazonaws.com",
            "preview": "https://workersandbox.mturk.com/mturk/preview",
            "manage": "https://requestersandbox.mturk.com/mturk/manageHITs",
            "reward": "0.11"
        },
}
mturk_environment = environments["live"] if create_hits_in_live else environments["sandbox"]

session = boto3.Session()
client = session.client(
    service_name='mturk',
    region_name='us-east-1',
    endpoint_url=mturk_environment['endpoint'],
)

def index(request):
    template = loader.get_template('phishing/index.html')
    context = {
        'testing': 'hi there',
    }
    return HttpResponse(template.render(context, request))

@xframe_options_exempt
def submit(request):
    template = loader.get_template('phishing/submit.html')
    context = {
        'directions': """
        Your target is Roger Johnson, a student employee at the University of Oak Creek.
	    Your message must be written as if sent by Thomas Smith, an HR employee at the University.
	    Your goal is to convince Roger to send ``Thomas'' his bank account information.

        The personal information you may include about Roger includes the following:

Name

Roger Johnson

Date of Birth

April 18, 1995

Supervisior

Alice Davis

Position

Math Grader

        """,
        'worker_id': request.GET.get('workerId', ''),
        'assignment_id': request.GET.get('assignmentId', ''),
        'turk_submit_to': request.GET.get('turkSubmitTo', '')
    }
    return HttpResponse(template.render(context, request))

def submit_template(request):
    tmpl = CreateTemplate({
        'worker_id': request.POST.get('worker_id', ''),
        'assignment_id':  request.POST.get('assignmentId', ''),
        'subject': request.POST.get('message_subject', ''),
        'message_template': request.POST.get('message_template', '')
    })
    if tmpl.is_valid():
        tmpl.execute()
    else:
        return JsonResponse({'result': False})

    return JsonResponse({'result': True})

@xframe_options_exempt
def review(request):
    template = loader.get_template('phishing/review.html')
    task_id = request.GET.get('task', '')
    objs = Submission.objects.filter(task=task_id).all()

    context = {
        'name': 'John Doe',
        'worker_id': request.GET.get('workerId', ''),
        'assignment_id': request.GET.get('assignmentId', ''),
        'turk_submit_to': request.GET.get('turkSubmitTo', ''),
        'task': request.GET.get('task', ''),
        'messages': list(map(lambda x: {
                    'from': 'John Doe <john@example.com>',
                    'subject': x.subject,
                    'body': x.text
                }, objs))
    }
    return HttpResponse(template.render(context, request))

def submit_review(request):
    logger.warning(request.POST)
    worker_id = request.POST.get('worker_id', '')
    task_id = request.POST.get('task', '')
    assignment_id = request.POST.get('assignmentId', '')
    results = request.POST.get('results', '').split(",")

    try:
        mt_usr = MTurkUser.objects.get(pk=worker_id)
    except MTurkUser.DoesNotExist:
        mt_usr = MTurkUser(workerId=worker_id)
        mt_usr.save()

    submissions = Submission.objects.filter(task=task_id).all()
    for (submission, result) in zip(submissions, results):
        rating = Rating(
            creator=mt_usr,
            assignmentId=assignment_id,
            when_submitted=datetime.datetime.now(),
            submission=submission,
            is_spam=result == 'spam',
            is_email=True,
            is_comprehensible=True,
            is_correct_info=True,
        )
        rating.save()

        if not submission.payout:
            all_ratings = Rating.objects.filter(assignmentId=assignment_id).all()
            if len(all_ratings) < 10:
                continue
            client.approve_assignment(
                AssignmentId=submission.assignmentId
            )
            spam_count = map(lambda x: x.is_spam, all_ratings).count(True)
            if spam_count <= 1:
                client.send_bonus(
                    WorkerId=submission.creator.workerId,
                    AssignmentId=submission.assignmentId,
                    BonusAmount=0.5, #TODO set the bonus amount
                    Reason="Your submission was almost universally seen as not spam"
                )
            submission.payout = True
            submission.save()

    return JsonResponse({'result': True})


#m×m의 정방형 행렬 M의 n-거듭제곱인 Mⁿ을 계산해 보기
#축소 정복 전략으로 행렬의 거듭제곱을 구현할 수 있음
#두 행렬을 곱하는 multMat(M1, M2)함수가 이미 있다고 가정하고 행렬 거듭제곱 코드를 구현해 보기

def powerMat(x, n) :
    if n == 1 :
        return x
    elif (n%2) == 0:
        return powerMat(multMat(x, x), n//2)
    else :
        return multMat(x, powerMat(multMat(x,x), (n-1) // 2))

def multMat(M1, M2):
    result = [[0 for _ in range(len(M2[0]))] for __ in range(len(M1))]
    for i in range(len(M1)):
        for j in range(len(M2[0])):
            for k in range(len(M1[0])):
                result[i][j] += M1[i][k] * M2[k][j]
    return result

n = int(input())
row = int(input())
x = [[int(m) for m in input().split()] for _ in range(row)]

result = powerMat(x, n)
print()
for row in result:
    for num in row:
        print(num, end=' ')
    print()


#==============================================================================
# TODO: ADD DOCUMENATION ORGANIZE
#==============================================================================

import datetime
import os
import time
import timeit
import fnmatch
import pandas as pd
import requests
import zipfile
import numpy as np
import math

from _00_additional_functions import (list_all_full_path, resampleDf,
                                      select_df_within_period)

#==============================================================================
#
#==============================================================================
build_one_df = True
delete_df_files = False

make_hdf5_dataset_new = False

temporal_freq = 'hourly'  # '1_minute' '10_minutes' 'hourly' 'daily'
time_period = 'historical'  # 'recent' 'historical'
temp_accr = 'stundenwerte'  # '1minuten' '10minuten' 'stundenwerte'  'tages'

ppt_act = 'RR'  # nieder 'rr' 'RR' 'RR'

stn_name_len = 5  # length of dwd stns Id, ex: 00023

start_date = '2019-01-01 00:00:00'
end_date = '2020-01-30 23:59:00'

temp_freq = 'H'  # '60Min'  # 'Min' '10Min' 'H' 'D'

# '%Y%m%d%H'  # when reading download dwd station df '%Y%m%d%H%M'
time_fmt = '%Y%m%d%H'  # :%S' # for 10Min data use: '%Y%m%d%H%M:%S'

# name of station id and rainfall column name in df
stn_id_col_name = 'STATIONS_ID'
ppt_col_name = 'TT_TU'  # 'TT_TU'  # RS_01 'RWS_10' '  R1' 'RS'
temp_col_name1 = ' LUFTTEMPERATUR'
temp_col_name2 = 'TT_TU'

#==============================================================================
#
#==============================================================================
# main_dir = os.path.join(r'X:\hiwi\ElHachem\Prof_Bardossy\Extremes\download_DWD_data_recent')

main_dir = r'F:\dwd'
os.chdir(main_dir)
#==============================================================================
out_dir = r'F:\dwd\pres_hourly_temp'
# if not os.path.exists(out_dir):
#     os.mkdir(out_dir)

os.chdir(out_dir)

# get all df files as list

#     all_df_files = list_all_full_path('.txt', out_extract_df_dir)

all_var_files = list_all_full_path('.txt', out_dir)
all_data_files = [_fi for _fi in all_var_files if 'produkt' in _fi]
all_stn_names = list(set([_fi.split('\\')[-1].split('_')[-1].split('.')[0]
                          for _fi in all_data_files]))
print('total nbr of stations is ', len(all_stn_names))

# create daterange and df full of nans

date_range = pd.date_range(start=start_date, end=end_date, freq=temp_freq)
data = np.zeros(shape=(date_range.shape[0], len(all_stn_names)))
data[data == 0] = np.nan

final_df_combined = pd.DataFrame(data=data,
                                 index=date_range,
                                 columns=all_stn_names)

# read df stn file and fill final df for all stns

for ix, df_txt_file in enumerate(all_data_files):
    print('\n File nbr ', ix, '/', len(all_data_files))

    stn_name = df_txt_file.split('\\')[-1].split('_')[-1].split('.')[0]
    if stn_name in all_stn_names:
        print('\n## Station ID is ##', stn_name)

        # TODO: FIX ME
        in_df = pd.read_csv(df_txt_file, sep=';',
                            dtype=str, engine='c', memory_map=True).dropna()

        try:
            in_df.index = pd.to_datetime(
                in_df[' MESS_DATUM'], format='%Y%m%d%H')
        except KeyError:
            try:
                in_df.index = pd.to_datetime(
                    in_df['MESS_DATUM'], format='%Y%m%d%H')
            except Exception as msg:
                print(msg, 'error with time idx')
                print('check index column')
                raise Exception
        assert int(stn_name) == int(in_df.loc[
            :, stn_id_col_name].values[0].strip(' '))
        assert stn_name in final_df_combined.columns

        in_df = select_df_within_period(in_df, start_date, end_date)

        if in_df.values.size > 0:
            print('\n++\n  Data shape is++',  in_df.values.size)
            try:
                var_data_str = in_df[temp_col_name1].values
                var_data_arr = [np.float(val.strip(' '))
                                for val in var_data_str]
            except Exception as msg:
                pass
                try:
                    var_data_str = in_df[temp_col_name2].values.ravel()
                    var_data_arr = [np.float(val.strip(' '))
                                    for val in var_data_str]
                except Exception as msg2:
                    print('no Var column name found, check again')
                    raise Exception

            try:
                final_df_combined.loc[in_df.index, stn_name] = var_data_arr
            except Exception:
                print('Error')

print('++-- DONE WITH ALL FILES ++--')
# final_df_combined.plot(legend=False)
print('Saving Dataframe')
final_df_combined.dropna(how='all', inplace=True)
# #final_df_combined.set_index('Time', inplace=True, drop=True)
final_df_combined.to_csv(
    os.path.join(main_dir,
                 r'all_dwd_60min_temp_data_combined_2019_2020.csv'),
    sep=';')
# # all_dwd_60min_temp_data_combined_2010_2018.csv
# #     final_df_combined.reset_index(inplace=True)
# #     final_df_combined.rename({'index': 'Time'}, inplace=True)
# # #
# #     final_df_combined.to_feather(
# #         os.path.join(out_dir,
# #                      'all_dwd_10min_ppt_data_combined_2018_2019.fk'))
#
print('done creating df')
# #==============================================================================
# # # In[129]:
# #==============================================================================
#
#
# if make_hdf5_dataset_new:
#     from a_functions import create_hdf5
#
#     print('\n+++\n reading df \n+++\n')
#     final_df_combined = pd.read_csv(
#         os.path.join(
#             main_dir, r'all_dwd_hourly_ppt_data_combined_1995_2019.csv'),
#         #                             r'all_ppt_data_combined.csv'),
#         sep=';',
#         index_col=0)
#     final_df_combined.index = pd.to_datetime(final_df_combined.index,
#                                              format='%Y-%m-%d %H:%M:%S')
#     print('\n+++\n resampling df \n+++\n')
#
#     for temp_freq_resample in freqs_list:
#         if temp_freq_resample == '60Min':
#             df_resampled = final_df_combined
#         else:
#             print(temp_freq_resample)
#             df_resampled = resampleDf(
#                 final_df_combined,
#                 temp_freq_resample)
#     #     ppt_data_all = np.array(df_60min.values)
#         df_resampled = df_resampled[df_resampled >= 0]
#         print('\n+++\n creating HDF5 file \n+++\n')
#
#         str_date = str(df_resampled.index[0]).replace(
#             '-', '').replace(':', '').replace(' ', '')
#         ed_date = str(df_resampled.index[-1]).replace(
#             '-', '').replace(':', '').replace(' ', '')
#
#         output_hdf5_file = r"DWD_%s_ppt_stns_%s_%s_new.h5" % (
#             temp_freq_resample, str_date, ed_date)
#
#         create_hdf5(hf5_file=output_hdf5_file,
#                     start_dt=df_resampled.index[0],
#                     end_dt=df_resampled.index[-1],
#                     nstats=len(df_resampled.columns),
#                     freq=temp_freq_resample,
#                     data_title=(r'Precipitation DWD Data Historical and Recent'
#                                 r'Aggregation %s') % temp_freq_resample,
#                     in_ppt_df=df_resampled,
#                     in_stns_df=stn_names_df,
#                     utm=False)


#!/usr/bin/env python3

import sys
import traceback

def Q3(sb):
    def is_in(char): # True if in [a-zA-Z’']
        return char in "’'" or \
            'a' <= char <= 'z' or \
            'A' <= char <= 'Z'  # python syntax, chained comparison
    s = ' '.join(sb)
    j = 0
    ans = set()
    for i, c in enumerate(s):
        if not is_in(c):
            if i - j > 0:  # if substr length > 0
                ans.add(s[j:i].upper())
            j = i + 1
    ans = sorted(ans)
    print(len(ans))
    for s in ans:
        print(s)

if __name__ == '__main__':
    """Verify test cases easily
    1. run the program
    2. paste test case to stdin
    3. press double Enter
    4. continue pasting next test case
    """
    do_next = True
    while do_next:
        try:
            do_next = False  # do_next won't set if encounter EOF
            sb = []
            for line in sys.stdin:  # s = data + '\n'
                line = line.rstrip('\r\n')
                if line:  # check str not empty
                    sb.append(line)
                elif sb:  # check list not empty
                    do_next = True
                    break
            Q3(sb)
        except Exception:
            traceback.print_exc()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Модуль формы <icCubesOLAPSrvRequestPanelProto>.
Сгенерирован проектом DEFIS по модулю формы-прототипа wxFormBuider.
"""

import wx
from . import cubes_olap_srv_request_form_proto

import ic
from ic.log import log
from ic.utils import wxfunc

# Для управления взаимодействия с контролами wxPython
# используется менеджер форм <form_manager.icFormManager>
from ic.engine import form_manager

__version__ = (0, 1, 1, 1)

OLAP_METHODS = ('aggregate', 'members', 'facts', 'fact', 'cell', 'report')

CUT_PARAMETER_HELP = u'cut - спецификация ячейки среза, например: cut=date:2004,1|category:2|entity:12345'
DRILLDOWN_PARAMETER_HELP = u'''drilldown - измерение, который нужно "сверлить". Например drilldown=date даст строки для каждого значения
следующий уровень даты измерения. Вы можете явно указать уровень для детализации в форме: dimension:level,
таких как: drilldown=date:month. Чтобы указать иерархию используйте dimension@hierarchy как в
drilldown=date@ywd для неявного уровня или drilldown=date@ywd:week явно указать уровень.'''
AGGREGATES_PARAMETER_HELP = u'''aggregates – список агрегатов для расчета, разделяется с помошью |,
например: aggergates=amount_sum|discount_avg|count'''
MEASURES_PARAMETER_HELP = u'''measures – список мер, для которых будут рассчитаны их соответствующие агрегаты.
Разделяется с помощью |, например: aggergates=proce|discount'''
PAGE_PARAMETER_HELP = u'page - номер страницы для нумерации страниц'
PAGESIZE_PARAMETER_HELP = u'pagesize - размер страницы для разбивки на страницы'
ORDER_PARAMETER_HELP = u'order - список атрибутов для сортировки'
SPLIT_PARAMETER_HELP = u'''split – разделенная ячейка, тот же синтаксис, что и у вырезки, определяет виртуальное двоичное (флаговое) измерение, которое указывает, является ли ячейка
принадлежит разделенному разрезу (true) или нет (false). Атрибут измерения называется __within_split__.
Обратитесь к бэкэнду, который вы используете для получения дополнительной информации, поддерживается ли эта функция или нет.'''

OLAP_SERVER_URL_FMT = 'cube/%s/%s'

class icCubesOLAPSrvRequestPanel(cubes_olap_srv_request_form_proto.icCubesOLAPSrvRequestPanelProto, form_manager.icFormManager):
    """
    Форма .
    """
    def __init__(self, *args, **kwargs):
        """
        Конструктор.
        """
        cubes_olap_srv_request_form_proto.icCubesOLAPSrvRequestPanelProto.__init__(self, *args, **kwargs)

        # Тестируемый OLAP сервер
        self._OLAP_server = None

        self._help_popup_win = None
        self.init()

    def setOLAPServer(self, olap_server):
        """
        Установить тестируемый OLAP сервер.
        :param olap_server: OLAP сервер
        """
        self._OLAP_server = olap_server

        if self._OLAP_server:
            # Настраиваем контрол выбора кубов
            choices = [cube.description if cube.description else cube.name for cube in self._OLAP_server.getCubes()]
            self.cube_choice.Clear()
            self.cube_choice.AppendItems(choices)
            if choices:
                self.cube_choice.setSelection(0)
                self.method_choice.setSelection(0)
                self.refreshDimensionChoice(0)

    def refreshDimensionChoice(self, i_cube):
        """
        Обновить список измерений в зависимости от выбранного куба.
        """
        cube = self._OLAP_server.getCubes()[i_cube] if i_cube >= 0 else None
        if cube:
            choices = [u''] + [dimension.getLabel() for dimension in cube.getDimensions()]

            self.dimension_choice.Clear()
            self.dimension_choice.AppendItems(choices)
            if choices:
                self.dimension_choice.setSelection(0)

    def init(self):
        """
        Инициализация панели.
        """
        self.init_img()
        self.init_ctrl()

    def init_img(self):
        """
        Инициализация изображений.
        """
        pass

    def init_ctrl(self):
        """
        Инициализация контролов.
        """
        self.method_choice.AppendItems(OLAP_METHODS)

        # Выключить все параметры
        self.cut_textCtrl.Enable(False)
        self.drilldown_textCtrl.Enable(False)
        self.aggregates_textCtrl.Enable(False)
        self.measures_textCtrl.Enable(False)
        self.page_textCtrl.Enable(False)
        self.pagesize_textCtrl.Enable(False)
        self.order_textCtrl.Enable(False)
        self.split_textCtrl.Enable(False)

    # def onCubeChoice(self, event):
    #     """
    #     Обработчик выбора куба.
    #     """
    #     i_cube = event.GetSelection()
    #     self.refreshDimensionChoice(i_cube)
    #
    #     event.Skip()

    def onAggregatesCheckBox(self, event):
        """
        Обработчик включения параметра aggregate.
        """
        enable = event.IsChecked()
        self.aggregates_textCtrl.Enable(enable)
        event.Skip()

    def show_help_popup_win(self, button, info_text):
        """
        Отобразить/скрыть всплывающее окно помощи.
        :param button: Кнопка вызова окна помощи.
        :param info_text: Текст помощи.
        :return:
        """
        if self._help_popup_win:
            self._help_popup_win.close()
            self._help_popup_win = None
        else:
            self._help_popup_win = wxfunc.showInfoWindow(parent=self,
                                                         ctrl=button,
                                                         info_text=info_text)

    def onAggregatesHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.aggregates_hlp_bpButton,
                                 info_text=AGGREGATES_PARAMETER_HELP)
        event.Skip()

    def onCutCheckBox(self, event):
        """
        Обработчик включения параметра cut.
        """
        enable = event.IsChecked()
        self.cut_textCtrl.Enable(enable)
        event.Skip()

    def onCutHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.cut_hlp_bpButton,
                                 info_text=CUT_PARAMETER_HELP)
        event.Skip()

    def onDrilldownCheckBox(self, event):
        """
        Обработчик включения параметра drilldown.
        """
        enable = event.IsChecked()
        self.drilldown_textCtrl.Enable(enable)
        event.Skip()

    def onDrilldownHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.drilldown_hlp_bpButton,
                                 info_text=DRILLDOWN_PARAMETER_HELP)
        event.Skip()

    def onMeasuresCheckBox(self, event):
        """
        Обработчик включения параметра measures.
        """
        enable = event.IsChecked()
        self.measures_textCtrl.Enable(enable)
        event.Skip()

    def onMeasuresHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.measures_hlp_bpButton,
                                 info_text=MEASURES_PARAMETER_HELP)
        event.Skip()

    def onOrderCheckBox(self, event):
        """
        Обработчик включения параметра order.
        """
        enable = event.IsChecked()
        self.order_textCtrl.Enable(enable)
        event.Skip()

    def onOrderHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.order_hlp_bpButton,
                                 info_text=ORDER_PARAMETER_HELP)
        event.Skip()

    def onPageCheckBox(self, event):
        """
        Обработчик включения параметра page.
        """
        enable = event.IsChecked()
        self.page_textCtrl.Enable(enable)
        event.Skip()

    def onPageHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.page_hlp_bpButton,
                                 info_text=PAGE_PARAMETER_HELP)
        event.Skip()

    def onPagesizeCheckBox(self, event):
        """
        Обработчик включения параметра pagesize.
        """
        enable = event.IsChecked()
        self.pagesize_textCtrl.Enable(enable)
        event.Skip()

    def onPagesizeHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.pagesize_hlp_bpButton,
                                 info_text=PAGESIZE_PARAMETER_HELP)
        event.Skip()

    def onSplitCheckBox(self, event):
        """
        Обработчик включения параметра split.
        """
        enable = event.IsChecked()
        self.split_textCtrl.Enable(enable)
        event.Skip()

    def onSplitHelpButtonClick(self, event):
        """
        Подсказка по параметру.
        """
        self.show_help_popup_win(self.split_hlp_bpButton,
                                 info_text=SPLIT_PARAMETER_HELP)
        event.Skip()

    def setRequest(self, request):
        """
        Установить запрос к серверу OLAP в структурном виде.
        :param request: Словарь параметров запроса к OLAP серверу.
        :return: True/False.
        """
        if request is None:
            request = dict()

        if 'url' in request:
            self.request_textCtrl.SetValue(request['url'])

        cube_name = request.get('cube', None)
        cube = None
        if cube_name:
            cubes = self._OLAP_server.getCubes()
            cube_names = [cube.getName() for cube in cubes]
            try:
                i_cube = cube_names.index(cube_name)
                cube = cubes[i_cube]
                self.cube_choice.setSelection(i_cube)
            except ValueError:
                log.error(u'Куб с именем <%s> не найден среди %s' % (cube_name, str(cube_names)))

        method_name = request.get('method', None)
        if method_name:
            try:
                i_method = OLAP_METHODS.index(method_name)
            except ValueError:
                log.error(u'Метод <%s> не найден среди %s' % (method_name, str(OLAP_METHODS)))
                i_method = 0
            self.method_choice.setSelection(i_method)

        dimension_name = request.get('dimension', None)
        if dimension_name and cube:
            dimensions = cube.getDimensions()
            dimension_names = [dimension.getName() for dimension in dimensions]
            try:
                i_dimension = dimension_names.index(dimension_name) + 1
            except ValueError:
                log.error(u'Измерение <%s> не найденj среди %s' % (dimension_name, str(dimension_names)))
                i_dimension = 0
            self.dimension_choice.setSelection(i_dimension)

        self.cut_checkBox.SetValue('cut' in request)
        self.cut_textCtrl.Enable('cut' in request)
        self.cut_textCtrl.SetValue(request.get('cut', u''))

        self.drilldown_checkBox.SetValue('drilldown' in request)
        self.drilldown_textCtrl.Enable('drilldown' in request)
        self.drilldown_textCtrl.SetValue(request.get('drilldown', u''))

        self.aggregates_checkBox.SetValue('aggregates' in request)
        self.aggregates_textCtrl.Enable('aggregates' in request)
        self.aggregates_textCtrl.SetValue(request.get('aggregates', u''))

        self.measures_checkBox.SetValue('measures' in request)
        self.measures_textCtrl.Enable('measures' in request)
        self.measures_textCtrl.SetValue(request.get('measures', u''))

        self.page_checkBox.SetValue('page' in request)
        self.page_textCtrl.Enable('page' in request)
        self.page_textCtrl.SetValue(request.get('page', u''))

        self.pagesize_checkBox.SetValue('pagesize' in request)
        self.pagesize_textCtrl.Enable('pagesize' in request)
        self.pagesize_textCtrl.SetValue(request.get('pagesize', u''))

        self.order_checkBox.SetValue('order' in request)
        self.order_textCtrl.Enable('order' in request)
        self.order_textCtrl.SetValue(request.get('order', u''))

        self.split_checkBox.SetValue('split' in request)
        self.split_textCtrl.Enable('split' in request)
        self.split_textCtrl.SetValue(request.get('split', u''))

        return True

    def getRequest(self):
        """
        Получить запрос к серверу OLAP в структурном виде.
        :return: Словарь параметров запроса к OLAP серверу.
            Словарь заполняется в соответствии с выбранными
            параметрами контролов панели.
        """
        request = dict()
        i_cube = self.cube_choice.GetSelection()
        cube = self._OLAP_server.getCubes()[i_cube] if i_cube >= 0 else None
        cube_name = cube.getName() if cube else None
        if cube_name:
            request['cube'] = cube_name

        i_func = self.method_choice.GetSelection()
        method_name = OLAP_METHODS[i_func] if i_func >= 0 else None
        if method_name:
            request['method'] = method_name

        i_dimension = self.dimension_choice.GetSelection() - 1
        # log.debug(u'Выбранное измерение %d' % i_dimension)
        dimension = (cube.getDimensions()[i_dimension] if cube else None) if i_dimension >= 0 else None
        if dimension:
            request['dimension'] = dimension.getName()

        # Наполнить параметрами
        if self.cut_checkBox.GetValue():
            param = self.cut_textCtrl.GetValue().strip()
            if param:
                request['cut'] = param
        if self.drilldown_checkBox.GetValue():
            param = self.drilldown_textCtrl.GetValue().strip()
            if param:
                request['drilldown'] = param
        if self.aggregates_checkBox.GetValue():
            param = self.aggregates_textCtrl.GetValue().strip()
            if param:
                request['aggregates'] = param
        if self.measures_checkBox.GetValue():
            param = self.measures_textCtrl.GetValue().strip()
            if param:
                request['measures'] = param
        if self.page_checkBox.GetValue():
            param = self.page_textCtrl.GetValue().strip()
            if param:
                request['page'] = param
        if self.pagesize_checkBox.GetValue():
            param = self.pagesize_textCtrl.GetValue().strip()
            if param:
                request['pagesize'] = param
        if self.order_checkBox.GetValue():
            param = self.order_textCtrl.GetValue().strip()
            if param:
                request['order'] = param
        if self.split_checkBox.GetValue():
            param = self.split_textCtrl.GetValue().strip()
            if param:
                request['split'] = param
        return request

    def getRequestURL(self, request=None):
        """
        Получить URL запроса к серверу OLAP по его структурному описанию.
        :return: Словарь параметров запроса к OLAP серверу.
            Если не определен, то берется из контролов.
        """
        if request is None:
            request = self.getRequest()

        try:
            full_request_url = self._OLAP_server.getRequestURL(request)
            return full_request_url
        except:
            log.fatal(u'Ошибка получения полного запроса URL к OLAP серверу')

        return u''

def show_cubes_olap_srv_request_panel(title=u''):
    """
    :param title: Заголовок страницы нотебука главного окна.
    """
    try:
        main_win = ic.getMainWin()

        panel = icCubesOLAPSrvRequestPanel(main_win)
        # panel.init()
        main_win.addPage(panel, title)
    except:
        log.fatal(u'Ошибка')


##### 0 #####

def count_elements(xss):
    counter = 0
    for x in xss:
        if isinstance(x,list):
            counter += count_elements(x)
        else:
            counter += 1
    return counter

# TEST CASES
# print(count_elements([]))
# print(count_elements([1,2,2]))
# print(count_elements([1,[2],2]))
# print(count_elements([1,[1,2,[1,4]]]))
# print(count_elements([[[[[[[],[[3,2,3]],3]]]]]]))
# print(count_elements([[[[3]],[3]],5,3,[7]]))
# print(count_elements([1,[5,2],[[3],[5,4]],[[[5,5,5,5]]],6,[5,[[5],[[9]]]]]))

# RESULTS
# 0
# 3
# 3
# 5
# 4
# 5
# 14

##### 1 #####

def flatten(xss):
    flat = []
    for x in xss:
        if isinstance(x,list):
            flat += flatten(x)
        else:
            flat.append(x)
    return flat

# TEST CASES
# print(flatten([]))
# print(flatten([1,2,3]))
# print(flatten([1,[],3]))
# print(flatten([1,[1,2,[3,4]]]))
# print(flatten([[[[[[[[1,2,3]]]]]]]]))
# print(flatten([[[[3]],[4]],5,6,[7]]))
# print(flatten([1,[2,2],[[3],[4,4]],[[[5,5,5,5]]],6,[7,[[8],[[9]]]]]))

# RESULTS
# []
# [1, 2, 3]
# [1, 3]
# [1, 1, 2, 3, 4]
# [1, 2, 3]
# [3, 4, 5, 6, 7]
# [1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 7, 8, 9]

#### 2 ####

def identity(mat):
    size = len(mat)
    for i in range(size):
        for j in range(size):
            if i == j and mat[i][j] != 1:
                return False
            elif i != j and mat[i][j] != 0:
                return False
    return True

xs0 = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
xs1 = [[1,0,0,0],[0,2,0,0],[0,0,1,0],[0,0,0,1]]
xs2 = [[0,-3,6,4],[3,0,-9,8],[-6,9,0,2],[-4,-8,-2,0]]
xs3 = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]

# TEST CASES
print(identity(xs0))
print(identity(xs1))
print(identity(xs2))
print(identity(xs3))

# RESULTS
# True
# False
# False
# False

##### 3 #####

def ascii_art(n):
	for i in range(n):
		for j in range(n):
			print('#', end=' ')
		print()

# TEST CASE
# ascii_art(5)

## (1) ## +
def ascii_art_cross(n):
	for i in range(n):
		for j in range(n):
			if i == n // 2 or j == n // 2:
				print('#', end=' ')
			else:
				print(' ', end=' ')
		print()

# TEST CASE
# ascii_art_cross(5)

## (2) ## X
def ascii_art_X(n):
	for i in range(n):
		for j in range(n):
			if i == j or i + j == n - 1:
				print('#', end=' ')
			else:
				print(' ', end=' ')
		print()

# TEST CASE
# ascii_art_X(5)

## (3) ## ㅁ
def ascii_art_square(n):
	for i in range(n):
		for j in range(n):
			if i == 0 or i == n - 1 or j == 0 or j == n - 1:
				print('#', end=' ')
			else:
				print(' ', end=' ')
		print()

# TEST CASE
# ascii_art_square(5)

## (4) ##
def ascii_art_diamond(n):
	mid = n // 2
	for i in range(n):
		for j in range(n):
			if abs(i-j) == mid or i+j == mid or i+j == n + mid - 1:
				print('#', end=' ')
			else:
				print(' ', end=' ')
		print()

# TEST CASE
# ascii_art_diamond(5)

##### 4 #####
## (1) ##
def substrings_of_length(k,s):
	if k == 0:
		return ['']
	elif 0 < k <= len(s):
		subs = []
		for i in range(len(s)-k+1):
			subs.append(s[i:i+k])
		return subs
	else:
		return None

# TEST CASES
# print(substrings_of_length(0,"ERICA"))
# print(substrings_of_length(1,"ERICA"))
# print(substrings_of_length(2,"ERICA"))
# print(substrings_of_length(3,"ERICA"))
# print(substrings_of_length(4,"ERICA"))
# print(substrings_of_length(5,"ERICA"))
# print(substrings_of_length(6,"ERICA"))

# RESULTS
# ['']
# ['E', 'R', 'I', 'C', 'A']
# ['ER', 'RI', 'IC', 'CA']
# ['ERI', 'RIC', 'ICA']
# ['ERIC', 'RICA']
# ['ERICA']
# None

## (2) ##
def substrings(s):
	subs = ['']
	for k in range(1,len(s)+1):
		subs += substrings_of_length(k,s)
	return subs

# TEST CASES
# print(substrings("ERICA"))
# print(substrings(""))

# RESULTS
# ['', 'E', 'R', 'I', 'C', 'A', 'ER', 'RI', 'IC', 'CA', 'ERI', 'RIC', 'ICA', 'ERIC', 'RICA', 'ERICA']
# ['']

##### 5 #####
## (1) ##
def longest_ascending_sublist(ns):
	if ns != []:
		longest = []
		current = [ns[0]]
		for n in ns[1:]:
			if current[-1] < n:
				current.append(n)
			else:
				if len(longest) < len(current):
					longest = current
				current = [n]
		return longest
	else:
		return []

# TEST CASES
# print(longest_ascending_sublist([1,5,3,4,8,2,3,5]))
# print(longest_ascending_sublist([]))
# sample = [59, 4, 38, 54, 33, 75, 19, 73, 49, 7, 86, 28, 54, 13, 6, 42, 97, 84, 26, 69, 86, 14, 79, 27, 68, 57, 35, 53, 92, 58, 68, 49, 93, 28, 31, 63, 51, 1, 44, 62, 14, 40, 53, 40, 5, 69, 81, 95, 58, 55, 90, 56, 91, 40, 55, 14, 65, 28, 37, 61, 66, 89, 26, 63, 98, 59, 7, 23, 34, 67, 77, 30, 49, 55, 31, 58, 10, 27, 15, 45, 42, 77, 11, 14, 9, 55, 88, 44, 53, 12, 54, 95, 25, 91, 29, 8, 25, 90, 34, 55]
# print(longest_ascending_sublist(sample))

# RESULTS
# [3, 4, 8]
# []
# [28, 37, 61, 66, 89]

## (2) ##
def longest_steepest_ascending_sublist(ns):
	def slope(ns):
		return (ns[-1] - ns[0]) / len(ns)
	if ns != []:
		longest = []
		steepest = 0
		current = [ns[0]]
		for n in ns[1:]:
			if current[-1] < n:
				current.append(n)
			else:
				if len(longest) < len(current):
					longest = current
					steepest = slope(longest)
				elif len(longest) == len(current) and steepest < slope(current):
					longest = current
					steepest = slope(current)
				current = [n]
		return longest
	else:
		return []

# TEST CASES
# print(longest_steepest_ascending_sublist([1,5,3,4,8,2,3,5]))
# print(longest_steepest_ascending_sublist([]))
# sample = [59, 4, 38, 54, 33, 75, 19, 73, 49, 7, 86, 28, 54, 13, 6, 42, 97, 84, 26, 69, 86, 14, 79, 27, 68, 57, 35, 53, 92, 58, 68, 49, 93, 28, 31, 63, 51, 1, 44, 62, 14, 40, 53, 40, 5, 69, 81, 95, 58, 55, 90, 56, 91, 40, 55, 14, 65, 28, 37, 61, 66, 89, 26, 63, 98, 59, 7, 23, 34, 67, 77, 30, 49, 55, 31, 58, 10, 27, 15, 45, 42, 77, 11, 14, 9, 55, 88, 44, 53, 12, 54, 95, 25, 91, 29, 8, 25, 90, 34, 55]
# print(longest_steepest_ascending_sublist(sample))

# RESULTS
# [3, 4, 8]
# []
# [7, 23, 34, 67, 77]


# Encapsulation is mechanism of hiding data implementation

class SoftwareEngineer:

    def __init__(self, name, age):
        # Public attributes
        self.name = name
        self.age = age
        # Protected attributes
        self._salary = None
        self._num_bugs_solved = 0

    def code(self):
        self._num_bugs_solved += 1
    # getter
    def get_salary(self):
        return self._salary

    # setter
    def set_salary(self, base_value):
        # Check value, enforce constraints
        # if value < 1000:
        #     self._salary = 1000
        # if value > 20000:
        #     self._salary = 20000
        self._salary = self._calculate_salary(base_value)

    def _calculate_salary(self, base_value):
        if self._num_bugs_solved > 10:
            return base_value
        if self._num_bugs_solved > 100:
            return base_value * 2
        return base_value * 3

se = SoftwareEngineer("Max", 25)
print(se._salary)

se.set_salary(6000)
print(se.get_salary())

for i in range(140):
    se.code()

print(se.get_salary())


from ast import Import
from flask_app.config.mysqlconnection import connectToMySQL

from flask_app.models.ninja import Ninja
from pprint import pprint

DATABASE = 'dojos_and_ninjas'
class Dojo:
    def __init__( self , data ):
        self.id = data['id']
        self.name = data['name']
        self.ninjas = []
        self.created_at = data['created_at']
        self.updated_at = data['updated_at']

    # ! READ ALL
    @classmethod
    def get_all(cls):
        query = "SELECT * FROM dojos;"
        results = connectToMySQL(DATABASE).query_db(query)
        print(results)
        dojos = []
        for dojo in results:
            dojos.append( cls(dojo) )
        return dojos

    # ! READ/RETRIEVE ONE
    @classmethod
    def get_one(cls,data):
        query = "SELECT * FROM dojos WHERE id = %(id)s;"
        result = connectToMySQL(DATABASE).query_db(query, data)
        dojo = Dojo(result[0])
        return dojo

    @classmethod
    def get_one_with_ninjas(cls, data):
        query = "SELECT * FROM dojos LEFT JOIN ninjas ON dojos.id = ninjas.dojo_id WHERE dojos.id = %(id)s ;"
        results = connectToMySQL(DATABASE).query_db(query, data)
        pprint(results)
        dojo = Dojo(results[0])
        for result in results:
            ninja_dict = {
                'id': result['ninjas.id'],
                'first_name': result['first_name'],
                'last_name': result['last_name'],
                'age': result['age'],
                'dojo_id': result['dojo_id'],
                'created_at': result['ninjas.created_at'],
                'updated_at': result['ninjas.updated_at'],
            }
            dojo.ninjas.append(Ninja(ninja_dict))
        return dojo
        print(dojo)

    # @classmethod
    # def save(cls, data ):
    #     query = "INSERT INTO dojos (name, created_at, updated_at ) VALUES ( %(name)s, NOW() , NOW() );"
    #     return connectToMySQL(DATABASE).query_db(query, data )

    # ! CREATE
    @classmethod
    def save(cls, data):
        query = "INSERT INTO dojos (name) VALUES (%(name)s);"
        return connectToMySQL(DATABASE).query_db(query, data)

    # ! UPDATE
    @classmethod
    def update(cls, data):
        query = "UPDATE dojos SET name = %(name)s WHERE id = %(id)s ;"
        return connectToMySQL(DATABASE).query_db(query, data)

    # ! DELETE
    @classmethod
    def destroy(cls, data):
        query = "DELETE FROM dojos WHERE id = %(id)s;"
        return connectToMySQL(DATABASE).query_db(query, data)

    @staticmethod
    def validate_dojo(dojo):
        is_valid = True
        if len(dojo['name']) < 3:
            is_valid = False
    # @classmethod
    # def destroy(cls, data):
    #     query = "DELETE FROM ninjas WHERE id = %(id)s ;"
    #     results = connectToMySQL(DATABASE).query_db(query, data)

    # @classmethod
    # def update(cls, data):
    #     query = "UPDATE ninjas SET first_name = %(first_name)s, last_name = %(last_name)s, email = %(email)s WHERE id = %(id)s ;"
    #     results = connectToMySQL(DATABASE).query_db(query, data)


import numpy as np
import os
import gzip
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras import models
import tensorflow as tf

# 网络加载数据集
# fashion_mnist = keras.datasets.fashion_mnist
# (train_images, train_labels),(test_images, test_labels) = fashion_mnist.load_data()

# 定义加载数据的函数，data_folder为保存gz数据的文件夹，该文件夹下有4个文件
# 'train-labels-idx1-ubyte.gz', 'train-images-idx3-ubyte.gz',
# 't10k-labels-idx1-ubyte.gz', 't10k-images-idx3-ubyte.gz'

def load_data(data_folder):
    files = [
        'train-labels-idx1-ubyte.gz', 'train-images-idx3-ubyte.gz',
        't10k-labels-idx1-ubyte.gz', 't10k-images-idx3-ubyte.gz'
    ]

    paths = []
    for fname in files:
        paths.append(os.path.join(data_folder, fname))

    with gzip.open(paths[0], 'rb') as lbpath:
        y_train = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[1], 'rb') as imgpath:
        x_train = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_train), 28, 28)

    with gzip.open(paths[2], 'rb') as lbpath:
        y_test = np.frombuffer(lbpath.read(), np.uint8, offset=8)

    with gzip.open(paths[3], 'rb') as imgpath:
        x_test = np.frombuffer(
            imgpath.read(), np.uint8, offset=16).reshape(len(y_test), 28, 28)

    return (x_train, y_train), (x_test, y_test)

(train_images, train_labels), (test_images, test_labels) = load_data('./datasets/fashion/')

# 查看训练集的个数
# print(train_images.shape)

# 展示训练集内的某个图像
# plt.imshow(train_images[0])
# plt.show()

# 构建简单的神经网络 (784+1)*128=100480 (128+1)*10=1290
# model = keras.Sequential([
#     keras.layers.Flatten(input_shape=(28, 28)),
#     keras.layers.Dense(128, activation=tf.nn.relu),
#     keras.layers.Dense(10, activation=tf.nn.softmax)
# ])

# 构建卷积神经网络
model = keras.Sequential([
    keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    keras.layers.MaxPool2D((2, 2)),
    keras.layers.Conv2D(64, (3, 3), activation='relu'),
    keras.layers.MaxPool2D((2, 2)),
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation=tf.nn.relu),
    keras.layers.Dense(10, activation=tf.nn.softmax)
])

# 展示神经网络
# model.summary()

# 训练模型 epoch设置训练次数
train_images = train_images/255
model.compile(optimizer=tf.optimizers.Adam(),
              loss=tf.losses.sparse_categorical_crossentropy,
              metrics=['accuracy'])
model.fit(train_images.reshape(-1, 28, 28, 1), train_labels, epochs=10)

# 展示神经网络工作过程的图像,卷积和池化可视化
# layer_outputs = [layer.output for layer in model.layers]
# activation_model = tf.keras.models.Model(inputs=model.input, outputs=layer_outputs)
# pred = activation_model.predict(test_images[0].reshape(-1, 28, 28, 1))
# plt.imshow(pred[0][0, :, :, 2])
# plt.show()

# 测试模型
test_images_scaled = test_images/255
model.evaluate(test_images_scaled.reshape(-1, 28, 28, 1), test_labels)

# 预测测试集的标签
# print(np.argmax(model.predict((test_images[0]/255).reshape(-1, 28, 28, 1))))


import json
import sys
import numpy

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

from keras.optimizer_v2.adam import Adam

import cv2
import tensorflow
import warnings

from keras.losses import categorical_crossentropy
from keras.models import model_from_json

from faceRecognition import  testFaceRecognition2
from utils import *

# numpy.set_printoptions(threshold=sys.maxsize)
# inputList, outputList = getData('sessions/**/*.jpg')
# trainingInputSet, trainingOutputSet, validationInputSet, validationOutputSet = divideData(inputList, outputList)
#
# tensorflow.compat.v1.disable_eager_execution()
# json_file = open('model_v1.json', 'r')
# loaded_model_json = json_file.read()
# json_file.close()
# loaded_model = model_from_json(loaded_model_json)
# loaded_model.load_weights("model_v1.h5")
#
# dataV = []
# labelsV = []
# facecasc = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
#
# for i in range(len(validationInputSet)):
#     imagePath = validationInputSet[i]
#     image = cv2.imread(imagePath)
#     image = cv2.resize(image, (64, 64))
#     gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#     roi_gray = adjusted_detect_face(gray,(64,64))
#     labelsV.append(validationOutputSet[i])
#     dataV.append(roi_gray)
#
# lenDataV = len(dataV)
# dataV = np.reshape(dataV, (lenDataV, 64, 64, 1))
# loaded_model.compile(loss=categorical_crossentropy,
#                      optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-7),
#                      metrics=['accuracy'])
# # y_predicted = loaded_model.predict(np.array(dataV))
# # outputNames = ["happy","sad","angry","disgust","neutral","surprisa","fearful"]
# # acc, prec, recall, cm = evalMultiClass(np.array(dataV), y_predicted, outputNames)
# # plotConfusionMatrix(cm, outputNames, "Emotion classification")
# #
# # print('acc: ', acc)
# # print('precision: ', prec)
# # print('recall: ', recall)
#
# test_eval = loaded_model.evaluate(np.array(dataV), np.array(labelsV), verbose=1)
# print('Test loss:', test_eval[0])
# print('Test accuracy:', test_eval[1])

# testFaceRecognition(trainingInputSet, trainingOutputSet, validationInputSet, validationOutputSet)
from utils import getDataTesting

def testEmotionDetection(imagePath):
    # tensorflow.compat.v1.disable_eager_execution()
    json_file = open('E:\\Informatique\\University\\Anul3\\MIRPR\\mirpr-emotional\\efficient_model.json', 'r')
    loaded_model_json = json_file.read()
    json_file.close()
    loaded_model = model_from_json(loaded_model_json)
    loaded_model.load_weights("E:\\Informatique\\University\\Anul3\\MIRPR\\mirpr-emotional\\efficient_model.h5")

    loaded_model.compile(optimizer=Adam(learning_rate=1e-3),
                         loss='categorical_crossentropy',
                         metrics=['accuracy'])

    # img = cv2.imread("E:\\Informatique\\University\\Anul3\\MIRPR\\mirpr-emotional\\test_sad_dragos.jpg")
    img = cv2.imread(imagePath)
    img = adjusted_detect_face(img, (64, 64), "emotion")
    prediction = loaded_model.predict(img)
    classes = np.argmax(prediction, axis=1)

    result = Emotions(classes[0]).name
    return {"emotion": result}

class MainWrapper:
    def __init__(self):
        numpy.set_printoptions(threshold=sys.maxsize)
        self.inputList, self.outputList = getDataTesting("E:\\Informatique\\University\\Anul3\\MIRPR\\mirpr-emotional\\poze\\*.jpg")

    def runFacialRecognition(self, jsonArguments):
        with(open("E:\\Informatique\\University\\Anul3\\MIRPR\\mirpr-emotional\\test-face.txt", 'w')) as f:
            f.write("ceaw din face hehe")
            f.write(jsonArguments)

        args = json.loads(jsonArguments)
        testImagePath = args['modelInput']['imagePath']
        return json.dumps(testFaceRecognition2(self.inputList, self.outputList, testImagePath))

    def runEmotionDetection(self, jsonArguments):
        with(open("E:\\Informatique\\University\\Anul3\\MIRPR\\mirpr-emotional\\test-emo.txt", 'w')) as f:
            f.write("ceaw din emo hehe")
            f.write(jsonArguments)

        args = json.loads(jsonArguments)

        testImagePath = args['modelInput']['imagePath']
        return json.dumps(testEmotionDetection(testImagePath))

if (__name__ == "__main__"):
    main = MainWrapper()
    # print(main.runFacialRecognition("{\"modelInput\": {\"imagePath\": \"test_happy_dragos.jpg\"}}"))

    # args = {
    #    "modelInput": {
    #        "imagePath": "E:\\Informatique\\University\\Anul3\\MIRPR\\mirpr-emotional\\emotional-backend\\emotional-backend\\temp_emotion_recog_images\\test.jpg"
    #    }
    # }
    print(main.runEmotionDetection("{\"modelInput\": {\"imagePath\": \"test_sad_dragos.jpg\"}}"))
    # print(main.runEmotionDetection(json.dumps(args)))


import openai
import os

engine_list = ['gpt-35-turbo', 'gpt-35-turbo-16k', 'gpt-4', 'gpt-4-32k', 'text-embedding-ada-002']

class Config:
    OPENAI_API_TYPE = "azure"
    OPENAI_API_BASE = "your_api_base"
    OPENAI_API_VERSION = "2023-07-01-preview"
    OPENAI_API_KEY = "your_api_key"
    MAX_TURNS = 10
    os.makedirs('logs', exist_ok=True)
    SD_URL = ""
    SD_T2I_API = ""
    serpapi_api_key = ""
    serper_api_key = ""

class OpenAIChat:
    def __init__(self, model_name="gpt-35-turbo"):
        openai.api_type = Config.OPENAI_API_TYPE
        openai.api_base = Config.OPENAI_API_BASE
        openai.api_version = Config.OPENAI_API_VERSION
        openai.api_key = Config.OPENAI_API_KEY
        if model_name not in engine_list:
            raise ValueError("The model name is not in the list of available models among gpt-35-turbo, gpt-35-turbo-16k, gpt-4, gpt-4-32k, text-embedding-ada-002.")
        self.model_name = model_name
        self.messages = [{"role": "system", "content": "You are an experienced python programmer which can write codes to fulfill user's requests."}]

    def chat(self, messages):
        message = ""
        if isinstance(messages, list):
            message += (tmp_message for tmp_message in messages)
        elif isinstance(messages, str):
            message = messages
        else:
            raise TypeError("Messages must be a list or str.")
        self.messages.append({"role": "user", "content": message})
        response = openai.ChatCompletion.create(
            engine=self.model_name,
            messages=self.messages,
            #max_tokens=2048
        )
        self.messages.append({"role": "assistant", "content": response['choices'][0]['message']['content']})
        return response['choices'][0]['message']['content']

    def set_system_prompt(self, prompt):
        system_messages = ""
        if isinstance(prompt, list):
            system_messages += (system_message for system_message in prompt)
        elif isinstance(prompt, str):
            system_messages = prompt
        else:
            raise TypeError("System messages must be a list or string.")
        self.messages[0]['content'] = prompt

    def get_history(self):
        return self.messages

if __name__ == "__main__":
    openai_chat = OpenAIChat()
    query = ""
    print(openai_chat.chat(query))


from .models import Teacher
from .models import Group
from .models import TeacherSubject
from .models import TypedSubject
from .models import Day
from .models import TimeTable
from .models import LessonType

import itertools

import itertools
from pulp import *
problem = LpProblem("schedule-opt", LpMaximize)
from faker import Faker
fake = Faker()
from collections import namedtuple

N_l = 20  # number of teachers
N_g = 20  # number of groups
N_s = 20  # number of courses
N_d = 12  # number of days
N_t = 8  # number of times per day
L = [fake.name() for _ in range(N_l)]
G = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,z,y,z"[0:2 * N_g].split(',')[:-1]
types = ['lection', 'lab', 'practice']
subjs = [fake.job().replace(',', '')[0:15] for _ in range(N_s)]
D = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,z,y,z"[0:2 * N_d].split(',')[:-1]
T = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,z,y,z"[0:2 * N_t].split(',')[:-1]

def get_all_sp_keys(L, G, types, subjs, D, T):
    return itertools.product(L, G, types, subjs, D, T)

def get_all_gdt_keys(GG, DD, TT):
    return itertools.product(GG, DD, TT)

def get_all_ldt_keys(LL, DD, TT):
    return itertools.product(LL, DD, TT)

SP = LpVariable.dicts("SP", get_all_sp_keys(L, G, types, subjs, D, T), 0, 1, cat=pulp.LpInteger)
Ig = LpVariable.dicts("Ig", get_all_gdt_keys(G, D, T[:-1]), -1, 1, cat=pulp.LpInteger)
Il = LpVariable.dicts("Il", get_all_ldt_keys(L, D, T[:-1]), -1, 1, cat=pulp.LpInteger)
one = LpVariable("one", 1, 1, cat=pulp.LpInteger)
zero = LpVariable("zero", 0, 0, cat=pulp.LpInteger)

def get_x_by_gdt(g, d, t, SP):
    s = lpSum([SP[key] for key in itertools.product(L, [g], types, subjs, [d], [t])])
    return s

def get_x_by_ldt(l, d, t, SP):
    s = lpSum([SP[key] for key in itertools.product([l], G, types, subjs, [d], [t])])
    return s

def get_x_by_ldt(l, d, t, SP):
    s = lpSum([SP[key] for key in itertools.product([l], G, types, subjs, [d], [t])])
    return s

def sum_x_by_g(g, SP):
    sum = lpSum([SP[key] for key in itertools.product(L, [g], types, subjs, D, T)])
    return sum

def sum_x_by_l(l, SP):
    sum = lpSum([SP[key] for key in itertools.product([l], G, types, subjs, D, T)])
    return sum

alpha = 1.0
beta = 1.0
gamma = 1.0

def get_c(key):
    return 1.0

#Problem
all_lectures = [alpha * get_c(key) * SP[key] for key in get_all_sp_keys(L, G, types, subjs, D, T)]
all_groups_no_gaps = [beta * Ig[key] for key in get_all_gdt_keys(G, D, T[:-1])]
all_teachers_no_gaps = [gamma * Il[key] for key in get_all_ldt_keys(L, D, T[:-1])]
all_lectures + all_groups_no_gaps + all_teachers_no_gaps
problem += lpSum(all_lectures + all_groups_no_gaps + all_teachers_no_gaps)
#Constraints
#Minimize gaps between lessons for teacher
def next_letter(symbol):
    return T[(T.index(symbol) + 1) % len(T)]

for (teacher, day, time) in itertools.product(L, D, T[:-1]):
    # problem += get_x_by_ldt(teacher, day, time, SP) + get_x_by_ldt(teacher, day, time + 1, SP) -1 >= Il[teacher, day, time]
    problem += get_x_by_ldt(teacher, day, time, SP) + get_x_by_ldt(teacher, day, next_letter(time), SP) - Il[
        teacher, day, time] >= 1
#Minimize gaps between lessons for group

for (group, day, time) in itertools.product(G, D, T[:-1]):
    # problem += get_x_by_gdt(group, day, time, SP) + get_x_by_gdt(group, day, time + 1, SP) -1 >= Ig[group, day, time]
    problem += get_x_by_gdt(group, day, time, SP) + get_x_by_gdt(group, day, next_letter(time), SP) - Ig[
        group, day, time] >= 1
#with open('problem.txt', 'w') as f: print(problem, file=f)

#Amount of lessons for group must be no more than payload in plan
for g in G:
    problem += sum_x_by_g(g, SP) <= len(D) * 3
#Amount of lessons for teacher must be no more than payload in plan
for teacher in L:
    problem += sum_x_by_l(teacher, SP) <= len(D) * 3

#One lesson per time slot for one group
def sum_x_for_group_at_dt(g, d, t, SP):
    s = 0
    for key in itertools.product(L, [g], types, subjs, [d], [t]):
        s += SP[key]
    return s

for key in get_all_gdt_keys(G, D, T):
    s = sum_x_for_group_at_dt(*key, SP)
    problem += s <= 1
    problem += s >= 0
#One lesson per time slot for one teacher
def sum_x_for_teacher_at_dt(l, d, t, SP):
    s = 0
    for key in itertools.product([l], G, types, subjs, [d], [t]):
        s += SP[key]
        return s
for key in get_all_ldt_keys(L, D, T):
    s = sum_x_for_teacher_at_dt(*key, SP)
    problem += s <= 1
    problem += s >= 0
#No more than 3 lessons for one group per day

def sum_x_for_group_per_day(g, d, SP):
    s = 0
    for key in itertools.product(L, [g], types, subjs, [d], T):
        s += SP[key]
    return s

for (group, day) in itertools.product(G, D):
    problem += sum_x_for_group_per_day(group, day, SP) <= 3

#No more than 4 lessons for one teacher per day
def sum_x_for_teacher_per_day(l, d, SP):
    s = 0
    for key in itertools.product([l], G, types, subjs, [d], T):
        s += SP[key]
    return s
for (teacher, day) in itertools.product(L, D):
    problem += sum_x_for_teacher_per_day(teacher, day, SP) <= 4

#No more than 2 lessons of one subject for group per day
def sum_x_of_same_subject_for_group_per_day(g, d, subj, SP):
    s = 0
    for key in itertools.product(L, [g], types, [subj], [d], T):
        s += SP[key]
    return s

for (group, day, subj) in itertools.product(G, D, subjs):
    problem += sum_x_of_same_subject_for_group_per_day(group, day, subj, SP) <= 2#Solution
#need to fix it problem.solve(solver=pulp.glpk(options=['--log', 'lessons.log']))
# problem.solve(solver=solvers.GLPK(options=['--log', 'lessons.log', '--wmps', 'lessons.mps', '--check']))

def print_solution(problem):
    print("Status:", LpStatus[problem.status])
    for v in problem.variables():
        if (v.varValue > 0.0):
            print(v.name, "=", v.varValue)
            # print("Total Cost =", pulp.value(problem.objective))

print_solution(problem)
print(value(problem.objective))
#Match lessons to rooms
TheSix = namedtuple('TheSix', ['teacher', 'group', 'lesson_type', 'subject', 'day', 'time'])

def get_tuple(v):
    # SP_('Shane_Gordon',_0,_'lab',_'Paramedic',_0,_'b')
    x = v.name.split(',_')  # ["SP_('Shane_Gordon'", '0', "'lab'", "'Paramedic'", '0', "'b')"]
    start = "'"
    end = "'"
    return TheSix(*list(map(lambda s: s[s.find(start) + len(start):s.rfind(end)].replace('_', ' '), x)))

def extract_optimal_solution(problem):
    optimals = [get_tuple(v) for v in problem.variables() if v.varValue > 0.0 and v.name.startswith('SP')]
    return optimals

N_r = 26
R = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,z,y,z"[0:2 * N_r].split(',')[:-1]

#TypedRoom
TypedRoom = namedtuple('TypedRoom', ['room', 'type'])
lection_rooms_number = 3
lab_rooms_number = 3
practice_rooms_number = 3
lections_rooms = list(map(lambda room: TypedRoom(room=room, type='lection'), R[0:lection_rooms_number]))
lab_rooms = list(
    map(lambda room: TypedRoom(room=room, type='lab'), R[lection_rooms_number:lection_rooms_number + lab_rooms_number]))
practice_rooms = list(map(lambda room: TypedRoom(room=room, type='practice'), R[
                                                                              lection_rooms_number + lab_rooms_number: lection_rooms_number + lab_rooms_number + practice_rooms_number]))
available_rooms = lections_rooms + lab_rooms + practice_rooms
lessons = extract_optimal_solution(problem)
problem_match = LpProblem("match-to-rooms", LpMaximize)
Z = LpVariable.dicts("Z", list(
    map(lambda pair: (tuple(pair[0]), tuple(pair[1])), itertools.product(lessons, available_rooms))), 0, 1,
                     cat=pulp.LpInteger)
#Rooms have priorities for appropriate lessons
priority = {
    'lection': {'lection': 1.0},
    'lection': {'practice': 0.5},
    'lection': {'lab': 0.0},

    'practice': {'lection': 0.0},
    'practice': {'practice': 1.0},
    'practice': {'lab': 0.0},

    'lab': {'lection': 0.0},
    'lab': {'practice': 0.5},
    'lab': {'lab': 1.0},
}  # from room type to lesson type

def get_c(key):
    return priority[key[1].type][key[0].lesson_type]

problem_match += lpSum([get_c(key) * Z[(key[0], key[1])] for key in itertools.product(lessons, available_rooms)])

def get_z_by_lesson(lesson, Z):
    s = lpSum([Z[(key[0], key[1])] for key in itertools.product([lesson], available_rooms)])
    return s

def get_lessons_by_day_time(d, t, lessons):
    return list(filter(lambda lesson: lesson.day == d and lesson.time == t, lessons))

def get_z_by_day_time(d, t, Z):
    lessons_at_moment = get_lessons_by_day_time(d, t, lessons)
    if len(lessons_at_moment) > 0:
        return lpSum([Z[(key[0], key[1])] for key in itertools.product(lessons_at_moment, available_rooms)])
    return None

for (d, t) in itertools.product(D, T):
    contraint = get_z_by_day_time(d, t, Z)
    if contraint:
        problem_match += contraint <= 1
for lesson in lessons:
    problem_match += get_z_by_lesson(lesson, Z) == 1
#Solution
#need to fix it with open('problem_match.txt', 'w') as f:
    #need to fix it print(problem_match, file=f)
#need to fix it problem_match.solve(solver=solvers.GLPK(options=['--log', 'match.log', '--wmps', 'match.mps']))
print(value(problem_match.objective))
print_solution(problem_match)


class Solution(object):
    def repeatedNTimes(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        temp = []
        for i in range(len(A)):
            if A[i] in temp:
                return A[i]
            temp.append(A[i])


import flask
import sqlite3
from flask import jsonify, Response
from config import DEBUG, DATABASE_PATH
from models import Application, ApplicationHistory

app = flask.Flask(__name__)
app.config["DEBUG"] = DEBUG

@app.route('/<app_id>', methods=['GET'])
def application(app_id):
    connection = sqlite3.connect(DATABASE_PATH)
    application = Application.from_app_id(app_id, connection)
    if application is not None:
        return jsonify(application.to_json())
    return jsonify({
        'error': f'Application with {app_id} not found'
    }), 204

app.run()


# import libraries
import argparse
import os
import json
import datetime
import boto3
import sagemaker
from sagemaker.tensorflow.estimator import TensorFlow
from sagemaker.tensorflow.model import TensorFlowModel

from env import *

def train():
    "Train the model in SageMaker"

    with open(HYPERPARAMETERS_FILE_PATH) as f:
        hyperparameters = json.load(f)

    # define the estimator
    print("Build Estimator...")
    estimator = TensorFlow(entry_point=ENTRY_POINT_TRAIN,
                           source_dir=SOURCE_DIR,
                           output_path=MODEL_ARTIFACTS_S3_LOCATION,
                           code_location=CUSTOM_CODE_TRAIN_UPLOAD_S3_LOCATION,
                           base_job_name=BASE_JOB_NAME,
                           role=ROLE_ARN,
                           py_version=PYTHON_VERSION,
                           framework_version=FRAMEWORK_VERSION,
                           hyperparameters=hyperparameters,
                           instance_count=TRAIN_INSTANCE_COUNT,
                           instance_type=TRAIN_INSTANCE_TYPE,
                           distributions=DISTRIBUTIONS)

    # train the model
    print("Fit the estimator...")
    estimator.fit({"train": TRAIN_DATA_S3_LOCATION, "test": TEST_DATA_S3_LOCATION})

    print("Store the training job name...")
    with open(FILENAME_TRAINING_JOB_NAME, "w+") as f:
        f.write(str(estimator.latest_training_job.name))

    return estimator

def deploy():
    "Deploy the model in a SageMaker Endpoint "

    print("Get the latest training job name...")
    with open(FILENAME_TRAINING_JOB_NAME) as f:
        training_job_name = f.read()

    print("Training job name :", training_job_name)

    print("Build the Model...")
    model = TensorFlowModel(
              entry_point=ENTRY_POINT_INFERENCE,
              source_dir=SOURCE_DIR,
              framework_version=FRAMEWORK_VERSION,
              model_data=f"{MODEL_ARTIFACTS_S3_LOCATION}/{training_job_name}/output/model.tar.gz",
              code_location=CUSTOM_CODE_SERVING_UPLOAD_S3_LOCATION,
              name=MODEL_NAME,
              role=ROLE_ARN,
              sagemaker_session=SESS)

    print("Build an endpoint...")
    predictor = model.deploy(endpoint_name=ENDPOINT_NAME,
                             initial_instance_count=DEPLOY_INSTANCE_COUNT,
                             instance_type=DEPLOY_INSTANCE_TYPE)

    return predictor

def main(args):
    # executing function
    if args.mode == "train":
        train()
    elif args.mode == "deploy":
        deploy()
    else:
        raise RuntimeError(f"{args.mode} is not recognized.")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--mode",
        type=str,
        required=True,
        choices=["train", "deploy"]
    )
    args = parser.parse_args()
    main(args)


import warnings
from torch.utils.data.dataloader import DataLoader
from dataloaders.datasets.cityscapes import CityscapesSegmentation
from config_utils.search_args import obtain_search_args
from utils.loss import SegmentationLosses
import torch
import numpy as np
from auto_deeplab import AutoDeeplab

model = AutoDeeplab(19, 12).cuda()

args = obtain_search_args()

args.cuda = True
criterion = SegmentationLosses(weight=None, cuda=args.cuda).build_loss(mode=args.loss_type)

def save_grad(name):
    def hook(grad):
        grads[name] = grad
    return hook

args.crop_size = 64

dataset = CityscapesSegmentation(args, r'E:\BaiduNetdiskDownload\cityscapes', 'train')

loader = DataLoader(dataset, batch_size=2, shuffle=True)

grads = {}

def save_grad(name):
    def hook(grad):
        grads[name] = grad
    return hook

for i, sample in enumerate(loader):
    image, label = sample['image'].cuda(), sample['label'].cuda()

    # from thop import profile

    # params, flops = profile(model, inputs=(image, ))

    # print(params)
    # print(flops)
    model.betas.register_hook(save_grad('y'))

    prediction = model(image)
    # y = 1e-3*torch.randn(12, 4, 3).cuda()
    # criterion = torch.nn.MSELoss()
    # z = criterion(prediction, label)
    z = prediction.mean()

    z.backward()

    print(grads['y'])
    print(grads['y'].shape)

    # print(grads['y1'])
    # print(grads['y1'].shape)

    if i == 0:
        exit()

# 查看 y 的梯度值


from __future__ import absolute_import, division
from collections import defaultdict
from .components import Edge, Node
from .exceptions import InvalidNodeTypeError, MaxNodeError, GraphTypeError
from .utils import check_cycle
from .algorithms._search import BFS, DFS
from .algorithms._sort import topological_sort
from ._vis.layout import plot_graph_directed, plot_graph_undirected
from graphnet import VECTOR, SCALAR
import matplotlib.pyplot as plt
import numpy as np

class Graph(object):
    """
    Implements the Graph data structure which contains nodes or vertices linked with edges between them

    Graph helps in managing relationship between nodes in a network with their edges.
    Parameters
    ----------
    max_node:int, float, optional, default=infinity
        the maximum amount of nodes that can be added to the graph,
        default is infinity which means in theory nodes can be added
        to the graph indefinitely.
    max_edge:int, float, optional, default=infinity
        the maximum amount of edges that can be added to the graph,
        default is infinity
    type:{'scalar'or'S', 'vector'or'V'},optional, default='scalar'
        this specifies the graph type, the are two graph types 'vector'
        which represents directional graphs and 'scalar' which represents
        un-directional graphs. the type of of graph determines the behavior
        of the graph instance and which algorithm work with it. optionally
        you can substutute 'scalar' with 'S' and 'vector' with 'V'.
    ref:str,optional,default="value"
        the attribute used by the graph for referencing the node object passed in
        for identification and accessing as key value for the graph. change this
        if you are using a inherited node object to the object identifier else if
        you're using the built in Node class directly then leave it as default.

    Attributes
    ----------
    edges:list
        This is a list of all edges in the graph instance
    connections:dict<defaultdict>
        A dictionary thats maps each node to its neighbor with an edge, a node
        in the connection dictionary contains a default dict and in the default dict
        the adjacent node is mapped with its edge object and if there is no relationship
        with the two node 0 will be returned.
    graph_matrix: numpy.array()
        this is a adjacent matrix form of the graph, it is read only.
    get_node: list
        lits of all the node object in the graph, read only.

    """

    def __init__(self, max_node=float("inf"), max_edge=float("inf"), type=SCALAR, ref="value"):
        self.__max_node = max_node
        self.max_edge = max_edge
        self.type = type
        self.ref = ref
        self.edges = []
        self.connections = {}
        self.__nodes = []
        self.__node_map = {}

    def __len__(self):
        return len(self.__nodes)

    def __iter__(self):
        self.__counter = 0
        return self

    def __next__(self):
        if self.__counter < self.__len__():
            res = self.__nodes[self.__counter]
            self.__counter += 1
            return res
        else:
            raise StopIteration

    def __getitem__(self, key):
        return self.__node_map[key]

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.clear()

    def add_node(self, node):
        """
        Adds an arbitrary object or Node object to the graph,
        all nodes added should be unique.
        parameters
        ----------
        node: str, int, float, Node

        """
        if self.__len__() <= self.__max_node:
            if type(node) in [str, int, float]:
                node = Node(node)
            if node not in self.__nodes:
                if type(node) == Node or issubclass(node.__class__, Node):
                    self.__nodes.append(node)
                    node_id = self.get_node_id(node)
                    self.__node_map[node_id] = node
                else:
                    raise InvalidNodeTypeError(
                        "Expected object of type str, float, int, Node or subclass of Node but %s was given." % type(node))
                self.connections[node_id] = defaultdict(int)
            else:
                raise ValueError("Node instance already in graph network")
        else:
            raise MaxNodeError(
                "Graph max size exceeded, expected %d node." % (self.__max_node))

    def add_edge(self, _from, _to, weight=1):
        """
        Adds a edge to the graph connecting the _from and _to nodes,
        the values passed to the parameters _from and _to must be a
        node in the graph or a node in the graph must contain the
        value passed in.
        if the type of the graph object is scalar an edge will be added
        from _to to _from.
        parameters
        ----------
        _from:int,str,float,Node
            this is the source from where the edge starts from
        _to:int,str,float,Node
            the destination of the edge
        weight:int, str, float, default=1
            this is the weight of the edge object connecting the nodes
            the default value is 1.
        """
        if len(self.connections) <= self.max_edge:
            if type(_from) == Node or issubclass(_from.__class__, Node):
                _from = self.get_node_id(_from)
            if type(_to) == Node or issubclass(_to.__class__, Node):
                _to = self.get_node_id(_to)
            node = self[_from]
            node_to = self[_to]
            edge = Edge(node, node_to, weight)
            self.connections[_from][_to] = edge
            node.add_node(node_to)
            self.edges.append(edge)
            if self.type == SCALAR:
                edge2 = Edge(_to, _from, weight)
                self.connections[_to][_from] = edge2
                node_to.add_node(node)
                self.edges.append(edge2)
        else:
            raise MaxNodeError(
                "Graph max size exceeded, expected %d node." % (self.max_edge))

    def add_nodes_from_iterable(self, iterable):
        """
        Adds nodes from a an iterable to the graph.
        Parameters
        ----------
        iterable:iter
            an iterable object containing nodes to be added to the graph
        """
        for node in iterable:
            self.add_node(node)

    def add_edges_from_iterable(self, iterable):
        """
        Adds nodes edge a an iterable to the graph.
        Parameters
        ----------
        iterable:iter
            an iterable object containing a iterable with size of 3 or 2
            where the first two values are values of nodes in the graph
            and if there's a third value it will be used as the weight of
            the edge to be added to the graph
        """
        for e in iterable:
            self.add_edge(*e)

    @property
    def graph_matrix(self):
        nodes = self.__nodes
        self.__adj_matrix = np.zeros((self.__len__(), self.__len__()))
        for i in range(self.__len__()):
            id_i = self.get_node_id(nodes[i])
            for j in range(self.__len__()):
                id_j = self.get_node_id(nodes[j])
                edge = self.connections[id_i][id_j] if not self.connections[id_i][id_j] else self.connections[id_i][id_j].weight
                self.__adj_matrix[i, j] = edge
        return self.__adj_matrix

    @property
    def get_nodes(self):
        return self.__nodes

    def from_dict(self, dictionary, weights=1):
        """
        creates and add node from a dictionary. The dictionary passed in must
        have a key with an iterable value which contains all adjacents node, and
        node in the iterable must be in the dictionary or graph. The weight will be
        uniform for all nodes.
        Parmeters
        ---------
        dictionary: dict
            dictionary object thats holds weights and their connections
        weights: int, str, float
            uniform weight passed to all edges.
        """
        self.add_nodes_from_iterable(list(dictionary.keys()))
        for key in dictionary:
            for edge in dictionary[key]:
                self.add_edge(key, edge, weights)

    def is_cyclic(self):
        """
        Checks if the graph contains a cycle, if the graph type is scalar

        returns
        -------
        bool
        """
        if self.type != VECTOR:
            raise GraphTypeError(
                "cyclic check only works for vector type graphs")
        visited = {}
        rec_stack = {}
        for node in self:
            visited[node] = False
            rec_stack[node] = False
        for source in self:
            if check_cycle(source, visited, rec_stack):
                return True

        return False

    def clear(self):
        """
        Clears all the graph content
        """
        self.__nodes.clear()
        self.connections = {}
        self.edges.clear()

    def is_connected(self):
        """
        Checks if a scalar graph is connected or not.

        returns
        -------
        bool
        """
        if self.type == SCALAR:
            traverse = self.BFS()
            for node in self.__nodes:
                if not node in traverse:
                    return False
            return True
        else:
            raise GraphTypeError(
                "Invalid graph type %s expected scalar" % (self.type))

    def display(self, weighted=False, weight_color=False, arrow_color=True, layout="polygon", polygon_radius=5, attr=None, ax=None):
        """
        creates a plot of the graph.

        parameters
        ----------
        weighted:bool, optional, default=False
            if true weights will be displayed.
        weight_color:bool, optional, default=False
            if true the weights will be colored with the edge object color attribute.
        arrow_color:bool, optional, default=True
            if true the arrow will be colored with the edge object color attribute.
        layout: optional, {random, polygon}, default=polygon
            The layout used to arrange the nodes in the plot
        polygon_radius: int, float, default=5
            if polygon layout is used this defines the radius of the polygon shape.
        attr:None, str, int, object, default=None
            The attribute of the Node object to be used as label. if omitted the default value
            will be the ref attribute of the graph.
        ax:.axes.Axes, default=None
            An axis object to plot the graph, if not specified a default axis will be created.

        """
        if attr == None:
            attr = self.ref
        if not ax:
            _, ax = plt.subplots(1, figsize=(20, 20))
        if self.type == VECTOR:
            plot_graph_directed(self, ax, len(
                self), weighted, weight_color, arrow_color, layout, polygon_radius, attr)
        elif self.type == SCALAR:
            plot_graph_undirected(self, ax, len(
                self), weighted, weight_color, arrow_color, layout, polygon_radius, attr)

    def remove_edge(self, _from, _to):
        """
        removes edge connecting to nodes if it exist.

        Parameters
        ----------
            _from:int, str, float
            _to:int, str, float
        """
        del self.connections[_from][_to]
        for i in range(len(self.edges)):
            if self.edges[i]._from == _from and self.edges[i]._to == _to:
                self.edges.pop(i)
                break

        src = self[_from]
        dest = self[_to]
        for i in range(len(src.adjacent_nodes)):
            if dest == src.adjacent_nodes[i]:
                src.adjacent_nodes.pop(i)
                break

    def get_node_id(self, node):
        """
        gets the value of the node object used in identifying
        the node
        Parameters
        ----------
        node:Node
        returns
        -------
        value:str, int, float, object

        """
        for vertex in self.__nodes:
            if vertex == node:
                v = node
                break
        return eval('v.%s' % self.ref)

    def topological_sort(self):
        """
        Sorts the nodes if graph type is vector
        returns
        -------
        res:List
            a list containing  all the node in the graph instance
            in a sorted form
        """
        return topological_sort(self)

    def BFS(self, source=None, key=None):
        """
        An Impelemetaion of breath-first-search for tranversing a
        graph of getting a node.
        Parameters
        ----------
        source:int, str, float, optional
            Value of the node to start the tranverse. if omitted the method
            uses a random node as source.
        key:int, str, float, optional
            Value of the node to stop the tranverse. if omitted the method
            stops when all  node in the graph are tranversed.
        returns
        -------
        value: list
            A list of the path tranversed in order from source to key.
        """
        return BFS(self, source, key)

    def DFS(self, source=None, key=None):
        """
        An Impelemetaion of depth-first-search for tranversing a
        graph of getting a node.
        Parameters
        ----------
        source:int, str, float, optional
            Value of the node to start the tranverse. if omitted the method
            uses the first node in the graph as source.
        key:int, str, float, optional
            Value of the node to stop the tranverse. if omitted the method
            stops when all  node in the graph are tranversed.
        returns
        -------
        value: list
            A list of the path traversed in order from source to key.
        """
        return DFS(self, source, key)

class GraphPriorityQueue:
    """
    A priority queue data structure which stores node
    and get them based on priority. if state is true nodes
    will be gotten by priority and if their state value evaluate
    to true.
    Parameters
    ----------
    graph: Graph
        graph object whose node will be stored in the queue.
    type: {"min", "max"}, default="min"
        the type of priority based on how the values in the
        graph will be retrived, if min the smallest value will
        be prioritized and if max the largest value will be prioritized.
    state: boolean, default=False
        this specifies if state will be used in the queue. If true an
        attribute status will be created to hold the states of all the
        nodes.
    Attributes
    ---------
    type: {"min", "max"}, default="min"
    queue: dict
        this holds node and value pair, the value is what is used in
        as priority in getting items.
    status: dict
        if state is true this will be created and hold a dictionary of
        nodes mapped with boolean.
    """

    def __init__(self, graph, type="min", state=False):
        if type == 'min' or type == 'max':
            self.type = type
        else:
            raise TypeError("type attribute most be 'min' or 'max'")
        self.__graph = graph
        self._top = float('inf') if self.type == 'min' else -float('inf')
        self.queue = dict()
        self.__state = state
        for node in self.__graph:
            self.queue[node] = float('inf')
        if self.__state:
            self.status = dict()
            for node in self.__graph:
                self.status[node] = False

    def __repr__(self):
        return str(list(self.queue.values()))

    def get(self):
        """
        gets a node based on priority if the queue isn't empty

        returns: Node
            if the queue isn't empty returns a Node object else it
            returns None.
        """
        if self.__state:
            if all(self.status.values()):
                return None
        if len(self.queue) != 0:
            sign = "<=" if self.type == "min" else ">=" if self.type == "max" else ''
            state = '' if not self.__state else 'and (not self.status[node])'
            for node in self.queue:
                if eval("(self.queue[node] %s self._top %s)" % (sign, state)):
                    self._top = self.queue[node]
                    res = node
            del self.queue[res]
            if self.__state:
                del self.status[res]
            self._top = float('inf') if self.type == 'min' else -float('inf')
            return res
        return None

    def set_status(self, node, value):
        """
        Tries to set the status of the node if state is true
        Parameters
        ----------
        node: Node
            node object to change state
        value: boolean
            value to change the node state.
        """
        assert (value == True or value == False) and (self.__state)
        self.status[node] = value

    def enqueue(self, node, value=0):
        """
        Inserts a node to the queue with the value to be used for
        prioritizing.
        Parameters
        ----------
        node: Node
            node object to insert
        value:int, float, default=0
            value to be used for prioritizing the node object.
        """
        self.queue[node] = value

    def is_empty(self):
        """
        Checks if the queue is empty
        returns
        -------
        out:boolean
            if True queue is empty else it's not.
        """
        if len(self.queue) != 0:
            return False
        return True