import os
import sys
from inaSpeechSegmenter import Segmenter
from inaSpeechSegmenter.export_funcs import seg2csv, seg2textgrid
from collections import deque
import common
import seg

logger = common.getLogger(__file__)

CONFIG_WORK_KEY = "split"

def main(input_file):
    # txtファイルに出力された無音検出結果から、音声ファイルをどのように分割するかを決定する（実際に分割はしない）
    logger.info("2-1. 音声分割設定開始 - {}".format(os.path.basename(input_file)))

    config = common.readConfig(input_file)
    if config["DEFAULT"].get(CONFIG_WORK_KEY) == common.DONE:
        logger.info("完了済みのためスキップ(音声分割設定)")
        return

    # 入力の音声ファイルのパスを指定
    logger.info("音声ファイル：{}".format(os.path.basename(input_file)))

    type = os.path.splitext(os.path.basename(input_file))[1][1:]  # 拡張子(読み込み時のフォーマット指定)

    # 分析結果ファイルを順に開く
    seg_resultfile_index = 0
    segmentation = deque()
    connect = False
    prev_fixed = False
    prev_noEnergy_length = 0  # 前回の無音部分の長さ
    prev_length = 0  # 前回の長さ
    index = 0

    logger.info("分析結果ファイル読み込み中…")

    isRecognizeNoize = common.isRecognizeNoize()
    logger.info("ノイズ部分も認識対象にするかどうか：{}".format(isRecognizeNoize))

    split_len = config["DEFAULT"].getint(
        seg.CONFIG_SEG_SPLIT, common.getSegTmpAudioLength()
    )  # 分割単位(バージョンによっては音声のiniに書いていないので、commonから取得)
    logger.info("分割単位：{}min".format(int(split_len / 60 / 1000)))

    while True:
        seg_result_file = common.getSegResultFile(input_file, seg_resultfile_index)

        # 分析結果ファイルがなければ終了
        if os.path.exists(seg_result_file) == False:
            break

        logger.info(
            "分析結果ファイル：{}({})".format(
                os.path.basename(seg_result_file), seg_resultfile_index + 1
            )
        )

        # 分析結果ファイル（タブ区切り）を開く
        with open(seg_result_file, "r") as f:
            segment_label = ""

            f.readline()  # ヘッダを読み捨て

            file_data = f.readlines()
            for line in file_data:
                segment = line.split("\t")

                index += 1
                # logger.info ("分析結果ファイル読み込み中… {}".format(index))

                segment_label = segment[0]

                # 区間の開始時刻の単位を秒からミリ秒に変換 + ファイル番号によって補正
                start_time = float(segment[1]) * 1000 + float(
                    split_len * seg_resultfile_index
                )
                end_time = float(segment[2]) * 1000 + float(
                    split_len * seg_resultfile_index
                )
                org_start_time = start_time
                org_end_time = end_time

                # 認識対象とするかどうか
                is_target = False
                if isRecognizeNoize:  # 無音区間以外を認識対象とする
                    if segment_label != "noEnergy":  # 無音区間以外なら認識対象とする（noiseなども対象）
                        is_target = True
                else:
                    if segment_label == "speech":  #  'speech' のみ認識対象とする
                        is_target = True

                if is_target:
                    if connect:  # 1つ前と連結させる
                        prev = segmentation.pop()
                        start_time = prev["start_time"]
                        org_start_time = prev["org_start_time"]
                    else:  # 今回が音がある部分の先頭
                        start_time -= min(
                            prev_noEnergy_length, 500
                        )  # 前回の無音部分の0.5秒を頭に入れる

                    connect = False
                    prev_fixed = False
                    prev_length = end_time - start_time

                    mlength = 2 * 60 * 1000  # N分ごとに区切る(これ以上長いと音声認識がエラーを返す可能性がある)
                    while True:
                        length = end_time - start_time

                        if length < mlength:
                            segmentation.append(
                                {
                                    "segment_label": segment_label,
                                    "start_time": start_time,
                                    "end_time": end_time,
                                    "org_start_time": org_start_time,
                                    "org_end_time": org_end_time,
                                }
                            )  # push(音声の末尾部分)
                            break
                        else:
                            segmentation.append(
                                {
                                    "segment_label": segment_label,
                                    "start_time": start_time,
                                    "end_time": start_time + mlength,
                                    "org_start_time": org_start_time,
                                    "org_end_time": start_time + mlength,
                                }
                            )  # push(N分)
                            start_time += mlength
                            org_start_time = start_time
                            logger.debug("length > mlength: length={}".format(length))

                else:  # 無音区間
                    length = end_time - start_time
                    prev_noEnergy_length = length
                    connect = False
                    if len(segmentation) > 0:
                        if (
                            length < 1 * 1000 and length + prev_length < 5 * 1000
                        ):  # 無音がX秒未満(息継ぎとかを無視したい)、Y秒未満の場合(長すぎにならないようにする)は、次の音声と接続させる
                            connect = True
                            logger.debug("connect. len:{}".format(length))
                        elif prev_fixed == False:
                            prev = (
                                segmentation.pop()
                            )  # 無音がX秒以上の場合は、前の音声が確定する。前の音声の終了時間を伸ばす（最後に無音がつく。最大5秒とする。5秒でいいかは微妙）⇒認識が遅くなるが、こっちの方が精度がいい
                            prev["end_time"] += min(length, 5000)
                            segmentation.append(prev)  # push
                            prev_fixed = True  # 何度も連結しないようにする
                            logger.debug(
                                "prev_fixed. {},{}".format(
                                    prev["start_time"], prev["end_time"]
                                )
                            )

        seg_resultfile_index += 1  # 次のファイルへ
        if segment_label != "noEnergy":  # 音声ありの状態でファイルが閉じた場合、次のファイルと連結させるために長さ0の無音区間を作る
            t = split_len * seg_resultfile_index
            segmentation.append(
                {
                    "segment_label": "noEnergy",
                    "start_time": t,
                    "end_time": t,
                    "org_start_time": t,
                    "org_end_time": t,
                }
            )
            logger.debug("ファイルの区切りで無音追加：{}({})".format(seg_resultfile_index, t))

    # 音声を分割する
    split_result_file = common.getSplitResultFile(input_file)
    logger.info("分割結果ファイル：{}".format(os.path.basename(split_result_file)))
    base = os.path.splitext(os.path.basename(input_file))[0]  # 拡張子なしのファイル名（話者）

    with open(split_result_file, "w") as f:  # 分割結果ファイルに結果書き込み+音声書き込み
        speech_segment_index = 1
        index = 0

        # 分割して出力する音声ファイルのフォルダとプレフィックスまで指定
        audio_file_prefix = common.getSplitAudioFilePrefix(input_file)

        logger.debug("音声分割設定中… {}".format(base))

        for segment in segmentation:
            # segmentはタプル
            # タプルの第1要素が区間のラベル
            segment_label = segment["segment_label"]

            index = index + 1
            # logger.debug ("音声分割中… {}/{}".format(index, len(segmentation)))

            if (index % 100) == 0 or (
                len(segmentation) == index
            ):  # 100行ごとか、最後の1行で進捗を出す
                logger.debug(
                    "　音声分割設定中… {} {}/{}".format(base, index, len(segmentation))
                )

            if segment_label != "noEnergy":  # 無音区間以外の部分だけを出力する
                start_time = segment["start_time"]
                end_time = segment["end_time"]
                org_start_time = segment["org_start_time"]
                org_end_time = segment["org_end_time"]

                filename = "{}{}.flac".format(audio_file_prefix, speech_segment_index)

                # 分割結果の時間やファイル名など
                # ID,分割した音声ファイル名(flac),開始時間(冒頭無音あり),終了時間(末尾無音あり),長さ(無音あり),開始時間(冒頭無音なし),長さ(末尾無音なし)の順
                f.write(
                    "{}	{}	{}	{}	{}	{}	{}\n".format(
                        speech_segment_index,
                        filename,
                        start_time,
                        end_time,
                        end_time - start_time,
                        org_start_time,
                        org_end_time,
                    )
                )

                speech_segment_index += 1

    # 終了したことをiniファイルに保存
    common.updateConfig(input_file, {CONFIG_WORK_KEY: common.DONE})

    logger.info("音声分割設定終了！ {}".format(os.path.basename(input_file)))

# 直接起動した場合
if __name__ == "__main__":
    if len(sys.argv) < 2:
        logger.error("ファイルが指定されていません")
        sys.exit(1)

    main(sys.argv[1])


import gym
from code import MultiArmedBandit, QLearning
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

env = gym.make('FrozenLake-v0')

def getavg(no=1, algo=MultiArmedBandit):
    lists = []
    out = pd.DataFrame()
    for i in range((no+1)):
        agent = algo()
        action_values, rewards = agent.fit(env, steps=500)
        lists.append(rewards)
    df = pd.DataFrame(lists, columns=list(range(100)))
    return list(df.mean())

def lrl(arr):
    return list(range(len(arr)))

#guy1 = getavg(no=1, algo=MultiArmedBandit)
#guy2 = getavg(no=5, algo=MultiArmedBandit)
print("mab")
guy3 = getavg(no=10, algo=MultiArmedBandit)

#q1 = getavg(no=1, algo=QLearning)
#q5 = getavg(no=5, algo=QLearning)
print("ql")
q10 = getavg(no=10, algo=QLearning)

fig, ax = plt.subplots()

#ax.plot(lrl(guy1), guy1, c='b', label="MAB-1")
#ax.plot(lrl(guy2), guy2, c='r', label="MAB-5")
ax.plot(lrl(guy3), guy3, c='g', label="MAB-10")

#ax.plot(lrl(q1), q1, c='y', label="QL-1")
#ax.plot(lrl(q5), q5, c='k', label="QL-5")
ax.plot(lrl(q10), q10, c='m', label="QL-10")

plt.legend(loc="lower right")
ax.set(xlabel='Index', ylabel='Rewards',
       title='Problem 2B')
ax.grid()

fig.savefig("2C.png")
plt.show()


"""
"""

import phantom.rules as phantom
import json
from datetime import datetime, timedelta

##############################
# Start - Global Code Block

import requests

# End - Global Code block
##############################

def on_start(container):
    phantom.debug('on_start() called')

    # call 'promote_to_case_1' block
    promote_to_case_1(container=container)

    return

def promote_to_case_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    phantom.debug('promote_to_case_1() called')

    phantom.promote(container=container, template="responses")
    get_case_note_count(container=container)

    return

def get_case_note_count(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    phantom.debug('no_op_1() called')

    # get the container id and phantom url to format for the request
    container_id = container.get('id', None)
    phantom_url = phantom.get_base_url()
    request_url = "{}/rest/container/{}/phases".format(str(phantom_url), str(container_id))

    # make the request
    r = requests.get(request_url, auth=("admin","password"), verify=False).json()

    # check to see if all notes fields are filled out
    notes_counter = 0
    for i in r["data"][0]["tasks"]:
        phantom.debug(i)
        if i["notes"]:
            notes_counter = notes_counter + 1

    # if all the fields are filled out prompt before emailing, if not sleep and check again
    if notes_counter != 3:
        no_op_2(container=container, handle=notes_counter)
    else:
        for i in r["data"][0]["tasks"]:
            raw = {}
            cef = {}
            cef['container_note'] = i["notes"][0]["content"]

            success, message, artifact_id = phantom.add_artifact(
                container=container, raw_data=raw, cef_data=cef, label='note',
                name='container note', severity='low',
                identifier=None,
                artifact_type='note')

        prompt_1(container=container)

    return

def send_email_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    phantom.debug('send_email_1() called')

    #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))

    # collect data for 'send_email_1' call
    formatted_data_1 = phantom.get_format_data(name='format_1')

    parameters = []

    # build parameters list for 'send_email_1' call
    parameters.append({
        'body': formatted_data_1,
        'from': "",
        'attachments': "",
        'to': "niroy@splunk.com",
        'cc': "",
        'bcc': "",
        'headers': "",
        'subject': "Test Container Note",
    })

    phantom.act("send email", parameters=parameters, assets=['smtp'], name="send_email_1")

    return

def no_op_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    # handle passes count from the previous get_case_note_count

    phantom.debug('no_op_2() called')

    parameters = []

    # build parameters list for 'no_op_2' call
    parameters.append({
        'sleep_seconds': 10,
    })

    #
    if handle != 3:
        phantom.act("no op", parameters=parameters, assets=['local phantom'], callback=get_case_note_count, name="no_op_2", parent_action=action)
    else:
        prompt_1(container=container)
    return

def prompt_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    phantom.debug('prompt_1() called')

    # set user and message variables for phantom.prompt call
    user = "admin"
    message = """is there enough information to send out"""

    # response options
    options = {
        "type": "list",
        "choices": [
            "Yes",
            "No",
        ]
    }

    phantom.prompt(container=container, user=user, message=message, respond_in_mins=30, name="prompt_1", options=options, callback=decision_2)

    return

def decision_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    phantom.debug('decision_2() called')

    # check for 'if' condition 1
    matched_artifacts_1, matched_results_1 = phantom.condition(
        container=container,
        action_results=results,
        conditions=[
            ["prompt_1:action_result.summary.response", "==", "Yes"],
        ])

    # call connected blocks if condition 1 matched
    if matched_artifacts_1 or matched_results_1:
        format_1(action=action, success=success, container=container, results=results, handle=handle)
        return

    # call connected blocks for 'else' condition 2

    return

def format_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None):
    phantom.debug('format_1() called')

    template = """{0}"""

    # parameter list for template variable replacement
    parameters = [
        "artifact:*.cef.container_note",
    ]

    phantom.format(container=container, template=template, parameters=parameters, name="format_1")

    send_email_1(container=container)

    return

def on_finish(container, summary):
    phantom.debug('on_finish() called')
    # This function is called after all actions are completed.
    # summary of all the action and/or all detals of actions
    # can be collected here.

    # summary_json = phantom.get_summary()
    # if 'result' in summary_json:
        # for action_result in summary_json['result']:
            # if 'action_run_id' in action_result:
                # action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)
                # phantom.debug(action_results)

    return


"""Schemas for various badge operations"""

from typing import List
from uuid import UUID

from pydantic import BaseModel, Field, model_validator

class UpdateBadges(BaseModel):
    """Update Badges schema"""

    new_badge_names: List[str] = Field(
        ...,
        description="List of new badges to be assigned to the user",
        max_length=2,
        min_length=1,
    )
    old_badge_names: List[str] = Field(
        ...,
        description="List of badges to be updated",
        max_length=2,
        min_length=1,
    )

    @model_validator(mode="before")
    # pylint: disable=E0213
    def validate_number_of_badges_to_update(
        cls,
        values,
    ):
        """Validate the number of badges to be updated

        :param values: schema values
        :return: schema values
        """
        new_badges = values.get("new_badge_names")
        old_badges = values.get("old_badge_names")
        if len(new_badges) != len(old_badges):
            raise ValueError("Number of new badges must match the number of old badges")

        return values

class AddBadges(BaseModel):
    """Add badges schema"""

    badge_names: List[str] = Field(
        ...,
        description="List of badges to be added to the user",
        max_length=2,
        min_length=1,
    )

class DeleteBadges(BaseModel):
    """Delete badges schema"""

    badge_names: List[str] = Field(
        ...,
        description="List of badges to be deleted to the user",
        max_length=2,
        min_length=1,
    )

class BadgeSchema(BaseModel):
    """Badge schema"""

    badge_name: str = Field(None, description="Badge name")

class UserSchema(BaseModel):
    """User schema"""

    id: UUID = Field(None, description="user id")
    customer_alias: str = Field(None, description="Customer alias")
    badges: List[BadgeSchema]

    class ConfigDict:
        """Configuration for this schema class"""

        from_attributes = True


import speech_recognition as sr
from gtts import gTTS
import os

# Créez un objet recognizer
recognizer = sr.Recognizer()

# Un dictionnaire pour faire correspondre les mots aux chiffres
word_to_number = {
    'zero': '0',
    'one': '1',
    'two': '2',
    'three': '3',
    'four': '4',
    'five': '5',
    'six': '6',
    'seven': '7',
    'eight': '8',
    'nine': '9',
}

def convert_words_to_numbers(text):
    # Convertit les mots en chiffres
    words = text.split()
    converted_words = []
    for word in words:
        if word.lower() in word_to_number:
            converted_words.append(word_to_number[word.lower()])
        else:
            converted_words.append(word)
    return ' '.join(converted_words)

def get_operations():
    while True:
        with sr.Microphone() as source:
            print("Speak your operations...")
            try:
                # Enregistrez les données audio
                audio_data = recognizer.listen(source, timeout=5)
                # Convertissez la parole en texte
                text = recognizer.recognize_google(audio_data, language='en-US')
                print(f"Recognized text: {text}")  # Ajout de cette ligne pour afficher la transcription
                return text
            except sr.WaitTimeoutError:
                print("Timeout: No speech detected. Please try again.")
            except sr.UnknownValueError:
                print("Speech not recognized. Please try again.")
            except sr.RequestError as e:
                print(f"Error with the service; {e}. Please try again.")

def convert_words_to_numbers(text):
    # Convertit les mots en chiffres
    words = text.split()
    for i, word in enumerate(words):
        if word.lower() in word_to_number:
            words[i] = word_to_number[word.lower()]
    return ' '.join(words)

def calculate_results(operations):
    results = []
    # Supprimez tous les espaces et séparez les opérations par le signe "+"
    operation_list = operations.replace(" ", "").split('+')

    for operation in operation_list:
        try:
            result = eval(operation)
            results.append(result)
        except (ValueError, SyntaxError):
            print(f"Invalid operation: {operation}. Skipping it.")

    return results

def speak_results(results):
    if results:
        total_result = sum(results)
        tts = gTTS(f'Total result: {total_result}')
        tts.save("result.mp3")
        os.system("start result.mp3")
    else:
        print("No valid results to speak.")

# Programme principal
if __name__ == "__main__":
    while True:
        operations = get_operations()
        if operations:
            results = calculate_results(operations)
            speak_results(results)
        else:
            print("No valid operations detected. Please try again.")

#merci


# coding=utf-8
#!/usr/bin/python3

''' Spell corrector with several operation modes

Corrects the input text according to default mode or indicated (aspell/hunspell/symspell).
Indicates also the load and correction time.
'''

import os
import sys
import time
import json
import getopt
import bisect
import fileinput
from collections import Counter, defaultdict

import spacy
import regex
from symspellpy.symspellpy import SymSpell, Verbosity
import aspell
import hunspell

####################           MODO MANUAL           ####################

def get_tag(token):
    "Tag of `token` (word or punctuation)"
    tags = list(filter(lambda x: x[0] != '<' and x[-1] != '>' and x[0] != '@', \
                        token.tag_.split('|')))
    if token.pos_ == 'ADV':
        token_str = str(token)
        if token_str == 'agora' or token_str == 'hoje':
            tags += '|Present'
        elif token_str == 'anteontem' or token_str == 'antes' or token_str == 'ontem' \
             or token_str == 'outrora':
            tags += '|Past'
        elif token_str == 'amanhã' or token_str == 'breve':
            tags += '|Future'
    return '<' + '|'.join(tags) + '>'

def get_pos_context(before_word, word, after_word, words_freq, nlp):
    "POS and tag context of `word`"
    if before_word and after_word:
        doc = nlp(before_word + ' ' + word + ' ' + after_word)
        pos_0 = '<UNKNOWN>' if before_word not in words_freq else doc[0].pos_ + get_tag(doc[0])
        pos_1 = '<UNKNOWN>' if word not in words_freq else doc[1].pos_ + get_tag(doc[1])
        pos_2 = '<UNKNOWN>' if after_word not in words_freq else doc[2].pos_ + get_tag(doc[2])
        context_pos = pos_0 + ' ' + pos_1 + ' ' + pos_2
    elif not before_word and after_word:
        doc = nlp(word + ' ' + after_word)
        pos_1 = '<UNKNOWN>' if word not in words_freq else doc[0].pos_ + get_tag(doc[0])
        pos_2 = '<UNKNOWN>' if after_word not in words_freq else doc[1].pos_ + get_tag(doc[1])
        context_pos = '__BEGIN__ ' + pos_1 + ' ' + pos_2
    elif before_word and not after_word:
        doc = nlp(before_word + ' ' + word)
        pos_0 = '<UNKNOWN>' if before_word not in words_freq else doc[0].pos_ + get_tag(doc[0])
        pos_1 = '<UNKNOWN>' if word not in words_freq else doc[1].pos_ + get_tag(doc[1])
        context_pos = pos_0 + ' ' + pos_1 + ' __END__'
    else:
        doc = nlp(word)
        pos_1 = '<UNKNOWN>' if word not in words_freq else doc[0].pos_ + get_tag(doc[0])
        context_pos = '__BEGIN__ ' + pos_1 + ' ' + '__END__'
    return context_pos

def probability(word, original_word, words_freq, pos_freqs, n_words, before_word, after_word, nlp):
    "Probability of `word`."
    context_pos = get_pos_context(before_word, word, after_word, words_freq, nlp)
    if word in words_freq:
        freq = (words_freq[word.lower()][word] / n_words) * \
                (60 if word.lower() != original_word.lower() else 100)
    else:
        freq = 0
    if context_pos:
        pos_freq = (99 * pos_freqs.get(context_pos, 0) + 1) / sum(pos_freqs.values())
        freq = freq * pos_freq * 100
    return freq

def correction(word, words_freq, pos_freqs, n_words, before_word, after_word, nlp):
    "Most probable spelling correction for word."
    return max(candidates(word, words_freq), key=lambda x: \
               probability(x, word, words_freq, pos_freqs, n_words, before_word, after_word, nlp))

def candidates(word, words_freq):
    "Generate possible spelling corrections for word."
    return known([word], words_freq) or known(edits1(word), words_freq) \
                or known(edits2(word), words_freq) or [word]

def known(words, words_freq):
    "The subset of `words` that appear in the dictionary of WORDS."
    res = set()
    for word in words:
        if word in words_freq:
            res.update(words_freq[word].keys())
    return res

def edits1(word):
    "All edits that are one edit away from `word`."
    letters = 'aáàãâbcçdeéèêfghiíìîjklmnoóòõôpqrstuúùûvwxyz'
    splits = [(word[:i], word[i:])        for i in range(len(word) + 1)]
    deletes = [L + R[1:]                  for L, R in splits if R]
    transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R) > 1]
    replaces = [L + c + R[1:]             for L, R in splits if R for c in letters]
    inserts = [L + c + R                  for L, R in splits for c in letters]
    return set(deletes + transposes + replaces + inserts)

def edits2(word):
    "All edits that are two edits away from `word`."
    return (e2 for e1 in edits1(word) for e2 in edits1(e1))

def next_word_on_sentence(next_words):
    "Next word or punctuation on sentence."
    for word in next_words:
        if not regex.search(r'\s+', word):
            return word
    return None

def correct_line(line, pos_freqs, words_freq, nlp):
    "Corrects words on `line`."
    words = regex.findall(r'\w+|\s+|\p{P}+', line, flags=regex.UNICODE)
    new_line = ''
    flatten = lambda l: [item for sublist in l for item in sublist]
    n_words = sum(flatten(map(lambda x: x.values(), words_freq.values())))
    last_word = None
    exceptions = ['sr', 'sra', 'sras', 'dr', 'dra', 'prof']
    for i, word in enumerate(words):
        if word.isspace():
            new_line += regex.sub(r' +', ' ', word)
        elif regex.search(r'\p{P}+', word, flags=regex.UNICODE) or not word.isalpha():
            new_line += word
        else:
            # candidates = candidates(word, words_freq)
            before_word = last_word
            after_word = next_word_on_sentence(words[i+1:])
            last_word = correction(word.lower(), words_freq, pos_freqs, n_words, before_word,
                                   after_word, nlp)
            new_line += last_word
    # Caracter maiúsculo no início da linha
    new_line = regex.sub(r'^\s*\w', lambda x: x[0].upper(), new_line)
    # Caracter maiúsculo após sinal de pontuação
    new_line = regex.sub(r'(?<=[^(?:' + r'|'.join(exceptions) + r')][\.!?])\s*\w',
                         lambda x: x[0].upper(), new_line)
    return new_line

####################             ASPELL              ####################

def correct_line_aspell(line):
    "Corrects words on `line`, using aspell library."
    speller = aspell.Speller('lang', 'pt_PT')
    words = regex.findall(r'\w+|\s+|\p{P}+', line, flags=regex.UNICODE)
    new_line = []
    for word in words:
        if regex.match(r'\s+|\p{P}+', word) or not word.isalpha():
            new_line.append(word)
        else:
            suggestions = speller.suggest(word)
            if suggestions:
                new_line.append(suggestions[0])
            else:
                new_line.append(word)
    return ''.join(new_line)

####################            HUNSPELL             ####################

def correct_line_hunspell(line):
    "Corrects words on `line`, using hunspell library."
    hobj = hunspell.HunSpell('dictionaries/hunspell-pt_PT-20171225/pt_PT.dic',
                             'dictionaries/hunspell-pt_PT-20171225/pt_PT.aff')
    words = regex.findall(r'\w+|\s+|\p{P}+', line, flags=regex.UNICODE)
    new_line = []
    for word in words:
        if regex.match(r'\s+|\p{P}+', word) or not word.isalpha():
            new_line.append(word)
        elif hobj.spell(word):
            new_line.append(word)
        else:
            suggestions = hobj.suggest(word)
            if suggestions:
                new_line.append(suggestions[0])
            else:
                new_line.append(word)
    return ''.join(new_line)

####################            SYMSPELL            #####################

def correct_line_symspell(line):
    "Corrects words on `line`, using symspell library."
    # create object
    initial_capacity = 83000
    max_edit_distance_dictionary = 2 # maximum edit distance per dictionary precalculation
    prefix_length = 7
    sym_spell = SymSpell(initial_capacity, max_edit_distance_dictionary, prefix_length)

    # load dictionary
    dictionary_path = os.path.join(os.path.dirname(__file__), "dictionaries/pt_PT-freq.txt")
    term_index = 0  # column of the term in the dictionary text file
    count_index = 1  # column of the term frequency in the dictionary text file
    if not sym_spell.load_dictionary(dictionary_path, term_index, count_index):
        print("ERROR: Dictionary file not found", file=sys.stderr)
        return line

    # lookup suggestions for single-word input strings
    max_edit_distance_lookup = 2
    suggestion_verbosity = Verbosity.CLOSEST  # TOP, CLOSEST, ALL

    words = regex.findall(r'\w+|\s+|\p{P}+', line, flags=regex.UNICODE)
    new_line = []
    for word in words:
        if regex.match(r'\s+|\p{P}+', word) or not word.isalpha():
            new_line.append(word)
        else:
            suggestions = sym_spell.lookup(word, suggestion_verbosity, max_edit_distance_lookup)
            if suggestions:
                new_line.append(suggestions[0].term)
            else:
                new_line.append(word)
    new_line = ''.join(new_line)

    new_line = regex.sub(r'^\s*\w', lambda x: x[0].upper(), new_line)
    # Caracter maiúsculo após sinal de pontuação
    exceptions = ['sr', 'sra', 'sras', 'dr', 'dra', 'prof']
    new_line = regex.sub(r'(?<=[^(?:' + r'|'.join(exceptions) + r')][\.!?])\s*\w',
                         lambda x: x[0].upper(), new_line)
    return new_line

####################           POS TAGGING           ####################

def exists(ordered_list, elem):
    "Verifies if `elem` exists on `ordered_list`."
    i = bisect.bisect_left(ordered_list, elem)
    return bool(i != len(ordered_list) and ordered_list[i] == elem)

# python -m spacy download pt
def get_pos_frequences(text_fd, dict_words):
    "Get POS 3-tuples and words frequences, processing train text."
    nlp = spacy.load('pt')
    pos_freq = Counter()
    words = defaultdict(Counter)
    lines = text_fd.readlines()
    n_lines = len(lines)
    for n_line, line in enumerate(lines):
        doc = nlp(line)
        added_words = []
        for word_doc in doc:
            # Pré-Requisito: Dicionário tem de estar ordenado
            word = str(word_doc)
            word_first_lower = None if word[0].islower() else word[0].lower() + word[1:]
            if exists(dict_words, word):
                words[word.lower()][word] += 1
                added_words.append(word_doc)
            elif word_first_lower and exists(dict_words, word_first_lower):
                words[word.lower()][word_first_lower] += 1
                added_words.append(word_doc)
        len_doc = len(doc)
        for i in range(1, len_doc-1):
            doc_0 = doc[i-1].pos_ + get_tag(doc[i-1]) \
                    if doc[i-1] in added_words or doc[i-1].pos_ == 'PUNCT' \
                    else '<UNKNOWN>'
            doc_1 = doc[i].pos_ + get_tag(doc[i]) \
                    if doc[i] in added_words or doc[i].pos_ == 'PUNCT' \
                    else '<UNKNOWN>'
            doc_2 = doc[i+1].pos_ + get_tag(doc[i+1]) \
                    if doc[i+1] in added_words or doc[i+1].pos_ == 'PUNCT' \
                    else '<UNKNOWN>'
            if doc_1 != '<UNKNOWN>':
                pos_freq[doc_0 + ' ' + doc_1 + ' ' + doc_2] += 1
                if doc_0 != '<UNKNOWN>' and doc_2 != '<UNKNOWN>':
                    pos_freq['<UNKNOWN>' + ' ' + doc_1 + ' ' + doc_2] += 1
                    pos_freq[doc_0 + ' ' + doc_1 + ' ' + '<UNKNOWN>'] += 1

        print(f'Processado {str(n_line)}/{str(n_lines)}', end='\r', file=sys.stderr)
    # Adiciona uma entrada para cada palavra do dicionário
    for word in dict_words:
        words[word.lower()][word] += 1

    return pos_freq, words

def analyze_large_text():
    "Process train text or load result of previous analsis."
    # iconv -f ISO-8859-1 -t UTF-8//TRANSLIT CETEMPublico1.7_100MB -o CETEMPublico_100MB_.txt

    # cat CETEMPublico_100MB_.txt | perl -pe 's/\s/ /g' | perl -pe 's/\s*<[^>]+>\s*/\n/g' | \
    # perl -pe 's/^\s*$//g' | perl -pe 's/ +/ /g' | perl -pe 's/ ([,.!?$%;:])/\1/g' | \
    # perl -pe 's/(\(|\[|\{|«|<) /\1/g' | perl -pe 's/ (\)|\]|\}|>|»)/\1/g' > CETEMPublico.txt
    if not os.path.isfile('dict_info_tags.json'):
        pos_freq = None
        words_freq = None
        with open('dictionaries/wordlist-ao-latest.txt') as dict_fd:
            dict_words = dict_fd.read().splitlines()
            dict_words.sort()
            with open('CETEMPublico_20MB.txt') as text_fd:
                pos_freq, words_freq = get_pos_frequences(text_fd, dict_words)
        with open('dict_info_tags.json', 'w') as file_desc:
            json.dump((pos_freq, words_freq), file_desc)
    else:
        with open('dict_info_tags.json', 'r') as file_desc:
            (pos_freq, words_freq) = json.load(file_desc)
    return pos_freq, words_freq

####################             CORRECT             ####################

def correct_text_files(args, pos_freq, words_freq, correct_function):
    "Corrects text of files, with manual mode."
    nlp = spacy.load('pt')
    for line in fileinput.input(args):
        new_line = correct_function(line.strip(), pos_freq, words_freq, nlp)
        print(new_line)

def correct_text_files_ext(args, correct_function):
    "Corrects text of files, with aspell, hunspell or symspell (`correct_function`) mode."
    for line in fileinput.input(args):
        new_line = correct_function(line.strip())
        print(new_line)

def correct_text(pos_freq, words_freq, text_lines):
    "Corrects text lines, with manual mode."
    new_text = []
    nlp = spacy.load('pt')
    for line in text_lines:
        new_text.append(correct_line(line.strip(), pos_freq, words_freq, nlp))
    return '\n'.join(new_text)

def correct_text_ext(text_lines, correct_function):
    "Corrects text lines, with aspell, hunspell or symspell (`correct_function`) mode."
    new_text = []
    for line in text_lines:
        new_text.append(correct_function(line.strip()))
    return '\n'.join(new_text)

####################              MAIN               ####################

def main():
    "Main function."
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hvm:", ["help", "version", "mode="])
    except getopt.GetoptError:
        print('USAGE: python3 spellcorrector.py [-h | -v | -m <CORRECT_MODE>] <INPUT_FILEAME> ' +\
                '<INPUT_FILEAME> ...\n' +\
                'OPTIONS:\n' +\
                '\t-h, --help\tShows this menu\n' +\
                '\t-v, --version\tShows program version\n' +\
                '\t-m, --mode\tUses specified mode - aspell, hunspell or symspell - ' +\
                    'to correct text words')
        exit(1)

    correct_function = correct_line
    for opt, arg in opts:
        if opt in ('-m', '--mode'):
            if arg == 'aspell':
                correct_function = correct_line_aspell
            elif arg == 'hunspell':
                correct_function = correct_line_hunspell
            elif arg == 'symspell':
                correct_function = correct_line_symspell
            else:
                print(f'ERROR: Mode name ({arg}) not recognized', file=sys.stderr)
                exit(1)
        if opt in ('-h', '--help'):
            print('USAGE: python3 spellcorrector.py [-h | -v | -m <CORRECT_MODE>] ' +\
                '<INPUT_FILEAME> <INPUT_FILEAME> ...\n' +\
                    'OPTIONS:\n' +\
                    '\t-h, --help\tShows this menu\n' +\
                    '\t-v, --version\tShows program version\n' +\
                    '\t-m, --mode\tUses specified mode - aspell, hunspell or symspell - ' +\
                        'to correct text words')
            exit(0)
        if opt in ('-v', '--version'):
            print('spellcorrector v1.0')
            exit(0)

    if correct_function == correct_line:
        print('--Geração de Estatísticas Iniciada--', file=sys.stderr)
        time1 = time.time()
        pos_freq, words_freq = analyze_large_text()
        time2 = time.time()
        print('--Geração de Estatísticas Terminada--', file=sys.stderr)
        print('\n--Processamento de texto Iniciado--', file=sys.stderr)
        correct_text_files(args, pos_freq, words_freq, correct_function)
        time3 = time.time()
        print('--Processamento de texto Terminado--', file=sys.stderr)

        print(file=sys.stderr)
        print('Time Load:\t %.2f sec' % (time2-time1), file=sys.stderr)
        print('Time Correct:\t %.2f sec' % (time3-time2), file=sys.stderr)

    else:
        time1 = time.time()
        correct_text_files_ext(args, correct_function)
        time2 = time.time()
        print('Time Correct:\t %.2f sec' % (time2-time1), file=sys.stderr)

if __name__ == "__main__":
    main()

__author__ = "João Barreira, Mafalda Nunes"
__email__ = "a73831@alunos.uminho.pt, a77364@alunos.uminho.pt"


'''
< 토마토 >
https://www.acmicpc.net/problem/7569
문제)
- 높이H, 세로N, 가로M
- 익은 토마토에 인접한 익지 않은 토마토들이 영향을 받아 익는다.
- 몇일 뒤에 토마토들이 다 익게 되는지 최소 일수
- 빈칸, 익은토마토, 익지않은토마토
입력)
- 1     : 상자의 가로 칸 M, 상자의 세로칸 N, 상자수 H
        - M ~ [2 \ 100], N ~ [2 \ 100], H ~ [1 \ 100]
- 2[NxH]: 익은 1, 익지않은 0, 토마토없는경우 -1
출력)
- 모두 익을 때까지 걸리는 일수
    - 초기에 모두 익어있으면 0
    - 모두 익지 못하면 -1
'''
from collections import deque
import sys
input = sys.stdin.readline

dr = (0, 1, 0, -1, 0, 0)
dc = (1, 0, -1, 0, 0, 0)
dl = (0, 0, 0, 0, 1, -1)

m, n, h = map(int, input().split()) # c, r, h
a = [[list(map(int, input().split())) for _ in range(n)] for _ in range(h)]
visited = [[[0] * m for _ in range(n)] for _ in range(h)]
t = []
ans = -1
for k in range(h): # l
    for i in range(n): # r
        for j in range(m): # c
            if a[k][i][j] == 1:
                t.append((0, k, i, j)) # d, l, r, c
                visited[k][i][j] = 1

def bfs():
    global t, ans
    q = deque(t)
    while q:
        d, l, r, c = q.popleft()
        ans = max(ans, d)
        for i in range(6):
            nr = r + dr[i]
            nc = c + dc[i]
            nl = l + dl[i]
            if 0 <= nr < n and 0 <= nc < m and 0 <= nl < h:
                if visited[nl][nr][nc]: continue
                if a[nl][nr][nc]: continue # 1익은 -1없음 pass
                a[nl][nr][nc] = 1
                visited[nl][nr][nc] = 1
                q.append((d + 1, nl, nr, nc))

bfs()
flag = True
for k in range(h):
    for i in range(n):
        for j in range(m):
            # if a[k][i][j] == 0: flag = False
            if a[k][i][j] == 0: print(-1); exit(0)

print(ans)


import math
import pandas as pd
import requests
import re
import numpy as np
import Hauser_matrix_functions as hmf
import itertools

meta_url = 'https://gpcrdb.org/services/residues/extended/'

gpcr_keys_1 = ['ICL1','ICL2','ICL3','ECL1','ECL2','ECL3','C-term','N-term']

def get_meta_df(url, file_path):
    """
    Obtiene los metadatos para cada GPCR, mediante la GPCRdb.
    :param url: URL donde consulta los datos de GPCRdb.
    :param file_path: Ruta donde se encuentra alojado el archivo estructural, para obtener el nombre del GPCR.
    :return: Un dataframe que contiene los metadatos para cada GPCR a procesar.
    """
    pdb_name = file_path.split('/')[-1][:-4].lower()
    url_pdb = url + pdb_name.lower()
    res = requests.get(url_pdb).json()
    df = pd.DataFrame(res)
    reduced_df = df[['sequence_number',
                     'amino_acid',
                     'protein_segment',
                     'display_generic_number']]
    reduced_df['display_generic_number'].fillna('Nan', inplace=True)
    return reduced_df

def df_2_list_of_lists(reduced_df):
    """
    Convierte el dataframe de metadatos en una lista de columnas (Row_list).
    :param reduced_df: El dataframe de metadatos.
    :return: La Row_list generada.
    """
    Row_list = []
    for index, rows in reduced_df.iterrows():
        append_list = [rows.sequence_number,
                       rows.amino_acid,
                       rows.protein_segment,
                       rows.display_generic_number]
        Row_list.append(append_list)
    Row_list = obtain_ballest_repr(Row_list)
    return Row_list

def selector_representacion_ballesteros(key_helix, ballest_index):
    """
    Genera las nuevas representaciones para los fragmentos de las helices de los GPCR.
    :param key_helix: Nombre de la helice a buscar.
    :param ballest_index: Indice de ballesteros a buscar.
    :return: Nueva representación para cada aminoacido en las helices del GPCR.
    """
    if key_helix in hmf.gpcr_keys_0.keys():
        for key, value in hmf.gpcr_keys_0[key_helix].items():
            try:
                if ballest_index in key:
                    return key_helix + value
            except:
                if ballest_index == key:
                    return key_helix + value
    elif key_helix in gpcr_keys_1:
        return key_helix

def make_ballest_index(generic_number):
    """
    Genera los índices de Ballesteros a partir de los números genéricos de GPCRdb
    :param generic_number: Número generico de GPCRdb.
    :return: Indice de Ballesteros
    """
    if generic_number != 'Nan':
        list_generic = re.split('\.|x', generic_number)
        return int(list_generic[-1])

def obtain_ballest_repr(Row_list):
    """
    Para cada elemento en la Row_list genera la representación de los fragmentos del GPCR.
    :param Row_list: Lista de columnas con los metadatos del GPCR.
    :return: Nueva lista de columnas (Row_list), donde el último valor ahora es la representación de fragmentos para
             el GPCR.
    """
    for aa in Row_list:
        repr_ballesteros = selector_representacion_ballesteros(aa[-2], make_ballest_index(aa[-1]))
        aa.append(repr_ballesteros)
    return Row_list

def filtrar_contactos_relevantes(mapa, filtro1, filtro2):
    """
    Filtra solo los contactos del mapa CAM que se encuentren entre las cotas establecidas pro el
    filtro1 y el filtro2.
    :param mapa: Mapa CAM a filtrar.
    :param filtro1: Cota inferior del filtro.
    :param filtro2: Cota superior del filtro.
    :return: Mapa CAM filtrado con los contactos relevantes de acuerdo a las cotas.
    """
    coord_filtro = []
    coordenadas_filtro_tupla = np.where((filtro2 >= mapa) & (mapa > filtro1))
    coord_x, coord_y = coordenadas_filtro_tupla
    for x, y in zip(coord_x, coord_y):
        coord_filtro.append([x, y])
    return coord_filtro

def get_claves_matriz(lista_coordenadas, diccionario_claves):
    """
    Genera una lista que almacena los contactos establecidos, a partir de un diccionario con coordenadas y una
    lista con contactos.
    :param lista_coordenadas: Lista con los residuos que establecen contacto.
    :param diccionario_claves: Diccionario que almacena las coordenadas de los residuos.
    :return: Lista con las coordenadas de los residuos que establecen contacto.
    """
    coords = []
    keys = list(diccionario_claves.keys())
    values = list(diccionario_claves.values())
    for coord in lista_coordenadas:
        index_x = values.index(coord[0])
        index_y = values.index(coord[1])
        key_x = keys[index_x]
        key_y = keys[index_y]
        coords.append((key_x, key_y))
    return coords

def get_secciones_relevantes(mapa, cota_inferior=0.5):
    """
    Encuentra las secciones que establecen contactos, de acuerdo a su relevancia en los mapas CAM.
    :param mapa: Mapa a evaluar.
    :param cota_inferior: Valor mínimo de los mapas CAM desde el que se evaluara la relevancia.
    :return: Diccionario {rango evaluado : secciones del GPCR con contactos relevantes en el rango evaluado}.
    """
    secciones = {}
    val = np.max(mapa) * 10
    frontera = math.ceil(val)
    c = cota_inferior * 10
    while c < frontera:
        cota_inf = c / 10
        cota_sup = (c + 1) / 10
        contactos = filtrar_contactos_relevantes(mapa, cota_inf, cota_sup)
        secciones[(cota_inf, cota_sup)] = get_claves_matriz(contactos, hmf.coords_matrix_ballesteros)
        c += 1
    return secciones

def get_row_list_protein(file_route_pdb):
    """
    Obtiene la información de los residuos del PDB correspondiente a 'file_route_pdb'.
    :param file_route_pdb: Ruta url del PDB a analizar.
    :return: Lista con la información de los residuos del PDB.
    """
    reduced_pdb_df = get_meta_df(url=meta_url, file_path=file_route_pdb)
    row_list = df_2_list_of_lists(reduced_df=reduced_pdb_df)
    return row_list

def get_relevant_residues(row_list, set_sections):
    """
    Obtiene los residuos relevantes por sección.
    :param row_list:
    :param set_sections:
    :return:
    """
    residuos = []
    for i in row_list:
        if i[-1] in set_sections:
            residuos.append(i[0])
    return residuos

def get_contact_residues(cam, pdb_path):
    """
    Obtiene los contactos relevantes que se establecen de acuerdo con un mapa CAM.
    :param cam: Mapa CAM a analizar.
    :param pdb_path: Ruta del PDB correspondiente.
    :return: Diccionario con los contactos relevantes por sección de acuerdo al mapa CAM.
    """
    contacts_by_section_dict = {}
    secc = get_secciones_relevantes(cam)
    row = get_row_list_protein(pdb_path)
    for key, value in secc.items():
        contacts_by_section_dict[key] = set()
        for contact_set in value:
            values_residues = get_relevant_residues(row,
                                                    contact_set)
            contacts_by_section_dict[key].update(set(values_residues))
    return contacts_by_section_dict

def to_ranges(iterable):
    """
    Genera mediante un 'yield' los intervalos numéricos de un iterable.
    :param iterable: iterable con los elementos numéricos.
    """
    iterable = sorted(set(iterable))
    for key, group in itertools.groupby(enumerate(iterable),
                                        lambda t: t[1] - t[0]):
        group = list(group)
        yield group[0][1], group[-1][1]

def prepare_pymol_strings(dict_contacts):
    """
    Genera un diccionario {sección:intervalo_residuos}, donde el intervalo_residuos es un string de los residuos a
    seleccionar en Pymol.
    :param dict_contacts: Diccionario que almacena los residuos involucrados en contactos por sección.
    :return: Diccionario {sección:intervalo_residuos}.
    """
    dict_pymol ={}
    for key, value in dict_contacts.items():
        x_range = to_ranges(list(value))
        dict_pymol[key]=f'select resi {list(x_range)}'
    return dict_pymol


import torch

from .aggregated import InstanceMetricAggregated
from .match_info import ImageEvalResults
from ..metric import sum_class_agg

class InstanceRecall(InstanceMetricAggregated):
    def compute_one(self, res: ImageEvalResults):
        device = res.pred_area.device
        selected = self.selection_target(res)
        selected[selected] &= res.target_class[selected] == res.pred_class[
            res.target_to_pred[selected]]
        tp = sum_class_agg(res.target_class[selected],
                           torch.ones(selected.sum(), device=device),
                           self.n_classes)
        fn = sum_class_agg(res.target_class[~selected],
                           torch.ones((~selected).sum(), device=device),
                           self.n_classes)

        ret = tp / (tp + fn)
        return ret


import argparse
import datetime, time, threading
import sys
sys.path.append("libs/")
import core_engine

# python worker.py --daily --size 5

MONTH_DELTA = 2592000
WEEK_DELTA = 604800
DAY_DELTA = 86400

def valid_time(s):
    try:
        return datetime.datetime.strptime(s, "%H:%M:%S")
    except ValueError:
        msg = "Not a valid date: '{0}'.".format(s)
        raise argparse.ArgumentTypeError(msg)

parser = argparse.ArgumentParser(description="Worker to create playlists for all users.")
#parser.add_argument('time', metavar='HH:MM:SS', type=valid_time, help='Time at which to create playlists. (format - HH:MM:SS)')

group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--daily', action="store_true", help="Create playlists daily.")
group.add_argument('--weekly', action="store_true", help="Create playlists weekly.")
group.add_argument('--monthly', action="store_true", help="Create playlists month.")

parser.add_argument('-s', '--size', action="store", type=int, default=10, help="Size of the playlists to be created.", required=True)

args = parser.parse_args()

def sleep_until(time):
    pass

def create_playlist(delta, size):
    start = time.time()
    print(time.ctime())
    ## GET ALL USERS
    ## FOR EACH USER GET REACTIONS
    processor = core_engine.Processor()
    users = processor.get_users()
    for user in users:
        reactions = user.reactions
        seed = user.positive_reactions() #songs that were heard for 80% of the total music time are considered positive
        print("Seed:", seed)
        print("User \"{}\" - Reactions: ".format(user.id, len(reactions)))
        if len(reactions) > 1:
            recommendations = processor.create_recommendations(seed, size)
            print(recommendations)
            processor.create_playlist(user.id, recommendations)
    end = time.time()
    runtime = end - start
    sleep = delta - runtime
    print("RUNTIME: ", runtime)
    print("SLEEP: ", sleep)
    threading.Timer(sleep, create_playlist, [delta, size]).start()

if __name__ == "__main__":
    now = datetime.datetime.now()
    if args.daily:
        delta = DAY_DELTA
    elif args.week:
        delta = WEEK_DELTA
    elif args.month:
        delta = MONTH_DELTA
    else:
        print("Wrong periodic input.")
        exit(1)
    delta = 60
    create_playlist(delta, args.size)


"""
Katex Render Plugin for Pelican
Literally no settings
"""
import os
import sys

from pelican import signals, generators
from bs4 import BeautifulSoup

from .pelican_katex_markdown_extension import PelicanKatexExtension

def process_settings(pelicanobj):
    """Sets user specified Katex settings"""

    katex_settings = {}

    katex_settings['auto_insert'] = True
    katex_settings['process_summary'] = True

    return katex_settings

def process_summary(article):
    """Ensures summaries are not cut off. Also inserts
    katex script so that math will be rendered"""

    summary = article.summary
    summary_parsed = BeautifulSoup(summary, 'html.parser')
    math = summary_parsed.find_all(class_='math')

    if len(math) > 0:
        last_math_text = math[-1].get_text()
        if len(last_math_text) > 3 and last_math_text[-3:] == '...':
            content_parsed = BeautifulSoup(
                article.content,
                'html.parser'
            )
            full_text = content_parsed.find_all(
                class_='math'
            )[len(math) - 1].get_text()
            math[-1].string = "%s ..." % full_text
            summary = summary_parsed.decode()

        article.summary = "%s<script type='text/javascript'>%s</script>" % (
            summary, process_summary.katex_script)

def process_katex_script(katex_settings):
    """Load the katex script template from file and render
    with settings"""

    with open(os.path.dirname(os.path.realpath(__file__))
              + '/katex_script_template', 'r') as script_template:
        return script_template.read()

def configure_typogrify(pelicanobj, katex_settings):
    """Instructs Typogrify to ignore math tags - which allows Typogrify
    to play nicely with math related content"""

    # If Typogrify is not being used, then just exit
    if not pelicanobj.settings.get('TYPOGRIFY', False):
        return

    try:
        import typogrify
        from distutils.version import LooseVersion

        if LooseVersion(typogrify.__version__) < LooseVersion('2.0.7'):
            raise TypeError('Incorrect version of Typogrify')

        from typogrify.filters import typogrify

        # At this point, we are happy to use Typogrify, meaning
        # it is installed and it is a recent enough version
        # that can be used to ignore all math
        # Instantiate markdown extension and append it to the current extensions
        pelicanobj.settings['TYPOGRIFY_IGNORE_TAGS'].extend(
            ['.math', 'script'])  # ignore math class and script

    except (ImportError, TypeError) as e:
        pelicanobj.settings['TYPOGRIFY'] = False  # disable Typogrify

        if isinstance(e, ImportError):
            print("\nTypogrify is not installed, so it is being ignored.\nIf you want to use it, please install via: pip install typogrify\n")

        if isinstance(e, TypeError):
            print("\nA more recent version of Typogrify is needed for the render_katex module.\nPlease upgrade Typogrify to the latest version (anything equal or above version 2.0.7 is okay).\nTypogrify will be turned off due to this reason.\n")

def katex_for_markdown(pelicanobj, katex_script, katex_settings):
    """Instantiates a customized markdown extension for handling
    katx related content"""

    config = {}
    config['katex_script'] = katex_script
    config['math_tag_class'] = 'math'
    config['auto_insert'] = katex_settings['auto_insert']

    try:
        if isinstance(pelicanobj.settings.get('MD_EXTENSIONS'), list):  # pelican 3.6.3 and earlier
            pelicanobj.settings['MD_EXTENSIONS'].append(PelicanKatexExtension(config))
        else:
            pelicanobj.settings['MARKDOWN'].setdefault(
                'extensions', []).append(PelicanKatexExtension(config))
    except:
        sys.excepthook(*sys.exc_info())
        sys.stderr.write(
            "\nError - the pelican katex markdown extension failed to configure. katex is non-functional.\n")
        sys.stderr.flush()

def rst_add_katex(content):
    """Adds katex script for reStructuredText"""

    # .rst is the only valid extension for reStructuredText files
    _, ext = os.path.splitext(os.path.basename(content.source_path))
    if ext != '.rst':
        return

    # If math class is present in text, add the javascript
    # note that RST hardwires mathjax to be class "math"
    if 'class="math"' in content.content:
        content.content += "<script type='text/javascript'>%s</script>" % rst_add_katex.katex_script

def mathjax_for_rst(pelicanobj, katex_script):
    """Setup math for RST"""
    docutils_settings = pelicanobj.settings.get('DOCUTILS_SETTINGS', {})
    docutils_settings['math_output'] = 'Katex'
    pelicanobj.settings['DOCUTILS_SETTINGS'] = docutils_settings
    rst_add_katex.katex_script = katex_script

def pelican_init(pelicanobj):
    """
    Loads the katex script. Instantiate the Python markdown
    extension, passing in the katex sript as config parameter
    """

    katex_settings = process_settings(pelicanobj)

    katex_script = process_katex_script(katex_settings)

    # Configure Typogrify
    configure_typogrify(pelicanobj, katex_settings)

    katex_for_markdown(pelicanobj, katex_script,
                       katex_settings)

    process_summary.katex_script = None
    if katex_settings['process_summary']:
        process_summary.katex_script = katex_script

def process_rst_and_summaries(content_generators):
    for generator in content_generators:
        if isinstance(generator, generators.ArticlesGenerator):
            for article in (
                generator.articles +
                generator.translations +
                generator.drafts
            ):
                rst_add_katex(article)
                if process_summary.katex_script is not None:
                    process_summary(article)
        elif isinstance(generator, generators.PagesGenerator):
            for page in generator.pages:
                rst_add_katex(page)

def register():
    """Plugin registration"""
    signals.initialized.connect(pelican_init)
    signals.all_generators_finalized.connect(process_rst_and_summaries)


import os, datetime
from shutil import copy2

replace_these_things = {  # use this dictionary to automatically replace things in your .tex to prep it for conversion to .docx; for example,
                r"\some_command_that_needs_to_be_commented_out": r"%\some_command_that_needs_to_be_commented_out"
                }

def unique(list1):
    unique_list = []
    for x in list1:
        if x not in unique_list:
            unique_list.append(x)
    return unique_list

def tabularize_eqns(fin, eqn_ids, cleanup=True):
    eqn_lookups = ["equation"]
    table_fill = [r"\begin{tabular}{cc}", r" & ", r" \end{tabular}"]
    tempfile = fin.replace(".tex", "_temp.tex")
    fout = fin.replace(".tex", "_temp_out.tex")
    copy2(src=fin, dst=tempfile)
    with open(tempfile, "r") as fp:
        lines = fp.readlines()
    eqn_starts = []
    eqn_ends = []
    eqn_replace = []
    for e in eqn_lookups:
        eqn_start = r"\begin{" + e + r"}"
        eqn_end = r"\end{" + e + r"}"
        starts = [i for i, n in enumerate(lines) if eqn_start in n]
        ends = [i+1 for i, n in enumerate(lines) if eqn_end in n]
        replace_flag = [False for i in range(len(starts))]
        for i in range(len(starts)):
            temp_eqn_lines = [j for j in range(starts[i], ends[i])]
            replace_eqn = False
            for id in eqn_ids.keys():
                label = r"\label" + id
                for j in temp_eqn_lines:
                    if label in lines[j]:
                        replace_eqn = True
            replace_flag[i] = replace_eqn
        eqn_starts = eqn_starts + starts
        eqn_ends = eqn_ends + ends
        eqn_replace = eqn_replace + replace_flag
    for i in range(len(eqn_starts)):
        if eqn_replace[i]:
            temp_eqn_lines = [j for j in range(eqn_starts[i], eqn_ends[i])]
            lines[temp_eqn_lines[0]] = lines[temp_eqn_lines[0]].replace(lines[temp_eqn_lines[0]], table_fill[0] + "\n" + lines[temp_eqn_lines[0]])
            for id in eqn_ids.keys():
                label = r"\label" + id
                temp_rep = False
                for j in temp_eqn_lines:
                    if label in lines[j]:
                        lines[j] = lines[j].replace(label, "")
                        temp_rep = True
                if temp_rep:
                    lines[temp_eqn_lines[-1]] = lines[temp_eqn_lines[-1]].replace(lines[temp_eqn_lines[-1]], lines[temp_eqn_lines[-1]] + table_fill[1] + label + "\n" + table_fill[2] + "\n")
    with open(fout, "wt") as fo:
        for line in lines:
            fo.write(line)
    if cleanup:
        os.remove(tempfile)
    return fout

def tex_label_ids(fin, id_flags=None, cleanup=True):
    label_flag = r"\label{"
    if id_flags is None:
        id_flags = ["eq:", "eqn:"]
    id_flags = [label_flag + e for e in id_flags]
    tempfile = fin.replace(".tex", "_temp.tex")
    copy2(src=fin, dst=tempfile)
    count = 0
    id_labels = []
    lookups = []
    id_labels2 = []
    ids = {}
    with open(tempfile) as fp:
        for line in fp:
            count += 1
            # print("Line{}: {}".format(count, line.strip()))
            for a in id_flags:
                if a in line:
                    id_labels = id_labels + [line]
                    lookups = lookups + [a]
    for i in range(len(id_labels)):
        tempe = id_labels[i].split(lookups[i])
        tempe = tempe[1].split(r"}")
        id = tempe[0]
        id_labels2 = id_labels2 + [lookups[i] + id + "}"]
    id_labels2_unique = unique(id_labels2)
    if len(id_labels2) != len(id_labels2_unique):
        print("WARNING: non-unique labels detected")
    id_count = 0
    for e in id_labels2_unique:
        id_count += 1
        id = e.split(r"\label")
        ids[id[1]] = str(id_count)
    print(ids)
    if cleanup:
        os.remove(tempfile)
    return ids

def tex_number_ref(fin, ids, label_prefix=None):
    tempfile = fin.replace(".tex", "_temp.tex")
    # count = 0
    if len(ids) > 0:
        with open(fin) as fi:
            with open(tempfile, "wt") as fo:
                for line in fi:
                    # count += 1
                    for id,n in ids.items():
                        if id in line:
                            # print(line)
                            if label_prefix is None:
                                line = line.replace(r"\label" + id, "(" + n + ")")
                            else:
                                line = line.replace(r"\label" + id, label_prefix + n)
                            line = line.replace(r"\ref" + id, n)
                            line = line.replace(r"\eqref" + id, "(" + n + ")")
                            # print(line)
                    fo.write(line)
    else:
        tempfile = fin
    return tempfile

def prep_eqns(fin, id_flags=None, cleanup=True):
    if id_flags is None:
        id_flags = ["eq:", "eqn:"]
    ids = tex_label_ids(fin, id_flags=id_flags, cleanup=cleanup)
    midfile = tabularize_eqns(fin, ids, cleanup=cleanup)
    newfile = tex_number_ref(midfile, ids)
    if cleanup:
        os.remove(midfile)
    return newfile

def prep_figs(fin, id_flags=None, cleanup=True, label_prefix="Figure "):
    if id_flags is None:
        id_flags = ["fig:"]
    ids = tex_label_ids(fin, id_flags=id_flags, cleanup=cleanup)
    newfile = tex_number_ref(fin, ids, label_prefix=label_prefix)
    return newfile

def pref_file(file=None, fileout=None):
    timestamp = str(datetime.datetime.now()).replace(" ", "_").replace(".", "_").replace(":", "-")
    tempfile = "temp_" + timestamp + ".tex"
    if fileout is None:
        fileout = tempfile
    copy2(file, tempfile)
    with open(tempfile, "r") as f:
        Lines = f.readlines()
    count = 0
    for line in Lines:
        for a in replace_these_things.keys():
            if a in line:
                print("Commenting out certain commands...")
                print("Replacing some code...")
                line = line.replace(a, replace_these_things[a])
        Lines[count] = line
        count += 1
    print("Writing temporary file...")
    with open(fileout, "w") as f:
        f.writelines(Lines)
    return fileout

def run_pandoc(file_in=None, file_out=None, refs=None, template=None, toc=True, header=None, ref_style=None):
    if file_out is None:
        file_out = file_in.replace(".tex", ".docx")
    if refs is None:
        refs_command = " --bibliography=refs.bib"
    else:
        refs_command = " --bibliography=" + refs
    if template is None:
        template_command = ""
    else:
        template_command = " --reference-doc=" + template
    if toc:
        table_of_contents = " --table-of-contents"
    else:
        table_of_contents = ""
    if header is None:
        header_command = ""
    else:
        header_command = " -H " + header
    if ref_style is None:  # default to chicago style
        ref_style_command = " --csl=./pandoc/chicago-author-date.csl"
    else:
        ref_style_command = " --csl=" + ref_style
    pandoc_command = "pandoc -s " + file_in + header_command + template_command + table_of_contents + " --standalone --filter pandoc-xnos" + refs_command + ref_style_command + " --citeproc -o " + file_out
    print("Running pandoc: ")
    print(pandoc_command)
    os.system(pandoc_command)
    return None

def tex2docx(filein=None, fileout=None, cleanup=False, refs=None, template=None, toc=True, header=None, ref_style=None):
    if fileout is None:
        fileout = "\"" + filein.replace(".tex", ".docx") + "\""
    if refs is None:
        refs = "refs.bib"
    tempfile1 = prep_eqns(filein, cleanup=cleanup)
    tempfile2 = prep_figs(tempfile1, cleanup=cleanup)
    tempfile3 = prep_figs(tempfile2, id_flags=["tab:"], cleanup=cleanup, label_prefix="Table ")
    tempfile4 = pref_file(file=tempfile3)
    run_pandoc(file_in=tempfile4, file_out=fileout, refs=refs, template=template, toc=toc, header=header, ref_style=ref_style)
    if cleanup:
        print("Removing temporary files...")
        tempfiles = [tempfile1, tempfile2, tempfile3, tempfile4]
        for f in tempfiles:
            if os.path.isfile(f):
                os.remove(f)
    return None

if __name__ == "__main__":
    # fin = "test.tex"
    # eids = tex_label_ids(fin=fin, id_flags=["eq:", "eqn:"])
    # fids = tex_label_ids(fin=fin, id_flags=["fig:"])
    # newfile = tabularize_eqns(fin, eqn_ids=eids)
    # newfile = prep_eqns(fin)
    # newfile2 = prep_figs(newfile)
    tex2docx(filein="Example.tex", refs="refs.bib", cleanup=True)


# encoding: utf-8
"""
..  _iso19115-extract:

ISO 19115 Extract
------------------
"""
__author__ = "Rhys Evans"
__date__ = "28 Jul 2021"
__copyright__ = "Copyright 2018 United Kingdom Research and Innovation"
__license__ = "BSD - see LICENSE file in top-level package directory"
__contact__ = "rhys.r.evans@stfc.ac.uk"

# Python imports
import logging
from string import Template
from xml.etree import ElementTree as ET

# Third party imports
import requests

# Package imports
from extraction_methods.core.extraction_method import ExtractionMethod

LOGGER = logging.getLogger(__name__)

iso19115_ns = {
    "gmd": "http://www.isotc211.org/2005/gmd",
    "gml": "http://www.opengis.net/gml/3.2",
    "gco": "http://www.isotc211.org/2005/gco",
    "gmx": "http://www.isotc211.org/2005/gmx",
    "srv": "http://www.isotc211.org/2005/srv",
    "xlink": "http://www.w3.org/1999/xlink",
}

class ISO19115Extract(ExtractionMethod):
    """
    .. list-table::

        * - Processor Name
          - ``iso19115``

    Description:
        Takes a URL template and calls out to URL to retrieve the
        iso19115 record. Use pre-processors to inject additional kwargs
        which are passed to the URL template.

    Configuration Options:
        - ``url_template``: ``REQUIRED`` String template to build the URL.
          Template uses the `python string template <https://docs.python.org/3/library/string.html#template-strings>`_ format.
        - ``extraction_keys``: List of keys to retrieve from the response.

    Extraction Keys:
        Extraction keys should be a map.

        .. list-table::

            * - Name
              - Description
            * - ``name``
              - Name of the outputted attribute
            * - ``key``
              - Access key to extract the required data. Passed to
                `xml.etree.ElementTree.find() <https://docs.python.org/3/library/xml.etree.elementtree.html?highlight=find#xml.etree.ElementTree.ElementTree.find>`_
                and also supports `xpath formatted <https://docs.python.org/3/library/xml.etree.elementtree.html#xpath-support>`_ accessors

        Example:
            .. code-block:: yaml

                  - method: start_datetime
                    key: './/gml:beginPosition'

    Example configuration:
        .. code-block:: yaml

            - method: iso19115
              inputs:
                url_template: 'api.catalogue.ceda.ac.uk/export/xml/$uri'
                extraction_keys:
                  - name: start_datetime
                    key: './/gml:beginPosition'
    """

    def run(self, body: dict, **kwargs) -> dict:
        # Build the template
        url = Template(self.url_template)

        try:
            url = url.substitute(kwargs)
        except KeyError:
            LOGGER.warning(
                f"URL templating failed. Template: {self.url_template} key not found in kwargs: {body['uri']}"
            )
            return {}

        # Retrieve the ISO 19115 record
        response = requests.get(url)

        if not response.status_code == 200:
            LOGGER.debug(f"Request {url} failed with response: {response.error}")
            return {}

        iso_record = ET.fromstring(response.text)

        # Extract the keys
        for key in self.extraction_keys:
            name = key["name"]
            location = key["key"]

            value = iso_record.find(location, iso19115_ns)

            if value is not None:
                body[name] = value.text

        return body


# In[]
import requests
import json
import time
import random
from Services import *

key = '031-45-155'
ip = 'http://localhost'
server_device_url = 'http://39.106.138.175/device/upload/'
server_service_url = 'http://39.106.138.175/scene/service/'

port = 39000
headers = {'Content-Type': 'application/json'}

# In[]
with open('/home/pi/Scripts/Devices.json') as f:
    data_dict = json.load(f)
with open('/home/pi/Scripts/Services.json') as f:
    service_dict = json.load(f)
# In[]
sendAll = 1
while 1:
    current_dict = {'sensors':[], 'accessories':[]}
    for i in range(len(data_dict['sensors'])):
        try:
            url = ip + ':' + str(port) + '/characteristics?id=' + str(data_dict['sensors'][i]['aid']) + '.' + str(data_dict['sensors'][i]['iid'])
            r = requests.get(url)
            di = json.loads(r.text)
            data_dict['sensors'][i]['type']['currentvalue'] = di['characteristics'][0]['value']
            current_dict['sensors'].append(data_dict['sensors'][i])
            print('Current ' + data_dict['sensors'][i]['name'] + ' value:' + str(data_dict['sensors'][i]['type']['currentvalue']))
        except:
            print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: Local Django no Response")

    for i in range(len(data_dict['accessories'])):
        try:
            for j in range(len(data_dict['accessories'][i]['iids'])):
                url = ip + ':' + str(port) + '/characteristics?id=' + str(data_dict['accessories'][i]['aid']) + '.' + str(data_dict['accessories'][i]['iids'][j]['iid'])
                r = requests.get(url)
                di = json.loads(r.text)
                #print(di)
                if(data_dict['accessories'][i]['iids'][j]['currentvalue'] != di['characteristics'][0]['value']):
                    data_dict['accessories'][i]['iids'][j]['currentvalue'] = di['characteristics'][0]['value']
                    current_dict['accessories'].append(data_dict['accessories'][i])
                print('Current ' + data_dict['accessories'][i]['name'] + ' value:' + str(data_dict['accessories'][i]['iids'][j]['currentvalue']))
        except:
            print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: HB no Response")
    # Send to Server
    try:
        if(sendAll == 1):
            response_server = requests.post(url=server_device_url, headers=headers, data=json.dumps(data_dict))
            sendAll = 0
        else:
            response_server = requests.post(url=server_device_url, headers=headers, data=json.dumps(current_dict))
        current_dict = {'sensors':[], 'accessories':[]}
        # Status Refresh
        # Alarm Switch
        try:
            ServerResponse_dict = json.loads(response_server.text)
            #alarm = alarm_control_service()
            #lamp_1 = lamp_control_service_1()
            #lamp_2 = lamp_control_service_2()

            try:
                # Power switch of all accessories
                for i in range(len(data_dict['accessories'])):
                    for j in range(len(ServerResponse_dict['accessories'])):
                        try:
                            if(data_dict['accessories'][i]['aid'] == ServerResponse_dict['accessories'][j]['aid']):
                                #print(data_dict['accessories'][i]['iids'][0]['currentvalue'])
                                #print(ServerResponse_dict['accessories'][i]['iids'][0]['currentvalue'])
                                try:
                                    if(data_dict['accessories'][i]['iids'][0]['currentvalue'] != ServerResponse_dict['accessories'][j]['iids'][0]['currentvalue']):
                                        data_dict['accessories'][i]['iids'][0]['currentvalue'] = ServerResponse_dict['accessories'][j]['iids'][0]['currentvalue']
                                        Control = ControlService(data_dict['accessories'][i]['aid'], data_dict['accessories'][i]['iids'][0]['iid'])
                                        Control.set_value(data_dict['accessories'][i]['iids'][0]['currentvalue'])
                                except:
                                    print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: Control Service Error")
                        except:
                            print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: ServerResponse_dict Value['accessories'][j]['aid'] Error")
            except:
                print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: ServerResponse_dict Value Error")
        except:
            print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: ServerResponse_dict loads failed")
    except:
        print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: Data post failed, Server no Response")

    try:
        requests.post(url=server_service_url, headers=headers, data=json.dumps(service_dict))
    except:
        print(str(time.localtime().tm_hour) + ':' + str(time.localtime().tm_min) + ':' + str(time.localtime().tm_sec) + "    " + "DataToServer.py: Service post failed, Server no Response")
    time.sleep(5)


import numpy as np
import cv2
import os
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import math

import torch
import torch.nn as nn
from torchvision import models
import torchvision.transforms.functional as TF

weights_path = '/home/rick/Desktop/model/pesi_pytorch/Soluzione_resnext50_noCrop_terzoGiro_screen.pth'

#OVAL=[10, 338, 297, 332, 284, 251, 389, 356, 454, 323, 361, 288, 397, 365, 379, 378, 400, 377, 152, 148, 176, 149, 150, 136, 172, 58, 132, 93, 234, 127, 162, 21, 54, 103, 67, 109]

class Network(nn.Module):
    def __init__(self,num_classes=94):
        super().__init__()
        self.model_name='resnext50_32x4d'
        self.model=models.resnext50_32x4d(pretrained=False)
        self.model.conv1=nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
        self.model.fc=nn.Linear(self.model.fc.in_features,num_classes)

    def forward(self, x):
        x=self.model(x)
        return x

best_network = Network()
best_network.load_state_dict(torch.load(weights_path, map_location=torch.device('cpu')))
best_network.eval()

# capture the webcam
cap = cv2.VideoCapture(0) #, cv2.CAP_DSHOW)
if (cap.isOpened() == False):
    print('Error while trying to open webcam. Plese check again...')

# get the frame width and height
w = int(cap.get(3))
h = int(cap.get(4))
y=0
x=0
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
output = cv2.VideoWriter('/home/rick/Videos/output.avi',fourcc, 20.0, (int(cap.get(3)), int(cap.get(4))))

while(cap.isOpened()):
    # capture each frame of the video
    ret, frame = cap.read()
    if ret == True:
        image = frame

        grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        #display_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

        image = grayscale_image[y:y+h, x:x+w]
        image = TF.resize(Image.fromarray(image), size=(224, 224))
        image = TF.to_tensor(image)
        image = TF.normalize(image, [0.5], [0.5])

        with torch.no_grad():
            landmarks = best_network(image.unsqueeze(0))

        landmarks = (landmarks.view(47,2).detach().numpy() + 0.5) * np.array([[w, h]]) + np.array([[x, y]])

        for elem in landmarks:
            cv2.circle(frame, (int(elem[0]), int(elem[1])), 1, (0, 0, 255), -1, cv2.LINE_AA)

        """
        for i in range(47):
                        if i==1:
                            cv2.circle(frame, (int(landmarks[i][0]), int(landmarks[i][1])), 3, (0, 5, 5), -1, cv2.LINE_AA)
                        if i==12:
                            cv2.circle(frame, (int(landmarks[i][0]), int(landmarks[i][1])), 3, (0, 5, 5), -1, cv2.LINE_AA)

                        if i==5:
                            cv2.circle(frame, (int(landmarks[i][0]), int(landmarks[i][1])), 3, (0, 255, 255), -1, cv2.LINE_AA)
                        if i==44:
                            cv2.circle(frame, (int(landmarks[i][0]), int(landmarks[i][1])), 3, (0, 255, 255), -1, cv2.LINE_AA)

        q=0
        for i in range(10,46):
            if q!=0:
                cv2.line(frame, (int(landmarks[i][0]),int(landmarks[i][1])), (a,b), (0,255,255),4)
            a=int(landmarks[i][0])
            b=int(landmarks[i][1])
            q=1
        """
        x1=int(landmarks[8,0])
        y1=int(landmarks[8,1])
        x2=int(landmarks[9,0])
        y2=int(landmarks[9,1])
        distance_r=math.sqrt((landmarks[17,0].item()-landmarks[0,0].item())**2+(landmarks[17,1].item()-landmarks[0,1].item())**2)
        distance_l=math.sqrt((landmarks[39,0].item()-landmarks[6,0].item())**2+(landmarks[39,1].item()-landmarks[6,1].item())**2)
        dist=distance_r/distance_l

        distance_up_r=math.sqrt((landmarks[1,0].item()-landmarks[12,0].item())**2+(landmarks[1,1].item()-landmarks[12,1].item())**2)
        distance_up_l=math.sqrt((landmarks[5,0].item()-landmarks[44,0].item())**2+(landmarks[5,1].item()-landmarks[44,1].item())**2)
        distance=math.sqrt((landmarks[10,0].item()-landmarks[28,0].item())**2+(landmarks[10,1].item()-landmarks[28,1].item())**2)

        dist_up_r=distance_up_r/distance
        dist_up_l=distance_up_l/distance

        if dist_up_r>0.25:
            #print("geom dice right")
            right="down right"
            print(dist_up_r)
        else:
            #print("geom dice attento")
            right="attento right"
            print(dist_up_r)

        if dist_up_l>0.25:
            #print("geom dice right")
            left="down left"
            print(dist_up_l)
        else:
            #print("geom dice attento")
            left="attento left"
            print(dist_up_l)
        """
                    if dist>1.7:
                        #print("geom dice right")
                        pytorch="right"
                        print(dist)
                    elif(dist<0.3):
                        #print("geom dice left")
                        pytorch="left"
                        print(dist)
                    else:
                        #print("geom dice attento")
                        pytorch="attento"
                        print(dist)

                    if((landmarks[46,1]).item()>0):
                            print("modello dice attento")
                            mediapipe="attento"
                    else:
                            print("modello dice di no")
                            mediapipe="no"
"""
                    #cv2.putText(frame, f"modello: {mediapipe}",(x1,y1),cv2.FONT_HERSHEY_PLAIN,1.2,(0,255,255),1, cv2.LINE_AA)
                    #cv2.putText(frame, f"g: {pytorch}",(x1,y1+30),cv2.FONT_HERSHEY_PLAIN,2,(255,0,150),1, cv2.LINE_AA)

        cv2.putText(frame, f"g: {right}",(x1,y1+30),cv2.FONT_HERSHEY_PLAIN,2,(255,0,150),1, cv2.LINE_AA)
        cv2.putText(frame, f"g: {left}",(x1,y1+60),cv2.FONT_HERSHEY_PLAIN,2,(255,0,150),1, cv2.LINE_AA)

        cv2.rectangle(frame, (x1,  y1), (x2, y2), (255, 200, 0), 2)
        cv2.imshow('Solution', frame)
        # press `q` to exit

        output.write(frame)

        if cv2.waitKey(27) & 0xFF == ord('q'):
            break

    else:
       break

# release VideoCapture()
cap.release()
output.release()

# close all frames and video windows
cv2.destroyAllWindows()


r"""Functions to find peaks in data above a certain threshold.

:copyright:
    EQcorrscan developers.

:license:
    GNU Lesser General Public License, Version 3
    (https://www.gnu.org/copyleft/lesser.html)
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import random
import numpy as np

from obspy import UTCDateTime
from scipy import ndimage

def is_prime(number):
    """
    Function to test primality of a number. Function lifted from online
    resource:
        http://www.codeproject.com/Articles/691200/Primality-test-algorithms-Prime-test-The-fastest-w

    This function is distributed under a separate licence:
        This article, along with any associated source code and files, is \
        licensed under The Code Project Open License (CPOL)

    :type number: int
    :param number: Integer to test for primality

    :returns: bool

    >>> is_prime(4)
    False
    >>> is_prime(3)
    True
    """
    ''' if number != 1 '''
    if number > 1:
        ''' repeat the test few times '''
        for time in range(3):
            ''' Draw a RANDOM number in range of number ( Z_number )  '''
            randomNumber = random.randint(2, number - 1)
            ''' Test if a^(n-1) = 1 mod n '''
            if pow(randomNumber, number - 1, number) != 1:
                return False
        return True
    else:
        ''' case number == 1 '''
        return False

def find_peaks2_short(arr, thresh, trig_int, debug=0, starttime=False,
                      samp_rate=1.0):
    """
    Determine peaks in an array of data above a certain threshold.

    Uses a mask to remove data below threshold and finds peaks in what is left.

    :type arr: numpy.ndarray
    :param arr: 1-D numpy array is required
    :type thresh: float
    :param thresh: The threshold below which will be considered noise and \
        peaks will not be found in.
    :type trig_int: int
    :param trig_int: The minimum difference in samples between triggers,\
        if multiple peaks within this window this code will find the highest.
    :type debug: int
    :param debug: Optional, debug level 0-5
    :type starttime: obspy.core.utcdatetime.UTCDateTime
    :param starttime: Starttime for plotting, only used if debug > 2.
    :type samp_rate: float
    :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2.

    :return: peaks: Lists of tuples of peak values and locations.
    :rtype: list

    >>> import numpy as np
    >>> arr = np.random.randn(100)
    >>> threshold = 10
    >>> arr[40] = 20
    >>> arr[60] = 100
    >>> find_peaks2_short(arr, threshold, 3)
    [(20.0, 40), (100.0, 60)]
    """
    if not starttime:
        starttime = UTCDateTime(0)
    # Set everything below the threshold to zero
    image = np.copy(arr)
    image = np.abs(image)
    image[image < thresh] = 0
    if len(image[image > thresh]) == 0:
        if debug > 0:
            print('No values over threshold found')
        return []
    if debug > 0:
        print(' '.join(['Found', str(len(image[image > thresh])),
                        'samples above the threshold']))
    initial_peaks = []
    peaks = []
    # Find the peaks
    labeled_image, number_of_objects = ndimage.label(image)
    peak_slices = ndimage.find_objects(labeled_image)
    for peak_slice in peak_slices:
        # print('Width of peak='+str(peak_slice[0].stop-peak_slice[0].start)
        window = arr[peak_slice[0].start: peak_slice[0].stop]
        initial_peaks.append((max(window),
                              int(peak_slice[0].start + np.argmax(window))))
    # Sort initial peaks according to amplitude
    peaks_sort = sorted(initial_peaks, key=lambda amplitude: amplitude[0],
                        reverse=True)
    # Debugging
    if debug >= 4:
        for peak in initial_peaks:
            print(peak)
    if initial_peaks:
        peaks.append(peaks_sort[0])  # Definitely take the biggest peak
        if debug > 3:
            print(' '.join(['Added the biggest peak of', str(peaks[0][0]),
                            'at sample', str(peaks[0][1])]))
        if len(initial_peaks) > 1:
            if debug > 3:
                msg = ' '.join(['Multiple peaks found, checking',
                                'them now to see if they overlap'])
                print(msg)
            for next_peak in peaks_sort:
                # i in range(1,len(peaks_sort)):
                # Loop through the amplitude sorted peaks
                # if the next highest amplitude peak is within trig_int of any
                # peak already in peaks then we don't want it, else, add it
                # next_peak=peaks_sort[i]
                if debug > 3:
                    print(next_peak)
                for peak in peaks:
                    # Use add as a switch for whether or not to append
                    # next peak to peaks, if once gone through all the peaks
                    # it is True, then we will add it, otherwise we won't!
                    if abs(next_peak[1] - peak[1]) < trig_int:
                        if debug > 3:
                            msg = ' '.join(['Difference in time is',
                                            str(next_peak[1] - peak[1]), '\n',
                                            'Which is less than',
                                            str(trig_int)])
                            print(msg)
                        add = False
                        # Need to exit the loop here if false
                        break
                    else:
                        add = True
                if add:
                    if debug > 3:
                        msg = ' '.join(['Adding peak of', str(next_peak[0]),
                                        'at sample', str(next_peak[1])])
                        print(msg)
                    peaks.append(next_peak)
                elif debug > 3:
                    msg = ' '.join(['I did not add peak of', str(next_peak[0]),
                                    'at sample', str(next_peak[1])])
                    print(msg)

        if debug >= 3:
            from eqcorrscan.utils import plotting
            _fname = ''.join(['peaks_',
                              starttime.datetime.strftime('%Y-%m-%d'),
                              '.pdf'])
            plotting.peaks_plot(data=image, starttime=starttime,
                                samp_rate=samp_rate, save=True,
                                peaks=peaks, savefile=_fname)
        peaks = sorted(peaks, key=lambda time: time[1], reverse=False)
        return peaks
    else:
        print('No peaks for you!')
        return peaks

def find_peaks_dep(arr, thresh, trig_int, debug=0, starttime=False,
                   samp_rate=1.0):
    """
    Determine peaks in an array of data above a certain threshold: depreciated.

    Depreciated peak-finding routine, very slow, but accurate.  If all else \
    fails this one should work.

    :type arr: numpy.ndarray
    :param arr: 1-D numpy array is required
    :type thresh: float
    :param thresh: The threshold below which will be considered noise and \
        peaks will not be found in.
    :type trig_int: int
    :param trig_int: The minimum difference in samples between triggers,\
        if multiple peaks within this window this code will find the highest.
    :type starttime: obspy.core.utcdatetime.UTCDateTime
    :param starttime: Starttime for plotting, only used if debug > 2.
    :type samp_rate: float
    :param samp_rate: Sampling rate in Hz, only used for plotting if debug > 2.

    :return: peaks: Lists of tuples of peak values and locations.
    :rtype: list

    >>> import numpy as np
    >>> arr = np.random.randn(100)
    >>> threshold = 10
    >>> arr[40] = 20
    >>> arr[60] = 100
    >>> find_peaks_dep(arr, threshold, 3)
    [(20.0, 40), (100.0, 60)]
    """
    if not starttime:
        starttime = UTCDateTime(0)
    # Perform some checks
    if trig_int < 3:
        msg = 'Trigger interval must be greater than 2 samples to find maxima'
        raise IOError(msg)
    # from joblib import Parallel, delayed
    # Will find peaks in the absolute then transfer these to the true values
    sig = np.abs(arr) - thresh
    true_peaks = []
    for i in range(int(trig_int), int(len(sig) - trig_int), int(trig_int)):
        window = sig[i - trig_int: i + trig_int]
        # Define a moving window containing data from +/- the trigger iterval
        peaks = []
        locs = []
        for j in range(1, len(window) - 1):
            # Find all turning points within the window
            if window[j] > 0.0 and window[j] > window[j + 1] and\
               window[j] > window[j - 1]:
                peaks.append(window[j])
                locs.append(i - trig_int + j)
        # Find maximum peak in window
        if peaks:
            true_peaks.append((np.max(np.array(peaks)),
                               locs[np.argmax(np.array(peaks))]))
    # Get unique values
    peaks = sorted(list(set(true_peaks)), key=lambda loc: loc[1])
    # Find highest peak in peaks within trig_int of each other
    for i in range(1, len(peaks) - 1):
        if peaks[i + 1][1] - peaks[i][1] < trig_int:
            if peaks[i][0] < peaks[i + 1][0]:
                peaks[i] = peaks[i + 1]
            else:
                peaks[i + 1] = peaks[i]
        elif peaks[i][1] - peaks[i - 1][1] < trig_int:
            if peaks[i][0] < peaks[i - 1][0]:
                peaks[i] = peaks[i - 1]
            else:
                peaks[i - 1] = peaks[i]
    peaks = sorted(list(set(peaks)), key=lambda loc: loc[1])
    if debug >= 3:
        from eqcorrscan.utils import plotting
        _fname = ''.join(['peaks_',
                          starttime.datetime.strftime('%Y-%m-%d'),
                          '.pdf'])
        plotting.peaks_plot(arr, starttime, samp_rate, True, peaks,
                            _fname)
    peaks = [(peak[0] + thresh, peak[1]) for peak in peaks]
    return peaks

def coin_trig(peaks, stachans, samp_rate, moveout, min_trig, trig_int):
    """
    Find network coincidence triggers within peaks of detection statistics.

    Useful for finding network detections from sets of detections on individual
    stations.

    :type peaks: list
    :param peaks: List of lists of tuples of (peak, index) for each \
        station-channel.  Index should be in samples.
    :type stachans: list
    :param stachans: List of tuples of (station, channel) in the order of \
        peaks.
    :type samp_rate: float
    :param samp_rate: Sampling rate in Hz
    :type moveout: float
    :param moveout: Allowable network moveout in seconds.
    :type min_trig: int
    :param min_trig: Minimum station-channels required to declare a trigger.
    :type trig_int: float
    :param trig_int:
        Minimum allowable time between network triggers in seconds.

    :return:
        List of tuples of (peak, index), for the earliest detected station.
    :rtype: list

    >>> peaks = [[(0.5, 100), (0.3, 800)], [(0.4, 120), (0.7, 850)]]
    >>> triggers = coin_trig(peaks, [('a', 'Z'), ('b', 'Z')], 10, 3, 2, 1)
    >>> print(triggers)
    [(0.45, 100)]
    """
    triggers = []
    for stachan, _peaks in zip(stachans, peaks):
        for peak in _peaks:
            trigger = (peak[1], peak[0], '.'.join(stachan))
            triggers.append(trigger)
    coincidence_triggers = []
    for i, master in enumerate(triggers):
        slaves = triggers[i + 1:]
        coincidence = 1
        trig_time = master[0]
        trig_val = master[1]
        for slave in slaves:
            if abs(slave[0] - master[0]) <= (moveout * samp_rate) and \
               slave[2] != master[2]:
                coincidence += 1
                if slave[0] < master[0]:
                    trig_time = slave[0]
                trig_val += slave[1]
        if coincidence >= min_trig:
            coincidence_triggers.append((trig_val / coincidence,
                                         trig_time))
    # Sort by trigger-value, largest to smallest - remove duplicate detections
    if coincidence_triggers:
        coincidence_triggers.sort(key=lambda tup: tup[0], reverse=True)
        output = [coincidence_triggers[0]]
        for coincidence_trigger in coincidence_triggers[1:]:
            add = True
            for peak in output:
                # If the event occurs within the trig_int time then do not add
                # it, and break out of the inner loop.
                if abs(coincidence_trigger[1] - peak[1]) < (trig_int *
                                                            samp_rate):
                    add = False
                    break
            if add:
                output.append((coincidence_trigger[0],
                               coincidence_trigger[1]))
        output.sort(key=lambda tup: tup[1])
        return output
    else:
        return []

if __name__ == "__main__":
    import doctest
    doctest.testmod()


# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring

from pathlib import Path
import sys
from types import ModuleType

import mkdocs_gen_files  # type: ignore

import ipyvizzu

REPO_PATH = Path(__file__).parent / ".." / ".." / ".."
TOOLS_PATH = REPO_PATH / "tools"
MKDOCS_PATH = TOOLS_PATH / "docs"

sys.path.insert(0, str(TOOLS_PATH / "modules"))

from chdir import (  # pylint: disable=import-error, wrong-import-position, wrong-import-order
    chdir,
)
from vizzu import (  # pylint: disable=import-error, wrong-import-position, wrong-import-order
    Vizzu,
    VIZZU_SITE_URL,
)

class Reference:
    @staticmethod
    def generate(package: ModuleType, folder: str) -> None:
        for path in sorted(Path("src").rglob("*.py")):
            module_path = path.relative_to("src").with_suffix("")

            doc_path = path.relative_to("src").with_suffix(".md")
            full_doc_path = Path(folder, doc_path)

            parts = tuple(module_path.parts)

            if parts[-1] == "__main__":
                continue
            if parts[-1] == "__init__":
                parts = parts[:-1]
                doc_path = doc_path.with_name("index.md")
                full_doc_path = full_doc_path.with_name("index.md")

            item = ".".join(parts)
            if item == package.__name__:
                mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path)
                with mkdocs_gen_files.open(full_doc_path, "w") as f_md:
                    f_md.write(f"{package.__doc__}\n")
                    for item in package.__all__:
                        f_md.write(f"::: {package.__name__}.{item}\n")
                        f_md.write("    options:\n")
                        f_md.write("      show_root_members_full_path: false\n")
            else:
                mkdocs_gen_files.set_edit_path(full_doc_path, ".." / path)
                with mkdocs_gen_files.open(full_doc_path, "w") as f_md:
                    f_md.write(f"::: {item}")

    @staticmethod
    def generate_version_script(file: str) -> None:
        with mkdocs_gen_files.open(file, "w") as f_js:
            vizzu_version = Vizzu.get_vizzu_version()
            f_js.write(
                f"""
document.addEventListener("DOMContentLoaded", (event) => {{
  if (window.location.href.includes("/reference/")) {{
    const links = document.links;
    for (let i = 0; i < links.length; i++) {{
      if (
        links[i].hostname !== window.location.hostname &&
        links[i].href.includes("{VIZZU_SITE_URL}")
      ) {{
        links[i].href = links[i].href.replace("latest", "{vizzu_version}");
      }}
    }}
  }}
}});
            """
            )

def main() -> None:
    with chdir(REPO_PATH):
        Reference.generate(ipyvizzu, "reference")
        Reference.generate_version_script("assets/javascripts/codereflinks.js")

main()