import sys
from os import path
import pymysql
import db_conn

sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
from db_conn import db_conn

CONFIG_FILE = "../config.live.ini"
APP_PATH = path.abspath(path.dirname(__file__))

class DatabaseInteraction:
    def __init__(self):
        # config file for db,  ie config.live.ini
        self.filename = path.join(APP_PATH, CONFIG_FILE)

        self.conn_obj = db_conn(self.filename)
        self.db_name = "koa"
        self.db = None

    def connect_db(self, db_name, second_try=False):
        conn = self.conn_obj.connect(db_name)
        if not conn:
            print(f"CANNOT Connect to DataBase: {db_name}")
        try:
            curse = conn.cursor(pymysql.cursors.DictCursor)
        except:
            if second_try:
                sys.exit(f"could not connect to the database: {db_name}")
            self.connect_db(db_name, second_try=True)

        return curse

    def close_db_connection(self, db_name):
        self.conn_obj.close(db_name)

    def get_db_connection(self):
        return self.db

    def make_query(self, query, params, db_name=None):
        """
        Query the DB.  Opening/Closing connection avoids issues with the cursor
        crashing.

        :param query:
        :param params: (tuple) the escaped parameters for the query string
        :return:
        """
        if db_name:
            self.db = self.connect_db(db_name)
        else:
            self.db = self.connect_db(self.db_name)

        if params:
            self.db.execute(query, params)
        else:
            self.db.execute(query)

        if 'UPDATE' in query.upper():
            result = self.db.rowcount
        else:
            result = self.db.fetchall()

        self.close_db_connection(self.db_name)

        return result


# -*- coding: utf-8 -*-
import scrapy

class HttpbinSpider(scrapy.Spider):
    name = 'httpbin'
    allowed_domains = ['httpbin.org']
    start_urls = ['http://httpbin.org/get']
    def __init__(self,httpname,httpage):
        self.httpname=httpname
        self.httpage=httpage
        print("httpname:",self.httpname)

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            httpname=crawler.settings.get('NAME'),
            httpage=crawler.settings.get('AGE')
        )
    def parse(self, response):
        print("hello", self.httpname)
        print(response.text)
    def parse_index(self,response):
       # print("--------------"+httpname+"---------------")

        pass
    #def start_requests(self):
    #    yield scrapy.Request(url="http://httpbin.org/",callback=self.parse_index)


from pprint import pprint
from subprocess import CalledProcessError
from unittest.mock import Mock

import pytest

from pybright import cli
from pybright.cli import BrightCallError, _version, bright, version

def mock_bright_response(response=None, side_effect=None):
    cli._call_command_and_parse_json = Mock(return_value=(response, None), side_effect=side_effect)

def test_version():
    mock_bright_response({'success': True, 'message': 'Version displayed',
                          'stdout': '1.0.2-next.201806261725\n', 'stderr': '', 'data': {'version': '1.0.2-next.201806261725\n'}})

    assert _version() == "1.0.2-next.201806261725"
    assert _version() == version()

def test_bright_syntax_error():
    mock_bright_response(side_effect=CalledProcessError(1, 'bright --rfj szos-jobs list jobs', output="""{
  "success": false,
  "message": "Command syntax invalid",
  "stdout": "",
  "stderr": "\\nSyntax Error:\\nYou specified the following unknown values: \\"list\\", \\"jobs\\".\\n\\n Could not interpret them as a group, command name, or positional option.\\n\\nUse \\"bright szos-jobs list jobs --help\\" to view command description, usage, and options.\\n",
  "data": [
    {
      "message": "You specified the following unknown values: \\"list\\", \\"jobs\\".\\n\\n Could not interpret them as a group, command name, or positional option.\\n",
      "optionInError": "unknown"
    }
  ]
}"""))

    with pytest.raises(BrightCallError) as excinfo:
        bright('bright --rfj syntax error')
    excinfo.value.returncode == 1

if __name__ == '__main__':
    pytest.main([__file__])


"""Collection of functions for training the models for the covid_lit_contra_claims pipeline."""

# -*- coding: utf-8 -*-

import os

import evaluate

import numpy as np

import pandas as pd

import torch
from torch.utils.data import DataLoader

from transformers import AdamW, AutoModelForSequenceClassification, DataCollatorWithPadding, get_scheduler

import wandb

from ..data.constants import MANCON_NEUTRAL_FRAC, MANCON_TRAIN_FRAC, WANDB_LOG_FREQ, WANDB_LOG_INTERVAL, model_id_mapper

# Use TF32 instead of FP32 -- decrease precision in a non-impactful way for a speed up
torch.backends.cuda.matmul.allow_tf32 = True

def run_validation(model, trainings_so_far, val_dataset_dict, config, data_collator, device, overall_results):
    """
    Run validation with an input (trained) model.

    :param model: Trained Transformer
    :param trainings_so_far: string ID indicating datasets already used in fine-tuning
    :param val_dataset_dict: HF DatasetDict for validation datasets
    :param config: config dictionary
    :param data_collator: DataCollator object for use in DataLoader
    :param device: GPU device
    :param overall_results: overall results (list of dictionaries) to be updated
    """
    for val_id, val_dataset in val_dataset_dict.items():
        # TODO: Do we want shuffle = True?
        val_dataloader = DataLoader(val_dataset,
                                    shuffle=False,
                                    batch_size=config['batch_size'],
                                    collate_fn=data_collator)

        print(f"EVAL: Created a DataLoader for corpus '{val_id}'...")

        acc_metric = evaluate.load('accuracy')
        f1_metric = evaluate.load('f1', average='macro')
        precision_metric = evaluate.load('precision', average='macro')
        recall_metric = evaluate.load('recall', average='macro')
        recall_metric2 = evaluate.load('recall', average=None)

        for batch_idx, batch in enumerate(val_dataloader):
            batch = {k: v.to(device) for k, v in batch.items()}
            with torch.no_grad():
                outputs = model(**batch)
                val_loss = outputs.loss

                if batch_idx % config['wandb_log_interval'] == 0:
                    wandb.log({f"Val Loss on {val_id} (trained: {trainings_so_far})": val_loss})

            logits = outputs.logits
            predictions = torch.argmax(logits, dim=-1)
            for metric in [acc_metric, f1_metric, precision_metric, recall_metric, recall_metric2]:
                metric.add_batch(predictions=predictions, references=batch["labels"])

        results = acc_metric.compute()  # Creates a dictionary
        for metric in [f1_metric, precision_metric, recall_metric]:
            results.update(metric.compute(average='macro'))  # Add these to the dict

        # Calculate recall of just contradictions class
        if val_id in ["roamPH", "roamDD", "roamDDPH"]:
            recall_ent_val = -1  # TODO: What should the value be?
            recall_con_val = -1  # Flag for recall con is undefined here
        else:
            recall_array = recall_metric2.compute(average=None)['recall']
            recall_ent_val = recall_array[0]  # 0 == entailment index
            recall_con_val = recall_array[2]  # 2 == contradictions index

        results.update({'recall_ent': recall_ent_val, 'recall_con': recall_con_val})

        # format the name of the result a bit
        wandb_results = {f"Val: {val_id.upper()} {k.capitalize()}": v for k, v in results.items()}
        wandb.log(wandb_results)
        # torch.onnx.export(model, batch, "model.onnx")
        # wandb.save("model.onnx")

        results["Cumulative Training"] = trainings_so_far
        results["Validation Set"] = val_id
        results.update(config)

        print(f"Results on {val_id}: {results}")
        overall_results.append(results)

    return None

def train_model(model_id, tokenizer, train_dataset_dict, val_dataset_dict, training_args, try_speed, out_dir, SEED,
                is_test=False):
    """
    Train the HF model.

    :param model_id: identifier of the model(s) to train.
    :param tokenizer: HF Tokenizer for corresponding model
    :param train_dataset_dict: dictionary of training Datasets
    :param val_dataset_dict: dictionary of validation Datasets
    :param training_args: arguments for training (config dict)
    :param try_speed: if True, try to optimize performance as per HF recommendations
    :param out_dir: directory to output weights/intermediate results
    :param SEED: random seed
    :param is_test: if True, this is the test split, only used for naming out file
    :return: trained model
    """
    # Set random seeds
    torch.manual_seed(SEED)
    np.random.seed(SEED)

    # Configs and init for WandB
    additional_configs = {"mancon_neutral_frac": MANCON_NEUTRAL_FRAC,
                          "mancon_train_frac": MANCON_TRAIN_FRAC,
                          "wandb_log_interval": WANDB_LOG_INTERVAL}

    config = dict(training_args, **additional_configs)  # Merge the dicts
    wandb.init(project='COVID Drug Contra Claims', config=config)
    print("WandB initialized.")

    # Load the model, initialize the optimizer
    checkpoint = model_id_mapper[model_id]
    model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=3)
    optimizer = AdamW(model.parameters(), lr=config['learning_rate'])
    wandb.watch(model, log_freq=WANDB_LOG_FREQ)
    print("Model loaded.")

    # Find the right device
    device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
    model.to(device)
    print(f"Using device {device}.")

    # Create data collator
    data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

    # Train on datasets in the input training dictionary
    overall_results = []
    training_list_so_far = ["none"]

    # Potential optimization
    num_workers = 4 if try_speed else 0

    # Calculate performance on all val corpora before any fine-tuning
    # NOTE: Not going to do this. Performance will be bad because model hasn't been fine-tuned on any NLI task yet.
    # model.eval()
    # run_validation(model, "none", val_dataset_dict, config, data_collator, device, overall_results)

    for train_id, train_dataset in train_dataset_dict.items():
        training_list_so_far.append(train_id)
        trainings_so_far = "_".join(training_list_so_far[:-1])
        # TODO: Do we want shuffle = True?
        train_dataloader = DataLoader(train_dataset,
                                      shuffle=False,
                                      batch_size=config['batch_size'],
                                      collate_fn=data_collator,
                                      num_workers=num_workers,  # speed up
                                      pin_memory=try_speed)  # speed up
        print(f"Created a DataLoader for corpus '{train_id}'...")

        # Create a learning rate scheduler
        num_training_steps = config['epochs'] * len(train_dataloader)
        lr_scheduler = get_scheduler(
            "linear",
            optimizer=optimizer,
            num_warmup_steps=0,
            num_training_steps=num_training_steps,
        )
        print(f"Created a learning rate scheduler for corpus '{train_id}'...")

        print("Beginning training...")
        print(f"# Epochs: {config['epochs']}")
        model.train()

        for epoch in range(config['epochs']):
            for batch_idx, batch in enumerate(train_dataloader):
                batch = {k: v.to(device) for k, v in batch.items()}
                outputs = model(**batch)
                loss = outputs.loss
                loss.backward()

                optimizer.step()
                lr_scheduler.step()
                optimizer.zero_grad()

                if batch_idx % config['wandb_log_interval'] == 0:
                    # Identifier for all trainings up to this one
                    wandb.log({"epoch": epoch, f"Training Loss on {train_id} (prev: {trainings_so_far})": loss})

        print(f"Training complete for corpus '{train_id}'.")
        print("Beginning evaluation...")

        # Run validation on all val corpora. Overall results will get updated.
        model.eval()
        trainings_so_far = "_".join(training_list_so_far)
        run_validation(model, trainings_so_far, val_dataset_dict, config, data_collator, device, overall_results)

    print("Overall evaluation complete.")

    # Establish output directory
    prep_args = f"PREPARGS_DR-{config['data_ratios']}_TPE-{config['train_prep_experiment']}_T-{config['truncation']}"
    experiment_id = f"EXP_E-{config['epochs']}_B-{config['batch_size']}_LR-{config['learning_rate']}"
    experiment_out_dir = os.path.join(out_dir,
                                      model_id,
                                      f"TRAIN_{config['train_datasets']}",
                                      f"VAL_{config['eval_datasets']}",
                                      prep_args,
                                      experiment_id)
    os.makedirs(experiment_out_dir, exist_ok=True)

    eval_split = "test" if is_test else "val"
    print(f"Eval split: {eval_split}")
    out_filepath = os.path.join(experiment_out_dir, f"{eval_split}_metrics.csv")
    print(f"Saving results to {out_filepath} ....")
    overall_results_df = pd.DataFrame(overall_results)
    overall_results_df.to_csv(out_filepath, index=False)

    return model, overall_results_df


import onir

COMPONENTS = {
    'rankers': onir.rankers.registry,
    'vocabs': onir.vocab.registry,
    'datasets': onir.datasets.registry,
    'trainers': onir.trainers.registry,
    'predictors': onir.predictors.registry,
    'pipelines': onir.pipelines.registry,
}

def main():
    for name, registry in COMPONENTS.items():
        print(name.upper())
        print('default: ' + registry.default)
        print('================')
        for cname, component in registry.registered.items():
            if cname is None:
                continue
            print(cname)
            if component.__doc__ is not None:
                print(component.__doc__)
            else:
                print('''
    (no docstring)
''')
            print('settings')
            for key, val in component.default_config().items():
                print(f'  {key}: {val}')
            print('----------------\n')
    print()

if __name__ == '__main__':
    main()


from .basenet import *
from PATH import PATH
from .TemporalModel import *
from .SpatialTemporalModel import SpatialTemporalModel
from .models import ModelWrapper
from utils.misc import mobile_facenet
class ModelsFactory:
    def __init__(self):
        pass
    @staticmethod
    def get_by_name(args,
        is_train,
        dropout = 0.5,
        pretrained = True):
        bk = mobile_facenet(pretrained, args.cuda)
        bk.remove_output_layer()
        ninp = 512 # 512 is the feature dimension for each task, produced by GDC module

        temporal_models = {}
        for t in args.tasks:
            if t == 'FA':
                dim = 68*2
            elif t == 'EXPR' or t == 'AU':
                dim = len(PATH().Aff_wild2.categories[t])
            else:
                dim = len(PATH().Aff_wild2.categories[t])*20 # digitize_num

            if args.TModel == 'transformer':
                temporal_models[t] = TransformerModel(ninp, args.nhead, args.nhid, args.nlayers, dim, dropout)
            else:
                temporal_models[t] = RNNModel(args.TModel, ninp, args.nhid, args.nlayers, dim, dropout)

        STmodel = SpatialTemporalModel(bk, temporal_models, args.tasks)
        if args.cuda:
            STmodel.cuda()
        model = ModelWrapper(STmodel, args.name, args.tasks, args.checkpoints_dir,
            args.loggings_dir, args.load_epoch, args.batch_size, args.seq_len,
            args.image_size, args.lr, args.lr_policy, args.lr_decay_epochs, args.T_max,
            args.optimizer, args.weight_decay,
            args.gpu_ids,
            args.AU_criterion, args.EXPR_criterion, args.VA_criterion, args.FA_criterion,
            args.lambda_AU, args.lambda_EXPR, args.lambda_VA, args.lambda_FA,
            is_train, args.cuda)
        return model


"""
Transform the RAMS data to a json that will be used
in order to apply event extraction. The target JSON
file will have the following format
[{
  sentence: "I will travel to Greece next week.",
  tokens: [{
    text: "I"
    part_of_speech: "VERB"
    id: 3,
    dependency_relation: "SUBJ"
    head: 1,
    word_embeddings: [...]
  }]
  event: TRANSFER
}]
"""
import argparse
import json
import random
import uuid
from pathlib import Path

import stanza
from corpy.udpipe import Model
from tqdm import tqdm

LANG_SPECIFIC_OPTIONS = {
    "en": {
        "model_ud_pipe": "./data/english-ewt-ud-2.5-191206.udpipe",
        "fasttext_lang": "en",
        "fasttext_model": "./dataset/fasttext/wiki.en.align.vec",
        "stanza_download": "en",
        "stanza_pipeline": "en",
    },
    # not used right now
    "fr": {
        "model_ud_pipe": "./data/french-gsd-ud-2.5-191206.udpipe",
        "fasttext_lang": "fr",
        "fasttext_model": "cc.fr.300.bin",
        "stanza_download": "fr",
        "stanza_pipeline": "fr"
    },
    "de": {
        "model_ud_pipe": "./data/german-gsd-ud-2.5-191206.udpipe",
        "fasttext_lang": "de",
        "fasttext_model": "./dataset/fasttext/wiki.de.align.vec",
        "stanza_download": "de",
        "stanza_pipeline": "de"
    }
}

def init_models(lang="en"):
    global m
    global ft
    global stanza_nlp

    if lang not in LANG_SPECIFIC_OPTIONS.keys():
        print("Can't handle lang", lang)
        exit(42)
    options = LANG_SPECIFIC_OPTIONS[lang]

    # see {http://lindat.mff.cuni.cz/services/udpipe/} for different language models
    # see {https://universaldependencies.org/format.html}
    m = Model(options["model_ud_pipe"])

    stanza.download(options["stanza_download"])
    stanza_nlp = stanza.Pipeline(options["stanza_pipeline"], processors='tokenize,ner')

def map_word_to_token(word):
    """
    Given a sentence return a list of tokens with the required data

    :param sentence: a sentence
    :return: a list of sentence with events
    """
    token = {}
    token['text'] = word.form
    token['part_of_speech'] = word.upostag
    token['id'] = word.id
    token['dependency_relation'] = word.deprel
    token['head'] = word.head
    # token['word_embeddings'] = ft.get_word_vector(word.form).tolist()
    return token

def map_tokens(sentence):
    """
    :param sentence: a sentence as string
    :return: a list of tokens with the required data
    """
    parsed = list(m.process(sentence))
    return list(map(map_word_to_token, parsed[0].words[1:]))

def get_event(events, sentence_start_index, sentence_end_index):
    """
    Returns whether a sentence given its start/end index contains an event.
    If a event exists it returns the event as a string and it's relative to sentence start/end index else NONE
    """
    for event in events:
        event_start = event[0]
        event_end = event[1]
        event_label = event[2][0][0]
        if sentence_start_index <= event_start <= sentence_end_index:
            return event_label, (event_start - sentence_start_index), (event_end - sentence_start_index)

    return None, None, None

def get_argument(arguments, sentence_start_index, sentence_end_index):
    """
    Returns whether a sentence given its start/end index contains an argument.
    If an argument exists it returns it's relative to sentence start/end index else NONE
    """
    for argument in arguments:
        argument_start = argument[1][0]
        argument_end = argument[1][1]
        if sentence_start_index <= argument_start <= sentence_end_index:
            return (argument_start - sentence_start_index), (argument_end - sentence_start_index)

    return None, None

def convert_line_to_target(line):
    """
    Given a line of .jsonline parse the line and convert it to a list of sentences
    with their event
    :param line: a line from RAMS dataset
    :return: a list of sentence with events
    """
    data = json.loads(line)
    events = data['evt_triggers']
    gold_evt_links = data['gold_evt_links']
    sentences = data['sentences']
    sentence_start_index = 0
    sentences_converted = []
    for sentence_tokens in sentences:
        sentence_end_index = sentence_start_index + len(sentence_tokens) - 1

        entry = dict()
        entry['id'] = str(uuid.uuid4())
        entry['sentence'] = " ".join(sentence_tokens)
        tokens_with_data = map_tokens(entry['sentence'])
        entry['token_ud'] = list(map(lambda x: x['text'], tokens_with_data))
        # todo check if we can skip tokenization
        parsed = stanza_nlp.process(entry['sentence'])

        entry['token'] = []
        entry['stanford_ner'] = []
        entry['stanford_pos'] = list(map(lambda x: x['part_of_speech'], tokens_with_data))
        entry['stanford_head'] = list(map(lambda x: x['head'], tokens_with_data))
        entry['stanford_deprel'] = list(map(lambda x: x['dependency_relation'], tokens_with_data))
        for index, token in enumerate(parsed.sentences[0].tokens):
            entry['token'].append(token.text)
            entry['stanford_ner'].append(token.ner)

        if len(entry['token_ud']) != len(entry['token']) or len(entry['token_ud']) != len(sentence_tokens):
            # global skipped_sentences
            # skipped_sentences += 1
            sentence_start_index = sentence_end_index + 1
            continue

        sentence_event, sentence_event_start, sentence_event_stop = get_event(events, sentence_start_index,
                                                                              sentence_end_index)
        if sentence_event is None:
            entry['relation'] = 'no_relation'

            subj_start = random.randint(0, len(entry['token']) - 1)

            entry['subj_start'] = subj_start
            entry['subj_end'] = subj_start
            entry['subj_type'] = entry["stanford_pos"][subj_start]

            obj_start = random.randint(0, len(entry['token']) - 1)
            for i in range(100):
                if subj_start != obj_start:
                    break
                obj_start = random.randint(0, len(entry['token']) - 1)

            entry['obj_start'] = obj_start
            entry['obj_end'] = obj_start
            entry['obj_type'] = entry["stanford_ner"][obj_start]
        else:
            entry['relation'] = sentence_event
            entry['subj_start'] = sentence_event_start
            entry['subj_end'] = sentence_event_stop
            entry['subj_type'] = entry['stanford_pos'][sentence_event_start]

            sentence_argument_start, sentence_argument_stop = get_argument(gold_evt_links, sentence_start_index,
                                                                           sentence_end_index)

            if sentence_argument_start is None:
                obj_start = random.randint(0, len(entry['token']) - 1)

                entry['obj_start'] = obj_start
                entry['obj_end'] = obj_start
                entry['obj_type'] = entry["stanford_ner"][obj_start]
            else:
                entry['obj_start'] = sentence_argument_start
                entry['obj_end'] = sentence_argument_stop
                entry['obj_type'] = entry['stanford_ner'][sentence_event_start]

        sentence_start_index = sentence_end_index + 1
        sentences_converted.append(entry)
    return sentences_converted

def transform_from_file_to_file(source_file_path, target_file_path, target_file_for_translation_path):
    num_lines = sum(1 for _ in open(source_file_path, 'r'))
    with open(source_file_path, "r") as read_file:
        sentences = []
        sentences_to_translate = []
        for line in tqdm(read_file, total=num_lines):
            converted_sentences = convert_line_to_target(line)
            sentences.extend(converted_sentences)
            sentences_to_translate.extend(converted_sentence['sentence'] for converted_sentence in converted_sentences)

        path = Path(target_file_path)
        path.parent.mkdir(parents=True, exist_ok=True)
        print("Writing to target file")
        with open(target_file_path, "w") as write_file:
            json.dump(sentences, write_file, separators=(',', ':'))

        path_for_translation = Path(target_file_for_translation_path)
        path_for_translation.parent.mkdir(parents=True, exist_ok=True)
        print("Writing to target translation file")
        with open(target_file_for_translation_path, "w") as write__translation_file:
            json.dump(sentences_to_translate, write__translation_file, separators=(',', ':'))

def convert_to_sentences_of_tokens(text):
    parsed = list(m.process(text))
    sentences = []
    for sentence_parsed in parsed:
        sentence = []
        for word in sentence_parsed.words[1:]:
            sentence.append(word.form)
        sentences.append(sentence)
    return sentences

def parse_single(text, target_file_path, lang):
    init_models(lang)
    sentences_of_tokens = convert_to_sentences_of_tokens(text)
    line = """
    {{
      "sentences": {},
      "evt_triggers": [],
      "gold_evt_links": []
    }}
    """.format(json.dumps(sentences_of_tokens))
    sentences = convert_line_to_target(line)
    sentences_all_possible = []
    for sentence in sentences:
        for i in range(len(sentence['token'])):
            for j in range(len(sentence['token'])):
                if i == j:
                    continue
                new_sentence = sentence.copy()
                new_sentence['obj_start'] = i
                new_sentence['obj_end'] = i
                new_sentence['obj_type'] = sentence["stanford_ner"][i]

                new_sentence['subj_start'] = j
                new_sentence['subj_end'] = j
                new_sentence['subj_type'] = sentence['stanford_pos'][j]

                sentences_all_possible.append(new_sentence)
    path = Path(target_file_path)
    path.parent.mkdir(parents=True, exist_ok=True)
    print("Writing to file")
    with open(target_file_path, "w") as write_file:
        json.dump(sentences_all_possible, write_file, separators=(',', ':'))

def parse_single_return(text):
    sentences_of_tokens = convert_to_sentences_of_tokens(text)
    line = """
    {{
      "sentences": {},
      "evt_triggers": [] ,
      "gold_evt_links": []
    }}
    """.format(json.dumps(sentences_of_tokens))
    sentences = convert_line_to_target(line)

    return sentences

if __name__ == '__main__':
    # global skipped_sentences
    # skipped_sentences = 0
    parser = argparse.ArgumentParser()
    parser.add_argument('--source', default="data/rams/dev.jsonlines")
    parser.add_argument('--target', default="data/parsed/dev.json")
    parser.add_argument('--target_translation', default="data/parsed/dev_translation.json")
    parser.add_argument('--lang', default="en")
    args = parser.parse_args()
    print("Converting {" + args.source + "} to {" + args.target + "}")
    print("Loading models...")
    init_models(args.lang)
    print("Done loading")
    transform_from_file_to_file(args.source, args.target, args.target_translation)
    # print("Skipped ", skipped_sentences, "sentences due to tokenizer ner and pos missalign")


#!/usr/bin/python
# -*- coding: utf-8 -*-

from __future__ import absolute_import, print_function, division

import sys
import argparse
import readline
import random
import traceback

try:
    import builtins
    raw_input = getattr(builtins, 'input')
except ImportError:
    pass

from game24 import calc, game

MSG_MENU_MAIN = '''1. Play (p)
2. Check answer (c)
3. Quit (q)'''

MSG_MENU_PLAY = '''1. Definitely no solutions (n)
2. Give me a hint (h)
3. I gave up, show me the answer (s)
4. Back to the main menu (b)
5. Quit the game (q)'''

MSG_MENU_SET_END = '''1. One more set (n)
2. Back to the main menu (b)
3. Quit the game (q)'''

MSG_MENU_PLAY_RIGHT = '''1. Try other solutions (t)
2. Next hand (n)
3. Show me the answers (s)
4. Quit the game (q)'''

MSG_SELECT = 'Your choice: '
MSG_INVALID_INPUT = 'Invalid input!'

MSG_MENU_HAND_END = '''1. One more hand (n)
2. Quit this set, back to the main menu (b)
3. Quit the game (q)'''

MSG_SELECT = 'Your choice: '
MSG_INVALID_INPUT = 'Invalid input!'
MSG_INVALID_INTEGER = 'Invalid integer: %s'

MSG_PLAY_NEW_SET = 'Set %d'
MSG_PLAY_NEW_HAND = 'Hand %d: %s'
MSG_PLAY_INPUT_EXPR = 'Input your solution or one of the above choices: '
MSG_PLAY_RIGHT = 'Good Job!'
MSG_PLAY_FIND_BUG = '''Great Job!
You not only solved the problem, but also found a bug!
Please report to me with the cards and your solution if you don't mind.'''
MSG_PLAY_WRONG = "Sorry! It's not correct!"
MSG_PLAY_NO_ANSWER = 'Seems no solutions'
MSG_PLAY_NO_CARDS = 'Set end, your result'

MSG_INPUT_NUMBERS = 'Please input %d integers: '

INPUT_EOF = '\x00'

class GameConsole(game.Game):
    def __init__(self, target=24, count=4, face2ten=False, showcard=False):
        super(GameConsole, self).__init__(target, count, face2ten)
        self.showcard = showcard

    @staticmethod
    def raw_input_ex(prompt='', default=''):
        '''enhance raw_input to support default input and also flat EOF'''
        try:
            readline.set_startup_hook(lambda: readline.insert_text(default))
            try:
                return raw_input(prompt)
            finally:
                readline.set_startup_hook()

        except EOFError:
            return INPUT_EOF

    @staticmethod
    def print_title(title, dechar='', delen=50):
        print(dechar * delen)
        print(title)
        print(dechar * delen)

    @staticmethod
    def ui_menu(menu, choices, eof=True):
        '''show a menu, and return the selection'''
        GameConsole.print_title(menu, dechar='-')
        while True:
            r = GameConsole.raw_input_ex(MSG_SELECT).strip()
            if r.lower() in choices or (eof and r == INPUT_EOF):
                print()
                return r
            print(MSG_INVALID_INPUT)

    def ui_check_answer(self):
        '''show answers for user provided integers'''
        while True:
            r = self.raw_input_ex(MSG_INPUT_NUMBERS % self.count).strip()
            try:
                integers = [int(s) for s in r.strip().split()]
            except ValueError:
                print(MSG_INVALID_INPUT)
                continue

            if len(integers) != self.count:
                print(MSG_INVALID_INPUT)
                continue
            break

        answers = calc.solve(integers, self.target)
        if answers:
            s = '\n'.join([str(expr) for expr in answers])
        else:
            s = MSG_PLAY_NO_ANSWER
        self.print_title(s)

    def main(self):
        '''the main entry of the game console'''
        choices = '1p2c3q'
        while True:
            r = self.ui_menu(MSG_MENU_MAIN, choices)
            if r in '1p':
                self.play()

            elif r in '2c':
                self.ui_check_answer()

            elif r in ('3q' + INPUT_EOF):
                return

    def print_result(self):
        solved = 0
        failed = 0
        hinted = 0
        for hand in self.hands:
            if hand.result == game.HAND_RESULT_SOLVED:
                solved += 1
            elif hand.result == game.HAND_RESULT_HINTED:
                hinted += 1
            elif hand.result == game.HAND_RESULT_FAILED:
                failed += 1
        print()
        print('Total %d hands solved' % solved)
        print('Total %d hands solved with hint' % hinted)
        print('Total %d hands failed to solve' % failed)
        print()

    def ui_menu_and_expr(self, menu, choices, eof=True):
        hand_ints = self.hands[-1].integers
        self.print_title(menu, dechar='-')
        while True:
            r = self.raw_input_ex(MSG_PLAY_INPUT_EXPR).strip()
            if r.lower() in choices or (eof and r == INPUT_EOF):
                print()
                return r

            try:
                expr = calc.parse(r)
            except ValueError as e:
                print(str(e))
                continue

            integers = expr.get_integers()
            for i in integers:
                if i not in hand_ints:
                    print(MSG_INVALID_INTEGER % i)
                    break
            else:
                return expr

    def play(self):
        while True:
            if not self.hands:
                self.print_title(MSG_PLAY_NEW_SET % self.seti, dechar='*')

            hand = self.new_hand()
            if not hand:
                # no enough cards for a new hand
                self.print_title(MSG_PLAY_NO_CARDS, dechar='*')
                self.print_result()

                choices = '1n2b3q'
                r = self.ui_menu(MSG_MENU_SET_END, choices)
                if r in '1n':
                    # renew the set
                    self.reset()
                    continue

                elif r in ('2b' + INPUT_EOF):
                    # back to the main menu
                    return

                elif r in '3q':
                    sys.exit(0)

            print()
            if self.showcard:
                sc = hand.str_cards()
            else:
                sc = ' '.join([str(i) for i in hand.integers])
            self.print_title(MSG_PLAY_NEW_HAND % (len(self.hands), sc),
                                                            dechar='+')
            print()
            while True:
                choices = '1n2h3s4b5q'
                r = self.ui_menu_and_expr(MSG_MENU_PLAY, choices)
                if isinstance(r, calc.Expr):
                    expr = r
                    if expr.value == self.target:
                        hand.solved()
                        if expr not in hand.answers:
                            s = MSG_PLAY_FIND_BUG
                        else:
                            s = MSG_PLAY_RIGHT
                        self.print_title(s)

                        choices = '1t2n3s4q'
                        r = self.ui_menu(MSG_MENU_PLAY_RIGHT, choices, eof=False)
                        if r in '1t':
                            continue
                        elif r in '2n':
                            break
                        elif r in '3s':
                            self.print_title(hand.str_answer())
                        elif r in '4q':
                            sys.exit(0)

                    else:
                        self.print_title(MSG_PLAY_WRONG)
                        continue

                elif r in '1n':
                    # no answer
                    if hand.answers:
                        self.print_title(MSG_PLAY_WRONG)
                        continue
                    else:
                        hand.solved()
                        self.print_title(MSG_PLAY_RIGHT)

                elif r in '2h':
                    # show a hint
                    if hand.answers:
                        hand.hinted()
                        self.print_title(hand.str_hint())
                        continue
                    else:
                        self.print_title(MSG_PLAY_NO_ANSWER)

                elif r in '3s':
                    # show the answer
                    if hand.answers:
                        s = hand.str_answer()
                    else:
                        s = MSG_PLAY_NO_ANSWER
                    self.print_title(s)

                elif r in ('4b' + INPUT_EOF):
                    # back to the main menu
                    return

                elif r in '5q':
                    sys.exit(0)

                # this hand is end
                break

def arg_parse():
    parser = argparse.ArgumentParser(description='Play the 24 Game')
    parser.add_argument('-c', type=int, default=4, dest='count',
            help='the number of integers to play with, default=4')
    parser.add_argument('-C', action='store_true', dest='showcard',
            help='show cards instead of integers under interactive mode')
    parser.add_argument('-d', action='store_true', dest='debug',
            help='enable debug output')
    parser.add_argument('-i', action='store_true', dest='interactive',
            help='interactive mode, all positional integers arguments omitted')
    parser.add_argument('-N', action='store_true', dest='face2ten',
            help='under interactive mode, set J Q K to 10, default=11,12,13')
    parser.add_argument('-t', type=int, default=24, dest='target',
            help='the game target, default=24')
    parser.add_argument('integers', nargs='*')

    r = parser.parse_args()

    if not r.interactive and len(r.integers) == 0:
        r.interactive = True

    elif not r.interactive and len(r.integers) != 1:
        if len(r.integers) != r.count:
            parser.error('invalid number of integers provided, expect %d' %
                                                                    r.count)

        err_nums = [s for s in r.integers if not s.isdigit()]
        if err_nums:
            parser.error('invalid integers: %s' % str(err_nums))

        r.integers = [int(s) for s in r.integers]

        err_nums = [i for i in r.integers if i < 1 or
                        i > (r.face2ten and 10 or 13)]
        if err_nums:
            parser.error('invalid integers: %s' % str(err_nums))

    return r

def main():
    args = arg_parse()
    try:
        if args.interactive:
            gc = GameConsole(args.target, args.count,
                        args.face2ten, args.showcard)
            gc.main()

        elif len(args.integers) == 1:
            # parse expression
            expr = calc.parse(args.integers[0])
            if args.debug:
                print(repr(expr))
                print(str(expr))
            print(expr.value)

        else:
            # solve
            exprs = calc.solve(args.integers, args.target)
            if not exprs:
                print(MSG_PLAY_NO_ANSWER)
            else:
                for expr in exprs:
                    print(args.debug and repr(expr) or str(expr))

        sys.exit(0)

    except KeyboardInterrupt:
        sys.exit(1)

    except Exception as e:
        if args.debug:
            traceback.print_exc()
        else:
            print(str(e), file=sys.stderr)
        sys.exit(3)

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
#import fit_position

from maya import cmds
from maya import mel
from maya import OpenMayaUI as OMUI
import os
from  inspect import getsourcefile

try:
    from PySide2.QtCore import *
    from PySide2.QtGui import *
    from PySide2.QtWidgets import *
    from PySide2.QtUiTools import *
    from shiboken2 import wrapInstance
except ImportError:
    from PySide.QtCore import *
    from PySide.QtGui import *
    from PySide.QtUiTools import *
    from shiboken import wrapInstance

mayaMainWindowPtr = OMUI.MQtUtil.mainWindow()
mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QWidget)

class AIFAE_FacialSetup(QWidget):
    '''不能有重名的字符串'''
    face_rig_dict = {
        "face_rig": [
            {"face_constraint": "face_constraint1"},
            {
                "face_ctrl": [
                    {
                        "ctrl_grp": [
                            {
                                "jaw_ctrl_locator": [
                                    {
                                        "lowerlip": [
                                            {
                                                "lowerlip2": "lowerlip_2_sufaceJoint"
                                            }
                                        ]
                                    }
                                ]
                            },
                            {
                                "lowerEyelid_left_ctrl_locator": [
                                    {
                                        "lowerEyelid_left": [
                                            "lowerEyelid_left_1_bn_ctrl",
                                            "lowerEyelid_left_2_bn_ctrl",
                                            "lowerEyelid_left_3_bn_ctrl",
                                            "lowerEyelid_left_4_bn_ctrl",
                                            "lowerEyelid_left_5_bn_ctrl"
                                        ]
                                    }
                                ]
                            },
                            {
                                "upperEyelid_left_ctrl_locator": [
                                    {
                                        "upperEyelid_left": [
                                            "upperEyelid_left_1_bn_ctrl",
                                            "upperEyelid_left_2_bn_ctrl",
                                            "upperEyelid_left_3_bn_ctrl",
                                            "upperEyelid_left_4_bn_ctrl",
                                            "upperEyelid_left_5_bn_ctrl",
                                        ]
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "brows_left": [
                            "brows_left_1_locator",
                            "brows_left_2_locator",
                            "brows_left_3_locator"
                        ]
                    },
                    {
                        "brows_right": [
                            "brows_right_1_locator",
                            "brows_right_2_locator",
                            "brows_right_3_locator"
                        ]
                    },
                    {
                        "mouth_conner": [
                            {
                                "upperlip": "upperlip_2_surfaceJoint"
                            },
                            {
                                "mouthCorner_left": [
                                    {
                                        "mouthCorner_left": [
                                            {
                                                "mouthCorner_left_jaw": [
                                                    {
                                                        "mouthCorner_left_ctrl": [
                                                            {
                                                                "mouthCorner_left_locator_grp": "mouthCorner_left_locator"},
                                                            "upperlip_1_sufaceJoint",
                                                            "lowerlip_1_sufaceJoint"
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            },
                            {
                                "mouthCorner_right": [
                                    {
                                        "mouthCorner_right": [
                                            {
                                                "mouthCorner_right_jaw": [
                                                    {
                                                        "mouthCorner_right_ctrl": [
                                                            {
                                                                "mouthCorner_right_locator_grp": "mouthCorner_right_locator"},
                                                            "upperlip_3_sufaceJoint",
                                                            "lowerlip_3_sufaceJoint"
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
    final_list = []
    move_list = [{"face_rig": "Head"},
                 {"face_constraint": ""},
                 {"face_ctrl": ""},
                 {"brows_left": "eye_control"},
                 {"brows_left_1_locator": "brows_left_1_bn"},
                 {"brows_left_2_locator": "brows_left_2_bn"},
                 {"brows_left_3_locator": "brows_left_3_bn"},
                 {"brows_right": "eye_control"},
                 {"brows_right_1_locator": "brows_right_1_bn"},
                 {"brows_right_2_locator": "brows_right_2_bn"},
                 {"brows_right_3_locator": "brows_right_3_bn"},
                 {"ctrl_grp": "Head"},
                 {"lowerEyelid_left_ctrl_locator": ""},
                 {"lowerEyelid_left": ""},
                 {"lowerEyelid_left_1_bn_ctrl": "lowerEyelid_left_1_bn"},
                 {"lowerEyelid_left_2_bn_ctrl": "lowerEyelid_left_2_bn"},
                 {"lowerEyelid_left_3_bn_ctrl": "lowerEyelid_left_3_bn"},
                 {"lowerEyelid_left_4_bn_ctrl": "lowerEyelid_left_4_bn"},
                 {"lowerEyelid_left_5_bn_ctrl": "lowerEyelid_left_5_bn"},
                 {"upperEyelid_left_ctrl_locator": ""},
                 {"lowerEyelid_left": ""},
                 {"upperEyelid_left_1_bn_ctrl": "upperEyelid_left_1_bn"},
                 {"upperEyelid_left_2_bn_ctrl": "upperEyelid_left_2_bn"},
                 {"upperEyelid_left_3_bn_ctrl": "upperEyelid_left_3_bn"},
                 {"upperEyelid_left_4_bn_ctrl": "upperEyelid_left_4_bn"},
                 {"upperEyelid_left_5_bn_ctrl": "upperEyelid_left_5_bn"},
                 {"jaw_ctrl_locator": "jaw_ctrl_bn"},
                 {"lowerlip": ""},
                 {"lowerlip_2": ""},
                 {"lowerlip_2_sufaceJoint": "jaw_1_bn"},
                 {"mouth_conner": "jaw_ctrl_bn"},
                 {"upperlip": ""},
                 {"upperlip_2_surfaceJoint": "jaw_1_bn"},
                 {"mouthCorner_right": "mouthCorner_right_bn"},
                 {"mouthCorner_right_jaw": "jaw_ctrl_bn"},
                 {"mouthCorner_right_ctrl": "mouthCorner_right_bn"},
                 {"lowerlip_3_sufaceJoint": ""},
                 {"upperlip_3_sufaceJoint": ""},
                 {"mouthCorner_right_locater_grp": ""},
                 {"mouthCorner_right_locater": ""},
                 {"mouthCorner_left": "mouthCorner_left_bn"},
                 {"mouthCorner_left_jaw": "jaw_ctrl_bn"},
                 {"mouthCorner_left_ctrl": "mouthCorner_left_bn"},
                 {"lowerlip_1_sufaceJoint": ""},
                 {"upperlip_1_sufaceJoint": ""},
                 {"mouthCorner_left_locater_grp": ""},
                 {"mouthCorner_right_locater": ""}, ]  # 位置信息对位字典
    def __init__(self, *args, **kwargs):
        super(AIFAE_FacialSetup, self).__init__(*args, **kwargs)
        self.setParent(mayaMainWindow)
        self.setWindowFlags(Qt.Window)
        self.setWindowTitle("AI FAE Facial Setup Window")
        self.initUI()

    def initUI(self):
        loader = QUiLoader()
        file_path =  os.path.abspath(getsourcefile(lambda : 0)) #获取脚本的绝对路径
        currentUI = file_path.replace(file_path.split('\\')[-1], "FacialSetUp.ui")
        #currentUI = file_path.replace(".py", ".ui")             #获取UI的的绝对路径
        print (file_path)
        file = QFile( currentUI)
        file.open(QFile.ReadOnly)
        self.ui = loader.load(file, parentWidget=self)

        self.ui.createControllerBtn.clicked.connect(self.auto_create_controller)
        self.ui.fitPositionBtn.clicked.connect(self.fit_position)
        self.ui.parentConstraintBtn.clicked.connect(self.doParentConstraint)
        self.ui.pointConstraintBtn.clicked.connect(self.doPointConstraint)
        self.ui.setDrivenKeyBtn.clicked.connect(self.doSetDrivenKey)
        self.ui.deleteConstraintBtn.clicked.connect(self.doDeleteConstraint)
        self.ui.parentConstraintBtn_2.clicked.connect(self.doParentConstraint2)
        self.ui.pointConstraintBtn_2.clicked.connect(self.doPointConstraint2)

    def go_though_dict(self, json_data, path=""):
        global depth
        if isinstance(json_data, dict):
            # depth += 1
            for key in json_data:
                path = path + key + "-->"
                self.go_though_dict(json_data[key], path)
        elif isinstance(json_data, list):
            # print len(json_data)
            for i in range(len(json_data)):
                # print json_data[i]
                if isinstance(json_data[i], dict):
                    for sub_key in json_data[i]:
                        depth += 1
                        self.go_though_dict(json_data[i], path)
                    depth -= 1
                else:
                    self.final_list.append((path + json_data[i], depth))
        else:
            self.final_list.append((path + json_data, depth))
        return self.final_list

    def create_tree(self, tree_leaf_edges):
        for element in  tree_leaf_edges:
            element_list = element[0].split("-->")
            for i in range(len(element_list)):
                if cmds.objExists(element_list[i]):
                    print (("{} has been created already!").format(element_list[i]))
                else:
                    if i != 0:
                        cmds.select(clear=True)
                        if "_loc" in element_list[i]:
                            cmds.spaceLocator(name=element_list[i])
                        elif "_bn_" in element_list[i] or "Joint" in element_list[i]:
                            cmds.joint(name=element_list[i])
                        else:
                            cmds.group(empty=True, name=element_list[i])
                        cmds.parent(element_list[i], element_list[i - 1])
                    else:
                        cmds.group(empty=True, name=element_list[i])
            print ("-------------------------------------------------------------------------")

    # 根据角色骨骼自动对位控制器位置。source_name为控制器名称， destination为移动目标。
    def move_to_position(self, source_name, destination_name):
        if cmds.objExists(source_name) and cmds.objExists(destination_name):
            destination_position = cmds.xform(destination_name, q=True, translation=True, worldSpace=True)
            cmds.move(destination_position[0], destination_position[1], destination_position[2], source_name)
        else:
            pass
            #print (source_name, destination_name)

    def set_position(self, obj_list):
        for element in obj_list:
            for key, value in element.items():
                self.move_to_position(key, value)

    def auto_create_controller(self):
        self.go_though_dict(json_data=self.face_rig_dict,path="")
        self.create_tree(tree_leaf_edges=sorted(self.final_list, key=lambda x: x[1]))

    def fit_position(self):
        if len(self.final_list)>0:
            self.set_position(self.move_list)
        else:
            cmds.error("Please create the controllers!")

    def doParentConstraint(self):  #遍历场景根据名称进行约束
        driverName = self.ui.driverNameLine.text()
        drivenName = self.ui.drivenNameLine.text()
        print  (driverName, drivenName)
        transformsObjects = cmds.ls(tr = True)
        for driverObj in transformsObjects:                                 #遍历场景中的物体
            if driverName in driverObj:                                     #查找驱动物体
                drivenObj =  driverObj.replace(driverName,drivenName)       #设置驱动物体名称
                if cmds.objExists(drivenObj):                               #确认被驱动物体是否存在
                    cmds.parentConstraint(driverObj, drivenObj , mo = True) #约束物体

    def doPointConstraint(self): #遍历场景根据名称进行约束
        driverName = self.ui.driverNameLine.text()
        drivenName = self.ui.drivenNameLine.text()
        print  (driverName,drivenName)
        transformsObjects = cmds.ls(tr = True)
        for driverObj in transformsObjects:                                 #遍历场景中的物体
            if driverName in driverObj:                                     #查找驱动物体
                drivenObj =  driverObj.replace(driverName,drivenName)       #设置驱动物体名称
                if cmds.objExists(drivenObj):                               #确认被驱动物体是否存在
                    #print driverObj,drivenObj
                    cmds.pointConstraint(driverObj,drivenObj , mo = True)   #约束物体

    def doParentConstraint2(self ):  #遍历场景根据名称进行约束
        driverName = self.ui.driverNameLineSecond.text()
        drivenName = self.ui.drivenNameLineSecond.text()
        print  (driverName, drivenName)
        transformsObjects = cmds.ls(tr = True)
        for driverObj in transformsObjects:                                 #遍历场景中的物体
            if driverName in driverObj:                                     #查找驱动物体
                drivenObj =  driverObj.replace(driverName,drivenName)       #设置驱动物体名称
                if cmds.objExists(drivenObj):                               #确认被驱动物体是否存在
                    cmds.parentConstraint(driverObj, drivenObj , mo = True) #约束物体

    def doPointConstraint2(self): #遍历场景根据名称进行约束
        driverName = self.ui.driverNameLine.text()
        drivenName = self.ui.drivenNameLine.text()
        print  (driverName,drivenName)
        transformsObjects = cmds.ls(tr = True)
        for driverObj in transformsObjects:                                 #遍历场景中的物体
            if driverName in driverObj:                                     #查找驱动物体
                drivenObj =  driverObj.replace(driverName,drivenName)       #设置驱动物体名称
                if cmds.objExists(drivenObj):                               #确认被驱动物体是否存在
                    #print driverObj,drivenObj
                    cmds.pointConstraint(driverObj,drivenObj , mo = True)   #约束物体

    def doDeleteConstraint2(self):  # 遍历场景根据名称进行删除
        # driverName = self.ui.driverNameLine.text()
        drivenName = self.ui.drivenNameLineSecond.text()
        # print  driverName
        transformsObjects = cmds.ls(tr=True)
        for obj in transformsObjects:
            if "Constraint" in obj and drivenName in obj:  # 确认被约束物体
                cmds.delete(obj)  # 删除约束

    def doDeleteConstraint(self):#遍历场景根据名称进行删除
        #driverName = self.ui.driverNameLine.text()
        drivenName = self.ui.drivenNameLine.text()
        #print  driverName
        transformsObjects = cmds.ls(tr=True)
        for obj in transformsObjects:
            if "Constraint" in obj and  drivenName in obj:  #确认被约束物体
                cmds.delete(obj)                            #删除约束

    def doSetDrivenKey(self):#遍历场景根据名称进行驱动
        driverName = self.ui.driverNameLine_2.text()
        drivenName = self.ui.drivenNameLine_2.text()
        driverAttrA = self.ui.driverAttrA.text()
        driverAttrB = self.ui.driverAttrB.text()
        drivenAttrA = self.ui.drivenAttrA.text()
        drivenAttrB = self.ui.drivenAttrB.text()
        minRotateX = self.ui.minSpinBoxX.value()
        midRotateX = self.ui.midSpinBoxX.value()
        maxRotateX = self.ui.maxSpinBoxX.value()
        minRotateY = self.ui.minSpinBoxY.value()
        midRotateY = self.ui.midSpinBoxY.value()
        maxRotateY = self.ui.maxSpinBoxY.value()
        #print (minRotateX, midRotateX, maxRotateX, minRotateY, midRotateY, maxRotateY)
        drivers = cmds.ls(sl=True)                                      #选择驱动关键帧的控制器
        if len(drivers)!=0:
            for driver in drivers:
                drivenObj = driver.replace(driverName, drivenName)      #查找被驱动物体名称
                if cmds.objExists(drivenObj):                           #如果被驱动物体存在，设置驱动关键帧
                    cmds.setDrivenKeyframe(drivenObj + ".%s"%drivenAttrA, currentDriver=driver+driverAttrA,
                                           driverValue=-1, value=minRotateX)
                    cmds.setDrivenKeyframe(drivenObj + ".%s" % drivenAttrA, currentDriver=driver + driverAttrA,
                                           driverValue=0, value=midRotateX)
                    cmds.setDrivenKeyframe(drivenObj + ".%s"%drivenAttrA, currentDriver=driver+driverAttrA,
                                           driverValue=1, value=maxRotateX)
                    cmds.setDrivenKeyframe(drivenObj + ".%s"%drivenAttrB, currentDriver=driver+driverAttrB,
                                           driverValue=-1, value=minRotateY)
                    cmds.setDrivenKeyframe(drivenObj + ".%s" % drivenAttrB, currentDriver=driver + driverAttrA,
                                           driverValue=0, value=midRotateY)
                    cmds.setDrivenKeyframe(drivenObj + ".%s"%drivenAttrB, currentDriver=driver+driverAttrB,
                                           driverValue=1, value=maxRotateY)
                else:
                    print ("Your select %s is not exists!"%drivenObj)
        else:
            print ("No object is selected!")

def main():

    ui = AIFAE_FacialSetup()
    ui.show()
    return ui

if __name__ == '__main__':
    main()


data = [(['Linux', 'is', 'the', 'best', 'OS'], ['OS','IR','IR','IR','IR']),

(['Ubuntu', 'is', 'my', 'favourite', 'OS'], ['OS','IR','IR','IR','IR'])]

corpus = []

for (doc, tags) in data:

    doc_tag = []

    for word, tag in zip(doc,tags):

        doc_tag.append((word, tag))

    corpus.append(doc_tag)

def doc2features(doc, i):

    word = doc[i][0]

    # Features from current word

    features={

        'word.word': word,

    }

    # Features from previous word

    if i > 0:

        prevword = doc[i-1][0]

        features['word.prevword'] = prevword

    else:

        features['BOS'] = True # Special "Beginning of Sequence" tag

    # Features from next word

    if i < len(doc)-1:

        nextword = doc[i+1][0]

        features['word.nextword'] = nextword

    else:

        features['EOS'] = True # Special "End of Sequence" tag

    return features

def extract_features(doc):

    return [doc2features(doc, i) for i in range(len(doc))]

X = [extract_features(doc) for doc in corpus]

print(X)

doc = '''Andrew Yan-Tak Ng is a Chinese American computer scientist.

He is the former chief scientist at Baidu, where he led the company's

Artificial Intelligence Group. He is an adjunct professor (formerly

associate professor) at Stanford University. Ng is also the co-founder

and chairman at Coursera, an online education platform. Andrew was born

in the UK in 1976. His parents were both from Hong Kong.'''
doc2features(doc,0)


"""Organisations admin."""

from django.contrib.gis import admin
from organisations.models import Organisation
from leaflet.admin import LeafletGeoAdmin

@admin.register(Organisation)
class OrganisationAdmin(LeafletGeoAdmin):
    """Marker admin."""

    list_display = (
        "name",
        "building_name_or_number",
        "street",
        "city_or_town",
        "postcode",
        "uprn",
    )


import torch
import torch.nn as nn

class vertical_net(nn.Module):
    def __init__(self):
        super(vertical_net, self).__init__()

        self.relu = nn.ReLU()
        self.conv1 = nn.Conv2d(3, 16, 3, 2, 1, bias=True)
        self.conv2 = nn.Conv2d(16, 32, 3, 2, 1, bias=True)
        self.conv3 = nn.Conv2d(32, 64, 3, 2, 1, bias=True)
        self.conv4 = nn.Conv2d(64, 128, 3, 2, 1, bias=True)
        self.conv5 = nn.Conv2d(358, 3, 1, 1, 0, bias=False)
        self.up = nn.Upsample(scale_factor=2, mode='bilinear')

        self.dconv1 = nn.Conv2d(128, 64, 3, 1, 1, bias=True)
        self.dconv2 = nn.Conv2d(64, 32, 3, 1, 1, bias=True)
        self.dconv3 = nn.Conv2d(32, 16, 3, 1, 1, bias=True)
        self.dconv4 = nn.Conv2d(16, 3, 3, 1, 1, bias=True)

        self.cconv1 = nn.Conv2d(128, 3, 1, 1, 0, bias=False)
        self.cconv2 = nn.Conv2d(64, 3, 1, 1, 0, bias=False)
        self.cconv3 = nn.Conv2d(32, 3, 1, 1, 0, bias=False)
        self.cconv4 = nn.Conv2d(6, 3, 1, 1, 0, bias=False)
        self.cconv5 = nn.Conv2d(15, 3, 1, 1, 0, bias=False)

    def forward(self, x):
        x1 = self.relu(self.conv1(x))
        x2 = self.relu(self.conv2(x1))
        x3 = self.relu(self.conv3(x2))
        x4 = self.relu(self.conv4(x3))
        x5 = nn.Upsample(scale_factor=2, mode='bilinear')(x4)
        x5 = self.relu(self.dconv1(x5))
        x6 = nn.Upsample(scale_factor=2, mode='bilinear')(x5)
        x6 = self.relu(self.dconv2(x6))
        x7 = nn.Upsample(scale_factor=2, mode='bilinear')(x6)
        x7 = self.relu(self.dconv3(x7))
        x8 = nn.Upsample(scale_factor=2, mode='bilinear')(x7)
        x8 = self.relu(self.dconv4(x8))

        # merge different feature
        x9 = torch.cat([x3, x5], 1)
        x9 = self.relu(self.cconv1(x9))
        x9 = nn.Upsample(scale_factor=8, mode='bilinear')(x9)

        x10 = torch.cat([x2, x6], 1)
        x10 = nn.Upsample(scale_factor=4, mode='bilinear')(x10)
        x10 = self.relu(self.cconv2(x10))

        x11 = torch.cat([x1, x7], 1)
        x11 = nn.Upsample(scale_factor=2, mode='bilinear')(x11)
        x11 = self.relu(self.cconv3(x11))

        x12 = torch.cat([x9, x10, x11, x, x8], 1)
        y = self.relu(self.cconv5(x12))

        return y


import random
import numpy as np
import torch

def data_set(data_url, vocab_size):
    """process data input."""
    data_list = []
    word_count = []
    with open(data_url) as fin:
        while True:
            line = fin.readline()
            if not line:
                break
            id_freqs = line.split()
            id_freqs = id_freqs[0:-1]
            doc = {}
            count = 0
            for id_freq in id_freqs:
                items = id_freq.split(':')
                doc[int(items[0]) - 1] = int(items[1])
                count += int(items[1])
            if count > 0:
                data_list.append(doc)
                word_count.append(count)
    data_mat = np.zeros((len(data_list), vocab_size), dtype=np.int16)
    for doc_idx, doc in enumerate(data_list):
        for word_idx, count in doc.items():
            data_mat[doc_idx, word_idx] += count
    return data_list, data_mat, word_count

def create_batches(data_size, batch_size, shuffle=True):
    batches = []
    ids = list(range(data_size))
    if shuffle:
        random.shuffle(ids)
    for i in range(int(data_size / batch_size)):
        start = i * batch_size
        end = (i + 1) * batch_size
        batches.append(ids[start:end])
    # the batch of which the length is less than batch_size
    rest = data_size % batch_size
    if rest > 0:
        batches.append(ids[-rest:] + [-1] * (batch_size - rest))  # -1 as padding
    return batches

def fetch_data(data, count, idx_batch, vocab_size):
    """fetch input data by batch."""
    batch_size = len(idx_batch)
    data_batch = np.zeros((batch_size, vocab_size))
    count_batch = []
    mask = np.zeros(batch_size)
    for i, doc_id in enumerate(idx_batch):
        if doc_id != -1:
            for word_id, freq in data[doc_id].items():
                data_batch[i, word_id] = freq
            count_batch.append(count[doc_id])
            mask[i] = 1.0
        else:
            count_batch.append(0)
    return data_batch, count_batch, mask

def variable_parser(var_list, prefix):
    """return a subset of the all_variables by prefix."""
    ret_list = []
    for var in var_list:
        varname = var.name
        varprefix = varname.split('/')[0]
        if varprefix == prefix:
            ret_list.append(var)
    return ret_list


from typing import Literal

import pytest
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import IntegrityError

from flask_ad_service.crud import crud_ad
from flask_ad_service.crud.common.exceptions import CrudItemNotFoundError
from flask_ad_service.crud.conditions import is_deleted
from flask_ad_service.model import AdDBModel, UserDBModel
from tests.faker.factories import AdFactory

pytestmark: pytest.MarkDecorator = pytest.mark.usefixtures(
    "_app_ctx", "db_test_session", "_populate_db"
)

@pytest.mark.parametrize("user", [1], indirect=True)
def test_ad_get_ad_by_id_returns_correct_value_and_type(
    database: SQLAlchemy, user: UserDBModel, non_existant_ad_id: Literal[10000]
) -> None:
    ad = AdFactory.create(author_id=user.id)
    q = crud_ad.get_ad_by_id(database, ad.id)
    assert ad == q
    assert isinstance(q, AdDBModel)

    # Should return none if the id is not found
    q = crud_ad.get_ad_by_id(database, non_existant_ad_id)
    assert q is None

@pytest.mark.parametrize("user", [1], indirect=True)
def test_ad_create_pass(database: SQLAlchemy, user: UserDBModel) -> None:
    ad, exc = crud_ad.create_ad(
        database,
        user.id,
        "created ad",
    )
    assert exc is None
    assert ad is not None
    assert isinstance(ad, AdDBModel)
    database.session.refresh(user)
    assert user.ads is not None
    assert user.ads[-1].id == ad.id

def test_crud_ad_create_ad_fail_for_user_that_does_not_exist(
    database: SQLAlchemy, non_existant_user_id: Literal[1000]
) -> None:
    with pytest.raises(IntegrityError):
        ad, exc = crud_ad.create_ad(
            database,
            non_existant_user_id,
            "created ad",
        )

@pytest.mark.parametrize("user", [1], indirect=True)
def test_crud_ad_delete_pass(database: SQLAlchemy, user: UserDBModel) -> None:
    ad = AdFactory.create(author_id=user.id)
    returned_ad, exc = crud_ad.delete_ad(database, ad.id)
    assert returned_ad is not None
    assert exc is None
    assert is_deleted(returned_ad)
    database.session.refresh(ad, attribute_names=["is_deleted"])
    assert ad == returned_ad

@pytest.mark.parametrize("user", [1], indirect=True)
def test_crud_ad_delete_returns_not_found_error(
    database: SQLAlchemy, user: UserDBModel, non_existant_ad_id: Literal[10000]
) -> None:
    returned_ad, exc = crud_ad.delete_ad(database, non_existant_ad_id)
    assert returned_ad is None
    assert exc is not None
    assert isinstance(exc, CrudItemNotFoundError)


import turtle
# Visualization
turtle.shape("circle")
turtle.shapesize(0.1, 0.1)
turtle.speed(0)

MOVES = {
    "n":  ( 2,  0),
    "ne": ( 1,  1),
    "se": (-1,  1),
    "s":  (-2,  0),
    "sw": (-1, -1),
    "nw": ( 1, -1)
}

def dist(x, y):
    x = abs(x)
    y = abs(y)
    ma = max(x,y)
    mi = min(x,y)
    return mi+((ma-mi)//2)

def find_pos(line):
    moves = line.strip().lower().split(",")
    x = 0
    y = 0
    max_dist = 0
    for m in moves:
        x += MOVES[m][0]
        y += MOVES[m][1]
        #turtle.goto(x, y) # Visualize path
        max_dist = max(max_dist, dist(x,y))
    return x, y, dist(x,y), max_dist

with open("input.txt", "r") as f:
    for line in f:
        print(find_pos(line))
        break


# Define the recursive function to calculate Fibonacci number
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

# Read the number of test cases
num_tests = int(input())

# Process each test case
for _ in range(num_tests):
    n = int(input())  # Read the input number
    ans = fib(n)  # Calculate Fibonacci number using the recursive function
    print(ans)


import bisect
from sys import stdin

def main():
    N, H = map(int, stdin.readline().split())
    stalag = []
    stalac = []

    for i in range(N):
        height = int(stdin.readline())
        if i % 2 == 0:
            # Stalagmites are even
            stalag.append(height)
        else:
            # Stalacmites are odd
            stalac.append(height)

    # Firefly will hit all obstacles >= a certain height regardless of their ordering
    # So sort them and find the number of collisions
    stalac.sort()
    stalag.sort()

    best = N
    num_levels = 0
    for i in range(H):
        # Find the number of collisions using binary search
        # The height of the obstacles start from 1, so add 1 to i
        top_collisions = len(stalac) - bisect.bisect_left(stalac, i+1)
        bot_collisions = len(stalag) - bisect.bisect_left(stalag, H-i)
        collisions = top_collisions + bot_collisions

        if collisions < best:
            # Found new minimum collisions
            best = collisions
            num_levels = 1
        elif collisions == best:
            # Found exisiting minimum
            num_levels += 1

    print(best, num_levels)

if __name__ == '__main__':
    main()


# SPDX-License-Identifier: BSD-3-Clause
from .soc import RemiruSoC

__all__ = (
	'cli',
)

def build(buildAs: str):
	if buildAs == 'gateware':
		from .platforms import RemiruSoCGatewarePlatform
		platform = RemiruSoCGatewarePlatform()
	# elif buildAs == 'asic':
	# 	from .platforms import RimuruSoCASICPlatform
	# 	platform = RimuruSoCASICPlatform()
	platform.build(RemiruSoC(), name = 'remiruSoC')

def cli():
	from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter

	parser = ArgumentParser(formatter_class = ArgumentDefaultsHelpFormatter,
		description = 'project remiru')
	actions = parser.add_subparsers(dest = 'action', required = True)

	buildAction = actions.add_parser('build', help = 'build the project remiru SoC gateware')
	actions.add_parser('sim', help = 'Simulate the gateware components')
	actions.add_parser('formal', help = 'Formally verify the gateware components')

	buildAction.add_argument('--as', dest = 'buildAs', action = 'store', required = True,
		choices = ('gateware', ))#'asic'

	args = parser.parse_args()

	if args.action == 'sim':
		from .sim.framework import runSims
		runSims(pkg = 'remiru/sim', result_dir = 'build')
		return 0
	elif args.action == 'build':
		build(args.buildAs)
		return 0


"""Exam0."""
from typing import Optional
import re

def find_capital_letters(s: str) -> str:
    """
    Return only capital letters from the string.

    #1

    If there are no capital letters, return empty string.
    The string contains only latin letters (a-z and A-Z).
    The letters should be in the same order as they appear in the input string.

    find_capital_letters("ABC") => "ABC"
    find_capital_letters("abc") => ""
    find_capital_letters("aAbBc") => "AB"
    """
    new_s = ""
    for letter in s:
        if letter.isupper():
            new_s += letter
    return new_s

def close_far(a: int, b: int, c: int) -> bool:
    """
    Return if one value is "close" and other is "far".

    #2

    Given three ints, a b c, return true if one of b or c is "close" (differing from a by at most 1),
    while the other is "far", differing from both other values by 2 or more.

    close_far(1, 2, 10) => True
    close_far(1, 2, 3) => False
    close_far(4, 1, 3) => True
    """
    if abs(a - b) <= 1 and abs(a - c) >= 2 and abs(b - c) >= 2:
        return True
    elif abs(a - c) <= 1 and abs(a - b) >= 2 and abs(b - c) >= 2:
        return True
    else:
        return False

def get_names_from_results(results_string: str, min_result: int) -> list:
    """
    Given a string of names and scores, return a list of names where the score is higher than or equal to min_result.

    #3

    Results are separated by comma (,). Result contains a score and optionally a name.
    Score is integer, name can have several names separated by single space.
    Name part can also contain numbers and other symbols (except for comma).
    Return only the names which have the score higher or equal than min_result.
    The order of the result should be the same as in input string.

    get_names_from_results("ago 123,peeter 11", 0) => ["ago", "peeter"]
    get_names_from_results("ago 123,peeter 11,33", 10) => ["ago", "peeter"]  # 33 does not have the name
    get_names_from_results("ago 123,peeter 11", 100) => ["ago"]
    get_names_from_results("ago 123,peeter 11,kitty11!! 33", 11) => ["ago", "peeter",  "kitty11!!"]
    get_names_from_results("ago 123,peeter 11,kusti riin 14", 12) => ["ago", "kusti riin"]
    """
    above_min = []
    separated_results = results_string.split(",")
    for ind_result in separated_results:
        pattern = r"(.+)[\D](\d+)$"
        results = re.findall(pattern, ind_result)
        if len(results) == 0:
            continue
        if len(results[0]) > 1:
            if int(results[0][1]) >= min_result:
                above_min.append(results[0][0])
        else:
            continue
    return above_min

def tic_tac_toe(game: list) -> int:
    """
    Find game winner.

    #4

    The 3x3 table is represented as a list of 3 rows, each row has 3 element (ints).
    The value can be 1 (player 1), 2 (player 2) or 0 (empty).
    The winner is the player who gets 3 of her pieces in a row, column or diagonal.

    There is only one winner or draw. You don't have to validate whether the game is in correct (possible) state.
    I.e the game could have four 1s and one 0 etc.

    tic_tac_toe([[1, 2, 1], [2, 1, 2], [2, 2, 1]]) => 1
    tic_tac_toe([[1, 0, 1], [2, 1, 2], [2, 2, 0]]) => 0
    tic_tac_toe([[2, 2, 2], [0, 2, 0], [0, 1, 0]]) => 2

    :param game
    :return: winning player id
    """
    for row in game:
        if row.count(1) == 3:
            return 1
        elif row.count(2) == 3:
            return 2
    columns = [[game[0][0], game[1][0], game[2][0]], [game[0][1], game[1][1], game[2][1]],
               [game[0][2], game[1][2], game[2][2]]]
    for column in columns:
        if column.count(1) == 3:
            return 1
        elif column.count(2) == 3:
            return 2
    diagonals = [[game[0][0], game[1][1], game[2][2]], [game[0][2], game[1][1], game[2][0]]]
    for diagonal in diagonals:
        if diagonal.count(1) == 3:
            return 1
        elif diagonal.count(2) == 3:
            return 2
    return 0

def rainbows(field: str, lower=False) -> int:
    """
    The function to count rainbows.

    #5

    Function has to be recursive.

    assert rainbows("rainbowThisIsJustSomeNoise") == 1  # Lisaks vikerkaarele on veel sümboleid
    assert rainbows("WoBniar") == 1  # Vikerkaar on tagurpidi ja sisaldab suuri tähti
    assert rainbows("rainbowobniar") == 1  # Kaks vikerkaart jagavad tähte seega üks neist ei ole valiidne

    :param field: string to search rainbows from
    :return: number of rainbows in the string
    """
    print(field)
    word_to_change = field.lower()
    if "rainbow" in word_to_change:
        rainbow_start_location = word_to_change.find("rainbow")
        end_pos = rainbow_start_location + len("rainbow")
        string_start = field[:rainbow_start_location]
        string_end = field[end_pos:]
        remaining_string = "".join([string_start, string_end])
        return 1 + rainbows(remaining_string)

    elif "wobniar" in word_to_change:
        rainbow_start_location = word_to_change.find("wobniar")
        end_pos = rainbow_start_location + len("wobniar")
        string_start = field[:rainbow_start_location]
        string_end = field[end_pos:]
        remaining_string = "".join([string_start, string_end])
        return 1 + rainbows(remaining_string)
    return 0

def longest_substring(text: str) -> str:
    """
    Find the longest substring.

    #6

    Substring may not contain any character twice.
    CAPS and lower case chars are the same (a == A)
    In output, the case (whether lower- or uppercase) should remain.
    If multiple substrings have same length, choose first one.

    aaa -> a
    abc -> abc
    abccba -> abc
    babcdEFghij -> abcdEFghij
    abBcd => Bcd
    '' -> ''
    """
    lowered_word = text.lower()
    long_word = ""
    for start_pos in range(len(lowered_word) + 1):
        for end_pos in range(start_pos + 1, len(lowered_word) + 1):
            current_word = lowered_word[start_pos:end_pos]
            current_set = set(current_word)
            if len(current_word) == len(current_set):
                if len(current_word) > len(long_word):
                    long_word = text[start_pos:end_pos]
            elif len(current_word) != len(current_set):
                break
    return long_word

class Student:
    """Student class."""

    def __init__(self, name: str, average_grade: float, credit_points: int):
        """Constructor."""
        self.credit_points = credit_points
        self.average_grade = average_grade
        self.name = name

def create_student(name: str, grades: list, credit_points: int) -> Student:
    """
    Create a new student where average grade is the average of the grades in the list.

    Round the average grade up to three decimal places.
    If the list of grades is empty, the average grade will be 0.
    """
    gpa = 0
    if len(grades) == 0:
        return Student(name, gpa, credit_points)
    else:
        average_grade = round(sum(grades) / len(grades), 3)
        print(average_grade)
        return Student(name, average_grade, credit_points)

def get_top_student_with_credit_points(students: list[Student], min_credit_points: int):
    """
    Return the student with the highest average grade who has enough credit points.

    If there are no students with enough credit points, return None.
    If several students have the same average score, return the first.
    """
    students_with_enough_credit = []
    for student in students:
        if student.credit_points >= min_credit_points:
            students_with_enough_credit.append(student)
    if len(students_with_enough_credit) == 0:
        return None
    else:
        return max(students_with_enough_credit, key=lambda x: x.average_grade)

def add_result_to_student(student: Student, grades_count: int, new_grade: int, credit_points) -> Student:
    """
    Update student average grade and credit points by adding a new grade (result).

    As the student object does not have grades count information, it is provided in this function.
    average grade = sum of grades / count of grades

    With the formula above, we can deduct:
    sum of grades = average grade * count of grades

    The student has the average grade, function parameters give the count of grades.
    If the sum of grades is known, a new grade can be added and a new average can be calculated.
    The new average grade must be rounded to three decimal places.
    Given credits points should be added to old credit points.

    Example1:
        current average (from student object) = 4
        grades_count (from parameter) = 2
        so, the sum is 2 * 4 = 8
        new grade (from parameter) = 5
        new average = (8 + 5) / 3 = 4.333
        The student object has to be updated with the new average

    Example2:
        current average = 0
        grades_count = 0
        calculated sum = 0 * 0 = 0
        new grade = 4
        new average = 4 / 1 = 4

    Return the modified student object.
    """
    current_gpa = student.average_grade
    new_gpa = round((current_gpa * grades_count + new_grade) / (grades_count + 1), 3)
    new_credit = student.credit_points + credit_points
    student.average_grade = new_gpa
    student.credit_points = new_credit
    return student

def get_ordered_students(students: list) -> list:
    """
    Return a new sorted list of students by (down).

    credit points (higher first), average_grade (higher first), name (a to z).
    """
    ordered_students = sorted(students, key=lambda x: (-x.credit_points, -x.average_grade, x.name))
    return ordered_students

class Room:
    """Room."""

    def __init__(self, number: int, price: int, features: list = [], booked: bool = False):
        """Constructor."""
        self.booked = booked
        self.features = features
        self.price = price
        self.number = number

    def __repr__(self):
        """Represent the Room."""
        return f"Room nr: {self.number}, {self.price} EUR"

    def add_feature(self, feature: str) -> bool:
        """
        Add a feature to the room.

        Do not add the feature and return False if:
        - the room already has that feature
        - the room is booked.
        Otherwise, add the feature to the room and return True
        """
        if self.booked:
            return False
        if not self.features:
            self.features = [feature]
            return True
        else:
            if feature in self.features:
                return False
            elif feature not in self.features:
                self.features.append(feature)
                return True

    def get_features(self) -> list:
        """Return all the features of the room."""
        return self.features

    def get_price(self) -> int:
        """Return the price."""
        return self.price

    def get_number(self) -> int:
        """Return the room number."""
        return self.number

    def get_booked(self) -> bool:
        """Return if the room is booked."""
        return self.booked

class Hotel:
    """Hotel."""

    def __init__(self, rooms: list[Room] = []):
        """Constructor."""
        self.rooms = rooms

    def add_room(self, room: Room) -> bool:
        """
        Add room to hotel.

        If a room with the given number already exists, do not add a room and return False.
        Otherwise add the room to hotel and return True.
        """
        if not self.rooms:
            self.rooms = [room]
            return True
        else:
            all_room_numbers = []
            for hotel_room in self.rooms:
                all_room_numbers.append(hotel_room.number)
            if room.number in all_room_numbers:
                return False
            elif room.number not in all_room_numbers:
                self.rooms.append(room)
                return True

    def book_room(self, required_features: list) -> Optional[Room]:
        """
        Book an available room which has the most matching features.

        Find a room which has most of the required features.
        If there are several with the same amount of matching features, return the one with the smallest room number.
        If there is no available rooms, return None
        """
        available_rooms = self.get_available_rooms()
        if len(available_rooms) == 0:
            return None
        else:
            features_covered = 0
            appropriate_room = None
            for room in available_rooms:
                current_features_covered = 0
                for room_feature in room.features:
                    if room_feature in required_features:
                        current_features_covered += 1
                if appropriate_room is None:
                    appropriate_room = [room]
                    features_covered = current_features_covered
                    continue
                else:
                    if current_features_covered > features_covered:
                        features_covered = current_features_covered
                        appropriate_room = [room]
                        print(appropriate_room)
                    elif current_features_covered == features_covered:
                        appropriate_room.append(room)
        room_to_book = min(appropriate_room, key=lambda app_room: (app_room.number, len(app_room.features)))
        room_to_book.booked = True
        return room_to_book

    def get_available_rooms(self) -> list:
        """Return a list of available (not booked) rooms."""
        all_available_rooms = []
        for room in self.rooms:
            if not room.get_booked():
                all_available_rooms.append(room)
        print(all_available_rooms)
        return all_available_rooms

    def get_rooms(self) -> list:
        """Return all the rooms (both booked and available)."""
        if not self.rooms:
            return []
        else:
            return self.rooms

    def get_booked_rooms(self) -> list:
        """Return all the booked rooms."""
        all_booked_rooms = []
        for room in self.rooms:
            if room.get_booked():
                all_booked_rooms.append(room)
        return all_booked_rooms

    def get_feature_profits(self) -> dict:
        """
        Return a dict where key is a feature and value is the total price for the booked rooms which have the feature.

        Example:
            room1, price=100, features=a, b, c
            room2, price=200, features=b, c, d
            room3, price=400, features=a, c

        all the rooms are booked
        result:
        {
        'a': 500,
        'b': 300,
        'c': 700,
        'd': 200
        }
        """
        booked_rooms = self.get_booked_rooms()
        booked_features = {}
        for room in booked_rooms:
            for feature in room.features:
                if feature not in booked_features:
                    booked_features[feature] = room.price
                elif feature in booked_features:
                    booked_features[feature] += room.price
        return booked_features

    def get_most_profitable_feature(self) -> Optional[str]:
        """
        Return the feature which profits the most.

        Use get_feature_profits() method to get the total price for every feature.
        Return the feature which has the highest value (profit).
        If there are several with the same max value, return the feature which is alphabetically lower (a < z)
        If there are no features booked, return None.
        """
        profitable_features = self.get_feature_profits()
        if not profitable_features:
            return None
        sort_profitable = sorted(profitable_features.items(), key=lambda x: (-x[1], x[0]))
        return sort_profitable[0][0]

if __name__ == '__main__':
    hotel = Hotel()
    room1 = Room(22, 100, ['view', 'personal trainer', 'tv', 'vodka'])
    room2 = Room(29, 200, ['moon', 'trump'])
    hotel.add_room(room1)
    hotel.add_room(room2)
    print(hotel.book_room(['moon', 'trump', 'radio', 'personal trainer', 'view', 'moon', 'lamp', 'toilet', 'mountain', 'pool']))

    # TODO: try to add a room so that two or more features have the same profit


from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(config_file):
    app = Flask(__name__)
    app.config.from_pyfile(config_file)
    db.init_app(app)
    with app.app_context():
        db.create_all()
        import routes
    return app


import streamlit as st

import time

from bs4 import BeautifulSoup

from selenium import webdriver

from selenium.webdriver.common.by import By

from wordcloud import WordCloud, STOPWORDS

import matplotlib.pyplot as plt

from PIL import Image
import numpy as np

options = webdriver.EdgeOptions()
options.add_argument('--incognito')
options.add_argument('--headless')

# driver = webdriver.Edge('./msedgedriver.exe', options=options)
driver = webdriver.Edge(options=options)

def make_transcript_file():
    driver.get("https://www.ted.com/talks/shannon_odell_what_s_the_smartest_age")

    # use xpath when same class or id is used for buttons. otherwise you will get invalidselectorexception error
    read_transcript_button = driver.find_element(By.XPATH, "/html/body/div[1]/div/main/div/div/div/div/div[2]/div[1]/div[4]/button")

    # click the button
    read_transcript_button.click()

    time.sleep(2)

    page_source = driver.page_source

    driver.close()

    soup = BeautifulSoup(page_source, 'html.parser')

    main = soup.find('div', class_ = "mb-10 w-full")

    transcripts = main.find('div', class_ = "w-full")

    transcripts_each = transcripts.find_all('div', class_ = "mb-6 w-full")

    # print(len(transcripts_each))

    speech_block = []
    for i in range(len(transcripts_each)):
        speech_block.append(transcripts_each[i].span.text)

    full_text = " ".join(speech_block)
    with open('transript_new.txt', 'w') as file:
        file.write(full_text)
        file.close()

    # read the file
    with open('transript_new.txt', 'r') as file:
        full_text = file.read()
        file.close()

    return full_text

    # print(speech_block)

# def make_binary_image():
#     image_file = Image.open("ted-logo-fb.png") # open colour image
#     thresh = 200
#     image_file = image_file.convert('L')
#     width, height = image_file.size
#     for x in range(width):
#         for y in range(height):
#             if image_file.getpixel((x, y)) < thresh:
#                 image_file.putpixel((x, y), 0)
#             else:
#                 image_file.putpixel((x, y), 255)

#     image_file.save('binary-logo.png')

text = make_transcript_file()

# discard = STOPWORDS

# cloud = WordCloud(background_color=(255, 255, 255), stopwords = discard, mask= customMask).generate(text)

st.text_area("Transcript", text, height=500)


import random

def guess_number():
    guess = int(input("Vennligst gjett et tall mellom 0-100:  "))
    random_number = random.randint(0, 99)

    while guess != random_number:
        if guess > random_number:
            print("Du gjettet før høyt! Prøv igjen ")
        else:
            print("Du gjettet for lavt! Prøv igjen ")
        guess = int(input("Vennligst gjett et tall mellom 0-100:  "))

    print("Gratulerer, du har gjettet riktig!")

guess_number()


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

# third-party modules
from flask_restx import Resource, reqparse

# own modules
from app.modules.article.bookmark.bookmark_controller import ArticleBookmarkController
from app.modules.article.bookmark.bookmark_dto import ArticleBookmarkDto
from common.utils.decorator import token_required

__author__ = "hoovada.com team"
__maintainer__ = "hoovada.com team"
__email__ = "admin@hoovada.com"
__copyright__ = "Copyright (c) 2020 - 2020 hoovada.com . All Rights Reserved."

api = ArticleBookmarkDto.api
_bookmark_response = ArticleBookmarkDto.model_response
_bookmark_get_params = ArticleBookmarkDto.model_get_parser

@api.route('/all/bookmark')
class BookmarkArticleAll(Resource):
    @api.expect(_bookmark_get_params)
    def get(self):
        """Get all bookmark that satisfy conditions"""

        args = _bookmark_get_params.parse_args()
        controller = ArticleBookmarkController()
        return controller.get(args=args)

@api.route('/<int:article_id>/bookmark')
class BookmarkArticle(Resource):
    @api.expect(_bookmark_get_params)
    def get(self, article_id):
        """Get all bookmarks using article_id"""

        args = _bookmark_get_params.parse_args()
        args['article_id'] = article_id
        controller = ArticleBookmarkController()
        return controller.get(args=args)

    @token_required
    @api.response(code=200, model=_bookmark_response, description='The model for bookmark.')
    def post(self, article_id):
        """Create a bookmark using article_id"""
        controller = ArticleBookmarkController()
        return controller.create(article_id=article_id)

    @token_required
    def delete(self, article_id):
        """Delete bookmark using article_id"""

        controller = ArticleBookmarkController()
        return controller.delete(article_id=article_id)