import pytest

from unittest import TestCase
from flask import request
from webargs import flaskparser

from tests import factories
from tests.common import ApiBaseTest

from webservices import args
from webservices import rest
from webservices import sorting
from webservices.resources import candidate_aggregates
from webservices.resources import elections
from webservices.rest import db
from webservices import utils
from webservices.common import models

class TestSort(ApiBaseTest):
    def test_single_column(self):
        candidates = [
            factories.CandidateFactory(district='01'),
            factories.CandidateFactory(district='02'),
        ]
        query, columns = sorting.sort(
            models.Candidate.query, 'district', model=models.Candidate
        )
        self.assertEqual(query.all(), candidates)

    def test_single_column_reverse(self):
        candidates = [
            factories.CandidateFactory(district='01'),
            factories.CandidateFactory(district='02'),
        ]
        query, columns = sorting.sort(
            models.Candidate.query, '-district', model=models.Candidate
        )
        self.assertEqual(query.all(), candidates[::-1])

    def test_multi_column(self):
        audit = [
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Boy',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Girl',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Ted',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Zoo',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2014,
                committee_name='Abc',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2014,
                committee_name='John',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2014,
                committee_name='Ted',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
        ]
        query, columns = sorting.multi_sort(
            models.AuditCase.query, ['cycle', 'committee_name', ], model=models.AuditCase
        )
        self.assertEqual(query.all(), audit)

    def test_multi_column_reverse_first_column(self):
        audit = [
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Zoo',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Ted',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Girl',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2012,
                committee_name='Abc',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2014,
                committee_name='Ted',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2014,
                committee_name='John',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
            factories.AuditCaseFactory(
                cycle=2014,
                committee_name='Abc',
                primary_category_id=-1,
                sub_category_id=-2,
                audit_case_id=1000,
            ),
        ]
        query, columns = sorting.multi_sort(
            models.AuditCase.query,
            ['-cycle', 'committee_name', ],
            model=models.AuditCase,
        )
        self.assertEqual(query.all(), audit[::-1])

    def test_hide_null(self):
        candidates = [
            factories.CandidateFactory(district='01'),
            factories.CandidateFactory(district='02'),
            factories.CandidateFactory(),
        ]
        query, columns = sorting.sort(
            models.Candidate.query, 'district', model=models.Candidate
        )
        self.assertEqual(query.all(), candidates)
        query, columns = sorting.sort(
            models.Candidate.query, 'district', model=models.Candidate, hide_null=True
        )
        self.assertEqual(query.all(), candidates[:2])

    def test_hide_null_candidate_totals(self):
        candidates = [
            factories.CandidateFactory(candidate_id='C1234'),
            factories.CandidateFactory(candidate_id='C5678'),
        ]
        candidateHistory = [  # noqa
            factories.CandidateHistoryFutureFactory(
                candidate_id='C1234',
                two_year_period=2016,
                election_years=[2016],
                cycles=[2016],
                candidate_election_year=2016,
            ),
            factories.CandidateHistoryFutureFactory(
                candidate_id='C5678',
                two_year_period=2016,
                election_years=[2016],
                cycles=[2016],
                candidate_election_year=2016,
            ),
        ]
        candidateTotals = [  # noqa
            factories.CandidateTotalFactory(
                candidate_id='C1234', is_election=False, cycle=2016
            ),
            factories.CandidateTotalFactory(
                candidate_id='C5678',
                disbursements='9999.99',
                is_election=False,
                cycle=2016,
            ),
        ]
        candidateFlags = [  # noqa
            factories.CandidateFlagsFactory(candidate_id='C1234'),
            factories.CandidateFlagsFactory(candidate_id='C5678'),
        ]

        tcv = candidate_aggregates.TotalsCandidateView()
        query, columns = sorting.sort(
            tcv.build_query(election_full=False), 'disbursements', model=None
        )
        self.assertEqual(len(query.all()), len(candidates))
        query, columns = sorting.sort(
            tcv.build_query(election_full=False),
            'disbursements',
            model=None,
            hide_null=True,
        )
        self.assertEqual(len(query.all()), len(candidates) - 1)
        self.assertTrue(candidates[1].candidate_id in query.all()[0])

    def test_hide_null_election(self):
        candidates = [
            factories.CandidateFactory(candidate_id='C1234'),
            factories.CandidateFactory(candidate_id='C5678'),
        ]
        cmteFacorty = [  # noqa
            factories.CommitteeDetailFactory(committee_id='H1234'),
            factories.CommitteeDetailFactory(committee_id='H5678'),
        ]
        db.session.flush()
        candidateHistory = [  # noqa
            factories.CandidateHistoryFactory(
                candidate_id='C1234',
                two_year_period=2016,
                state='MO',
                candidate_election_year=2016,
                candidate_inactive=False,
                district='01',
                office='S',
                election_years=[2016],
                cycles=[2016],
            ),
            factories.CandidateHistoryFactory(
                candidate_id='C5678',
                candidate_election_year=2016,
                two_year_period=2016,
                state='MO',
                election_years=[2016],
                cycles=[2016],
                candidate_inactive=False,
                district='02',
                office='S',
            ),
        ]
        candidateCmteLinks = [  # noqa
            factories.CandidateCommitteeLinkFactory(
                committee_id='H1234',
                candidate_id='C1234',
                fec_election_year=2016,
                committee_designation='P',
                election_yr_to_be_included=2016,
            ),
            factories.CandidateCommitteeLinkFactory(
                committee_id='H5678',
                candidate_id='C5678',
                fec_election_year=2016,
                committee_designation='P',
                election_yr_to_be_included=2016,
            ),
        ]
        cmteTotalsFactory = [  # noqa
            factories.CommitteeTotalsHouseSenateFactory(
                committee_id='H1234', cycle=2016
            ),
            factories.CommitteeTotalsHouseSenateFactory(
                committee_id='H1234', cycle=2016, disbursements='9999.99'
            ),
            factories.CommitteeTotalsHouseSenateFactory(
                committee_id='H5678', cycle=2016
            ),
        ]
        db.session.flush()

        electionView = elections.ElectionView()
        query, columns = sorting.sort(
            electionView.build_query(office='senate', cycle=2016, state='MO'),
            'total_disbursements',
            model=None,
        )

        # print(str(query.statement.compile(dialect=postgresql.dialect())))
        self.assertEqual(len(query.all()), len(candidates))
        query, columns = sorting.sort(
            electionView.build_query(office='senate', cycle=2016, state='MO'),
            'total_disbursements',
            model=None,
            hide_null=True,
        )
        # Taking this assert statement out because I believe, at least how the FEC interprets null (i.e. none) primary
        # committees for a candidate is that they have in fact raised/spent 0.0 dollars, this can be shown as true
        # using the Alabama special election as an example
        # self.assertEqual(len(query.all()), len(candidates) - 1)
        self.assertTrue(candidates[1].candidate_id in query.all()[0])
        self.assertEqual(query.all()[0].total_disbursements, 0.0)

class TestArgs(TestCase):
    def test_currency(self):
        with rest.app.test_request_context('?dollars=$24.50'):
            parsed = flaskparser.parser.parse({'dollars': args.Currency()}, request, location='query')
            self.assertEqual(parsed, {'dollars': 24.50})

class TestEnvVarSplit(TestCase):
    def test_env_var_split(self):
        test_cases = [
            "1.2.3.4, 5.6.7.8",
            "1.2.3.4,  5.6.7.8",
            "1.2.3.4,5.6.7.8",
            " 1.2.3.4,  5.6.7.8 ",
        ]
        expected = ["1.2.3.4", "5.6.7.8"]
        for test_case in test_cases:
            result = utils.split_env_var(test_case)
            self.assertEqual(result, expected)

class TestPercentages(TestCase):
    def test_get_percentage(self):
        test_cases = [
            ([3], [9], 33.33),
            ([2, 3], [10], 50.0),
            ([1, 2, 3], [10], 60.0),
            ([2], [5, 5], 20.0),
            ([0], [10], 0),
            ([0, 0, 0], [10], 0),
            # Unusual but should still calculate
            ([10], [5], 200.0),  # Over 100%
            ([-5], [10], -50.0),  # Negative numerator
            ([5], [-10], -50.0),  # Negative denominator
            ([-5], [-10], 50.0),  # Both negative
            ([1], [10000], .01),  # Under 1%
            # None == Unable to calculate
            # Divide by zero
            ([1, 2, 3], [0], None),
            # Null values
            ([None], [None], None),
            ([0], [None], None),
            ([None], [100], None),
            ([], [], None),
            ([1, None, 3], [10], None),
        ]
        for test_case in test_cases:
            numerators, denominators, expected = test_case
            result = utils.get_percentage(numerators, denominators)
            self.assertEqual(result, expected)

        # Developer forgets to put values in list
        with pytest.raises(TypeError):
            utils.get_percentage(5, 10)


import cupy as cp

from concurrent.futures.thread import ThreadPoolExecutor
from concurrent.futures import as_completed
import time
from vs_knn.vs_knn import CupyVsKnnModel
import pickle

class SimpleModel:
    def __init__(self):
        pass

    def predict(self, N, power, use_own_stream=True):

        if use_own_stream:
            compute_stream = cp.cuda.stream.Stream(non_blocking=True)
            compute_stream.use()
        d_mat = cp.random.randn(N * N, dtype=cp.float64).reshape(N, N)
        d_ret = d_mat

        cp.matmul(d_ret, d_mat)

        start = time.time()
        for i in range(power - 1):
            d_ret = cp.matmul(d_ret, d_mat)

        pre_synch = time.time()
        if use_own_stream:
            compute_stream.synchronize()

        return pre_synch - start, time.time() - pre_synch

sm_model = SimpleModel()
vsk_model = CupyVsKnnModel()
vsk_model.load('../saved_model')
# with open('../test_data.pkl', 'rb') as f:
#     test_array = pickle.load(f)

def multi_thread_calls(model, inputs, use_own_stream=True):

    presynch_time, synch_time, pct_time = [], [], []
    start = time.time()
    with ThreadPoolExecutor(20) as executor:
        futures = []
        for in_params in inputs:
            futures.append(executor.submit(model.predict, **in_params, use_own_stream=use_own_stream))
            # futures.append(executor.submit(model.predict, in_params['x'], use_cuda_streams))
        for future in as_completed(futures):
            pre_synch, synch = future._result
            presynch_time.append(pre_synch)
            synch_time.append(synch)
            gpu_pct = round((100 * synch) / (synch + pre_synch), 2)
            pct_time.append(gpu_pct)

    print(f"CPU time: {sum(presynch_time)}, GPU time {sum(synch_time)}, GPU% = {sum(pct_time) / len(pct_time)}")

    p_res = f"ran {len(inputs)} calls in {time.time() - start} seconds."
    p_res = p_res + " Using CUDA streams" if use_own_stream else p_res + "NOT using CUDA steams"
    print(p_res)

if __name__ == '__main__':
    sm_calls = 4
    vsk_calls = 1000
    sm_input = [{'N': 1024, 'power': 256}] * sm_calls
    vsk_input = [{'queries': [214716935]}] * vsk_calls

    multi_thread_calls(sm_model, sm_input,  True)
    multi_thread_calls(sm_model, sm_input,  False)
    multi_thread_calls(vsk_model, vsk_input,  True)
    multi_thread_calls(vsk_model, vsk_input,  False)


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Ruta al ejecutable de ChromeDriver
driver = webdriver.Chrome()

# Abre WhatsApp Web en el navegador Brave
driver.get('https://web.whatsapp.com')

# Espera a que el usuario escanee el código QR manualmente

# Encuentra el campo de búsqueda y escribe el nombre del contacto o grupo
wait = WebDriverWait(driver, 10)
search_box = wait.until(EC.presence_of_element_located((By.XPATH, '//div[@contenteditable="true"]')))
search_box.send_keys('Sistemas 2023 Deltec')

# Espera un segundo para que aparezcan los resultados
driver.implicitly_wait(4)

# Abre la conversación
search_box.send_keys(Keys.RETURN)

# Espera un segundo para que la conversación se cargue completamente
driver.implicitly_wait(4)

contacto = driver.find_element(By.XPATH, '(//*[@role="listitem"])[1]')
contacto.click()
driver.implicitly_wait(3)
# Encuentra el cuadro de texto para el mensaje y escribe tu mensaje
message_box = wait.until(EC.presence_of_element_located((By.XPATH, '(//div[@contenteditable="true"])[2]')))
message_box.send_keys('HOLA DESDE PYTHON LOKAS')

# Envía el mensaje
message_box.send_keys(Keys.RETURN)
send = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@aria-label="Send" or @aria-label="Enviar"]')))
driver.implicitly_wait(5)
send.click()
driver.implicitly_wait(5)
# Cierra el navegador cuando hayas terminado
driver.quit()


import os
import re
from bs4 import BeautifulSoup as bs
from collections import Counter
from nltk.tokenize import word_tokenize
from nltk.util import ngrams
import json

raw_dir = "" # Path to original novel files in xml format
clean_files_dir = "" # Path for saving cleaned text files of each novel

def get_files(directory):
    """Get a list of file paths for a given directory"""
    file_paths = []
    for filename in os.listdir(directory):
        f = os.path.join(directory, filename)

        if os.path.isfile(f) and f.endswith("xml") or f.endswith("txt"):
            file_paths.append(f)
    return file_paths

def get_author_names(directory, out_file):
    """Creates a file listing all authors (and their years of living) in the raw data."""
    novel_files = get_files(directory)
    names = []

    for file_name in novel_files:
        with open(file_name, "r", encoding="utf8") as file:
            content = file.readlines()
            content = "".join(content)
            bs_content = bs(content, "lxml")
            author = str(bs_content.find("author").string)
            if author not in names:
                names.append(author)

    # Save to file
    with open(out_file, "w", encoding = "utf8") as f:
        for name in names:
            f.write(f"{name}\n")

def create_info(corpus_obj, outfile):
    """Create a tab separated text file listing all authors, their number of works and number of
    tokens. Input is a corpus class object. An existing tokenized json corpus is required"""
    author_info = {}
    for author in corpus_obj.corpus:
        n_texts = len(corpus_obj.corpus[author])
        total_tokens = 0
        gender = author[-1]

        for text in corpus_obj.corpus[author]:
            token_counts = len(corpus_obj.corpus[author][text])
            total_tokens += token_counts

        author_info[author[:-3]] = [n_texts, total_tokens, gender]

    # Save to file
    with open(outfile, "w", encoding = "utf8") as f:
        f.write("{:<30}{:<10}{:<10}{:<10}\n".format("Author", "Works", "Tokens", "Gender"))
        for name in author_info:
            f.write("{:<30}{:<10}{:<10}{:<10}\n".format(name, author_info[name][0], author_info[name][1], author_info[name][2]))
        f.write("\n")
        f.write(f"Number of authors: {len(author_info)}\n")
        f.write(f"Number of works: {sum([v[0] for v in author_info.values()])}")

def create_clean_files(directory):
    """Preprocess all xml file novels and saves them to new text files."""
    novel_files = get_files(directory)
    print(len(novel_files))
    for i, file in enumerate(novel_files):
        print(i)
        print(f"Processing {file}")
        novel = Novel(file)
        novel.prepare_data()

def load_author_names(filename):
    """Get a list of author names and genders from an existing text file."""
    authors = []
    with open(filename, "r", encoding="utf8") as f:
        for line in f:
            author = line.split("\t")[0]
            gender = line.split("\t")[1]
            name = author[:-12]
            name_gender = name + "@@" + gender.strip()
            authors.append(name_gender)
    return authors

class Novel:
    """Class for preprocessing and saving a novel from an xml file."""
    def __init__(self, file_path):
        with open(file_path, "r", encoding="utf8") as file:
            content = file.readlines()
            content = "".join(content)
            bs_content = bs(content, "lxml")

            self.raw_text = (bs_content.find("body"))
            self.novel_text = self.clean_text(self.raw_text)
            self.author = str(bs_content.find("author").string)
            self.title = str(bs_content.find("title").string)

    def clean_text(self, raw_text):
        """Removes unwanted characters."""
        cleaned = str(raw_text).replace("<lb></lb>", "")
        cleaned = str(cleaned).replace('»', '').replace("«", "")
        cleaned = re.sub(r'<.*>', '', cleaned)
        cleaned = cleaned.replace("\n", " ")
        cleaned = re.sub('\s\s+', ' ', cleaned)
        cleaned = cleaned.replace(u'\u00AD', "@")
        cleaned = re.sub(r'@\W', "", cleaned)
        cleaned = re.sub('\s\s+', '', cleaned)
        return cleaned

    def write_to_file(self, text, name, filepath):
        complete_name = os.path.join(filepath, name)
        with open(complete_name, "w", encoding="utf8") as file:
            file.write(text)

    def prepare_data(self):
        """Creates a filename and saves the novel to a file."""
        author_name = self.author[:-12].split()
        author_name = "_".join(author_name)
        title_name = self.title.split()
        title_name = "_".join(title_name)
        title_name = re.sub("[.,:?*»«]", "", title_name)
        title_name = title_name[:100]

        # Write the cleaned text of the novel to a file, all on one line without tokenization.
        clean_file = author_name + "_" + title_name + "_clean.txt"
        self.write_to_file(self.novel_text, clean_file, clean_files_dir)

class Corpus:
    """Class for creating and managing a corpus with authors and their works."""
    def __init__(self, authors):
        self.authors = authors
        self.corpus = None

    def create_authors_corpus(self, data_dir, tokenize=False):
        """Creates a nested dictionary with author name, names of each text for the author, and the texts in themselves.
        If tokenize = True, it has the format {'Author 1': {'name of text 1' : ['token1', token2'], 'name of text 2': ['token1', token2']}, 'Author 2': ...}
        If tokenize = False, it has the format {'Author 1': {'name of text 1' : 'words in string 1', 'name of text 2': 'words in string 2'}, 'Author 2': ...}
        """
        corpus = {}
        files = get_files(data_dir)

        for path in files:
            file_name = path.split("_")
            file_name = " ".join(file_name)
            file_name = re.sub("C:.*\\\\", "", file_name)

            with open(path, "r", encoding="utf8") as f:
                text = f.readlines()[0]
                text = text.lower()

            if tokenize == True:
                text = word_tokenize(text, language="swedish")

            for i, author_name in enumerate(self.authors):
                if author_name[:-3] in file_name:
                    text_name = re.sub(author_name[:-3], "", file_name)
                    text_name = re.sub("clean", "", text_name)
                    text_name = re.sub(" .txt", "", text_name)
                    text_name = text_name.strip()

                    if author_name in corpus:
                        corpus[self.authors[i]][text_name] = text
                    else:
                        corpus[self.authors[i]] = {text_name : text}
        self.corpus = corpus

        if tokenize == True:
            filename = "author_corpus_tok.json"
        else:
            filename = "author_corpus.json"

        with open(filename, "w", encoding="utf8") as file:
            json.dump(self.corpus, file)

        return self.corpus

    def load_corpus(self, tokenized=False):
        if tokenized == True:
            filename = "author_corpus_tok.json"
        else:
            filename = "author_corpus.json"

        with open(filename, "r", encoding="utf8") as file:
            data = json.load(file)
            self.corpus = data
            print(f"Loaded {filename}")

def load_features(feature_type, ngram=None):
    """Load a file with feature words into a list. Available feature types are 'freq_250',
    freq_140', 'freq_120', 'freq_22', 'ngrams'"""
    features = []
    if feature_type == "freq_250":
        filename = "top_250_tokens.txt"
    elif feature_type == "freq_120":
        filename = "top_120_tokens.txt"
    elif feature_type == "freq_140":
        filename = "top_140_tokens.txt"
    elif feature_type == "freq_22":
        filename = "top_22_tokens.txt"

    elif feature_type == "ngrams":
        if ngram == 4:
            filename = "top_4_grams.txt"
        elif ngram == 5:
            filename = "top_5_grams.txt"
        elif ngram == 6:
            filename = "top_6_grams.txt"
        elif ngram == 7:
            filename = "top_7_grams.txt"
        else:
            print("There is no file with the specified ngram size.")
            return

    with open(filename, "r", encoding="utf8") as file:
        for line in file:
            if ngram == None:
                features.append(line.strip())
            else:
                line = line.replace("\n", "")
                features.append(line)

    return features

def check_features(feature_type, corpus, ngram=None, tokenize=True):
    """Counts how many of the features in the specified feature set that do not occur in all the texts"""
    not_in_all = []
    features = load_features(feature_type, ngram)

    for author in corpus:
        list_of_texts = corpus[author].values()

        for text in list_of_texts:
            if tokenize == False:
                    characters = [c for c in text]
                    ngram_tuples = list(ngrams(characters, ngram))
                    joined_ngrams = ["".join(t) for t in ngram_tuples]
                    novel = joined_ngrams
            else:
                novel = text

            for feature in features:
                feature = feature.strip("\n")
                if feature not in novel:
                    not_in_all.append(feature)

    result = Counter(not_in_all)
    return result

def get_top_n_words(files_dir, n):
    """Get the top n most frequent words in all files from a directory, and write the words to a file."""
    all_counts = Counter()
    files = get_files(files_dir)

    for file in files:
        with open(file, "r", encoding="utf8") as f:
            text = f.readlines()[0]
            text = word_tokenize(text.lower(), language="swedish")
        token_counts = Counter(text)
        all_counts += token_counts
    top_n = all_counts.most_common(350)
    top_n = [tup[0] for tup in top_n]

    filename = "top_" + str(n) + "_tokens.txt"
    with open(filename, "w", encoding="utf8") as file:
        for token in top_n:
            file.write(token)
            file.write("\n")
    print(f"Created {filename}")

def get_top_ngrams(files_dir, n, length):
    """Get the {length} most frequent ngrams in all files from a directory, and write the words to a file.
    n: ngram size"""
    all_counts = Counter()
    files = get_files(files_dir)
    for file in files:
        with open(file, "r", encoding="utf8") as f:
            text = f.readlines()[0]
            text = text.lower()

        characters = [c for c in text]
        ngram_tuples = ngrams(characters, n)
        ngram_counts = Counter(ngram_tuples)
        all_counts += ngram_counts

    top_ngrams = all_counts.most_common(length)
    top_ngrams = [tup[0] for tup in top_ngrams]
    ngram_list = ["".join(t) for t in top_ngrams]

    filename = "top_" + str(n) + "_grams" + ".txt"
    with open(filename, "w", encoding="utf8") as file:
        for token in ngram_list:
            file.write(token)
            file.write("\n")
    print(f"Created {filename}")

def create_feature_files():
    """Create all the feature files to use as style representations"""
    get_top_ngrams(clean_files_dir, 4, 2500)
    get_top_ngrams(clean_files_dir, 5, 2500)
    get_top_ngrams(clean_files_dir, 6, 2500)
    get_top_ngrams(clean_files_dir, 7, 2500)
    get_top_n_words(clean_files_dir, 22)
    get_top_n_words(clean_files_dir, 120)
    get_top_n_words(clean_files_dir, 140)
    get_top_n_words(clean_files_dir, 250)

def remove_uncommon_features(feature_file, corpus, limit, feature_type, ngram, n, tokenize):
    """Removes features that do not occur in a high number of texts. This number is set using 'limit'.
       n: the intended number of features in the file."""
    uncommon = check_features(feature_type, corpus, ngram, tokenize)
    uncommon = dict(uncommon)
    remove = []
    for token in uncommon.keys():
        if uncommon[token] > limit:
            remove.append(token)

    filtered_features = []
    features = []
    with open(feature_file, "r", encoding="utf8") as file:
        for line in file:
            if ngram == None:
                features.append(line.strip())
            else:
                line = line.replace("\n", "")
                features.append(line)

    for feature in features:
        if feature not in remove:
            filtered_features.append(feature)

    filtered_features = filtered_features[:n]

    with open(feature_file, "w", encoding="utf8") as f:
        for token in filtered_features:
            f.write(token + "\n")
    print(f"Filtered {feature_file}")

def filter_features(corpus_obj):
    """Filter out uncommon features from all feature sets."""
    corpus_obj.load_corpus(tokenized=True)
    corpus = corpus_obj.corpus
    remove_uncommon_features("top_22_tokens.txt", corpus, 124, "freq_22", ngram=None, n=22, tokenize=True)
    remove_uncommon_features("top_120_tokens.txt", corpus, 124, "freq_120", ngram=None, n=120, tokenize=True)
    remove_uncommon_features("top_140_tokens.txt", corpus, 124, "freq_140", ngram=None, n=140, tokenize=True)
    remove_uncommon_features("top_250_tokens.txt", corpus, 124, "freq_250", ngram=None, n=250, tokenize=True)

    corpus_obj.load_corpus(tokenized=False)
    corpus = corpus_obj.corpus
    remove_uncommon_features("top_5_grams.txt", corpus, 124, "ngrams", ngram=5, n=2000, tokenize=False)
    remove_uncommon_features("top_6_grams.txt", corpus, 124, "ngrams", ngram=6, n=2000, tokenize=False)
    remove_uncommon_features("top_7_grams.txt", corpus, 124, "ngrams", ngram=7, n=2000, tokenize=False)
    remove_uncommon_features("top_4_grams.txt", corpus, 124, "ngrams", ngram=4, n=2000, tokenize=False)

def count_tokens_in_texts(files_dir):
    """Counts the number of tokens in each text and prints the longest and shortest counts."""
    counts = []
    files = get_files(files_dir)
    for file in files:
        with open(file, "r", encoding="utf8") as f:
            text = f.readlines()[0]
        text = word_tokenize(text.lower(), language="swedish")
        count = len(text)
        counts.append(count)
    print(counts)
    print(f"shortest: {min(counts)}")
    print(f"longest: {max(counts)}")

def remove_token(token, directory):
    """Ad-hoc function. Used to remove single token types in all cleaned text
       found upon manual inspection after initial cleaning and file creation."""
    files = get_files(directory)
    for file in files:
        with open(file, "r", encoding="utf8") as f:
            content = f.readlines()
        if token in content[0]:
            new_text = content[0].replace(token, "")
            with open(file, "w", encoding="utf8") as f:
                f.write(new_text)
            print("removed token")

def main():
    print("Creating clean files...")
    create_clean_files(raw_dir) # Create cleaned files from raw xml data
    print("File creation done.")
    get_author_names(raw_dir, "author_names.txt") # Create file with author names. Genders need to be added manually into
                                                # this file before use in load_author_names()
    authors = load_author_names("author_names.txt") # Get author names from saved file
    novel_corpus = Corpus(authors) # Create corpus object with authors

    print("Creating corpora...")
    novel_corpus.create_authors_corpus(clean_files_dir, tokenize=True) # Create json file with tokenized novels
    novel_corpus.create_authors_corpus(clean_files_dir, tokenize=False) # Create json file with novels as strings
    print("Corpus creation done.")

    novel_corpus.load_corpus(tokenized=True)
    create_info(novel_corpus, "info_1.txt") # Create information on existing authors in the corpus and save to file
    print("Info file created.")

    print("Creating feature files...")
    create_feature_files() # Create lists of features saved in textfiles
    print("Filtering features...")
    filter_features(novel_corpus) # Filter out uncommon features and create new files

    print("The novel data is ready to use in classification/similarity calculations.")

if __name__ == "__main__":
    main()


import math
import skimage.graph
import numpy as np

from skimage.graph import route_through_array
from skimage.draw import circle as disk

def _get_max_of_image_between_two_points(im, x0, y0, x1, y1):
    n_points = int(np.hypot(x1 - x0, y1 - y0))
    x_between, y_between = np.linspace(x0, x1, n_points), np.linspace(y0, y1, n_points)
    z_between = im[y_between.astype(np.uint8), x_between.astype(np.uint8)]
    z_argmax = np.argmax(z_between)
    x_max, y_max, z_max = x_between[z_argmax], y_between[z_argmax], np.max(z_between)
    return z_max, (y_max, x_max)

def _get_cost_arrays_for_each_route(heatmap, landmarks, raise_to_power=4, block_cost=10, use_smaller_radius=False):
    heatmap_epi, heatmap_end = heatmap
    lv_x, lv_y = landmarks[2]
    (rv_ant_x, rv_ant_y), (rv_inf_x, rv_inf_y) = landmarks[:2]
    cost_epi = (1 - heatmap_epi) ** raise_to_power
    cost_end = (1 - heatmap_end) ** raise_to_power

    # outer paths (inner blocked)
    rv_mid_x, rv_mid_y = int(rv_ant_x + rv_inf_x) // 2, int(rv_ant_y + rv_inf_y) // 2
    double_rv_mid_x, double_rv_mid_y = lv_x + (rv_mid_x - lv_x) * 2, lv_y + (rv_mid_y - lv_y) * 3
    # print("inner")
    _, (inner_circle_y, inner_circle_x) = _get_max_of_image_between_two_points(heatmap_epi,
                                                                               double_rv_mid_x, double_rv_mid_y,
                                                                               lv_x, lv_y)

    inner_circle_radius = math.sqrt((rv_ant_x - rv_inf_x) ** 2 + (rv_ant_y - rv_inf_y) ** 2) * 0.3
    rr, cc = disk(inner_circle_y, inner_circle_x, inner_circle_radius//2 if use_smaller_radius else inner_circle_radius, shape=cost_epi.shape)

    # ended up dividing by 2 as sometimes so large it interferes... this seems to work, ugly!
    # See 'T1T2_141613_57381537_57381545_528_20201116-134335__T1_T2_PD_SLC0_CON0_PHS0_REP0_SET0_AVE0_1.npy' for e.g.

    cost_outer_epi = cost_epi.copy()
    cost_outer_epi[rr, cc] = block_cost
    cost_outer_end = cost_end.copy()
    cost_outer_end[rr, cc] = block_cost

    # inner paths (outer blocked)
    double_opposite_x, double_opposite_y = lv_x - (rv_mid_x - lv_x) * 2, lv_y - (rv_mid_y - lv_y) * 3
    # print("outer")
    _, (outer_circle_y, outer_circle_x) = _get_max_of_image_between_two_points(heatmap_epi,
                                                                               double_opposite_x, double_opposite_y,
                                                                               lv_x, lv_y)

    outer_circle_radius = math.sqrt((outer_circle_x - lv_x) ** 2 + (outer_circle_y - lv_y) ** 2)
    rr, cc = disk(outer_circle_y, outer_circle_x, outer_circle_radius, shape=cost_epi.shape)
    cost_inner_epi = cost_epi.copy()
    cost_inner_epi[rr, cc] = block_cost
    cost_inner_end = cost_end.copy()
    cost_inner_end[rr, cc] = block_cost

    # import matplotlib.pyplot as plt
    # plt.imshow(cost_outer_epi)
    # plt.show()
    # plt.imshow(cost_inner_epi)
    # plt.show()

    return cost_outer_epi, cost_inner_epi, cost_outer_end, cost_inner_end

def _get_landmarks_on_epi_and_end(heatmap, landmarks):
    lv_x, lv_y = landmarks[2]
    # print("epi ant")
    _epi_ant_conf, (epi_ant_y, epi_ant_x) = _get_max_of_image_between_two_points(heatmap[0],
                                                                                *landmarks[0],
                                                                                lv_x,
                                                                                lv_y)
    # print("epi inf")
    _epi_inf_conf, (epi_inf_y, epi_inf_x) = _get_max_of_image_between_two_points(heatmap[0],
                                                                                *landmarks[1],
                                                                                lv_x,
                                                                                lv_y)
    # print("end ant")
    _end_ant_conf, (end_ant_y, end_ant_x) = _get_max_of_image_between_two_points(heatmap[1],
                                                                                *landmarks[0],
                                                                                lv_x,
                                                                                lv_y)
    # print("end inf")
    _end_inf_conf, (end_inf_y, end_inf_x) = _get_max_of_image_between_two_points(heatmap[1],
                                                                                *landmarks[1],
                                                                                lv_x,
                                                                                lv_y)

    return (epi_ant_x, epi_ant_y), (epi_inf_x, epi_inf_y), (end_ant_x, end_ant_y), (end_inf_x, end_inf_y)

def _get_path_for_cost_array_and_coords(cost_array, coord_from, coord_to):
    coord_from = [int(round(c)) for c in coord_from]
    coord_to = [int(round(c)) for c in coord_to]
    path, _cost = route_through_array(cost_array, coord_from, coord_to)
    return path

def get_epi_end_paths_from_heatmap_and_landmarks(heatmap, landmarks):
    (epi_ant_x, epi_ant_y), (epi_inf_x, epi_inf_y), (end_ant_x, end_ant_y), (end_inf_x, end_inf_y) = \
        _get_landmarks_on_epi_and_end(heatmap, landmarks)

    cost_outer_epi, cost_inner_epi, cost_outer_end, cost_inner_end = _get_cost_arrays_for_each_route(heatmap, landmarks)

    path_epi_inner = _get_path_for_cost_array_and_coords(cost_inner_epi, (epi_ant_y, epi_ant_x), (epi_inf_y, epi_inf_x))
    path_epi_outer = _get_path_for_cost_array_and_coords(cost_outer_epi, (epi_inf_y, epi_inf_x), (epi_ant_y, epi_ant_x))
    path_end_inner = _get_path_for_cost_array_and_coords(cost_inner_end, (end_ant_y, end_ant_x), (end_inf_y, end_inf_x))
    path_end_outer = _get_path_for_cost_array_and_coords(cost_outer_end, (end_inf_y, end_inf_x), (end_ant_y, end_ant_x))
    path_epi = path_epi_inner + path_epi_outer
    path_end = path_end_inner + path_end_outer

    ys_epi, xs_epi = np.array(path_epi).transpose((1, 0))
    ys_end, xs_end = np.array(path_end).transpose((1, 0))

    return (xs_epi, ys_epi), (xs_end, ys_end)


# IAP-2017_MIT_CSAIL-HCIE: Parinya Punpongsanon

import cv2
import numpy as np

# Camera 0 is the integrated web cam on a netbook or the one with USB cable (Camera 1)
camera_port = 1

#Number of frames to throw away while the camera adjusts to light levels
ramp_frames = 30

# Now we can initialize the camera capture object with the cv2.VideoCapture class.
# All it needs is the index to a camera port.
camera = cv2.VideoCapture(camera_port)

# Captures a single image from the camera and returns it in PIL format
def get_image():
 # read is the easiest way to get a full image out of a VideoCapture object.
 retval, im = camera.read()
 return im

# Ramp the camera - these frames will be discarded and are only used to allow v4l2
# to adjust light levels, if necessary
for i in xrange(ramp_frames):
	temp = get_image()
print("Taking image...")

# Take the actual image we want to keep
camera_capture = get_image()
file = "test_image.png"

# A nice feature of the imwrite method is that it will automatically choose the
# correct format based on the file extension you provide. Convenient!
cv2.imwrite(file, camera_capture)

# Capture and display in real-time
while(True):
    # Capture frame-by-frame
    ret, frame = camera.read()

    # Our operations on the frame come here
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # Display the resulting frame
    cv2.imshow('frame',hsv)

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

# When everything done, release the capture
cv2.destroyAllWindows()

# You'll want to release the camera, otherwise you won't be able to create a new
# capture object until your script exits
del(camera)


"""
06/31/2019
Each passed in batch must contain info:
    1. method of model to save itself
    2. the way to parsing the batch keys
    3. meta information of each sample
    4. batch head (phase)
Logger can be selected from init file
"""
import os
from tensorboardX import SummaryWriter as writer
from .logger_meta import LOGGER_REGISTED
from copy import deepcopy
import logging

class Logger(object):

    def __init__(self, cfg):
        self.cfg = deepcopy(cfg)
        tb_path = os.path.join(cfg['root'], 'log', cfg['logging']['log_dir'], 'tensorboardx')
        self.tb_writer = writer(tb_path)
        self.logger_list = self.compose(self.cfg['logging']['loggers'])
        return

    def compose(self, names):
        loggers_list = list()
        mapping = LOGGER_REGISTED
        for name in names:
            if name in mapping.keys():
                loggers_list.append(mapping[name](self.tb_writer, os.path.join(
                    os.path.join(self.cfg['root'], 'log', self.cfg['logging']['log_dir'], name)), self.cfg))
            else:
                raise Warning('Required logger ' + name + ' not found!')
        logging.debug("Loggers [{}] registered".format(names))
        return loggers_list

    def log_phase(self):
        for lgr in self.logger_list:
            lgr.log_phase()

    def log_batch(self, batch):
        for lgr in self.logger_list:
            lgr.log_batch(batch)

    def end_log(self):
        for lgr in self.logger_list:
            lgr.log_phase()


# -*- coding: utf-8 -*-
from tornado.httpclient import AsyncHTTPClient, HTTPRequest

class BaseInterface:

    def __init__(self):
        self.client = AsyncHTTPClient()
        self.request_params = None

    async def communicate(self,** request_params):
        """
        Communicate with remote server with request_params.
        :param request_params: Query arguments. Please refer to:
        http://www.tornadoweb.org/en/stable/httpclient.html#request-objects
        :return: Response from server. tornado.httpclient.HTTPResponse instance
        """
        self.request_params = request_params
        try:
            response = await self.client.fetch(HTTPRequest(**self.request_params,
                                                           allow_nonstandard_methods=True))
        except Exception as e:
            await self.on_failure(e)
            raise e
        else:
            await self.on_success(response)
            return response

    async def on_success(self, response):
        """
        This method will be called if no error occurred.
        :param response:
        :return:
        """
        pass

    async def on_failure(self, error):
        """
        This method will be called if any error occurred.
        :param error:
        :param response:
        :return:
        """
        raise error


import os
import matplotlib.pyplot as plt
from settings import prepare_times, plot_line, save_legend_time
import sys
import pandas as pd

if len(sys.argv) != 2:
    raise ValueError("Please give log and output folder")
log_dir = sys.argv[1]

plt.rcParams.update({'font.size': 20})

datasets = ['YELP', 'GDELT', 'ENRON', 'FLICKR', 'DBLP', 'MIND']
sub_methods = ['OT', 'SMK', 'FJK', 'TJK']
no_methods = len(sub_methods) + 1

total_df = pd.DataFrame()

for pos, name in enumerate(datasets):
    if name != 'DBLP':
        ks = [500, 1000, 5000, 10000]
    else:
        ks = [50, 100, 500, 1000]
    no_axis = {(k, m):no for no, (k, m) in enumerate([(k, m) for k in ks for m in sub_methods+['']])}
    file = f'{log_dir}logs/topk_k/{name.lower()}.log'
    if not os.path.exists(file):
        continue
    with open(file) as f:
        rows = prepare_times(f.readlines(), sub_methods)
        rows = pd.DataFrame(rows)
        df = rows.pivot(index='K', columns='Method', values='Total')
        df = df.loc[ks, sub_methods]
        total_df = pd.concat([total_df, df])

        fig, axes = plt.subplots(nrows=1, ncols=1)
        plot_line(df, axes, (0, int(ks[-1]*1.05)))
        if pos == 0:
            axes.set_ylabel('Time (sec)')
        axes.set_xlabel(r'Number of Results $k$')

    plt.savefig(f'{log_dir}/plots/topk_time_{name}.pdf', bbox_inches='tight')
plt.show()
save_legend_time(sub_methods, f'{log_dir}/plots/topk_time_legend.pdf')
        # df = pd.DataFrame(rows).pivot(index=['Size', 'K'], columns='Method', values='total')
        # total_df = pd.concat([total_df, pd.concat({name: df}, names=['Dataset'])])

# plt.show()
print(total_df.apply(lambda x: x['SMK'] / x['TJK'], axis=1).describe())
print(total_df.apply(lambda x: x['FJK'] / x['TJK'], axis=1).describe())


import collections

def part1(file):
    with open(file) as f:
        jolts = [int(l) for l in f.readlines()]
        jolts = [0] + sorted(jolts) + [max(jolts)+3]
        jumps = [jolts[i]-jolts[i-1] for i in range(1,len(jolts))]
        counts = collections.Counter(jumps)
        print(counts[1]*counts[3])

def makechildgraph(jolts):
    jolts = [max(jolts)+3] + sorted(jolts,reverse=True) + [0]
    dchild = {}
    for i,jolt in enumerate(jolts):
        dchild[jolt] = [test for test in jolts[i+1:i+4] if (jolt-test) < 4]
    return(dchild)

def makedistdict(jolts,dchild):
    jolts = sorted(jolts) + [max(jolts)+3]
    ddist = {0:1}
    for jolt in jolts:
        ddist[jolt] = sum([ddist[child] for child in dchild[jolt]])
    return ddist

def part2(file):
    with open(file) as f:
        jolts = [int(l) for l in f.readlines()]
        dchild = makechildgraph(jolts)
        ddist = makedistdict(jolts,dchild)
        print(ddist[max(jolts)+3])

def main():
    filename = '../example.txt'
    filename = '../datasets/10.txt'
    part1(filename)
    part2(filename)

if __name__ == '__main__':
    main()


import logging
import sys

from PyQt5.QtWidgets import QApplication

from Tools.decoratorTools import *
from Tools.AutoTestQThread import AutoTestQThread
from Tools.func_test import DI, DO
from UISet.UISet_AutoTest import AutoTestWindow
from Tools.Interfaces import JDK23
from Tools.DevicesPools import *
class Control_autoTest(AutoTestWindow):
    def __init__(self):
        super(Control_autoTest, self).__init__()
        self.auto_tabWidget.setCurrentIndex(1)  # 测试用
        self.pb_auto_test.released.connect(self.startBtn_clicked)  # 点击“Ztest on”按钮触发事件
        self.initProperty()  # 初始化属性
        self.initGroups()  # 初始化按钮组
        self.initControler()  # 初始化控制器

    def initControler(self):
        """
        初始化按钮组
        """
        # self.DI_controler =
        ...

    def initProperty(self):
        """
        初始化属性
        """
        self.groups = {}
        self.re_groups={}
    def initGroups(self):
        """
        初始化按钮组
        """
        self.initGroups_DI()  # DI
        self.initGroups_DO()  # DO
        self.initGroups_AI()  # AI
        self.initGroups_AO()  # AO

    def do_change_testItem(self, testItem: str):
        """
        跳转到对应测试项
        Args:
            testItem:测试项名称['DITest','DOTest']
        Returns:
        """
        if testItem == 'DITest':
            self.auto_tabWidget.setCurrentIndex(1)
        elif testItem == 'DOTest':
            self.auto_tabWidget.setCurrentIndex(2)
        elif testItem == 'AITest':
            self.auto_tabWidget.setCurrentIndex(3)
        elif testItem == 'AOTest':
            self.auto_tabWidget.setCurrentIndex(4)

    # DI Test
    @using_tryCatch
    def do_DI_test(self, chan: int, choice: int):
        """
        DI Test:离散量输入测试
        Args:
            chan:
            choice:
        Returns:
        """
        self.do_DI_test_FE(chan, choice)  # DI Test FrontEnd
        # self.do_DI_test_BE(chan,choice)

    @using_tryCatch
    def do_DI_test_FE(self, chan: int, choice: int):

        """
        DI的前端包括按钮点击，监视框显示发送指令
        DI Test FrontEnd
        离散量测试页面显示功能
        Args:
            chan: 通道号
            choice: 测试值 0,1,2 (2为 0/1中的一种)
        Returns:
        """
        self.initUI_DI()
        for w in self.re_groups["DI"][chan]:
            w.setText("1")
        if chan in range(0, 6):  # 遍历 0 ~ 5 通道
            if chan in [0, 1]:  # 处理通道 [0 1]
                needClickBtns = self.groups['DI'][str(chan)]  # 设置需要点击的按钮
                if choice == 0:  # 测试“地” 需要点击按钮 测试“开”则不需要
                    for btn in needClickBtns:  # 遍历按钮
                        btn.click()  # 点击
            elif chan == 2:  # 处理通道 [2]
                if choice == 0:  # 测试“开”
                    needClickBtns = self.groups['DI'][str(chan)] | {self.pb_auto_di_28VKIN5_2}
                elif choice == 1:  # 测试“28V”
                    needClickBtns = self.groups['DI'][str(chan)] | {self.pb_auto_di_28VKIN5_1}
                elif choice == 2:  # 测试“地”
                    needClickBtns = self.groups['DI'][str(chan)] | {self.pb_auto_di_28VKIN5_3}
                if choice in [1]:  # 测试“28V”
                    for btn in needClickBtns:
                        btn.click()  #
                elif choice in [2]:  # 测试“地”
                    self.pb_auto_di_28VKIN5_3.click()
            elif chan == 3:  # 处理通道 [3]
                if choice == 0:  # 测试“地”
                    needClickBtns = self.groups['DI'][str(chan)] | {self.pb_auto_di_28VDIN2_3}
                elif choice == 1:  # 测试“开”
                    needClickBtns = self.groups['DI'][str(chan)] | {self.pb_auto_di_28VDIN2_2}
                elif choice == 2:  # 测试“28V”
                    needClickBtns = self.groups['DI'][str(chan)] | {self.pb_auto_di_28VDIN2_1}
                if choice in [0]:  # 测试“地”
                    for btn in needClickBtns:  # 点击按钮
                        btn.click()
                elif choice in [1, 2]:  # 测试“开”和“28V"
                    self.pb_auto_di_28VDIN2_1.click()
            elif chan in [4, 5]:  # 处理通道 [4,5]
                needClickBtns = self.groups['DI'][str(chan)]  # 设置需要点击按钮
                if choice == 1:  # 测试”地“时 需要点击
                    for btn in needClickBtns:  # 点击按钮
                        btn.click()
            BtnsInfos = ""  # 测试用
            for c in needClickBtns:  # 测试用
                BtnsInfos = BtnsInfos + "  " + c.objectName().split('_')[-1] + ":"+ c.text()  # 测试用
            # 获取发送指令
            if choice == 2 and chan == 2:
                sends = JDK23.DITest.CHES[str(chan)][str(choice - 2)]
            elif choice == 2 and chan == 3:
                sends = JDK23.DITest.CHES[str(chan)][str(choice - 1)]
            else:
                sends = JDK23.DITest.CHES[str(chan)][str(choice)]
            # 显示发送指令
            self.pte_di_insIn.setPlainText(f"chan{chan} : {choice} : {sends} {BtnsInfos}")  # 测试用
            logging.debug(f"chan{chan} : {choice} : {sends} {BtnsInfos}")
        else:  # 恢复原状
            self.pte_di_insIn.setPlainText('')  # 清空
            self.pb_auto_di_28VDIN2_2.click()  # 恢复原状
            self.pb_auto_di_28VKIN5_2.click()  # 恢复原状

    def do_DI_test_BE(self,chan,choice):
        '''
        DI Test 后端的执行代码
        :param chan: 0-5的通道号
        :param choice: 0  接地  1 断开  2  28V
        :return:
        '''
        pass
        # 获取发送指令
        # if choice == 2 and chan == 2:
        #     sends = JDK23.DITest.CHES[str(chan)][str(choice - 2)]
        # elif choice == 2 and chan == 3:
        #     sends = JDK23.DITest.CHES[str(chan)][str(choice - 1)]
        # else:
        #     sends = JDK23.DITest.CHES[str(chan)][str(choice)]
        # dcp=DCPower1()
        # dcp.connect()
        # print(chan,type(chan))
        # sendmessage='volt '+str(chan)
        # print(sendmessage)
        # dcp.write(sendmessage)
        # dcp.write('outp 1')
#------------------以下代码为真正实现的功能，需要时可解开注释--------------------
        # try:
        #     di=DI()
        #     result=di.test_channel(chan,choice)
        #     for x in self.re_groups["DI"][chan]:
        #         x.setText(str(result))
        # except Exception as e:
        #     logging.info("DI 执行后端出现 {}".format(e))
        #     logging.error(e)
    # DO Test
    @using_tryCatch
    def do_DO_test(self, chan: int, choice: int):
        """
        DO Test:离散量驱动输出测试
        Args:
            chan: 通道号
            choice: 测试值 0,1
        Returns:
        """
        self.do_DO_test_FE(chan, choice)  # DO Test FrontEnd
        # self.do_DO_test_BE(chan,choice)
    @using_tryCatch
    def do_DO_test_BE(self, chan: int, choice: int):
        '''

        :param chan:
        :param choice:
        :return:
        '''
        a=DO()
        print("channel{}".format(chan))
        re_volt=a.test_channel(chan,choice)
        print("mult回读的电压"+str(re_volt))
        for x in self.re_groups["DO"][chan+1]:
            x.setText(re_volt)
        #
    @using_tryCatch
    def do_DO_test_FE(self, chan: int, choice: int):
        """
        DO Test FrontEnd
        离散量驱动输出测试页面显示功能
        Args:
            chan: 通道号
            choice: 测试值 0,1
        Returns:
        """
        self.initUI_DO()
        if chan in range(0, 21):  # 遍历 0 ~ 20 通道
            for i in self.groups['DO'][str(chan)]:  # 点击需要点击的按钮
                if choice == 1:
                    i.click()  # 点击

            sends = JDK23.DOTest.CHES['{:02X}'.format(chan)][str(choice)]  # 获取发送指令
            print('{:02X}  {}'.format(chan,str(choice)))
            print(sends)
            self.pte_auto_do_insIn.setPlainText(f"chan{'{:02X}'.format(chan)} : {choice} : {sends}")  # 测试用
            logging.debug(f"chan{'{:02X}'.format(chan)} : {choice} : {sends}")  #
        else:
            self.pte_auto_do_insIn.setPlainText('')  # 清空

    # AI Test
    @using_tryCatch
    def do_AI_test_UI(self, chan: int, choice: float):
        self.do_AI_test_FE(chan, choice)  # AI Test FrontEnd

    def do_AI_test_FE(self, chan: int, choice: float):
        self.initUI_AI()
        if chan in range(0, 17):
            idx = JDK23.AITest.CHES['{:02X}'.format(chan)]['tpvf'].index(choice)
            sends = JDK23.AITest.CHES['{:02X}'.format(chan)]['tps'][idx]  # 获取发送指令
            self.pte_auto_ai_insIN.setPlainText(f"chan{'{:02X}'.format(chan)} : {choice} : {sends}")  # 测试用
            logging.debug(f"chan {chan} : {choice} : {sends} [{idx}]")
            for i in self.groups['AI'][str(chan)]:
                i.setValue(choice)
                i.setStyleSheet("background-color: green;")
        else:
            self.pte_auto_ai_insIN.setPlainText("")

    # AO Test
    @using_tryCatch
    def do_AO_test(self, chan: int, choice: float):
        self.do_AO_test_FE(chan, choice)  # AO Test FrontEnd

    def do_AO_test_FE(self, chan: int, choice: float):
        self.initUI_AO()
        if chan in range(0, 8):
            idx = JDK23.AOTest.CHES['{:02X}'.format(chan)]['tpvf'].index(choice)
            sends = JDK23.AOTest.CHES['{:02X}'.format(chan)]['tps'][idx]  # 获取发送指令
            self.pte_auto_ao_insIN.setPlainText(f"chan{'{:02X}'.format(chan)} : {choice} : {sends}")  # 测试用
            logging.debug(f"chan {chan} : {choice} : {sends} [{idx}]")
            for i in self.groups['AO'][str(chan)]:
                i.setText(str(choice))
                i.setStyleSheet("background-color: green;font-size:20px;")
        else:
            self.pte_auto_ao_insIN.setPlainText("")

    # def getRecvData(self,dic):
    #     for key,value in dic.items():
    #         if key =='device1':
    #             self.pte_auto_ai_insIN.setPlainText(value)
    #         elif key=='device2':
    #             self.pte_auto_ai_insOUT.setPlainText(value)

    def getRecvData(self, reback):
        print(reback)
    def startBtn_clicked(self):
        """
        点击开始测试按钮 触发函数
        Returns:
        """
        self.initGroups()  # 初始按钮组
        if self.pb_auto_test.isChecked():  # 如果点击 开始运行
            self.autothread = AutoTestQThread()  # 定义
            self.autothread.DITestSignal.connect(self.do_DI_test)  # 绑定信号与槽函数
            self.autothread.DOTestSignal.connect(self.do_DO_test)  # 绑定信号与槽函数
            self.autothread.AITestSignal.connect(self.do_AI_test_UI)  # 绑定信号与槽函数
            self.autothread.RecvDataSignal.connect(self.getRecvData)

            self.autothread.AOTestSignal.connect(self.do_AO_test)  # 绑定信号与槽函数
            self.autothread.InterruptSignal.connect(self.do_interrupt)  # 绑定信号与槽函数
            self.autothread.ChangeSignal.connect(self.do_change_testItem)  # 绑定信号与槽函数
            self.autothread.finished.connect(
                lambda: (self.pb_auto_test.click() if self.pb_auto_test.isChecked() else ...))  # 绑定信号与槽函数
            self.autothread.start()  # 开始运行
        else:  # 结束运行
            # self.pb_auto_test.click()
            self.autothread.flag = False  # 设置为False 结束运行

    def initGroups_DI(self):
        # 初始化DI
        #通道号0-5
        #这里的控件组合都没有加上启动监视器1和2
        self.groups = {'DI': {}}
        self.re_groups={"DI":{}}
        self.groups['DI']['0'] = {
            self.btn_auto_di_DKIN1, self.btn_auto_di_DKIN2, self.btn_auto_di_DKIN3,
            self.btn_auto_di_DKIN4, self.btn_auto_di_DKIN5, self.btn_auto_di_DKIN6,
        }
        self.groups['DI']['1'] = {
            self.btn_auto_di_DKIN7, self.btn_auto_di_DKIN8, self.btn_auto_di_DKIN9,
            self.btn_auto_di_DKIN10, self.btn_auto_di_DKIN11, self.btn_auto_di_DKIN12, self.btn_auto_di_DKIN13,
        }
        self.groups['DI']['2'] = {
            self.btn_auto_di_28VKIN1, self.btn_auto_di_28VKIN2, self.btn_auto_di_28VKIN3,
            self.btn_auto_di_28VDIN1, self.btn_auto_di_28VKIN4,
        }
        self.groups['DI']['3'] = {
            self.btn_auto_di_28VDIN3, self.btn_auto_di_28VDIN4,
        }
        self.groups['DI']['4'] = {
            self.btn_auto_di_RDKIN1,
        }
        self.groups['DI']['5'] = {
            self.btn_auto_di_RDKIN2,
        }
        self.groups['DI']['ALL'] = set()
        for i in range(6):
            self.groups['DI']['ALL'] = self.groups['DI']['ALL'] | self.groups['DI'][str(i)]
        self.re_groups["DI"][0]=[
            self.le_auto_di_DKIN1r,self.le_auto_di_DKIN2r,self.le_auto_di_DKIN3r,
            self.le_auto_di_DKIN4r,self.le_auto_di_DKIN5r,
            self.le_auto_di_DKIN6r
        ]
        self.re_groups["DI"][1]=[
            self.le_auto_di_lDKIN7r,self.le_auto_di_DKIN8r,self.le_auto_di_DKIN9r,self.le_auto_di_DKIN10r
            ,self.le_auto_di_DKIN11r,self.le_auto_di_DKIN12r,self.le_auto_di_DKIN13r
        ]
        self.re_groups["DI"][2]=[
            self.le_auto_di_28VKIN1r,self.le_auto_di_28VKIN2r,self.le_auto_di_28VKIN3r,
            self.le_auto_di_28VDIN1r,self.le_auto_di_28VKIN4r
        ]
        self.re_groups["DI"][3]=[
            self.le_auto_di_28VDIN4r,self.le_auto_di_28VDIN3r
        ]
        self.re_groups["DI"][4]=[
            self.le_auto_di_APUr
        ]
        self.re_groups["DI"][5] = [
            self.le_auto_di_RDKIN2r
        ]
        self.re_groups['DI']['ALL'] = set()
        for i in range(6):
            self.re_groups['DI']['ALL'] = self.re_groups['DI']['ALL'] | set(self.re_groups['DI'][i])
    def initGroups_DO(self):
        """
        初始化DO
        Returns:
        """
        self.groups['DO'] = {"DO":{}}
        self.groups['DO']['0'], self.groups['DO']['1'], = {self.pb_auto_do_28VKOUT1}, {self.pb_auto_do_28VKOUT2}
        self.groups['DO']['2'], self.groups['DO']['3'], = {self.pb_auto_do_28VKOUT3}, {self.pb_auto_do_28VKOUT4}
        self.groups['DO']['4'], self.groups['DO']['5'], = {self.pb_auto_do_28VKOUT5}, {self.pb_auto_do_28VKOUT6}
        self.groups['DO']['6'], self.groups['DO']['7'], = {self.pb_auto_do_28VKOUT7}, {self.pb_auto_do_28VKOUT8}
        self.groups['DO']['8'], self.groups['DO']['9'], = {self.pb_auto_do_28VKOUT9}, {self.pb_auto_do_28VKOUT10}
        self.groups['DO']['10'], self.groups['DO']['11'], = {self.pb_auto_do_28VKOUT11}, {self.pb_auto_do_28VKOUT12}
        self.groups['DO']['12'], self.groups['DO']['13'], = {self.pb_auto_do_28VKOUT13}, {self.pb_auto_do_28VKOUT14}
        self.groups['DO']['14'], self.groups['DO']['15'], = {self.pb_auto_do_DKOUT1}, {self.pb_auto_do_DKOUT2}
        self.groups['DO']['16'], self.groups['DO']['17'], = {self.pb_auto_do_DKOUT3}, {self.pb_auto_do_DKOUT4}
        self.groups['DO']['18'], self.groups['DO']['19'], = {self.pb_auto_do_DKOUT5}, {self.pb_auto_do_DKOUT6}
        self.groups['DO']['20'] = {self.pb_auto_do_DKOUT7}
        self.groups['DO']['ALL'] = set()
        for i in range(21):
            self.groups['DO']['ALL'] = self.groups['DO']['ALL'] | self.groups['DO'][str(i)]
        #对回读的lineedit组件按照通道号组成、排序
        self.re_groups["DO"]={"DO":{}}
        self.re_groups['DO']['ALL'] = set()
        for i in range(1, 15):
            # print( getattr(self, f"le_auto_do_28VKOUT{i}"))
            self.re_groups["DO"][i] =[ getattr(self, f"le_auto_do_28VKOUT{i}")]
        for i in range(1, 8):
            self.re_groups["DO"][i+14] = [getattr(self, f"le_auto_do_DKOUT{i}")]
        for i in range(1,22):
            self.re_groups['DO']['ALL'] = self.re_groups['DO']['ALL'] | set(self.re_groups['DO'][i])
    def initGroups_AI(self):
        self.groups['AI'] = {}
        self.groups['AI']['0'] = {self.dsb_auto_ai_AIN_EDT}
        self.groups['AI']['1'] = {self.dsb_auto_ai_AIN_NVT}
        self.groups['AI']['2'] = {self.dsb_auto_ai_AIN_SVM}
        self.groups['AI']['3'] = {self.dsb_auto_ai_AIN_KTM_1}
        self.groups['AI']['4'] = {self.dsb_auto_ai_AIN_KTM_2}
        self.groups['AI']['5'] = {self.dsb_auto_ai_AIN_KTM_3}
        self.groups['AI']['6'] = {self.dsb_auto_ai_AIN_KTM_4}
        self.groups['AI']['7'] = {self.dsb_auto_ai_AIN_KTM_5}
        self.groups['AI']['8'] = {self.dsb_auto_ai_AIN_PT100_1}
        self.groups['AI']['9'] = {self.dsb_auto_ai_AIN_PT100_2}
        self.groups['AI']['10'] = {self.dsb_auto_ai_AIN_PT100_3}
        self.groups['AI']['11'] = {self.dsb_auto_ai_AIN_CTSENSOR}
        self.groups['AI']['12'] = {self.dsb_auto_ai_IGV_IN, self.dsb_auto_ai_IGV_incentive}
        self.groups['AI']['13'] = {self.dsb_auto_ai_SCV_IN, self.dsb_auto_ai_SCV_incentive}
        self.groups['AI']['14'] = {self.dsb_auto_ai_FCU_IN, self.dsb_auto_ai_FCU_incentive}
        self.groups['AI']['15'] = {self.dsb_auto_ai_AIN_FRE_N1}
        self.groups['AI']['16'] = {self.dsb_auto_ai_AIN_FRE_N2}

        self.groups['AI']['ALL'] = set()
        for i in range(12):
            self.groups['AI']['ALL'] = self.groups['AI']['ALL'] | self.groups['AI'][str(i)]

    def initGroups_AO(self):
        self.groups['AO'] = {}
        self.groups['AO']['0'] = {self.le_auto_ao_AOUT_PREPS}
        self.groups['AO']['1'] = {self.le_auto_ao_AOUT_FLPPS}
        self.groups['AO']['2'] = {self.le_auto_ao_LVDT_IGVPRI_STATEv, self.le_auto_ao_LVDT_IGVPRI_STATEf}
        self.groups['AO']['3'] = {self.le_auto_ao_LVDT_SGVPRI_STATEv, self.le_auto_ao_LVDT_SGVPRI_STATEf}
        self.groups['AO']['4'] = {self.le_auto_ao_RVDT_FCUPRI_STATEv, self.le_auto_ao_RVDT_FCUPRI_STATEf}
        self.groups['AO']['5'] = {self.le_auto_ao_AOUT_IGVCD}
        self.groups['AO']['6'] = {self.le_auto_ao_AOUT_FCUCD}
        self.groups['AO']['7'] = {self.le_auto_ao_AOUT_SCVCD}

        self.groups['AO']['ALL'] = set()
        for i in range(8):
            self.groups['AO']['ALL'] = self.groups['AO']['ALL'] | self.groups['AO'][str(i)]

    def do_interrupt(self):
        """
        终止测试 恢复默认状态
        Returns:
        """
        # DI
        self.initUI_DI()
        # DO
        self.initUI_DO()
        # AI
        self.initUI_AI()
        # AO
        self.initUI_AO()

    def initUI_DI(self):
        for i in self.groups['DI']['ALL']:  # 默认回到初始状态
            if i.isChecked():  # 如果是点击状态
                i.click()  # 恢复原状
        self.pb_auto_di_28VDIN2_2.click()  # 恢复
        self.pb_auto_di_28VKIN5_2.click()  # 恢复
        self.pte_di_insIn.setPlainText('')  # 清空

    def initUI_DO(self):
        for i in self.groups['DO']['ALL']:  # 默认回到初始状态
            if i.isChecked():  # 如果是点击状态
                i.click()  # 恢复原状
        self.pte_auto_do_insIn.setPlainText('')  # 清空

    def initUI_AI(self):
        for i in range(17):
            for j in self.groups['AI'][str(i)]:
                j.setValue(0)
                j.setStyleSheet("background-color:''")

        self.pte_auto_ai_insIN.setPlainText('')

    def initUI_AO(self):
        for i in range(8):
            for j in self.groups['AO'][str(i)]:
                j.setText('')
                j.setStyleSheet("background-color:'';font-size:20px;")

        self.pte_auto_ao_insIN.setPlainText('')

if __name__ == "__main__":
    try:
        app = QApplication(sys.argv)
        ContorlAutoTestWindow = Control_autoTest()
        ContorlAutoTestWindow.show()
        sys.exit(app.exec_())
    except Exception as e:
        print(e)


import numpy as np
import cv2
from openalpr import Alpr

alpr = Alpr("eu", "openalpr.conf", "runtime_data")
if not alpr.is_loaded():
    print("Error loading OpenALPR")
    sys.exit(1)

alpr.set_top_n(1)
alpr.set_default_region("eu")

#cap = cv2.VideoCapture("http://91.190.227.198/mjpg/video.mjpg")
cap = cv2.VideoCapture("numPlates.mpg")

while(True):
    ret, frame = cap.read()

    if ret:
        cv2.imshow('frame', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

        cv2.imwrite("img.jpg", frame)

        results = alpr.recognize_file("img.jpg")

        i = 0

        for plate in results['results']:
            i += 1
            print("Plate #%d" % i)
            print("   %12s %12s" % ("Plate", "Confidence"))
            for candidate in plate['candidates']:
                prefix = "-"
                if candidate['matches_template']:
                    prefix = "*"

                print("  %s %12s%12f" % (prefix, candidate['plate'], candidate['confidence']))
    else:
        break;

# When everything done, release the capture
cap.release()
alpr.unload()
cv2.destroyAllWindows()


import pprint
import re
from os.path import dirname, basename, isfile, join
from glob import glob

from utils.constants import bcolors

import cordelia
import cordelia.opcodes

#---receive a list of unity
#---return a list of tokens for each unity
#lexer = cordelia.Lexer()

modules = glob(join(dirname(__file__), 'opcodes', '*.py'))
opcode_names = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]

def lexer(unit) -> list():

	#remove tabs
	unit = re.sub(r'[\t]*', '', unit)

	#each line is separated in a list
	unit_lines = unit.splitlines()

	try:

		if len(unit_lines) == 1:

			if re.search(r'^@', unit_lines[0]):
				pre_instrument = cordelia.opcodes.sonvs(unit_lines[0])
				print(pre_instrument)
				return pre_instrument

			else:
				pre_instrument = cordelia.Instrument([unit_lines[0]])
				return pre_instrument

		else:

			opcode_match = re.search(r'^\w+', unit_lines[0])[0]

			if opcode_match in opcode_names:
				opcode_function = getattr(cordelia.opcodes, unit_lines[0].split(':')[0])
				pre_instrument = opcode_function(unit_lines)
				return pre_instrument

			else:
				print(f'{bcolors.WARNING}WARNING{bcolors.ENDC}: your code has an unknown opcode {unit_lines}{bcolors.ENDC}')

	except Exception as e:
		print(f'{bcolors.WARNING}WARNING{bcolors.ENDC}: these lines {bcolors.WARNING}{unit_lines}{bcolors.ENDC} have a problem!')
		print(e)


import itertools
import random
import matplotlib.pyplot as plt

def min_step(m):
    ls = list(itertools.chain.from_iterable(m))
    return min(abs(x - y) for x, y in zip(ls, ls[1:]))

def is_kaccept(m, k):
    ls = list(itertools.chain.from_iterable(m))
    return all(abs(x - y) >= k for x, y in zip(ls, ls[1:]))

def findk(m):
    k = 0
    perm = m
    for rs in itertools.permutations(m):
        ms = min_step(rs)
        if ms > k:
            k = max(k, ms)
            perm = rs
    return k, perm

def subsumes(r1, r2):  # r1 subsumes r2
    a, b = r1
    c, d = r2
    return a <= c and b >= d

def max_list_subsumes(ls1, ls2):
    # all segs of ls1 subsumes at least 1 of ls2
    return all(any(subsumes(r1, r2) for r2 in ls2) for r1 in ls1)

def min_subsume_set(ls):
    s = []
    for r1 in ls:
        if any(subsumes(r1, r2) for r2 in s):
            continue
        s = [r2 for r2 in s if not subsumes(r2, r1)]
        s.append(r1)
    return s

def max_list_subsume_set(ls):
    s = []
    for r1 in ls:
        if any(max_list_subsumes(r2, r1) for r2 in s):
            continue
        s = [r2 for r2 in s if not max_list_subsumes(r1, r2)]
        s.append(r1)
    return s

def max_list_subsume_set_n(n):
    sort_key = lambda r: (abs(r[0] - r[1]), r[0])
    s = set()
    for perm in itertools.permutations(range(n)):
        ls = [sorted(x) for x in zip(perm, perm[1:])]
        ls.sort()
        ls_rs = min_subsume_set(ls)
        ls_rs.sort(key=sort_key)
        ls_rs = tuple(tuple(x) for x in ls_rs)
        s.add(ls_rs)
    s = max_list_subsume_set(s)
    return s

if __name__ == '__main__':
    # r, c = map(int, input().split())
    # m = [[int(x) for x in input().split()] for _ in range(r)]
    # print(r, c)
    # print(m)

    n = 9
    def dprint(*args, debug=True, **kwargs):
        if debug:
            print(*args, **kwargs)

#     for _ in range(10):
#         rrs = [[random.randrange(10)] for _ in range(n)]
#         rrs.sort()
#         dprint(rrs)
#         k, perm = findk(rrs)
#         dprint('k =', k)
#         dprint('perm =', perm)
#         res = max(min(abs(a[0] - b[0]) for a, b in segs) for segs in itertools.combinations(list(zip(rrs, rrs[n // 2:])), n // 2))
#         dprint('res =', res)
#         if res == k:
#             print('OK')
#         print('---')
#     exit()

    s = max_list_subsume_set_n(n)
    y = 0
    print('max', s)
    # exit()
    for t in s:
        for a, b in t:
            plt.plot((a, b), (y, y), marker='o')
            y += 1
        y += 2
        plt.plot((0, n - 1), (y, y), color='gray', linestyle='--')
        y += 2
    # plt.yticks(range(len(s)))
    plt.title(f'n = {n}')
    plt.show()