"""Layer utilities"""
import math
from zipfile import ZipFile

import lzo
from PIL import Image

# this code owes an incredible amount to:
#  - https://github.com/jaromvogel/ProcreateViewer
#  - https://github.com/redstrate/procreate-viewer

def process_chunk(
    archive: ZipFile,
    layer_id: str, chunk_name: str,
    imagesize: list[int], tilesize: int,
    columns: int, rows: int,
    difference_x: int, difference_y: int,
    strict: bool
) -> tuple[Image.Image, tuple[int, int]]:
    """iterate through chunks, decompress them, create images"""
    # Get row and column from filename
    column = int(chunk_name.strip('.chunk').split('~')[0])
    row = int(chunk_name.strip('.chunk').split('~')[1]) + 1
    chunk_tilesize = {
        "x": tilesize,
        "y": tilesize
    }

    # Account for columns or rows that are too short
    if (column + 1) == columns:
        chunk_tilesize['x'] = tilesize - difference_x
    if row == rows:
        chunk_tilesize['y'] = tilesize - difference_y

    try:
        # read the actual data and create an image
        file = archive.read(layer_id + '/' + chunk_name)
        # 262144 is the final byte size of the pixel data for 256x256 square.
        # This is based on 256*256*4 (width * height * 4 bytes per pixel)
        # finalsize is chunk width * chunk height * 4 bytes per pixel
        finalsize = chunk_tilesize['x'] * chunk_tilesize['y'] * 4
        decompressed = lzo.decompress(file, False, finalsize)
        # Will need to know how big each tile is instead of just saying 256
        image = Image.frombytes('RGBA', (chunk_tilesize['x'],chunk_tilesize['y']), decompressed)
        # Tile starts upside down, flip it
        image = image.transpose(Image.FLIP_TOP_BOTTOM)

        # Calculate pixel position of tile
        position_x = column * tilesize
        position_y = (imagesize[1] - (row * tilesize))
        if  row == rows:
            position_y = 0

        return (image, (position_x, position_y))
    except: # pylint: disable=bare-except
        if strict:
            raise
        print("failed to decompress: " + layer_id + '/' + chunk_name)
        return None

def write_layer(
    out_file: str, archive: ZipFile,
    layer_id: str,
    imagesize: tuple[int, int], tilesize: int,
    orientation: int, h_flipped: bool, v_flipped: bool,
    strict: bool = True
):
    """Write a layer to a bitmap"""
    # detect files
    all_files = archive.namelist()
    layer_files = list(filter(lambda x: layer_id in x, all_files))
    chunk_list = list(map(lambda x: x.strip(layer_id).strip('/'), layer_files))

    # create a new image
    canvas = Image.new('RGBA', (imagesize[0], imagesize[1]))

    # Figure out how many total rows and columns there are
    columns = int(math.ceil(float(imagesize[0]) / float(tilesize)))
    rows = int(math.ceil(float(imagesize[1]) / float(tilesize)))

    # Calculate difference-x and difference-y
    difference_x = 0
    difference_y = 0
    if imagesize[0] % tilesize != 0:
        difference_x = (columns * tilesize) - imagesize[0]
    if imagesize[1] % tilesize != 0:
        difference_y = (rows * tilesize) - imagesize[1]

    tilelist = []
    # print(chunk_list)
    for chunk_name in chunk_list:
        if (chunk_name == '' and not strict):
            continue
        response = process_chunk(
            archive,
            layer_id, chunk_name,
            imagesize, tilesize,
            columns, rows,
            difference_x, difference_y,
            strict)
        if response is not None:
            tilelist.append(response)

    # Add each tile to composite image
    for tile in tilelist:
        canvas.paste(tile[0], tile[1])

    # Make sure the image appears in the correct orientation
    if orientation == 3:
        canvas = canvas.rotate(90, expand=True)
    elif orientation == 4:
        canvas = canvas.rotate(-90, expand=True)
    elif orientation == 2:
        canvas = canvas.rotate(180, expand=True)

    if h_flipped == 1 and (orientation == 1 or orientation == 2):
        canvas = canvas.transpose(Image.FLIP_LEFT_RIGHT)
    if h_flipped == 1 and (orientation == 3 or orientation == 4):
        canvas = canvas.transpose(Image.FLIP_TOP_BOTTOM)
    if v_flipped == 1 and (orientation == 1 or orientation == 2):
        canvas = canvas.transpose(Image.FLIP_TOP_BOTTOM)
    if v_flipped == 1 and (orientation == 3 or orientation == 4):
        canvas = canvas.transpose(Image.FLIP_LEFT_RIGHT)

    canvas.save(out_file)


from ray.rllib.agents.ddpg.ddpg_torch_policy import *

def xaddpg_actor_critic_loss(policy, model, _, train_batch):
	twin_q = policy.config["twin_q"]
	gamma = policy.config["gamma"]
	n_step = policy.config["n_step"]
	use_huber = policy.config["use_huber"]
	huber_threshold = policy.config["huber_threshold"]
	l2_reg = policy.config["l2_reg"]

	input_dict = {
		"obs": train_batch[SampleBatch.CUR_OBS],
		"is_training": True,
	}
	input_dict_next = {
		"obs": train_batch[SampleBatch.NEXT_OBS],
		"is_training": True,
	}

	model_out_t, _ = model(input_dict, [], None)
	model_out_tp1, _ = model(input_dict_next, [], None)
	target_model_out_tp1, _ = policy.target_model(input_dict_next, [], None)

	# Policy network evaluation.
	# prev_update_ops = set(tf1.get_collection(tf.GraphKeys.UPDATE_OPS))
	policy_t = model.get_policy_output(model_out_t)
	# policy_batchnorm_update_ops = list(
	#	set(tf1.get_collection(tf.GraphKeys.UPDATE_OPS)) - prev_update_ops)

	policy_tp1 = \
		policy.target_model.get_policy_output(target_model_out_tp1)

	# Action outputs.
	if policy.config["smooth_target_policy"]:
		target_noise_clip = policy.config["target_noise_clip"]
		clipped_normal_sample = torch.clamp(
			torch.normal(
				mean=torch.zeros(policy_tp1.size()),
				std=policy.config["target_noise"]).to(policy_tp1.device),
			-target_noise_clip, target_noise_clip)

		policy_tp1_smoothed = torch.min(
			torch.max(
				policy_tp1 + clipped_normal_sample,
				torch.tensor(
					policy.action_space.low,
					dtype=torch.float32,
					device=policy_tp1.device)),
			torch.tensor(
				policy.action_space.high,
				dtype=torch.float32,
				device=policy_tp1.device))
	else:
		# No smoothing, just use deterministic actions.
		policy_tp1_smoothed = policy_tp1

	# Q-net(s) evaluation.
	# prev_update_ops = set(tf1.get_collection(tf.GraphKeys.UPDATE_OPS))
	# Q-values for given actions & observations in given current
	q_t = model.get_q_values(model_out_t, train_batch[SampleBatch.ACTIONS])

	# Q-values for current policy (no noise) in given current state
	q_t_det_policy = model.get_q_values(model_out_t, policy_t)

	actor_loss = -torch.mean(train_batch[PRIO_WEIGHTS] * q_t_det_policy)

	if twin_q:
		twin_q_t = model.get_twin_q_values(model_out_t,
										   train_batch[SampleBatch.ACTIONS])
	# q_batchnorm_update_ops = list(
	#	 set(tf1.get_collection(tf.GraphKeys.UPDATE_OPS)) - prev_update_ops)

	# Target q-net(s) evaluation.
	q_tp1 = policy.target_model.get_q_values(target_model_out_tp1,
											 policy_tp1_smoothed)

	if twin_q:
		twin_q_tp1 = policy.target_model.get_twin_q_values(
			target_model_out_tp1, policy_tp1_smoothed)

	q_t_selected = torch.squeeze(q_t, axis=len(q_t.shape) - 1)
	if twin_q:
		twin_q_t_selected = torch.squeeze(twin_q_t, axis=len(q_t.shape) - 1)
		q_tp1 = torch.min(q_tp1, twin_q_tp1)

	q_tp1_best = torch.squeeze(input=q_tp1, axis=len(q_tp1.shape) - 1)
	q_tp1_best_masked = \
		(1.0 - train_batch[SampleBatch.DONES].float()) * \
		q_tp1_best

	# Compute RHS of bellman equation.
	q_t_selected_target = (train_batch[SampleBatch.REWARDS] +
						   gamma**n_step * q_tp1_best_masked).detach()

	# Compute the error (potentially clipped).
	if twin_q:
		td_error = q_t_selected - q_t_selected_target
		twin_td_error = twin_q_t_selected - q_t_selected_target
		if use_huber:
			errors = huber_loss(td_error, huber_threshold) \
				+ huber_loss(twin_td_error, huber_threshold)
		else:
			errors = 0.5 * \
				(torch.pow(td_error, 2.0) + torch.pow(twin_td_error, 2.0))
	else:
		td_error = q_t_selected - q_t_selected_target
		if use_huber:
			errors = huber_loss(td_error, huber_threshold)
		else:
			errors = 0.5 * torch.pow(td_error, 2.0)

	critic_loss = torch.mean(train_batch[PRIO_WEIGHTS] * errors)

	# Add l2-regularization if required.
	if l2_reg is not None:
		for name, var in policy.model.policy_variables(as_dict=True).items():
			if "bias" not in name:
				actor_loss += (l2_reg * l2_loss(var))
		for name, var in policy.model.q_variables(as_dict=True).items():
			if "bias" not in name:
				critic_loss += (l2_reg * l2_loss(var))

	# Model self-supervised losses.
	if policy.config["use_state_preprocessor"]:
		# Expand input_dict in case custom_loss' need them.
		input_dict[SampleBatch.ACTIONS] = train_batch[SampleBatch.ACTIONS]
		input_dict[SampleBatch.REWARDS] = train_batch[SampleBatch.REWARDS]
		input_dict[SampleBatch.DONES] = train_batch[SampleBatch.DONES]
		input_dict[SampleBatch.NEXT_OBS] = train_batch[SampleBatch.NEXT_OBS]
		[actor_loss, critic_loss] = model.custom_loss(
			[actor_loss, critic_loss], input_dict)

	# Store values for stats function.
	policy.actor_loss = actor_loss
	policy.critic_loss = critic_loss
	policy.td_error = td_error
	policy.q_t = q_t

	# Return two loss terms (corresponding to the two optimizers, we create).
	return policy.actor_loss, policy.critic_loss


def coordinate_input():
    x1 = input("Enter x1: ")
    y1 = input("Enter y1: ")
    x2 = input("Enter x2: ")
    y2 = input("Enter y2: ")
    x3 = input("Enter x3: ")
    return (x1, y1), (x2, y2), x3

def y_online(A, B, x3):
    x1 = float(A[0])
    y1 = float(A[1])
    x2 = float(B[0])
    y2 = float(B[1])
    y3 = ((y2-y1)*(float(x3)-x1)/(x2-x1))+y1
    return y3

def y_output(y3):
    print(y3)

def y_driver():
    A, B, x3 = coordinate_input()
    y3 = y_online(A, B, x3)
    y_output(y3)

if __name__ == "__main__":
    y_driver()


import rainbowmindmachine as rmm

def setup():
    k = rmm.TxtKeymaker()
    k.set_apikeys_file('apikeys.json')
    k.make_keys('data/')

def shepherd():
    sh = rmm.TwitterShepherd(
            json_keys_dir = 'keys/',
            flock_name = 'apollo space junk bot flock',
            sheep_class = rmm.QueneauSheep
    )
    return sh

def set_url():
    sh = shepherd()
    sh.perform_serial_action(
            'change_url',
            url = 'https://pages.charlesreid1.com/b-apollo/'
    )

def tweet():
    sh = shepherd()
    sh.perform_parallel_action(
            'tweet',
            publish = False
    )

def fave():
    sh = shepherd()
    sh.perform_parallel_action(
            'favorite',
            search_term = 'Neil Armstrong',
            sleep = 15
    )

if __name__=="__main__":
    #setup()
    #tweet()
    fave()


"""Nástroj pro ověření vlastností sekundární struktury RNA.

Projekt: Bakalářská práce Regulované jazykové operace a jejich užití, Brno 2023.

Tento soubor obsahuje třídu nástroje reprezentujícího aplikaci vymazávacího systému pro ověření vlastností sekundární
struktury RNA.

:Author: David Chocholatý
:Contact: xchoch09@stud.fit.vutbr.cz
:Filename: secondary_structure_properties_tool.py
"""

import argparse
import sys

from typing import Tuple

from es_tools.custom_exceptions.final_states_not_states_subset_exception import FinalStatesNotStatesSubsetException
from es_tools.custom_exceptions.illegal_symbol_occurrence_exception import IllegalSymbolOccurrenceException
from es_tools.custom_exceptions.initial_state_not_in_states_exception import InitialStateNotInStatesException
from es_tools.custom_exceptions.internal_error_exception import InternalErrorException
from es_tools.custom_exceptions.invalid_argument_exception import InvalidArgumentException
from es_tools.custom_exceptions.invalid_regular_language_pattern_exception import InvalidRegularLanguagePatternException
from es_tools.custom_exceptions.invalid_transition_exception import InvalidTransitionException
from es_tools.custom_exceptions.invalid_value_exception import InvalidValueException
from es_tools.custom_exceptions.invalid_input_data_structure_exception import InvalidInputDataStructure
from es_tools.custom_exceptions.maximum_input_string_length_exceeded_exception import \
    MaximumInputStringLengthExceededException
from es_tools.error_utils.exit_code import ExitCode
from es_tools.handlers.argument_handler.argument_handler import ArgumentHandler
from es_tools.shared_utils.input_data_check import is_rna_secondary_structure_sequence
from es_tools.tools.secondary_structure_properties_tool.custom_utils.custom_constants import INPUT_LINES_NUMBER, \
    ABSOLUTE_MIN, ABSOLUTE_MAX, MIN_FLAG, MAX_FLAG
from es_tools.tools.secondary_structure_properties_tool.custom_utils.custom_erasing_system_creation \
    import create_erasing_system
from es_tools.tools.secondary_structure_properties_tool.custom_utils.custom_transducer_creation import create_transducer
from es_tools.tools.secondary_structure_properties_tool.custom_utils.symbols_count_calculation \
    import symbols_count_calculation
from es_tools.tools.tool import Tool

class SecondaryStructurePropertiesTool(Tool):
    """Nástroj reprezentující aplikaci pro ověření vlastností sekundární struktury RNA.

    Tato třída implementuje nástroj realizující navržený algoritmus aplikující vymazávací systém na ověření
    vlastností sekundární struktury RNA. Hlavní algoritmus představený v textu práce na stranách 57-60 reprezentuje
    metoda _run_main_algorithm().
    """

    def __init__(self) -> None:
        """**Konstruktor třídy SecondaryStructurePropertiesTool**

        Konstruktor slouží pouze pro nastavení základních hodnot atributů třídy, přičemž jsou nastaveny atributy
        zdědené od rodičovské třídy Tool. Dvěma atributy, které jsou specifické pro třídu
        SecondaryStructurePropertiesTool, jsou atributy __min a __max. Atribut __min určuje minimální hodnotu
        v procentech a atribut __max určuje maximální hodnotu v procentech.
        """
        super().__init__(INPUT_LINES_NUMBER)
        self.__min = ABSOLUTE_MIN
        self.__max = ABSOLUTE_MAX

    @property
    def min(self) -> int:
        """Minimální hodnota v procentech pro ověření vlastností sekundární struktury RNA.

        :getter: získání minimální hodnoty v procentech.
        :setter: nastavení minimální hodnoty v procentech.
        :type: int
        :raises InvalidValueException: nová nastavovaná hodnota není v povoleném rozsahu nebo je vyšší jak nastavená
                                       maximální hodnota.
        """
        return self.__min

    @min.setter
    def min(self, min_percentual: int) -> None:
        if min_percentual not in range(ABSOLUTE_MIN, ABSOLUTE_MAX + 1):
            raise InvalidValueException
        elif min_percentual > self.__max:
            raise InvalidValueException
        else:
            if min_percentual % 10 != 0:
                min_percentual = min_percentual // 10 * 10

                print("Info: The value of the minimum percentage has been rounded to optimize the calculations "
                      "(rounded down).")
                print("New minimum value: " + str(min_percentual) + "\n")

            self.__min = min_percentual

    @property
    def max(self) -> int:
        """Maximální hodnota v procentech pro ověření vlastností sekundární struktury RNA.

        :getter: získání maximální hodnoty v procentech.
        :setter: nastavení maximální hodnoty v procentech.

        :type: int
        :raises InvalidValueException: nová nastavovaná hodnota není v povoleném rozsahu nebo je nižší jak nastavená
                                       minimální hodnota.
        """
        return self.__max

    @max.setter
    def max(self, max_percentual: int) -> None:
        if max_percentual not in range(ABSOLUTE_MIN, ABSOLUTE_MAX + 1):
            raise InvalidValueException
        elif max_percentual < self.__min:
            raise InvalidValueException
        else:
            if max_percentual % 10 != 0:
                max_percentual = max_percentual // 10 * 10

                print("Info: The value of the maximum percentage has been rounded to optimize the calculations "
                      "(rounded down).")
                print("New maximum value: " + str(max_percentual) + "\n")

            self.__max = max_percentual

    def set_new_min_max(self, min_percentual: int, max_percentual: int) -> None:
        """Nastavení nových hodnot minima a maxima.

        Tato funkce slouží pro společné nastavení specifických argumentů pro daný nástroj, a to minimální a maximální
        hodnoty pro ověření vlastností sekundární struktury RNA.

        :param min_percentual: nová hodnota pro minimum v procentech.
        :type min_percentual: int
        :param max_percentual: nová hodnota pro maximum v procentech.
        :type max_percentual: int
        :raises InvalidValueException: nové nastavované hodnoty pro minimum a maximum nejsou v povoleném rozsahu, nebo
                                       nesplňují podmínku, že minimální hodnota je nižší nebo rovna hodnotě maximální.
        """
        if min_percentual not in range(ABSOLUTE_MIN, ABSOLUTE_MAX + 1):
            raise InvalidValueException
        elif max_percentual not in range(ABSOLUTE_MIN, ABSOLUTE_MAX + 1):
            raise InvalidValueException
        elif min_percentual > max_percentual:
            raise InvalidValueException
        else:
            if min_percentual % 10 != 0:
                min_percentual = min_percentual // 10 * 10

                print("Info: The value of the minimum percentage has been rounded to optimize the calculations "
                      "(rounded down).")
                print("New minimum value: " + str(min_percentual) + "\n")

            if max_percentual % 10 != 0:
                max_percentual = max_percentual // 10 * 10

                print("Info: The value of the maximum percentage has been rounded to optimize the calculations "
                      "(rounded down).")
                print("New maximum value: " + str(max_percentual) + "\n")

            self.__min = min_percentual
            self.__max = max_percentual

    def _add_custom_arguments(self, argument_parser: argparse.ArgumentParser) -> None:
        """Metoda pro přidání specifických uživatelských argumentů pro nástroj.

        Tato metoda implementuje přidání specifických uživatelských argumentů ke společným pro všechny nástroje. Metoda
        přepisuje stejnojmennou metodu z rodičovské třídy Tool.

        :param argument_parser: analyzátor uživatelských argumentů.
        :type argument_parser: argparse.ArgumentParser
        """
        argument_parser.add_argument("-i", "--input", dest="input",
                                     help="the input file with an RNA secondary structure on a single line")
        argument_parser.add_argument("--min", dest="min", type=int, default=0,
                                     help="the minimum percentage value of the pair nucleotides "
                                          "versus non-pair nucleotides")
        argument_parser.add_argument("--max", dest="max", type=int, default=100,
                                     help="the maximum percentage value of the pair nucleotides "
                                          "versus non-pair nucleotides")

    def _create_custom_argument_handler(self) -> ArgumentHandler:
        """Metoda pro vytvoření manipulátoru s uživatelskými argumenty.

        Tato metoda implementuje vytvoření manipulátoru s uživatelskými argumenty, přičemž ke společným argumentům jsou
        přidány i specifické pro tento nástroj. Metoda přepisuje stejnojmennou metody z rodičovské třídy Tool.

        :return: manipulátor s uživatelskými argumenty.
        :rtype: ArgumentHandler
        """
        argument_handler = ArgumentHandler(self.get_tool_name())
        self._add_custom_arguments(argument_handler.handler())

        return argument_handler

    def _load_arguments(self) -> None:
        """Načtení uživatelských argumentů.

        Hlavním cílem této metody je vytvoření manipulátoru s uživatelskými argumenty, včetně přidání specifických
        argumentů ke společným pro všechny nástroje. Zároveň tato metoda, pokud je to možné, provede načtení zadaných
        vstupních hodnot.
        """
        try:
            argument_handler = self._create_custom_argument_handler()
            self.arguments = argument_handler.parse_arguments()
        except InvalidArgumentException:
            raise

        if self.arguments.min is not None and self.arguments.max is not None:
            try:
                self.set_new_min_max(self.arguments.min, self.arguments.max)
            except InvalidValueException:
                raise
        else:
            raise InvalidValueException

        if self.arguments.greedy_quantifier is None or self.arguments.verbose is None:
            raise InternalErrorException

    def _initialize_tool(self) -> None:
        """Inicializace nástroje včetně zpracování vstupních dat.

        Tato metoda slouží pro inicializaci nástroje, to znamená pro načtení vstupních dat ze souboru a zpracování
        uživatelských argumentů.

        :raises OSError: chyba při pokusu o načtení vstupních dat ze souboru (soubor neexistuje, jedná se o adresář,
                         ...).
        :raises InternalErrorException: neočekávaný výskyt interní chyby programu.
        :raises InvalidArgumentException: zadání neplatného uživatelského argumentu.
        :raises InvalidInputDataStructure: neplatná struktura vstupních dat.
        :raises InvalidValueException: neplatná hodnota argumentu.
        """
        self.print_tool_name()

        try:
            self._load_arguments()
            self.load_input_data()
        except OSError:
            raise
        except InternalErrorException:
            raise
        except InvalidArgumentException:
            raise
        except InvalidInputDataStructure:
            raise
        except InvalidValueException:
            raise

    def _requirements_met(self, min_max_flag: bool, input_secondary_structure: str) -> Tuple[bool, bool]:
        """Funkce pro ověření vlastností sekundární struktury RNA pro minimum nebo maximum.

        Tato funkce implementuje část hlavního algoritmu aplikace vymazávacího systému na ověření vlastností sekundární
        struktury RNA, která je prezentována v textu na stranách 57-60. Konkrétně se metoda zaměruje na ověření
        vlastností pro jednu konkrétní hodnotu, a to minimální nebo maximální.

        :param min_max_flag: příznak určující, zda má být ověřována minimální nebo maximální hodnota.
        :type min_max_flag: bool
        :param input_secondary_structure: vstupní řetězec obsahující sekundární strukturu RNA.
        :type input_secondary_structure: int
        :return: dvojice obsahující pravdivostní hodnoty, které po řadě určují, zda vstupní řetězec je přijat vstupní
                 částí převodníku a zda převedený řetězec přijme vymazávací systém.
        :rtype: Tuple[bool, bool]
        :raises InitialStateNotInStatesException: počáteční stav nenáleží do množiny stavů převodníku.
        :raises FinalStatesNotStatesSubsetException: množina konečných stavů převodníku není podmnožinou množiny všech
                                                     stavů.
        :raises InvalidTransitionException: převodník obsahuje neplatný přechod pro splnění požadovaných podmínek.
        :raises IllegalSymbolOccurrenceException: výskyt nepovoleného symbolu ve vymazávacím řetězci vymazávacího
                                                  systému.
        :raises InvalidRegularLanguagePatternException: nevalidní nebo nepovolený tvar regulárního jazyka vymazávacího
                                                        systému.
        """
        if min_max_flag:
            percentage = self.__min
        else:
            percentage = self.__max

        paired_count, unpaired_count = symbols_count_calculation(percentage)

        try:
            transducer = create_transducer(paired_count, unpaired_count)
        except InitialStateNotInStatesException:
            raise
        except FinalStatesNotStatesSubsetException:
            raise
        except InvalidTransitionException:
            raise

        generated_output_strings = transducer.run(input_secondary_structure)
        output_strings = list(generated_output_strings)

        if len(output_strings) != 1:
            return False, False

        try:
            erasing_system = create_erasing_system(min_max_flag,
                                                   self.arguments.greedy_quantifier,
                                                   self.arguments.verbose)
        except IllegalSymbolOccurrenceException:
            raise
        except InvalidRegularLanguagePatternException:
            raise

        return True, erasing_system.run(output_strings[0])

    def _run_main_algorithm(self) -> None:
        """Spuštění hlavního algoritmu nástroje.

        Tato metoda implementuje hlavní tok algoritmu nástroje pro ověření vlastností sekundární struktury RNA.

        :raises InitialStateNotInStatesException: počáteční stav nenáleží do množiny stavů převodníku.
        :raises FinalStatesNotStatesSubsetException: množina konečných stavů převodníku není podmnožinou množiny všech
                                                     stavů.
        :raises IllegalSymbolOccurrenceException: výskyt nepovoleného symbolu ve vymazávacím řetězci vymazávacího
                                                  systému.
        :raises InvalidRegularLanguagePatternException: nevalidní nebo nepovolený tvar regulárního jazyka vymazávacího
                                                        systému.
        :raises MaximumInputStringLengthExceededException: překročena maximální povolená délka vstupního řetězce pro
                                                           vymazávací systém.
        :raises InvalidTransitionException: převodník obsahuje neplatný přechod pro splnění požadovaných podmínek.
        """
        input_secondary_structure = self.input_data[0]

        print("Input RNA secondary structure: " + input_secondary_structure + "\n")
        print("Entered minimum value:", self.arguments.min if self.__min == self.arguments.min else
            str(self.arguments.min) + " (rounded to: " + str(self.__min) + ")")  # noqa: E128
        print("Entered maximum value:", self.arguments.max if self.__max == self.arguments.max else
            str(self.arguments.max) + " (rounded to: " + str(self.__max) + ")")  # noqa: E128

        if not is_rna_secondary_structure_sequence(input_secondary_structure):
            print("------------------------------------------------------------------------------------\n")
            print("### Invalid input data format - RNA secondary structure expected. ###")
            return

        if self.__min != ABSOLUTE_MIN:
            try:
                accepted_transducer, accepted_erasing_system = self._requirements_met(MIN_FLAG,
                                                                                input_secondary_structure)
            except IllegalSymbolOccurrenceException:
                raise
            except InvalidRegularLanguagePatternException:
                raise
            except MaximumInputStringLengthExceededException:
                raise
            except InitialStateNotInStatesException:
                raise
            except FinalStatesNotStatesSubsetException:
                raise
            except InvalidTransitionException:
                raise

            if not accepted_transducer:
                print("------------------------------------------------------------------------------------\n")
                print("### Input RNA secondary structure rejected by the transducer. ###")
                return

            if accepted_erasing_system:
                print("------------------------------------------------------------------------------------\n")
                print("### Minimum Accepted ###")
            else:
                print("------------------------------------------------------------------------------------\n")
                print("### Minimum Rejected ###")
        else:
            print("------------------------------------------------------------------------------------\n")
            print("### Minimum Accepted ###")

        if self.__max != ABSOLUTE_MAX:
            try:
                accepted_transducer, accepted_erasing_system = self._requirements_met(MAX_FLAG,
                                                                                input_secondary_structure)
            except IllegalSymbolOccurrenceException:
                raise
            except InvalidRegularLanguagePatternException:
                raise
            except MaximumInputStringLengthExceededException:
                raise
            except InitialStateNotInStatesException:
                raise
            except FinalStatesNotStatesSubsetException:
                raise
            except InvalidTransitionException:
                raise

            if not accepted_transducer:
                print("------------------------------------------------------------------------------------\n")
                print("### Input RNA secondary structure rejected by the transducer. ###")
                return

            if accepted_erasing_system:
                print("------------------------------------------------------------------------------------\n")
                print("### Maximum Accepted ###")
            else:
                print("------------------------------------------------------------------------------------\n")
                print("### Maximum Rejected ###")
        else:
            print("------------------------------------------------------------------------------------\n")
            print("### Maximum Accepted ###")

    def run(self) -> None:
        """Spuštění běhu nástroje.

        Cílem této metody je spuštění inicializace nástroje a poté samotného hlavního algoritmu implementované aplikace
        vymazávacího systému.

        :raises OSError: chyba při pokusu o načtení vstupních dat ze souboru (soubor neexistuje, jedná se o adresář,
                         ...).
        :raises InternalErrorException: neočekávaný výskyt interní chyby programu.
        :raises InvalidArgumentException: zadání neplatného uživatelského argumentu.
        :raises InvalidInputDataStructure: neplatná struktura vstupních dat.
        :raises IllegalSymbolOccurrenceException: výskyt nepovoleného symbolu ve vymazávacím řetězci vymazávacího
                                                  systému.
        :raises InvalidRegularLanguagePatternException: nevalidní nebo nepovolený tvar regulárního jazyka vymazávacího
                                                        systému.
        :raises MaximumInputStringLengthExceededException: překročena maximální povolená délka vstupního řetězce pro
                                                           vymazávací systém.
        :raises InitialStateNotInStatesException: počáteční stav nenáleží do množiny stavů převodníku.
        :raises FinalStatesNotStatesSubsetException: množina konečných stavů převodníku není podmnožinou množiny všech
                                                     stavů.
        :raises InvalidTransitionException: převodník obsahuje neplatný přechod pro splnění požadovaných podmínek.
        """
        try:
            self._initialize_tool()
        except OSError:
            raise
        except InternalErrorException:
            raise
        except InvalidArgumentException:
            raise
        except InvalidInputDataStructure:
            raise
        except InvalidValueException:
            raise

        try:
            self._run_main_algorithm()
        except IllegalSymbolOccurrenceException:
            raise
        except InvalidRegularLanguagePatternException:
            raise
        except MaximumInputStringLengthExceededException:
            raise
        except InitialStateNotInStatesException:
            raise
        except FinalStatesNotStatesSubsetException:
            raise
        except InvalidTransitionException:
            raise

def main() -> None:
    """Hlavní funkce pro spuštění nástroje reprezentujícího aplikaci vymazávacího pro ověření vlastností sekundární
    struktury RNA."""
    tool = SecondaryStructurePropertiesTool()

    try:
        tool.run()
    except OSError:
        print("\nError: An attempt to open the file failed (an invalid file was provided).")
        sys.exit(ExitCode.FILE_NOT_FOUND.value)
    except InternalErrorException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.INTERNAL_ERROR.value)
    except InvalidArgumentException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.WRONG_ARGUMENT.value)
    except InvalidInputDataStructure as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.INVALID_INPUT_DATA_STRUCTURE.value)
    except InvalidValueException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.INVALID_ARGUMENT_VALUE.value)
    except IllegalSymbolOccurrenceException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.INVALID_ERASING_STRING.value)
    except InvalidRegularLanguagePatternException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.INVALID_REGULAR_LANGUAGE.value)
    except MaximumInputStringLengthExceededException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.MAXIMUM_INPUT_STRING_LENGTH_EXCEEDED.value)
    except InitialStateNotInStatesException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.INITIAL_STATE_NOT_IN_STATES.value)
    except FinalStatesNotStatesSubsetException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.FINAL_STATES_NOT_STATES_SUBSET.value)
    except InvalidTransitionException as error:
        print("\nError: " + error.msg)
        sys.exit(ExitCode.INVALID_TRANSITION.value)

if __name__ == "__main__":
    main()


import openai
import time

def set_openai_api_key(api_key):
    openai.api_key = api_key

def call_openai_api(retry_count=2):
    print("체크중입니다!!!")
    try:
        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=[
                    {"role": "system", "content": "You are a helpful assistant."},
                    {"role": "user", "content": "Hello, chatbot!"}
                ]
        )
        print(response)
        print("참입니다!!!")

        return True
    except openai.error.APIError as e:
        if retry_count > 0:
            print("API 호출 오류:", e)
            print("다시 시도합니다...")
            time.sleep(2)
            return call_openai_api(model, msg, retry_count - 1)
        else:
            print("API 호출 오류: 재시도 횟수를 초과했습니다.")
            return False
    except openai.error.RateLimitError as e:
        if retry_count > 0:
            print("API 호출 오류:", e)
            print("다시 시도합니다...")
            time.sleep(20)
            return call_openai_api(model, msg, retry_count - 1)
        else:
            print("API 호출 오류: 재시도 횟수를 초과했습니다.")
            return False


#
# @lc app=leetcode.cn id=4 lang=python3
#
# [4] 寻找两个正序数组的中位数
#

# @lc code=start
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:

        lst=nums1.extends(nums2)
        lst.sort()
        s1=len(lst)
        if s1%2 != 0:
            return lst[s1//2-1]
        return lst[s1]

# @lc code=end

day5/4.寻找两个正序数组的中位数.py

4.寻找两个正序数组的中位数.py


import matplotlib.pyplot as plt
import numpy as np
import random
from scipy.stats import chi2, norm

def histogram(parameters):

    hist, bins = np.histogram(parameters['data'], parameters['bins'])
    width = 0.7 * (bins[1] - bins[0])
    center = (bins[:-1] + bins[1:]) / 2

    plt.figure(parameters['figure'])
    plt.xlabel(parameters['xLabel'])
    plt.ylabel(parameters['yLabel'])
    plt.suptitle(parameters['title'])
    plt.bar(center, hist, align='center', width=width)

def calculate_sample_size(baseline_odds, alpha, beta, minimum_effect_size):

    if baseline_odds is None or alpha is None or beta is None or minimum_effect_size is None:
        return None

    # f(alpha, beta, baseline_odds, minimum_effect_size) = samples_per_trial
    # http://sphweb.bumc.bu.edu/otlt/MPH-Modules/BS/BS704_Power/BS704_Power_print.html
    # http://www.itl.nist.gov/div898/handbook/prc/section2/prc222.htm
    return int(2 * baseline_odds * (1 - baseline_odds) * ((norm.ppf(1-alpha/2) + norm.ppf(1-beta)) / minimum_effect_size)**2)

# run_simulation()
# simulate an A/B experiment by modeling a series of coin flips (draw samples from a binomial distribution)
#
# inputs
#   baseline_odds: float between 0 and 1; the control threshold for heads
#   test_odds_delta: float between 0 and 1; baseline_odds + test_odds_delta indicates the test threshold for heads
#   alpha: float between 0 and 1; false positive rate
#   beta: float between 0 and 1; false negative rate
#   minimum_effect_size: float between 0 and 1; min. desired effect size to detect if the control and treatment are different
#   total_trials: integer; total number of trials to run (each trial draws a dynamically calculated number of samples)
#
# outputs
#   significant_differences: the number of trials that resulted in a statistically different number of heads
def run_simulation(baseline_odds=0.01, test_odds_delta=0, alpha=0.05, beta=0.2, minimum_effect_size=0.005,
                   total_trials=100, samples_per_trial=None):

    if samples_per_trial == None:
        samples_per_trial = calculate_sample_size(baseline_odds, alpha, beta, minimum_effect_size)

    # chi-squared inputs, degrees of freedom
    # http://www.ling.upenn.edu/%7Eclight/chisquared.htm
    # -----------------------------------
    # |         | test | control | TOTAL
    # -----------------------------------
    # | heads   | 50    | 50     | 100
    # -----------------------------------
    # | tails   | 50    | 50     | 100
    # -----------------------------------
    # | TOTAL   | 100   | 100    | 200
    #
    # degrees of freedom: (rows - 1)(columns - 1) = (2 - 1)(2 - 1) = 1
    degrees_of_freedom = 1

    significant_differences = 0

    for _ in range(total_trials):

        control_heads_per_trial = 0
        for _ in range(samples_per_trial):
            if random.random() < baseline_odds:
                control_heads_per_trial += 1

        control_tails_per_trial = samples_per_trial - control_heads_per_trial

        test_heads_per_trial = 0
        for _ in range(samples_per_trial):
            if random.random() < baseline_odds + test_odds_delta:
                test_heads_per_trial += 1

        test_tails_per_trial = samples_per_trial - test_heads_per_trial

        total_number_of_samples = samples_per_trial * 2

        expected_heads_percentage = (control_heads_per_trial + test_heads_per_trial) / (total_number_of_samples)
        expected_tails_percentage = (control_tails_per_trial + test_tails_per_trial) / (total_number_of_samples)

        expected_heads = expected_heads_percentage * samples_per_trial
        expected_tails = expected_tails_percentage * samples_per_trial
        X_2_control_heads = ((control_heads_per_trial - expected_heads) ** 2) / expected_heads
        X_2_control_tails = ((control_tails_per_trial - expected_tails) ** 2) / expected_tails
        X_2_test_heads = ((test_heads_per_trial - expected_heads) ** 2) / expected_heads
        X_2_test_tails = ((test_tails_per_trial - expected_tails) ** 2) / expected_tails

        X_2 = X_2_control_heads + X_2_control_tails + X_2_test_heads + X_2_test_tails

        p = chi2.sf(X_2, degrees_of_freedom)
        significant = p < alpha

        if significant:
            significant_differences += 1

    return significant_differences

def generate_normal_distribution_ppf():

    inverse_cdf_values = []

    for x in range(0, 1000, 1):
        inverse_cdf_values.append(norm.ppf(x / 1000))

    print(inverse_cdf_values)

def main():

    # number of trials to perform for each simulation; each
    # trial draws 'samples_per_trial' samples (dynamically calculated based on A/B experiment parameters)
    total_trials = 100

    # number of times to run the simulation; each run contains total_trials number of trials
    # multiple runs allow us to observe the variance in false positives/negatives across runs
    # any individual run may have a lower or higher number of false positives/negatives than specified by
    # alpha and beta, but the average of false positives/negatives across runs should correspond to the
    # selected alpha and beta values
    total_runs = 100

    # A/B test parameters
    baseline_odds = 0.5
    test_odds_delta = 0.05
    alpha = 0.05
    beta = 0.2
    minimum_effect_size = 0.05

    samples_per_trial = calculate_sample_size(baseline_odds, alpha, beta, minimum_effect_size)
    print("Samples per trial: %s" % samples_per_trial)
    print("Trials per run: %s" % total_trials)
    print("Total runs: %s" % total_runs)

    # false positives exploration
    if test_odds_delta == 0:
        false_positives_simulation = {'data': [], 'bins': 100,
                      'figure': 0,
                      'xLabel': 'False positives',
                      'yLabel': 'Counts',
                      'title': 'A/B Experiments'}

        for runs in range(total_runs):
            significant = run_simulation(
                baseline_odds=baseline_odds,
                test_odds_delta=test_odds_delta,
                alpha=alpha,
                beta=beta,
                minimum_effect_size=minimum_effect_size,
                total_trials=total_trials,
                samples_per_trial=samples_per_trial
            )
            false_positives_simulation['data'].append(significant)

        average = sum(false_positives_simulation['data']) / len(false_positives_simulation['data'])
        print("Mean false positives per run: %s" % average)
        histogram(false_positives_simulation)

    # false negatives exploration
    # draw samples using the thresholds p+test_odds_delta and p-test_odds_delta because if p != 0.5,
    # changing 'p' by a constant 'test_odds_delta' does not increase the odds of observing heads
    # by the same relative amount as it decreases the odds of observing tails
    #
    # p=baseline odds of observing heads; delta=change to baseline odds
    # relative chance of observing heads: (p+delta) / p
    # relative chance of observing tails: (1-(p+delta)) / p
    # (p+delta) / p == (1-(p+delta)) / p if and only if p=0.5
    #
    # for example:
    # if p=0.5, and delta=0.1: (0.4+0.1)/0.5 == (1-(0.4+0.1))/0.5
    # if p=0.49, and delta=0.1: (0.49+0.1)/0.49 != (1-(0.49+0.1))/0.49
    #
    # if we sample only from p+delta or only from p-delta, we'll get more or fewer false negatives than
    # expected based on the calculated sample size
    else:
        false_negatives_simulation = {'data': [], 'bins': 100,
                      'figure': 1,
                      'xLabel': 'False negatives',
                      'yLabel': 'Counts',
                      'title': 'A/B Experiments'}

        # baseline + delta
        for runs in range(total_runs):
            significant = run_simulation(
                baseline_odds=baseline_odds,
                test_odds_delta=test_odds_delta,
                alpha=alpha,
                beta=beta,
                minimum_effect_size=minimum_effect_size,
                total_trials=total_trials,
                samples_per_trial=samples_per_trial
            )
            false_negatives_simulation['data'].append(total_trials - significant)

        # baseline - delta
        for runs in range(total_runs):
            significant = run_simulation(
                baseline_odds=baseline_odds,
                test_odds_delta=-test_odds_delta,
                alpha=alpha,
                beta=beta,
                minimum_effect_size=minimum_effect_size,
                total_trials=total_trials,
                samples_per_trial=samples_per_trial
            )

            false_negatives_simulation['data'].append(total_trials - significant)

        average = sum(false_negatives_simulation['data']) / len(false_negatives_simulation['data'])
        print("Mean false negatives per run: %s" % average)
        histogram(false_negatives_simulation)

    plt.show()

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
import os
import time
import unittest
from configparser import ConfigParser
import subprocess
import logging

from kraken2.kraken2Impl import kraken2
from kraken2.kraken2Server import MethodContext
from kraken2.authclient import KBaseAuth as _KBaseAuth

from installed_clients.WorkspaceClient import Workspace
from installed_clients.AssemblyUtilClient import AssemblyUtil

class kraken2Test(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        token = os.environ.get('KB_AUTH_TOKEN', None)
        config_file = os.environ.get('KB_DEPLOYMENT_CONFIG', None)
        cls.cfg = {}
        config = ConfigParser()
        config.read(config_file)
        for nameval in config.items('kraken2'):
            cls.cfg[nameval[0]] = nameval[1]
        # Getting username from Auth profile for token
        authServiceUrl = cls.cfg['auth-service-url']
        auth_client = _KBaseAuth(authServiceUrl)
        user_id = auth_client.get_user(token)
        # WARNING: don't call any logging methods on the context object,
        # it'll result in a NoneType error
        cls.ctx = MethodContext(None)
        cls.ctx.update({'token': token,
                        'user_id': user_id,
                        'provenance': [
                            {'service': 'kraken2',
                             'method': 'please_never_use_it_in_production',
                             'method_params': []
                             }],
                        'authenticated': 1})
        cls.wsURL = cls.cfg['workspace-url']
        cls.wsClient = Workspace(cls.wsURL)
        cls.serviceImpl = kraken2(cls.cfg)
        cls.scratch = cls.cfg['scratch']
        cls.callback_url = os.environ['SDK_CALLBACK_URL']
        suffix = int(time.time() * 1000)
        cls.wsName = "test_Kraken2_" + str(suffix)
        ret = cls.wsClient.create_workspace({'workspace': cls.wsName})  # noqa

    @classmethod
    def tearDownClass(cls):
        if hasattr(cls, 'wsName'):
            cls.wsClient.delete_workspace({'workspace': cls.wsName})
            print('Test workspace was deleted')

    # NOTE: According to Python unittest naming rules test method names
    # should start from 'test'. # noqa
    def test_param(self):
        print('test_param')
        # Prepare test objects in workspace if needed using
        # self.getWsClient().save_objects({'workspace': self.getWsName(),
        #                                  'objects': []})
        #
        # Run your method by
        # ret = self.getImpl().your_method(self.getContext(), parameters...)
        #
        # Check returned data with
        # self.assertEqual(ret[...], ...) or other unittest methods
        input_genomes = ["79/16/1"]
        input_refs = ['22956/5/2']
        input_paired_refs = ['22956/8/1', '22956/7/1']
        print(f"input_refs {input_refs}")
    #
    #     # Test that either input_genomes or reads
    #     with self.assertRaises(ValueError):
    #         self.serviceImpl.run_kraken2(self.ctx,
    #                                        {'workspace_name': self.wsName,
    #                                         'input_genomes': [],
    #                                         'input_refs': [],
    #                                         'input_paired_refs': [None],
    #                                         'db_type': 'minikraken2_v1_8GB'
    #                                         })
    #     with self.assertRaises(ValueError):
    #         ret = self.serviceImpl.run_kraken2(self.ctx,
    #                                        {'workspace_name': self.wsName,
    #                                         'input_genomes': input_genomes,
    #                                         'input_refs': input_refs,
    #                                         'input_paired_refs': [],
    #                                         'db_type': 'minikraken2_v1_8GB'
    #                                         })
    #         print(f'ret {ret[0]}')
    #
    #     with self.assertRaises(ValueError):
    #         ret = self.serviceImpl.run_kraken2(self.ctx,
    #                                        {'workspace_name': self.wsName,
    #                                         'input_genomes': [],
    #                                         'input_refs': input_refs,
    #                                         'input_paired_refs':
    #                                             input_paired_refs,
    #                                         'db_type': 'minikraken2_v1_8GB'
    #                                         })
    #
    #
        # Test with single-ended reads
        ret = self.serviceImpl.run_kraken2(self.ctx,
                                           {'workspace_name': self.wsName,
                                            'input_refs': input_refs,
                                            'db_type': 'minikraken2_v1_8GB'})
        self.assertTrue('report_name' in ret[0].keys())
        self.assertTrue('report_ref' in ret[0].keys())
        self.assertTrue('report_params' in ret[0].keys())
        print(f"ret {ret[0]['report_params']['file_links']}")
        file_flags = [False, False, False]
        for link in ret[0]['report_params']['file_links']:
            file_flags[0] = True if link['name'] == 'kraken2.out.tab_tree' else \
            file_flags[0]
            file_flags[1] = True if link['name'] == 'kraken2.report.csv' else \
            file_flags[1]
            file_flags[2] = True if link['name'] == 'kraken2.krona.html' else \
            file_flags[2]
        [logging.info(flag) for flag in file_flags]
        [self.assertTrue(flag) for flag in file_flags]
        # self.assertEqual('df_style.css',
        #                  ret[0]['report_params']['file_links'][0]['name'])
        # self.assertEqual('report.txt',
        #                  ret[0]['report_params']['file_links'][1]['name'])
        # self.assertEqual('kraken2_output.zip',
        #                  ret[0]['report_params']['file_links'][2]['name'])
        self.assertIn('test_Kraken2_',
                      ret[0]['report_params']['workspace_name'])
        self.assertIn('minikraken2_v1_8GB', ret[0]['report_params']['message'])
    #
    #     # Test with paired single-end reads
        ret = self.serviceImpl.run_kraken2(self.ctx,
                                           {'workspace_name': self.wsName,
                                            'input_paired_refs':
                                                input_paired_refs,
                                            'db_type': 'minikraken2_v1_8GB'})
        print(f'ret {ret[0]}')
        self.assertTrue('report_name' in ret[0].keys())
        self.assertTrue('report_ref' in ret[0].keys())
        self.assertTrue('report_params' in ret[0].keys())
        file_flags = [False, False, False]
        for link in ret[0]['report_params']['file_links']:
            file_flags[0] = True if link['name'] == 'kraken2.out.tab_tree' else \
            file_flags[0]
            file_flags[1] = True if link['name'] == 'kraken2.report.csv' else \
            file_flags[1]
            file_flags[2] = True if link['name'] == 'kraken2.krona.html' else \
            file_flags[2]
        [print(flag) for flag in file_flags]
        [self.assertTrue(flag) for flag in file_flags]
    #     # self.assertEqual('df_style.css',
    #     #                  ret[0]['report_params']['file_links'][0]['name'])
    #     # self.assertEqual('report.txt',
    #     #                  ret[0]['report_params']['file_links'][1]['name'])
    #     # self.assertEqual('kraken2_output.zip',
    #     #                  ret[0]['report_params']['file_links'][2]['name'])
    #     self.assertIn('test_Kraken2_', ret[0]['report_params']
    #     ['workspace_name'])
    #     self.assertIn('minikraken2_v1_8GB', ret[0]['report_params']['message'])
    #
    #
    #     # Test with Assemblies
        ret = self.serviceImpl.run_kraken2(self.ctx,
                                           {'workspace_name': self.wsName,
                                            'input_genomes': input_genomes,
                                            'confidence': 0.1,
                                            'db_type': 'minikraken2_v1_8GB'})

        print("report", ret[0])
        self.assertTrue('report_name' in ret[0].keys())
        self.assertTrue('report_ref' in ret[0].keys())
        self.assertTrue('report_params' in ret[0].keys())
        file_flags = [False, False, False]
        for link in ret[0]['report_params']['file_links']:
            file_flags[0] = True if link['name'] == 'kraken2.out.tab_tree' else file_flags[0]
            file_flags[1] = True if link['name'] == 'kraken2.report.csv' else file_flags[1]
            file_flags[2] = True if link['name'] == 'kraken2.krona.html' else file_flags[2]
        [print(flag) for flag in file_flags]
        [self.assertTrue(flag) for flag in file_flags]
    #     # self.assertEqual('df_style.css',
    #     #                  ret[0]['report_params']['file_links'][0]['name'])
    #     # self.assertEqual('report.txt',
    #     #                  ret[0]['report_params']['file_links'][1]['name'])
    #     # self.assertEqual('kraken2_output.zip',
    #     #                  ret[0]['report_params']['file_links'][2]['name'])
    #     self.assertIn('test_Kraken2_', ret[0]['report_params']
    #     ['workspace_name'])
    #     self.assertIn('Shewanella_oneidensis_MR-1_assembly.fa',
    #                   ret[0]['report_params']['message'])
    #     self.assertIn('minikraken2_v1_8GB', ret[0]['report_params']['message'])

    def test_kraken2(self):
        print('test_kraken2')
        self.assertTrue(
            os.path.exists('/data/kraken2/16S_Greengenes_20190418'))
        self.assertTrue(os.path.exists(
            '/data/kraken2/minikraken2_v1_8GB/database100mers.kmer_distrib'))

        # Test fasta input with kraken-microbial database -- much larger db and
        # takes a long time to run
        # cmd = ['kraken2', '-db', '/data/kraken2/kraken-microbial',
        #        '--report', 'test_fasta.txt', '--threads', '1',
        #        '/data/kraken2/test.fasta']
        # logging.info(f'cmd {cmd}')
        # p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
        #                      stderr=subprocess.STDOUT)
        # logging.info(p.communicate())
        #
        # self.assertTrue(os.path.exists('test_fasta.txt'))
        # logging.info(f'current directory {os.getcwd()}')
        # with open('test_fasta.txt', 'r') as fp:
        #     logging.info('print summary')
        #     lines = fp.readlines()
        #     # for line in lines:
        #     #     logging.info(line.split('\t')[-1].strip())
        # self.assertEqual(lines[-1].split('\t')[-1].strip(),
        # 'Zaire ebolavirus')

        # Test fasta input with minikraken2 db
        # cmd = ['kraken2', '-db', '/data/kraken2/minikraken2_v1_8GB',
        #        '--report', 'test_fasta.txt', '--threads', '1',
        #        '/data/kraken2/test.fasta']
        output_dir = '/kb/module/work/output'
        output_csv = os.path.join(output_dir, 'kraken2.report.csv')
        cmd = ['/kb/module/lib/kraken2/src/kraken2.sh',
               '-d', '/data/kraken2/minikraken2_v1_8GB',
               '-o', output_dir,'-t','1','-p', 'kraken2',
               '-i', '/data/kraken2/test.fasta']

        logging.info(f'cmd {cmd}')
        p = subprocess.Popen(' '.join(cmd), stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT, shell=True)
        logging.info(p.communicate())

        self.assertTrue(os.path.exists(output_csv))
        logging.info(f'current directory {os.getcwd()}')
        with open(output_csv, 'r') as fp:
            logging.info('print summary')
            lines = fp.readlines()
            # for line in lines:
            #     logging.info(line.split('\t')[-1].strip())
        self.assertEqual(lines[-1].split('\t')[-1].strip(), 'Zaire ebolavirus')
        #
        # # Test fastq input
        # cmd = ['kraken2', '-db', '/data/kraken2/minikraken2_v1_8GB',
        #        '--report', 'test_fastq.txt', '--threads', '1', '--fastq-input',
        #        '/data/kraken2/test.fastq']
        cmd = ['/kb/module/lib/kraken2/src/kraken2.sh',
               '-d', '/data/kraken2/minikraken2_v1_8GB',
               '-o', output_dir, '-t', '1', '-p', 'kraken2',
               '-i', '/data/kraken2/test.fastq']
        logging.info(f'cmd {cmd}')
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT, shell=True)
        logging.info(p.communicate())

        self.assertTrue(os.path.exists(output_csv))
        logging.info(f'current directory {os.getcwd()}')
        with open(output_csv, 'r') as fp:
            logging.info('print summary')
            lines = fp.readlines()
            for line in lines:
                logging.info(line.split('\t')[-1].strip())
        if len(line.split('\t')) == 0:
            self.assertEqual(lines[-1].strip(),
                             'Zaire ebolavirus')
        else:
            self.assertEqual(lines[-1].split('\t')[-1].strip(), 'Zaire ebolavirus')


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

from django.shortcuts import render
from my_game.models import MyUser, UserCity, TurnProduction
from my_game.models import HullPattern, ShellPattern, ShieldPattern, GeneratorPattern, EnginePattern, \
    ArmorPattern, ModulePattern, WeaponPattern, FactoryInstalled, FuelPattern, DevicePattern
from my_game.models import BasicResource
from my_game.models import ManufacturingComplex
from my_game.factory import verification_stage_production
from my_game.building import assembly_line_workpieces

def choice_element(request):
    if "live" not in request.session:
        return render(request, "index.html", {})
    else:
        session_user = MyUser.objects.filter(id=int(request.session['user'])).first()
        session_user_city = UserCity.objects.filter(id=int(request.session['user_city'])).first()
        assembly_line_workpieces.check_assembly_line_workpieces(session_user)
        verification_stage_production.verification_stage_production(session_user)
        factory_installed = FactoryInstalled.objects.filter(id=request.POST.get('factory_id')).first()
        if not factory_installed:
            factory_installeds = FactoryInstalled.objects.filter(user=session_user, user_city=session_user_city,
                                                                 complex_status=0)
            manufacturing_complexs = ManufacturingComplex.objects.filter(user=session_user, user_city=session_user_city)
            user_citys = UserCity.objects.filter(user=session_user)
            message = 'Выберите завод'
            request.session['user'] = session_user.id
            request.session['user_city'] = session_user_city.id
            request.session['live'] = True
            output = {'user': session_user, 'warehouse': session_user_city.warehouse, 'user_city': session_user_city,
                      'user_citys': user_citys, 'manufacturing_complexs': manufacturing_complexs,
                      'factory_installeds': factory_installeds, 'message': message}
            return render(request, "factory.html", output)

        factory_installeds = FactoryInstalled.objects.filter(user=session_user, user_city=session_user_city,
                                                             complex_status=0)
        attributes = {}
        element_patterns = {}

        if factory_installed.factory_pattern.production_class == 1:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit",
                "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material", "price_chemical",
                "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "hull_health", "generator", "engine", "weapon", "armor", "shield",
                "main_weapon", "module", "hold_size", "hull_size", "hull_mass", "power_consuption")
            element_patterns = HullPattern.objects.filter(user=session_user).all()
        elif factory_installed.factory_pattern.production_class == 2:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit",
                "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material", "price_chemical",
                "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "armor_health",
                "value_energy_resistance", "value_phisical_resistance", "armor_power", "armor_regeneration",
                "armor_mass")
            element_patterns = ArmorPattern.objects.filter(user=session_user).all()
        elif factory_installed.factory_pattern.production_class == 3:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "shield_health", "value_energy_resistance", "value_phisical_resistance",
                "number_of_emitter", "shield_regeneration", "shield_mass", "shield_size", "power_consuption")
            element_patterns = ShieldPattern.objects.filter(user=session_user).all()
        elif factory_installed.factory_pattern.production_class == 4:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "engine_health", "system_power", "intersystem_power", "giper_power",
                "nullT_power", "engine_mass", "engine_size", "power_consuption")
            element_patterns = EnginePattern.objects.filter(user=session_user).all()
        elif factory_installed.factory_pattern.production_class == 5:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "generator_health", "produced_energy", "fuel_necessary", "generator_mass",
                "generator_size")
            element_patterns = GeneratorPattern.objects.filter(user=session_user).all()
        elif factory_installed.factory_pattern.production_class == 6:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "weapon_health", "weapon_energy_damage", "weapon_regenerations",
                "number_of_bursts", "weapon_range", "weapon_accuracy", "weapon_mass", "weapon_size", "power_consuption")
            element_patterns = WeaponPattern.objects.filter(user=session_user).all()

        elif factory_installed.factory_pattern.production_class == 7:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "shell_phisical_damage", "shell_speed", "shell_mass", "shell_size")
            element_patterns = ShellPattern.objects.filter(user=session_user).all()

        elif factory_installed.factory_pattern.production_class == 8:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "module_health", "param1", "param2", "param3", "module_mass",
                "module_size", "power_consuption")
            element_patterns = ModulePattern.objects.filter(user=session_user).all()

        elif factory_installed.factory_pattern.production_class == 9:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "device_health", "produced_energy", "fuel_necessary", "device_mass",
                "device_size", "power_consuption")
            element_patterns = DevicePattern.objects.filter(user=session_user).all()

        elif factory_installed.factory_pattern.production_class == 14:
            attributes = (
                "price_internal_currency", "price_nickel", "price_iron", "price_cooper", "price_aluminum",
                "price_veriarit", "price_inneilit", "price_renniit", "price_cobalt", "price_construction_material",
                "price_chemical", "price_high_strength_allov", "price_nanoelement", "price_microprocessor_element",
                "price_fober_optic_element", "fuel_mass", "fuel_size", "fuel_efficiency")
            element_patterns = FuelPattern.objects.filter(user=session_user).all()

        basic_resources = BasicResource.objects.filter()
        manufacturing_complexs = ManufacturingComplex.objects.filter(user=session_user,
                                                                     user_city=session_user_city).all()
        turn_productions = TurnProduction.objects.filter(user=session_user, user_city=session_user_city).all()
        user_citys = UserCity.objects.filter(user=session_user).all()
        request.session['user'] = session_user.id
        request.session['user_city'] = session_user_city.id
        request.session['live'] = True
        output = {'user': session_user, 'warehouse': session_user_city.warehouse, 'user_city': session_user_city,
                  'factory_installeds': factory_installeds, 'factory_installed': factory_installed,
                  'element_patterns': element_patterns, 'attributes': attributes, 'turn_productions': turn_productions,
                  'user_citys': user_citys, 'manufacturing_complexs': manufacturing_complexs,
                  'factory_warehouse': factory_installed.factory_warehouse, 'basic_resources': basic_resources}
        return render(request, "factory.html", output)


from . import crawler
from bs4 import BeautifulSoup
import re

def list_musics_by_artistid(aid):
    r = crawler.fetch('http://www.uta-net.com/artist/{}/'.format(aid))
    results = []
    bso = BeautifulSoup(r, 'lxml')
    result_tables = bso.select('.result_table')

    for rt in result_tables:
        mitems = rt.select_one('table').select_one('tbody').select('tr')
        for mitem in mitems:
            titlename = mitem.select_one('td.side.td1').select_one('a').text
            kasi_regexp = re.search('^/song/([0-9]+)/$', mitem.select_one('td.side.td1').select_one('a')['href'])
            kasi_id = kasi_regexp.group(1)
            #artistname = mitem.select_one('td.td2').select_one('a').text
            words_artistname = mitem.select_one('td.td3').text
            music_artistname = mitem.select_one('td.td4').text
            results.append({
                'id': kasi_id,
                'artist_id': aid,
                'titlename': titlename,
                'words_artistname': words_artistname,
                'music_artistname': music_artistname,
            })
    return results

def get_kasi_by_kasiid(kid):
    def _convert_text(t):
        return re.sub('\u3000', ' ', t)

    a = crawler.fetch('http://www.uta-net.com/song/{}/'.format(kid))
    bso1 = BeautifulSoup(a, 'lxml')
    target1 = bso1.select_one('#ipad_kashi').select_one('img')
    b = crawler.fetch('http://www.uta-net.com' + target1['src'])
    bso2 = BeautifulSoup(b, 'lxml')
    texts = [
        _convert_text(t.text)
        for t in bso2.select_one('svg').select('text')
        if not t.text == ''
    ]
    return texts

def list_top100_artists():
    result = {}

    raw1 = crawler.fetch('http://www.uta-net.com/user/artist_ranking_100/2016/ranking_100_top.html')
    bso1 = BeautifulSoup(raw1, 'lxml')
    r1 = bso1.select_one('td[height="1693"]').select('table[width="231"]')
    for t in r1:
        tr = t.select('tr')
        atag = tr[0].select_one('a')
        gname_c = tr[2].select('td')[1].select_one('span')
        aid = re.search('http://www.uta-net.com/artist/([0-9]+)/?', atag['href']).group(1)
        aname = re.sub('\n', '', gname_c.text)
        result[aid] = aname
    r2 = bso1.select_one('#main').select_one('div[align="center"]').select_one('table').select_one('table').select_one('tr').select('td')
    for t in r2:
        for tt in t.select('table'):
            tr = tt.select('tr')
            atag = tr[0].select_one('a')
            gname_c = tr[2].select('td')[1].select_one('span')
            if gname_c is None: # 静的ファイルなのかspanついてないことがある...orz
                gname_c = tr[2].select('td')[1]
            aid = re.search('http://www.uta-net.com/artist/([0-9]+)/?', atag['href']).group(1)
            aname = re.sub('\n', '', gname_c.text)
            result[aid] = aname

    raw2 = crawler.fetch('http://www.uta-net.com/user/artist_ranking_100/2016/ranking_100_2.html')
    bso2 = BeautifulSoup(raw2, 'lxml')
    r3 = bso2.select_one('#main').select('table')[1].select_one('td').select('table')[1].select_one('table').select('td')
    for t in r3:
        for tt in t.select('table[width="231"]'):
            tr = tt.select('tr')
            atag = tr[0].select_one('a')
            gname_c = tr[2].select('td')[1].select_one('span')
            if gname_c is None: # 静的ファイルなのかspanついてないことがある...orz
                gname_c = tr[2].select('td')[1]
            aid = re.search('http://www.uta-net.com/artist/([0-9]+)/?', atag['href']).group(1)
            aname = re.sub('\n', '', gname_c.text)
            result[aid] = aname

    return result


import unittest
import pandas as pd
import os
import pytest

from data_dag import lazy, dep, pipeline, lazy_read_csv

class TestLazy(unittest.TestCase):

    def test_lazy_function(self):
        l = lazy(print, {'hello':'world'})
        self.assertDictEqual(l.params, {'hello': 'world'})

    def test_lazy_function_except(self):
        with self.assertRaises(Exception) as context:
            l = lazy('hi', {'hello':'world'})

    def test_lazy_function_param(self):
        with self.assertRaises(Exception) as context:
            l = lazy(print, 'hi')

    def test_lazy_correct(self):
        l = lazy(print, {'hello': 'world'}) # Should work
        self.assertDictEqual(l.params, {'hello': 'world'})

    def test_lazy_error_key(self):
        with self.assertRaises(Exception) as context:
            lazy(print, {5: 'world'}) # Throws an exception

class TestPipeline(unittest.TestCase):
    def test_pipeline_is_dict(self):
        with self.assertRaises(Exception):
            x = pipeline()
            x.define('x')

class TestLazyReadCSV(unittest.TestCase):

    def test_lazy_read_csv(self):
        f = pd.read_csv("test.csv")
        x = lazy_read_csv({"filepath_or_buffer": "test.csv"})

        self.assertTrue(not x.cache)
        self.assertTrue(not x.hash)

        self.assertEqual(f.iloc[0,0], x.eval().iloc[0,0])

        self.assertTrue(isinstance(x.cache, pd.DataFrame))
        self.assertTrue(isinstance(x.hash, str))
        # Check that dataframes are equal
        self.assertTrue(f.equals(x.cache))

    def test_lazy_read_csv_in_pipeline(self):
        ex_pipe = pipeline()

        ex_pipe.define({
            "first": lazy_read_csv(
                params = {'filepath_or_buffer': "test.csv"})
        })
        # Check if the hash and cache are empty
        self.assertTrue(not ex_pipe.pipes['first'].cache)
        self.assertTrue(not ex_pipe.pipes['first'].hash)

        # Check if the step is a dataframe
        self.assertTrue(isinstance(ex_pipe.get_step('first'), pd.DataFrame))

        # Check if the cache is a dataframe
        self.assertTrue(isinstance(ex_pipe.pipes['first'].cache, pd.DataFrame))

        # Check if the hash is a string
        self.assertTrue(isinstance(ex_pipe.pipes['first'].hash, str))

    def test_lazy_read_csv_cache_invalidation(self):
        # Create new minimal CSV file to test cache invalidation
        with open('test2.csv', 'w') as f:
            f.write('a,b,c\n1,2,3\n4,5,6\n7,8,9')
        test_pipeline = pipeline()
        test_pipeline.define({
            "first": lazy_read_csv(
                params = {'filepath_or_buffer': "test2.csv"})
        })
        # Check if the hash and cache are empty
        self.assertTrue(not test_pipeline.pipes['first'].cache)
        self.assertTrue(not test_pipeline.pipes['first'].hash)
        # Save the cache to comparae later
        cache = test_pipeline.pipes['first'].cache
        # Check if the step is a dataframe
        self.assertTrue(isinstance(test_pipeline.get_step('first'), pd.DataFrame))
        # Check if the cache is non-empty
        self.assertTrue(test_pipeline.pipes['first'].hash)
        # Change the CSV file
        with open('test2.csv', 'w') as f:
            f.write('a,b,c\n1,2,3\n4,5,6\n7,8,9\n10,11,12')
        # Read the step again
        test_pipeline.get_step('first')
        # Check if the cache is different
        self.assertTrue(not test_pipeline.pipes['first'].cache.equals(cache))
        # Delete the test file
        os.remove('test2.csv')

    def test_lazy_lambda_eval_in_pipeline(self):
        ex_pipe = pipeline()
        ex_pipe.define({
            "first": lazy_read_csv(
                params = {'filepath_or_buffer': "test.csv"}),
            "second": lazy(
                func = lambda x,y: x.rename(**y),
                params = {'x': dep('first'), 'y': {'columns': {'hello': 'what'}}})
        })
        self.assertTrue(isinstance(ex_pipe.get_step('second'), pd.DataFrame))
        self.assertTrue(ex_pipe.get_step('second').columns[0] == 'what')

if __name__ == "__main__":
    unittest.main()


def clean_rated_salaries_df(df):
    # 1) droping star column
    df.drop(columns=["Star"], inplace=True)
    # 2) Changing some data types
    df["Rating"] = df["Rating"].astype(np.float32)
    df["Company"] = df["Company"].astype(str)
    df["Job_Title"] = df["Job_Title"].astype(str)

    # Cleaning Min & Max range
    df[["Min Range", "Max Range"]] = df[["Min Range", "Max Range"]].replace([' ', 'K'],
                                                                                ['', '000'],
                                                                                regex=True)
    ##removing non-digit characters
    df["Min Range"] = df["Min Range"].str.extract('(\d+)', expand=False).astype(float)
    df["Max Range"] = df["Max Range"].str.extract('(\d+)', expand=False).astype(float)

    # Cleaning Annual Salary
    series = df["Annual Salary"]
    df["Annual Salary"] = [s.encode('ascii', 'ignore').strip()
                                          for s in series.str.decode('unicode_escape')]

    df["Annual Salary"] = df["Annual Salary"].str.decode("utf-8")

    ##removing non-digit characters
    # df["Annual Salary"] = df["Annual Salary"].str.extract('(\d+)', expand=False).astype(float)

    # If df["Annual Salary"] is not number it is "About": we take the minimum range as salary and we place yearly "an" in the column Yearl/Monthyly
    for r in range(0, len(df["Annual Salary"])):
        if not df["Annual Salary"][r].isdigit():
            # replace with minimum range salary
            df["Annual Salary"][r] = df["Min Range"][r]
            # fillin Yearly/Monthly with "yr"  "mo"
            if df["Annual Salary"][r] > 15000:
                df.iloc[r, 4] = "yr"
            else:
                df.iloc[r, 4] = "mo"

    # Changing annual salary to float
    df["Annual Salary"] = df["Annual Salary"].astype(float)

    # removing all non-digits characters from "Based_On Count", "How many salaries on Glassdoor"
    count_list = ["Based_On Count", "How many salaries on Glassdoor"]
    for r in count_list:
        df[r] = df[r].str.extract('(\d+)', expand=False).astype(int)

    # Cleaning "Yearly/Monthly"
    df["Yearly/Monthly"] = df["Yearly/Monthly"].apply(
        lambda x: re.sub('[^a-zA-Z]+', '', x))

    return df