import pickle
from LabelRanking import *
import copy
from tqdm import tqdm

def run_algorithm(
  classifier,
  classifier_name,
  dimensionality='SFN',
  noise_type='additive',
  noise_measurement='alpha'
  ):
  with open(f'datasets/{dimensionality}/X_train.pickle', 'rb') as handle: X_train = pickle.load(handle)
  with open(f'datasets/{dimensionality}/X_test.pickle', 'rb') as handle: X_test = pickle.load(handle)
  with open(f'datasets/{dimensionality}/P_test.pickle', 'rb') as handle: P_test = pickle.load(handle)

  clfs = []
  measurement_params = []

  for i in range(50):
    with open(f'datasets/{dimensionality}/{noise_type}/{noise_measurement}_{i}.pickle', 'rb') as handle:
      data = pickle.load(handle)
    # print(data[noise_measurement])
    measurement_params.append(data[noise_measurement])
    P_train_noisy = data['P_train_noisy']
    clf = copy.deepcopy(classifier).fit(X_train, P_train_noisy)
    clfs.append(clf)

  clf_preds = [clf.predict(X_test) for clf in clfs]
  clf_KT_corr = [mean_KTcorrelation(P_test, clf_pred) for clf_pred in clf_preds]

  res = [x for _, x in sorted(zip(measurement_params, clf_KT_corr))]

  with open(f'results/{dimensionality}/{noise_type}/{noise_measurement}_{classifier_name}.pickle', 'wb') as handle:
    pickle.dump(res, handle, protocol=pickle.HIGHEST_PROTOCOL)

  print(classifier_name, res)

hh_params = {
  'SFN': dict(beta=0.005, sigma=0.1),
  'MFN': dict(beta=0.0008, sigma=0.15)
}

dt_params = {
  'SFN': dict(max_depth=10),
  'MFN': dict(max_depth=7)
}

rf_params = {
  'SFN': dict(max_features='log2', n_jobs=-1),
  'MFN': dict(max_features='log2', n_jobs=-1)
}

if __name__ == '__main__':
  for dimensionality in tqdm(['SFN', 'MFN']):
    for noise_type in tqdm(['additive', 'mallows']):
      for noise_measurement in tqdm(['alpha', 'beta']):
        run_algorithm(
          classifier=LabelwiseLabelRanking('Linear', dict(n_jobs=-1)),
          classifier_name='labelwise_lr',
          dimensionality=dimensionality,
          noise_type=noise_type,
          noise_measurement=noise_measurement
        )

        run_algorithm(
          classifier=LabelwiseLabelRanking('Decision Tree', dt_params[dimensionality]),
          classifier_name='labelwise_dt',
          dimensionality=dimensionality,
          noise_type=noise_type,
          noise_measurement=noise_measurement
        )

        run_algorithm(
          classifier=PairwiseLabelRanking('Decision Tree', dt_params[dimensionality], aggregation='tournament'),
          classifier_name='pairwise_dt',
          dimensionality=dimensionality,
          noise_type=noise_type,
          noise_measurement=noise_measurement
        )

        run_algorithm(
          classifier=LabelwiseLabelRanking('Random Forest', rf_params[dimensionality]),
          classifier_name='labelwise_rf',
          dimensionality=dimensionality,
          noise_type=noise_type,
          noise_measurement=noise_measurement
        )

        run_algorithm(
          classifier=PairwiseLabelRanking('Random Forest', rf_params[dimensionality], aggregation='tournament'),
          classifier_name='pairwise_rf',
          dimensionality=dimensionality,
          noise_type=noise_type,
          noise_measurement=noise_measurement
        )

        run_algorithm(
          classifier=PairwiseLabelRanking('Homogeneous Halfspace', hh_params[dimensionality], aggregation='tournament'),
          classifier_name='pairwise_hh',
          dimensionality=dimensionality,
          noise_type=noise_type,
          noise_measurement=noise_measurement
        )


import sys
import nltk
# skip first line
sys.stdout.write(sys.stdin.readline())

lastSentence = ""
for line in sys.stdin:
   parts = line.split("\n")[0].split("\t")
   if parts[1] != lastSentence:
      sys.stdout.write(line)
      lastSentence = parts[1]


# -*- coding: utf-8 -*-
"""
	Title:
	Description:
	Author:			haithem ben abdelaziz
	Date:
	Version:
	Environment:
"""

from __future__ import absolute_import

import stbt
import time
import logging
import os
import csv
import cv2
import inspect
import subprocess
import stbts
import unicodedata
from multiprocessing.pool import ThreadPool

logging.basicConfig(format="[%(asctime)s] %(message)s", level=logging.INFO)

def write_csv_file(file_name, rows, mode="a"):
    """

    write_csv_file  append to a csv file the rows passed on params if the file is exist
    and create it if not
    file_name: is the csv file name
    rows is a list of lines (rows) and not just one line
    mode:method of write into the csv file, default mode is append
    Example:
    write_csv_file("csv_file_name.csv", [ ["a", 1], ["b", 2], ["c", 3] ])
    the csv file will contain
    a | 1
    b | 2
    c | 3

    """
    csv_file = open(file_name, mode)
    writer = csv.writer(csv_file)
    writer.writerows(rows)

def detect_many_match(image, timeout_secs=10, match_parameters=None, region=stbt.Region.ALL):
    count = 0
    _exit = False
    # import time
    while (count < len(image) and _exit == False):
        if stbt.detect_match(image[count], timeout_secs=timeout_secs, match_parameters=match_parameters,
                             region=region).next().match:
            _exit = True
        count += 1
        # time.sleep(0.1)
    return _exit

def wait_for_many_match(image, timeout_secs=5, match_parameters=None, region=stbt.Region.ALL):
    _exit = False
    if stbt.wait_until(lambda: detect_many_match(image=image,
                                                 region=region,
                                                 match_parameters=match_parameters,
                                                 timeout_secs=10),
                       timeout_secs=timeout_secs,
                       interval_secs=0):
        _exit = True
        # time.sleep(0.3)
    return _exit

def press_until_many_match(key, image, max_presses=1, interval_secs=3, region=stbt.Region.ALL,match_parameters=None):
    occurence = 0
    _exit = False
    if match_parameters is None:
        match_parameters = stbt.get_config("navigation", "match_param_template")
    while not _exit and (occurence < max_presses):
        press(key)
        wait(interval_secs)
        for i in range(0, len(image)):
            try:
                _exit = stbt.wait_for_match(image=image[i],
                                            timeout_secs=interval_secs,
                                            region=region,
                                            match_parameters=match_parameters).match
                if _exit is True:
                    break
                time.sleep(0.3)
            except:
                pass
        occurence += 1
    return _exit

def wait(interval_secs):
    time.sleep(interval_secs)

def get_all_templates_in_directory(_path):
    result_templates = []
    list_dir = os.listdir(_path)
    for element in list_dir:
        if element.endswith(".png"):
            if _path.endswith("/"):
                result_templates.append(_path + element)
            else:
                result_templates.append(_path + "/" + element)

    return result_templates

def fuzzy_match(string1, string2, threshold=None):
    import difflib
    # logging.info("(found: %s - wanted: %s)", str(string1), str(string2))
    # logging.info(str(difflib.SequenceMatcher(None, string1, string2).ratio()))
    if difflib.SequenceMatcher(None, string1, string2).ratio() >= threshold:
        # stbt.draw_text("FOUND: " + "'" + string1 + "'", duration_secs=4)
        return True
    else:
        # stbt.draw_text("NOT FOUND: " + "'" + string2 + "'", duration_secs=4)
        return False
        # return difflib.SequenceMatcher(None, string1, string2).ratio() >= threshold

def crop(frame, region, file_name):
    frame_region = stbt.Region(x=0, y=0, width=frame.shape[1], height=frame.shape[0])
    region = stbt.Region.intersect(frame_region, region)
    stbt.save_frame(frame[region.y:region.bottom, region.x:region.right], file_name + ".png")

def get_text(region, frame=None, menu_text=None, threshold=None, mode=stbt.OcrMode.PAGE_SEGMENTATION_WITHOUT_OSD,
             tesseract_user_patterns=None, text_color=None, lang="eng"):
    """
    get_text, core, read text with ocr and compared with menu_text
    region: region where to detect the reference text
    Frame: None or disable parameter ==> detect frame automatically in real time

    """
    if threshold is None:
        threshold = stbt.get_config("core", "fuzzy_threshold", type_=float)

    text = stbt.ocr(frame=frame, region=region, mode=mode, lang=lang,
                    tesseract_user_patterns=tesseract_user_patterns, text_color=text_color)
    if menu_text is None:
        return text
    else:
        if not(isinstance(menu_text, str)):
            menu_text = menu_text.encode("utf-8")
        else:
            menu_text  = unicode(menu_text, "utf-8")
        return fuzzy_match(text, menu_text, threshold)

def is_text(region, frame=None, threshold=None, mode=stbt.OcrMode.PAGE_SEGMENTATION_WITHOUT_OSD,
             tesseract_user_patterns=None, text_color=None, lang="eng", timeout=7):
    """
    is_text: get text
    :return: True when text is not empty
    """
    if threshold is None:
        threshold = stbt.get_config("core", "fuzzy_threshold", type_=float)
    start_time = time.time()
    while time.time() - start_time < timeout:
        text = get_text(frame=frame,
                        threshold=threshold,
                        region=region,
                        mode=mode,
                        text_color=text_color,
                        tesseract_user_patterns=tesseract_user_patterns,
                        lang=lang)
        if text != "":
            debug("Text is not empty")
            return text
    assert False, "Empty text"

def ocr_until(region, menu_text, threshold, timeout, interval_secs, text_color=None,
              mode=stbt.OcrMode.PAGE_SEGMENTATION_WITHOUT_OSD,
              tesseract_user_patterns=None, lang="eng", filter=False):
    """
    ocr_until, core, implements get_text until found text or timeout

    region: region where to detect the reference text
    menu_text:  reference string used to refer to the menu

    """
    if filter == True:

        if filter_template(thresh_value=None,
                           callable=lambda: stbt.wait_until(lambda: get_text(region=region,
                                                                             frame=stbt.load_image("end_frame.png"),
                                                                             menu_text=menu_text,
                                                                             threshold=threshold,
                                                                             mode=mode,
                                                                             tesseract_user_patterns=tesseract_user_patterns,
                                                                             text_color=text_color,
                                                                             lang=lang),
                                                            timeout_secs=timeout,
                                                            interval_secs=interval_secs)):
            debug("FOUND: " + "'" +str(menu_text) + "'")
            return True
        else:
            return False
    else:
        frame = None
        if stbt.wait_until(
                lambda: get_text(region, frame, menu_text, threshold, mode, tesseract_user_patterns, text_color, lang),
                timeout_secs=timeout, interval_secs=interval_secs):
            debug("FOUND: " + "'" +str(menu_text) + "'")
            return True
        else:
            debug("NOT FOUND: " + "'" + str(menu_text) + "'")
            return False

def repeat(callable, occurence=None, time_out=1000, tolerance=None, wait_=2):
    """
    repeat, core, repeat a callable

    Repeating a processing of the functions for occurrence times
    time_out: unity time of execution on the function callable
    occurence: numbers of repeat
    tolerance: time added to global time_out
    """

    if occurence is not None:
        time_out = time_out * occurence
        if tolerance is None:
            tolerance = 10 * time_out / 100

    else:
        if tolerance is None:
            tolerance = 0

    start = time.time()
    repeat_test = 0
    while time.time() - start < (time_out + tolerance):
        callable()
        wait(wait_)
        if occurence is not None:
            repeat_test += 1
            if repeat_test == occurence:
                break

def debug(msg=None, text=""):
    # Get the previous frame in the stack, otherwise it would
    # be this function!!!
    func = inspect.currentframe().f_back.f_code
    if not( isinstance(msg, str) ):
        msg=msg.encode("utf-8")
    if not( isinstance(text, str) ):
        text=text.encode("utf-8")

    #logging.info("%s: %s", msg, str(text))
    #print "%s" % inspect.stack()[1][3]
    # Dump the message + the name of this function to the log.
    message = msg + text
    logging.info("%s in %s:%i : %s " % (func.co_name, func.co_filename, func.co_firstlineno, message))
    stbt.draw_text(msg + ":" + text, duration_secs=3)

def press(press, delay_sec=2, second_press=None, hold=False):
    """
     Press key using some delay

    """
    from android import press_adb
    quad = eval(stbt.get_config("quad","quad_press"))
    adb  = eval(stbt.get_config("adb","adb_press"))
    automate = eval(stbt.get_config("bluetooth" , "automate"))
    usb_automate = stbt.get_config("bluetooth" , "usb_automate")
    ble_press = eval(stbt.get_config("ble_rcu" , "ble_press"))
    if ble_press :
        blePress(press ,delay_sec, second_press, hold)
    elif adb :
         press_adb(key=press)
    elif quad :
        quad_press(key=press)
    elif automate :
        subprocess.call(get_generic_template_path()+"/../../../trunk/tests/bleutooth/./wakeup_by_RC_multi /dev/ttyUSB"+usb_automate+" "+press+" "+str(delay_sec*10), shell=True)

    else:
        stbt.press(press, interpress_delay_secs=delay_sec)
        logging.info("Pressing %s", str(press))

_dicBlePres= { "KEY_OK" : "101001" , "KEY_POWER" : "110001" , "KEY_1" : "111001" , "KEY_2" : "100001" , "KEY_3" : "101101" , "KEY_4" : "110101",
               "KEY_5" : "111101" , "KEY_6" : "100101" , "KEY_7" : "101011" , "KEY_8" : "110011" ,  "KEY_9" : "111011" ,  "KEY_0" : "100011",
               "KEY_MUTE" : "101111"  , "KEY_UP" : "110111" , "KEY_DOWN" : "111111" , "KEY_RIGHT" : "100111" , "KEY_VOICE" : "201001",
               "KEY_LEFT" : "210001" ,  "KEY_CHANNELUP" : "211001" ,  "KEY_CHANNELDOWN" : "200001" ,  "KEY_VOLUMEDOWN" : "201101",
               "KEY_VOLUMEUP" : "210101", "KEY_BACK" : "211101" , "KEY_STOP" : "200101" , "KEY_PLAY" : "200101" , "KEY_FASTFORWARD" : "201011",
               "KEY_REWIND" : "210011", "KEY_RECORD" : "211011" , "KEY_EXIT" : "200011" , "KEY_RED" : "201111",
               "KEY_GREEN" : "210111" , "KEY_YELLOW" : "211111" , "KEY_BLUE" : "200111", "KEY_MENU" : "301001",
               "KEY_ZOOM" : "310001" , "KEY_VIDEO_NEXT" : "311001" , "KEY_VIDEO_PREV" : "300001"  }

#dictionary for mapping pin-address
#Pins reserved pin1 to pin36

 #dic_pin = { "pin1" : "101001" | "pin9" :  "101011" | "pin17" : "201001" | "pin25" : "201011" | "pin33" : "301001" | "pin41" : "301011" |
            # "pin2" : "110001" | "pin10" : "110011" | "pin18" : "210001" | "pin26" : "210011" | "pin34" : "310001" | "pin42" : "310011" |
            # "pin3" : "111001" | "pin11" : "111011" | "pin19" : "211001" | "pin27" : "211011" | "pin35" : "311001" | "pin43" : "311011" |
            # "pin4" : "100001" | "pin12" : "100011" | "pin20" : "200001" | "pin28" : "200011" | "pin36" : "300001" | "pin44" : "300011" |
            # "pin5" : "101101" | "pin13" : "101111" | "pin21" : "201101" | "pin29" : "201111" | "pin37" : "301101" | "pin45" : "301111" |
            # "pin6" : "110101" | "pin14" : "110111" | "pin22" : "210101" | "pin30" : "210111" | "pin38" : "310101" | "pin46" : "310111" |
            # "pin7" : "111101" | "pin15" : "111111" | "pin23" : "211101" | "pin31" : "211111" | "pin39" : "311101" | "pin47" : "311111" |
            # "pin8" : "100101" | "pin16" : "100111" | "pin24" : "200101" | "pin32" : "200111" | "pin40" : "300101" | "pin48" : "300111" }

def setCommand(frame_key, init_frame="000000000000000"):
    """
    setCommand: configure frame key
    :param frame_key: frame key
    :return: new frame configured
    """
    # logging.info("Frame BLE %s", frame_key)

    if frame_key[0]=="1":
        key = frame_key[1:]+ init_frame[5:]

    elif frame_key[0]=="2":
        key = init_frame[:5] + frame_key[1:]+ init_frame[10:]

    elif frame_key[0]=="3":
        key = init_frame[:10] + frame_key[1:]

    else:
        return frame_key
    return key

def blePress(press, delay_sec, second_press, hold):
    """
    blePress: unit function to press with ble rcu
    :param press: keyt press
    :param delay_sec:  delay seconds between press
    :param second_press: the second press
    :param hold: enable hold press
    :return:
    """
    uart = stbt.get_config("ble_rcu", "uart")
    device = stbt.get_config("ble_rcu", "device")

    press_frame_init = _dicBlePres.get(press)
    press_frame = setCommand(press_frame_init)

    if second_press is not None:
        second_press_frame = _dicBlePres.get(second_press)
        second_press_frame = setCommand(second_press_frame)
        press_frame = setCommand(press_frame_init,second_press_frame)

    press_frame = uart + press_frame + "1"

    os.system("stty -F "+device+" 9600 cs8 -cstopb -parenb")

    subprocess.call("echo -e '"+press_frame+"' >"+device+"", shell=True)
    if second_press is not None:
        press = press+"+"+second_press
    logging.info("Pressing BL %s", press)
    stbt.draw_text(press)

    if hold:
        wait(delay_sec)

    subprocess.call("echo -e '00000000000000000' >"+device+"" , shell=True)

def quad_press(key):
    # Take the path of the valid folders
    dir_path = get_generic_template_path()+'/../../../trunk/_sc_stbt/'
    INTERPRESS_DELAY_SECS=0.3
    #Check the STB id on config file
    stb_id=stbt.get_config("quad","stb-id")
    logging.info("Pressing %s", str(press))
    #Printing the remote commands on the fifo file
    with open(dir_path + '/ir_commands', 'w') as fifo:
        ir_commands = "{} ".format(stb_id) + key + "\n"
        print ("Sending : " + ir_commands)
        fifo.write(ir_commands)
        fifo.flush()
        fifo.close()
        time.sleep(INTERPRESS_DELAY_SECS)
        stbt.draw_text(key)
        logging.info("Pressing %s", str(key))

def combo_press(combo=None, delay_sec=2, number_press=None):
    """
    combo_press ; press combo list press
    """
    if number_press is None:
        for i in range(0, len(combo)):
            press(combo[i], delay_sec=delay_sec)
    else:
        for j in range(number_press):
            for i in range(0, len(combo)):
                press(combo[i], delay_sec=delay_sec)

def get_generic_template_path():
    path = os.environ.get('STBT_PROJECT_PATH')
    return path

def write_statut_test(statut):
    """

    :return:
    """
    import os
    config_file = os.environ.get('STBT_CONFIG_FILE_CUSTOM')

    command = "sed -i -e 's,^'state' =.*,'state' = '" + statut + "',' " + config_file

    os.system(command)

def get_statut_test(message):
    """

    :return:
    """
    state = stbt.get_config("global", "state")
    if state == "test_ko":
        assert False, 'TEST IS BLOCKED: %s' % message

def write_statut_boot_test(statut):
    """

    :return:
    """
    import os
    config_file = os.environ.get('STBT_CONFIG_FILE_CUSTOM')

    command = "sed -i -e 's,^'boot_state' =.*,'boot_state' = '" + statut + "',' " + config_file

    os.system(command)

def get_statut_boot_test(message):
    """

    :return:
    """
    state = stbt.get_config("global", "boot_state")
    if state == "test_ko":
        assert False, 'TEST IS BLOCKED: %s' % message

list_timer = []

def timer(region_current_timer,
          region_end_timer,
          timer_value=False,
          press="KEY_UP",
          wait_after_press=1):
    """

    :param timer_value:
    :return:
    """
    import re
    global list_timer
    check_current_time = None
    check_end_time = None
    check_end_time2 = None
    list_timer.__init__()
    current_time = ''
    end_time = ''
    start_time = time.time()
    while (check_current_time is None and (
            check_end_time is None or check_end_time2 is None)) and time.time() - start_time < 5:
        # Read current time & end time
        current_time = get_text(region=region_current_timer,
                                mode=stbt.OcrMode.SINGLE_WORD,
                                tesseract_user_patterns=[r'\d\d\d\d\d']).replace(" ", "")
        end_time = get_text(region=region_end_timer,
                            mode=stbt.OcrMode.SINGLE_WORD,
                            tesseract_user_patterns=[r'\d\d\d\d\d']).replace(" ", "")

        # delete all caracteres only 0-9
        current_time = re.sub(r"[^0-9:]+", '', current_time)
        end_time = re.sub(r"[^0-9:]+", '', end_time)
        # check if current_time and end_time content a  right time format

        check_current_time = re.match(r"\d?\:?\d+\d?:\d+\d+", current_time)
        check_end_time = re.match(r"\d+\d?\:+\d+\d?", end_time)
        check_end_time2 = re.match(r"\d+\:+\d+\d?\:+\d+\d?", end_time)

    if (check_current_time is not None) or (check_end_time is not None or check_end_time2 is not None):
        # debug("CURRENT TIME",current_time)
        # debug("END_TIME",end_time)
        if timer_value:
            list_timer.append(current_time)
            list_timer.append(end_time)
        return True
    else:
        import sc_stbt
        if press is None:
            return False
        else:
            sc_stbt.press(press)
            wait(wait_after_press)
            return False

def get_timer_value(region_current_timer,
                    region_end_timer,
                    timer_value=True,
                    press="KEY_UP",
                    wait_after_press=1):
    """
    get_timer_value: get timer
    :return:
    """
    if timer(region_current_timer=region_current_timer,
             region_end_timer=region_end_timer,
             timer_value=timer_value,
             press=press,
             wait_after_press=wait_after_press):
        return list_timer
    else:
        assert False, "timer not detected"

def filter_template(thresh_value=None, callable=None):
    """

    :return:
    """
    stbt.save_frame(stbt.get_frame(), 'start_frame.png')
    img = cv2.imread('start_frame.png', 0)
    # create a CLAHE object (Arguments are optional).
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
    cl1 = clahe.apply(img)
    cv2.imwrite('clahe.png', cl1)

    # binarisation
    im_gray = cv2.imread('clahe.png', cv2.CV_LOAD_IMAGE_GRAYSCALE)
    (thresh, im_bw) = cv2.threshold(im_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    debug("Thresh detected:", str(thresh))
    if thresh_value is not None:
        thresh_compter = thresh_value
    else:
        thresh_compter = thresh
    if callable is None:
        debug("callable none")
        im_bw_1 = cv2.threshold(im_gray, thresh_compter, 255, cv2.THRESH_BINARY)[1]
        cv2.imwrite('end_frame.png', im_bw_1)
        debug("save end_frame with filter")
        return True
    else:
        while thresh_compter < 255:
            im_bw_1 = cv2.threshold(im_gray, thresh_compter, 255, cv2.THRESH_BINARY)[1]
            # cv2.imwrite('end_frame.png',im_bw_1)
            stbt.save_frame(im_bw_1, 'end_frame.png')
            thresh_compter += 10
            debug("Thresh", str(thresh_compter))
            if callable():
                return True
    return False

def write_technical_information(callable):
    """
    write_technical_information: this function write in file.txt the technical information
    :param callable: it is a function wish return two parametres: UI and MW
    :return: True if
    """
    ui_version, mw_version = callable()
    if ui_version and mw_version is not None:
        file = open('technical_information.txt', 'a')
        printinfo = "UI:" + ui_version + '\n' "MW:" + mw_version + '\n'
        file.write(printinfo.encode('utf8'))
        file.close()
        return True
    else:
        return False

def convert_mask_to_regions(path_mask):
    """
    Function: convert a mask to list of regions
    :param path_mask:
    :return: list of regions if mask contain white spaces
             None if passed mask is black screen
    """
    mask = cv2.imread(path_mask, cv2.CV_LOAD_IMAGE_GRAYSCALE)
    regions_list = []
    contours, hierarchy = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    for contour in contours:
        if cv2.contourArea(contour) > 0:
            [x, y, width, height] = cv2.boundingRect(contour)
            region = stbt.Region(x=x, y=y, width=width, height=height)
            regions_list.append(region)

    if regions_list:
        return regions_list
    else:
        return None

def play_voice_command(command = None, android_ = None):
    """
    play_voice_command
    :return:
    """
    if android_ is None :

       android_ = eval(stbt.get_config("voice","android"))

    if android_ :
       voice_path= get_generic_template_path() + "/../../../android/tests/templates"
    else :
       voice_path= get_generic_template_path()

    command_=command.replace(" ","_")
    voice_path=(voice_path+"/../voice_templates/"+command_+".mp3")
    empty_path=(get_generic_template_path() + "/../../../android/tests/voice_templates/empty.mp3")
    # os.system("cvlc --play-and-exit "+empty_path)   #old api take much time in execution
    # os.system("cvlc --play-and-exit "+voice_path)   #old api take much time in execution
    os.system("mpg123  "+empty_path) #new api take less time in execution
    os.system("mpg123  "+voice_path) #new api take less time in execution

def press_voice_command(device=None, android_=True, port_voice=None ,press_time=None):
    """
    press_voice_command
    :param device:
    :param android_:
    :param port_voice:
    :param press_time:
    :return:
    """

    from android import remote_ATV_press,press_adb

    if port_voice is None :
       port_voice = stbt.get_config("voice", "port_voice")
    if press_time is None :
       press_time = stbt.get_config("voice", "press_time")

    debug("waiting for key voice")
    if device is None :
        usb_automate = stbt.get_config("bluetooth", "usb_automate")
        subprocess.call(get_generic_template_path()+"/../../../android/tests/bluetooth/./wakeup_by_RC_multi /dev/ttyUSB"+usb_automate+" "+port_voice+" "+press_time, shell=True)
    else :
        remote_ATV_press("KEY_VOICE")

    if android_ :
        if wait_for_many_match(get_all_templates_in_directory(get_generic_template_path()+ "/../../../android/tests/templates/voice/" ),
                                                 region=eval(stbt.get_config("voice","logo_voice")),
                                                 timeout_secs=10):
            debug("Key voice pressed")
        else :
            assert False , "No Key Voice"
    else:
        if wait_for_many_match(get_all_templates_in_directory(get_generic_template_path()+ "/voice/" ),
                                                 region=eval(stbt.get_config("voice","logo_voice")),
                                                 timeout_secs=10):
            debug("Key voice pressed")
        else :
            assert False , "No Key Voice"

def voice_command(callable=None, command=None, device=None, port_voice=None, press_time=None, android_= None,wait_ = 5,threshold = 0.8):
    """
    Press on KEY_VOICE and command the box then check if the callable is done
    :return: True when the command is excecuted , False if not
    """
    press_voice_command(device ,android_ , port_voice , press_time)
    wait(1)
    play_voice_command(command , android_)

    if stbts.match_text(text=command,region=eval(stbt.get_config("voice","region_command")) ,threshold=threshold, timeout_secs=5):
        debug("Your command is "+ command)
    else:
        assert False, "Your request is not considered"
    wait(wait_)
    if callable is None :
        pass
    else :
        if callable():
            return True, " OK  voice command executed "
        else:
            assert False ," FAIL  voice command NOT executed "

def multi_threading(callable_1, callable_2, callable_3=None, callable_4=None):
    """
    multi_threading:  run 4 API in parallel
    :param callable_1: API 1
    :param callable_2: API 2
    :param callable_3: API 3
    :param callable_4: API 4
    :return:
    """
    if callable_3 is None and callable_4 is None:
        pool = ThreadPool(processes=2)
        pool.map(apply, [callable_1, callable_2])
        pool.terminate()

    if (callable_3 is not None or callable_4 is not None) and (callable_3 is None or callable_4 is None):
        pool = ThreadPool(processes=3)
        pool.map(apply, [callable_1, callable_2, callable_3])
        pool.terminate()

    if callable_3 is not None and callable_4 is not None:
        pool = ThreadPool(processes=4)
        pool.map(apply, [callable_1, callable_2, callable_3, callable_4])
        pool.terminate()


import asyncio
import functools

import aiohttp
import aiohttp_jinja2

import aio.http.server

import logging
log = logging.getLogger("aio.web")
apps = {}

def template(*la, **kwa):
    """
    calls handler
    - hander can return a response object or context
    - if response object, response is returned
    - else the the template is rendered
    """
    app_key = kwa.get("app_key", aiohttp_jinja2.APP_KEY)
    encoding = kwa.get("encoding", 'utf-8')
    status = kwa.get("status", 200)

    try:
        template_name = la[0]
        assert(isinstance(template_name, str))
    except (IndexError, AssertionError):
        raise TypeError(
            "Template decorator must specify template: %s" % la[0])

    def wrapper(func):

        @asyncio.coroutine
        @functools.wraps(func)
        def wrapped(*la, **kwa):
            try:
                request = la[0]
                assert(isinstance(
                    request, aiohttp.web.Request))
            except (IndexError, AssertionError):
                raise TypeError(
                    "Template handler (%s) should be called with " % func
                    + "a request object, got: %s %s" % (type(la[0]), la[0]))

            if asyncio.iscoroutinefunction(func):
                coro = func
            else:
                coro = asyncio.coroutine(func)

            try:
                context = yield from coro(*la)
            except Exception as e:
                import traceback
                traceback.print_exc()
                log.error("Error calling template handler: %s" % e)
                raise e

            if isinstance(context, aiohttp.web.StreamResponse):
                return context

            try:
                response = aiohttp_jinja2.render_template(
                    template_name, request, context,
                    app_key=app_key,
                    encoding=encoding)
                response.set_status(status)
            except Exception as e:
                import traceback
                traceback.print_exc()
                log.error("Error calling template (%s): %s" % (
                    template_name, e))
                raise e
            return response
        return wrapped
    if len(la) == 1 and callable(la[0]):
        return wrapper(la[0])
    return wrapper

def fragment(*la, **kwa):
    app_key = kwa.get("app_key", aiohttp_jinja2.APP_KEY)

    template_name = None
    if isinstance(la[0], str):
        template_name = la[0]

    def wrapper(func):

        @asyncio.coroutine
        @functools.wraps(func)
        def wrapped(*la, **kwa):
            try:
                request = la[0]
                assert(isinstance(
                    request, aiohttp.web.Request))
            except (IndexError, AssertionError):
                raise TypeError(
                    "Fragment handler (%s) should be called with " % func
                    + "a request object, got: %s %s" % (type(la[0]), la[0]))

            if asyncio.iscoroutinefunction(func):
                coro = func
            else:
                coro = asyncio.coroutine(func)

            try:
                context = yield from coro(*la)
            except Exception as e:
                import traceback
                traceback.print_exc()
                log.error("Error calling fragment handler: %s" % e)
                raise e

            if isinstance(context, str):
                return context

            if not isinstance(context, dict):
                error_message = (
                    "Fragment handler (%s) should return a string " % func
                    + "or context dictionary, got: %s %s" % (
                        type(context), context))
                log.error(error_message)
                raise TypeError(error_message)

            if not template_name:
                error_message = (
                    "Fragment handler (%s) should specify a template" % func
                    + " or return a string")
                log.error(error_message)
                raise TypeError(error_message)

            try:
                response = aiohttp_jinja2.render_string(
                    template_name, request, context,
                    app_key=app_key)
            except Exception as e:
                import traceback
                traceback.print_exc()
                log.error("Error calling fragment (%s): %s" % (
                    template_name, e))
                raise e
            return response
        return wrapped
    if len(la) == 1 and callable(la[0]):
        return wrapper(la[0])
    return wrapper

# this needs to be done after fragment is defined
from aio.web.page import fragments
fragments = fragments

class View(object):

    def __init__(self, request, template_name=None,
                 app_key=None, encoding=None, status=None,
                 context=None):
        self.request = request
        self._template = template_name
        self._app_key = app_key
        self._encoding = encoding
        self._status = status
        self._context = context or {}
        self._responder = None

    def get_template(self):
        return self._template

    def set_template(self, template_name):
        self._template = template_name

    def get_encoding(self):
        return self._encoding or "utf-8"

    def set_encoding(self, encoding):
        self._encoding = encoding

    def get_status(self):
        return self._status or 200

    def get_app_key(self):
        return self._app_key or aiohttp_jinja2.APP_KEY

    def get_context(self):
        return self._context

    def set_context(self, context):
        self._context = context

    def update_context(self, context):
        self._context.update(context)

    def get_responder(self):
        return self._responder or aiohttp_jinja2.render_template

    def get_response_args(self):
        return (
            self.get_template(),
            self.request,
            self.get_context())

    def get_response_kwargs(self):
        return dict(
            app_key=self.get_app_key(),
            encoding=self.get_encoding())

    @asyncio.coroutine
    def handle_request(self, request):
        pass

    @asyncio.coroutine
    def handle_success(self):
        try:
            response = self.get_responder(
                *self.get_responder_args(),
                **self.get_responder_kwargs())
            response.set_status(self.get_status())
        except Exception as e:
            return self.handle_error(e)
        return response

    @asyncio.coroutine
    def handle_error(self, e):
        import traceback
        traceback.print_exc()
        log.error("Error calling view (%s): %s" % (
            self, e))
        raise e

    @asyncio.coroutine
    def respond(self, context=None):
        self.update_context(context or {})
        try:
            yield from self.handle_request(self.request)
            return (yield from self.handle_success())
        except Exception as e:
            return (yield from self.handle_error(e))

class FormView(View):

    def get_redirect_url(self):
        return self._redirect_url

    def get_success_template(self):
        return self._success_template

    def get_form_class(self):
        return self._form_class

    def set_form_class(self, form_class):
        self._form_class = form_class

    def get_form(self):
        return self.get_form_class(
            *self.get_form_args(),
            **self.get_form_kwargs())

    def get_form_args(self):
        return self.reqest.post,

    def get_form_kwargs(self):
        return {}

    @asyncio.coroutine
    def handle_request(self, request):
        if request.post:
            try:
                yield from self.get_form().post(
                    *self.get_form_args(),
                    **self.get_form_kwargs())
            except Exception as e:
                yield from self.handle_error(e)

    @asyncio.coroutine
    def handle_form_success(self):
        if self.get_redirect_url():
            return aio.http.server.redirect(
                self.get_redirect_url())
        elif self.get_success_template():
            self.set_template(
                self.get_success_template())
        try:
            response = self.get_responder(
                *self.get_responder_args(),
                **self.get_responder_kwargs())
            response.set_status(self.get_status())
        except Exception as e:
            return self.handle_error(e)
        return response

    @asyncio.coroutine
    def handle_form_failure(self):
        # set any errors on the context here...
        try:
            response = self.get_responder(
                *self.get_responder_args(),
                **self.get_responder_kwargs())
            response.set_status(self.get_status())
        except Exception as e:
            return self.handle_error(e)
        return response

    @asyncio.coroutine
    def handle_success(self):
        if self.get_form().errors:
            return (yield from self.handle_form_failure())
        else:
            return (yield from self.handle_form_success())

def view(*la, **kwa):
    """
    calls handler
    - hander can return a response object or context
    - if response object, response is returned
    - else the the template is rendered
    """
    app_key = kwa.get("app_key", aiohttp_jinja2.APP_KEY)
    encoding = kwa.get("encoding", 'utf-8')
    status = kwa.get("status", 200)

    try:
        template_name = kwa.get("template_name", la[0])
        assert(isinstance(template_name, str))
    except (IndexError, AssertionError):
        raise TypeError(
            "Template decorator must specify template: %s" % la[0])

    view_class = kwa.get('view', View)

    def wrapper(func):

        @asyncio.coroutine
        @functools.wraps(func)
        def wrapped(*la, **kwa):
            try:
                request = la[0]
                assert(isinstance(
                    request, aiohttp.web.Request))
            except (IndexError, AssertionError):
                raise TypeError(
                    "Template handler (%s) should be called with " % func
                    + "a request object, got: %s %s" % (type(la[0]), la[0]))

            if asyncio.iscoroutinefunction(func):
                coro = func
            else:
                coro = asyncio.coroutine(func)

            try:
                view = view_class(la[0], template_name=template_name)
                return (yield from coro(view, *la[1:]))
            except Exception as e:
                import traceback
                traceback.print_exc()
                log.error("Error calling template handler: %s" % e)
                raise e

            return view

        return wrapped
    if len(la) == 1 and callable(la[0]):
        return wrapper(la[0])
    return wrapper


"""
Python wrapper and related helpers for directed_network using proxy widgets.
"""

from jp_doodle import doodle_files, dual_canvas, nd_frame, data_tables, svg_translation
from jp_doodle.dual_canvas import clean_dict
import jp_proxy_widget
import csv
from IPython.display import display, HTML
import numpy as np

directed_network_js = doodle_files.vendor_path("js/directed_network.js")
gd_graph_js = doodle_files.vendor_path("js/gd_graph.js")
additional_js = [gd_graph_js, directed_network_js]

class Network_Widget(jp_proxy_widget.JSProxyWidget, dual_canvas.SaveImageMixin):

    "Wrapper for an nd-scatter structure."

    def __init__(self, config=None, display=False, *pargs, **kwargs):
        "Create a canvas drawing area widget."
        super(Network_Widget, self).__init__(*pargs, **kwargs)
        data_tables.widen_notebook()
        nd_frame.load_requirements(self, additional=additional_js)
        if config is None:
            config = {}
        self.js_init("""
            element.empty();
            element.d_network = element.directed_network(config);
        """, config = config)
        self.file_path = "Network.png"
        self.svg_path = "Network.svg"
        self.customize()
        if display:
            self.display_all()

    def customize(self):
        """
        Add special user interface elements for Jupyter.
        """
        # add a button to save as PNG image
        self.js_init("""
            debugger;
            var d_network = element.d_network;
            var list_buttons = d_network.side_lists;

            var save_png_click = function() {
                save_png(element.png_path_input.val())
            };

            d_network.add_button("save as PNG", list_buttons, save_png_click);

            element.png_path_input = $('<input type="text" value="' + path + '">').appendTo(list_buttons);

            element.png_path_input.change(
                function () {
                    set_path(element.png_path_input.val());
                }
            );

            var save_svg_click = function() {
                debugger;
                var file_path = element.svg_path_input.val();
                save_svg(file_path)
            };

            d_network.add_button("save as SVG", list_buttons, save_svg_click);

            element.svg_path_input = $('<input type="text" value="' + svg_path + '">').appendTo(list_buttons);
        """, save_png=self.save_png, set_path=self.set_path, path=self.file_path,
            save_svg = self.save_svg, svg_path = self.svg_path)

    def display_all(self):
        self.element.d_network.display_all()

    def node(
        self,
        node_name,
        color=None,
        background=None,
        font=None,
        position=None,
        **other_args
        ):
        if position is not None:
            if type(position) is not dict:
                (x, y) = position
                position = {"x": x, "y": y}
        s = clean_dict(color=color, background=background, font=font, position=position)
        s.update(other_args)
        self.element.d_network.node(node_name, s)

    def edge(
        self,
        source_name,
        destination_name,
        weight=1,
        color=None,
        lineWidth=None,
        lineDash=None,
        **other_args
        ):
        s = clean_dict(color=color, lineWidth=lineWidth, lineDash=lineDash)
        s.update(other_args)
        self.element.d_network.edge(source_name, destination_name, weight, s)

    def set_path(self, path):
        self.file_path = path

    def save_png(self, file_path=None):
        if file_path is None:
            file_path = self.file_path
        self.clear_information()
        self.inform("Attempting to save as " + repr(file_path))
        def after():
            self.inform("Saved image " + repr(file_path))
        def error(e):
            self.inform("Image save failed.")
            self.inform("Exception: " + repr(e))
        self.save_pixels_to_png_async(
            file_path,
            canvas_element="element.d_network.canvas_element",
            after=after, error=error)

    def save_svg(self, file_path = None):
        self.clear_information()
        self.inform("Save svg click: " + repr(file_path))
        if file_path is None:
            file_path = self.svg_path
        self.inform("Attempting to save SVG as " + repr(file_path))
        try:
            canvas_raw_info = self.element.d_network.canvas_element.get_raw_draw_information().sync_value(level=5)
        except Exception as e:
            self.inform ("Could not get drawing information " + repr(e))
            raise e
        self.inform("Got drawing information.")
        try:
            self.inform("Converting...")
            svg_format = svg_translation.interpret_dump(canvas_raw_info)
        except Exception as e:
            self.inform("Could not convert to SVG: " + repr(e))
            raise e
        try:
            svg_file = open(file_path,"w")
            txt = svg_format.to_svg_text()
            self.inform("got svg text " + str(repr(type(txt))))
            svg_file.write(txt)
            svg_file.close()
            self.inform("Wrote to file: " + repr(file_path) + " " + str(len(txt)))
        except Exception as e:
            self.inform("failed to write " + repr((file_path, e)))
            raise e

    def clear_information(self):
        self.element.d_network.clear_information()

    def inform(self, message):
        self.element.d_network.inform(message)

def graph(
        network_json=None,
        canvas_size=500,
        info_height=150,
        selector_size=90,
        sidebar_size=150,
        gap=10,
        min_color="#00f",
        min_threshold_color="#aaa",
        max_threshold_color="#bbb",
        max_color="orange",
        default_layout="grid",  # or "relax" or "skeleton"
        separator_radius=6,
        link_radius=1,
        min_change=1,
        undo_limit=10,
        font="normal 10px Arial",  # default node font
        color="#999", # default node font
        shape="text", # or "circle", "rect"
        radius=4,  # radius for circle or rect
        background=None,  # default node background
        src_font=None,  # overrides for src nodes
        src_color=None,
        src_background=None,
        src_shape=None,
        src_radius=None,
        **other_attributes
    ):
    s = clean_dict(
        network_json=network_json,
        canvas_size=canvas_size,
        info_height=info_height,
        selector_size=selector_size,
        sidebar_size=sidebar_size,
        gap=gap,
        min_color=min_color,
        min_threshold_color=min_threshold_color,
        max_threshold_color=max_threshold_color,
        max_color=max_color,
        default_layout=default_layout,  # or "relax" or "skeleton"
        separator_radius=separator_radius,
        link_radius=link_radius,
        min_change=min_change,
        undo_limit=undo_limit,
        font=font,
        color=color,
        background=background,
        shape=shape,
        radius=radius,
        src_font=src_font,
        src_color=src_color,
        src_background=src_background,
        src_shape=src_shape,
        src_radius=src_radius,
    )
    s.update(other_attributes)
    return Network_Widget(s)


# КОД ОБРАЩЕНИЯ НА ЛЕНДИНГИ

import urllib.request
from bs4 import BeautifulSoup

response = urllib.request.urlopen("https://noukash.com/intensive").read().decode('utf-8')

soup = BeautifulSoup(response, "html.parser")
text = soup.body.get_text().strip()

if "Ниже форма предзаписи" in text:
    print('Предзапись ещё открыта')

# Код взят тут:  https://stackoverflow.com/questions/27803503/get-html-using-python-requests

# КОД УВЕДОМЛЕНИЙ

import os

command = f'''notify-send'''
os.system(command)


import tensorflow as tf
import tensorflow.contrib.slim as slim
import numpy as np
import random
import os

import Perception
import Reward

class Qnetwork():
    def __init__(self, frame_height, frame_width, frame_channels, num_stacked_frames, total_num_actions):
        flattened_frame_size = frame_height*frame_width*frame_channels*num_stacked_frames
        self.flattened_image = tf.placeholder(shape=[None, flattened_frame_size], dtype=tf.float32)
        #[batch, in_height, in_width, in_channels]
        #[filter_height, filter_width, in_channels, out_channels]
        # Must have strides[0] = strides[3] = 1. For the most common case of the same horizontal and vertices strides, strides = [1, stride, stride, 1].

        self.state_feature_vector, self.CNN_params = Perception.CNN(input=self.flattened_image,height=frame_height,width=frame_width,in_channel=frame_channels*num_stacked_frames,out_channel=128,weights=[])

        #NOTE :::: Split is not really required, also even if you use split, it should be done on the dimension of feature maps. Also the weight matrices have to be correctly shaped.
        with tf.variable_scope("advantage_stream"):
            self.streamAC = self.state_feature_vector
            self.streamA = tf.contrib.layers.flatten(self.streamAC)
            xavier_init = tf.contrib.layers.xavier_initializer(seed=8739)
            self.AW1 = tf.Variable(xavier_init([self.streamA.shape[1].value, 512]), name='FC_1_Weights')
            self.ABias1 = tf.Variable(tf.constant(0.1, shape=[512]), name='FC_1_Bias')
            self.Advantage_FC1 = tf.matmul(self.streamA, self.AW1) + self.ABias1
            self.Advantage_FC1 = tf.nn.relu(self.Advantage_FC1)
            xavier_init = tf.contrib.layers.xavier_initializer(seed=8536)
            self.AW2 = tf.Variable(xavier_init([self.Advantage_FC1.shape[1].value, total_num_actions]), name='FC_2_Weights')
            self.ABias2 = tf.Variable(tf.constant(0.1, shape=[total_num_actions]), name='FC_2_Bias')
            self.Advantage = tf.matmul(self.Advantage_FC1, self.AW2) + self.ABias2
            self.advantage_w = [self.AW1, self.ABias1,self.AW2,self.ABias2]
        with tf.variable_scope("value_stream"):
            self.streamVC = self.state_feature_vector
            self.streamV = tf.contrib.layers.flatten(self.streamVC)
            xavier_init = tf.contrib.layers.xavier_initializer(seed=8635)
            self.VW1 = tf.Variable(xavier_init([self.streamV.shape[1].value, 512]), name='FC_1_Weights')
            self.VBias1 = tf.Variable(tf.constant(0.1, shape=[512]), name='FC_1_Bias')
            self.Value_FC1 = tf.matmul(self.streamV, self.VW1) + self.VBias1
            self.Value_FC1 = tf.nn.relu(self.Value_FC1)
            xavier_init = tf.contrib.layers.xavier_initializer(seed=8267)
            self.VW2 = tf.Variable(xavier_init([self.Value_FC1.shape[1].value, 1]), name='FC_2_Weights')
            self.VBias2 = tf.Variable(tf.constant(0.1, shape=[1]), name='FC_2_Bias')
            self.Value = tf.matmul(self.Value_FC1, self.VW2) + self.VBias2
            self.value_w = [self.VW1,self.VBias1,self.VW2,self.VBias2]
        # NOTE ::: Add the state value and advantage value to get the q values but note that we subtract the average advantage value from advantage value of all actions.
        self.Qout = self.Value + tf.subtract(self.Advantage, tf.reduce_mean(self.Advantage, axis=1, keep_dims=True))
        # NOTE :: we take argmax over advantage values instead of Q values
        self.predict = tf.argmax(self.Advantage, 1)

        # Below we obtain the loss by taking the sum of squares difference between the target and prediction Q values.
        self.targetQ = tf.placeholder(shape=[None], dtype=tf.float32)
        self.actions = tf.placeholder(shape=[None], dtype=tf.int32)
        self.actions_onehot = tf.one_hot(self.actions, total_num_actions, dtype=tf.float32)

        self.Q = tf.reduce_sum(tf.multiply(self.Qout, self.actions_onehot), axis=1)

        self.td_error = tf.square(self.targetQ - self.Q)
        self.loss = tf.reduce_mean(self.td_error)
        network_scope_name = tf.get_variable_scope().name
        if(network_scope_name=='Q_main'):
            Q_vars = self.advantage_w + self.value_w
            self.optimizer = tf.train.AdamOptimizer(learning_rate=0.0004, name='main_Q_network_adam_opt')
            self.gvs_Q = self.optimizer.compute_gradients(self.loss,var_list=Q_vars)
            with tf.variable_scope("gradient_clipping_Q_vars"):
                self.capped_gvs_Q = [(tf.clip_by_norm(grad, 10.0), var) for grad, var in self.gvs_Q]
            self.train_Q_op = self.optimizer.apply_gradients(self.capped_gvs_Q, name='Q_vars_grad_update')
            self.gvs_cnn = self.optimizer.compute_gradients(self.loss,var_list=self.CNN_params)
            with tf.variable_scope("gradient_clipping_cnn_vars"):
                self.capped_gvs_cnn = [(tf.clip_by_norm(grad, 10.0), var) for grad, var in self.gvs_cnn]
            self.train_cnn_op = self.optimizer.apply_gradients(self.capped_gvs_cnn, name='CNN_vars_grad_update')
            # self.train_op = self.optimizer.minimize(self.loss)

def target_network_update_op(Q_main_variables, Q_target_variables, tau):
    target_network_update_ops = []
    with tf.variable_scope("target_network_update_ops"):
        for main_network_var, target_network_var in zip(sorted(Q_main_variables, key=lambda v: v.name), sorted(Q_target_variables, key=lambda v: v.name)):
            #print('main var name {0}'.format(main_network_var.name))
            #print('tgt var name {0}'.format(target_network_var))
            assign_value = (main_network_var.value()*tau) + ((1 - tau)*target_network_var.value())
            update_op = target_network_var.assign(assign_value)
            target_network_update_ops.append(update_op)
        grouped_target_network_update_op = tf.group(*target_network_update_ops)
    return grouped_target_network_update_op