from __future__ import absolute_import, division, print_function

import tensorflow as tf
import tensorflow_datasets as tfds

# Helper libraries
import math
import numpy as np
import matplotlib.pyplot as plt

# Improve progress bar display
import tqdm
import tqdm.auto

tf.logging.set_verbosity(tf.logging.ERROR)
tqdm.tqdm = tqdm.auto.tqdm

print(tf.__version__)       # 1.12.0

# tf.enable_eager_execution()

dataset, metadata = tfds.load('fashion_mnist', as_supervised=True, with_info=True)
train_dataset, test_dataset = dataset['train'], dataset['test']

'''
Dataset fashion_mnist downloaded and prepared to /home/hdh/tensorflow_datasets/fashion_mnist/1.0.0. Subsequent calls will reuse this data.
Process finished with exit code 0
'''

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

# Explorer the data
num_train_examples = metadata.splits['train'].num_examples
num_test_examples = metadata.splits['test'].num_examples

print('Number of training examples: {}'.format(num_train_examples))
print('Number of testing examples: {}'.format(num_test_examples))

# Preprocess the data(normalize)
def normalize(images, labels):
    images = tf.cast(images, tf.float32)
    images /= 255
    return images, labels

train_dataset = train_dataset.map(normalize)
test_dataset = test_dataset.map(normalize)

'''
# Explorer the progressed data
# Take a single image and remove the color dimension
for image, label in test_dataset.take(1):
    break
image = image.numpy().reshape((28, 28))

plt.figure()
plt.imshow(image, cmap=plt.cm.binary)
plt.colorbar()
plt.grid(False)
plt.show()

plt.figure(figsize=(10, 10))
i = 0
for (image, label) in test_dataset.take(25):
    image = image.numpy().reshape((28, 28))
    plt.subplot(5, 5, i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(image, cmap=plt.cm.binary)
    plt.xlabel(class_names[label])
    i += 1
plt.show()
'''

# Build a model only with fully connected layers
# l0 = tf.keras.layers.Flatten(input_shape=(28, 28, 1))       # input
# l1 = tf.keras.layers.Dense(128, activation=tf.nn.relu)      # hidden
# l2 = tf.keras.layers.Dense(10, activation=tf.nn.softmax)    # output

# Build a model only with fully connected layers
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), activation=tf.nn.relu,
                           padding='same', input_shape=(28, 28, 1)),
    tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), padding='same'),
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
    tf.keras.layers.Conv2D(filters=128, kernel_size=(3, 3), activation=tf.nn.relu, padding='same'),
    tf.keras.layers.Conv2D(filters=128, kernel_size=(3, 3), activation=tf.nn.relu, padding='valid'),
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
    tf.keras.layers.Conv2D(filters=256, kernel_size=(3, 3), activation=tf.nn.relu, padding='same'),
    tf.keras.layers.Conv2D(filters=256, kernel_size=(3, 3), activation=tf.nn.relu, padding='same'),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(512, activation=tf.nn.relu),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
# input_shape = (28, 28, 1)
# Conv : (28, 28, 64)
# Conv : (28, 28, 64)
# Pool : (14, 14, 64)
# Conv : (14, 14, 128)
# Conv : (12, 12, 128)
# Pool : (6, 6, 128)
# Conv : (6, 6, 256)
# Conv : (6, 6, 256)
# Flatten : 6*6*256
# Dense1 : 512
# Dense2 : 10

# Compile the model
# opt = tf.keras.optimizers.SGD(lr=0.1, decay=0.000225, momentum=0.5)
opt = tf.keras.optimizers.Adam(lr=0.001)
model.compile(optimizer=opt,
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
# adam 옵티마이저와 tf.enable_eager_execution()과는 문제가 있는듯.
# https://github.com/tensorflow/tensorflow/issues/25324
# 위 문장을 주석처리하면 정상적으로 실행됨

# train the model
batch_size = 32
train_dataset = train_dataset.repeat().shuffle(num_train_examples).batch(batch_size)
test_dataset = test_dataset.batch(batch_size)

model.fit(train_dataset, epochs=1, steps_per_epoch=math.ceil(num_train_examples/batch_size))

# Evaluate accuracy
test_loss, test_accuracy = model.evaluate(test_dataset, steps=math.ceil(num_test_examples/batch_size))
print('Accuracy on testset: {}'.format(test_accuracy))

# Make predictions and explore
for test_images, test_labels in test_dataset.take(1):
    test_images = test_images.numpy()
    test_labels = test_labels.numpy()
    predictions = model.predict(test_images)
print(predictions.shape)
print(predictions[0])
'''
(32, 10)
[9.9332246e-04 3.0070751e-07 5.4520708e-02 5.4992433e-03 5.0916857e-01
 4.4711786e-08 4.2935511e-01 2.3336844e-08 4.6259694e-04 3.6422879e-08]
'''
# https://classroom.udacity.com/courses/ud187/lessons/e52f6e56-2fbc-4ba8-9f74-377937b7da5c/concepts/69c86393-9b29-4875-b0b6-68b1d3cef4ed
# 05:35 진행. eager 옵션을 주석처리해서 에러 발생.
'''
Traceback (most recent call last):
  File "/home/hdh/Documents/TensorflowStudy/DeepLearning Basic/Udacity/lab04_Fashion_Mnist.py", line 109, in <module>
    for test_images, test_labels in test_dataset.take(1):
  File "/home/hdh/Env/p3ten10/lib/python3.5/site-packages/tensorflow/python/data/ops/dataset_ops.py", line 167, in __iter__
    raise RuntimeError("dataset.__iter__() is only supported when eager "
RuntimeError: dataset.__iter__() is only supported when eager execution is enabled.
'''
# Solve: Adjust the environment to Tensorflow 1.13, Cuda 10.0(Not 10.1), CuDNN7

print(np.argmax(predictions[0]))
print(test_labels[0])

def plot_image(i, predictions_array, true_labels, images):
    predictions_array, true_labels, img = predictions_array[i], true_labels[i], images[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img[..., 0], cmap=plt.cm.binary)

    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_labels:
        color = 'blue'
    else:
        color = 'red'
    plt.xlabel("{} {:0.2f}% ({})".format(class_names[predicted_label],
                                         100*np.max(predictions_array),
                                         class_names[true_labels]), color=color)

def plot_value_array(i, predictions_array, true_labels):
    predictions_array, true_labels = predictions_array[i], true_labels[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    thisplot = plt.bar(range(10), predictions_array, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)

    thisplot[predicted_label].set_color('red')
    thisplot[true_labels].set_color('blue')

# i = 0
# plt.figure(figsize=(6, 3))
# plt.subplot(1, 2, 1)
# plot_image(i, predictions, test_labels, test_images)
# plt.subplot(1, 2, 2)
# plot_value_array(i, predictions, test_labels)
# plt.show()

# num_rows = 5
# num_cols = 3
# num_images = num_rows * num_cols
# plt.figure(figsize=(2*2*num_cols, 2*num_rows))
# for i in range(num_images):
#     plt.subplot(num_rows, 2*num_cols, 2*i+1)
#     plot_image(i, predictions, test_labels, test_images)
#     plt.subplot(num_cols, 2*num_cols, 2*i+2)
#     plot_value_array(i, predictions, test_labels)

# img = test_images[0]
# print(img.shape)
#
# img = np.array([img])
# print(img.shape)
#
# prediction_single = model.predict(img)
# print(prediction_single)
#
# plot_value_array(0, prediction_single, test_labels)\
# _ = plt.xticks(range(10), class_names, rotation=45)
#
# np.argmax(prediction_single[0])


from typing import Iterable

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from mutagen.id3 import TALB, TDRC, TIT2, TOPE, TPE1, TPE2, TRCK
from mutagen.oggopus import OggOpus

class BaseMetadataSetter:
    input_metadata_key_to_target_tag_map = {
        "artist": "",
        "album": "",
        "title": "",
        "track_number": "",
        "recording_year": "",
    }

    def __init__(self, filething, filepath, input_metadata_key, *args, **kwargs):
        if input_metadata_key not in self.input_metadata_key_to_target_tag_map.keys():
            raise ValueError(
                "Input metadata key not supported. Supported input names: {}".format(
                    ",".join(self.input_metadata_key_to_target_tag_map.keys())
                )
            )
        super().__init__(*args, **kwargs)
        self.filething = filething
        self.filepath = filepath
        self.input_metadata_key = input_metadata_key

    def set_tag(self, value):
        key = self.input_metadata_key_to_target_tag_map[self.input_metadata_key]
        self.filething.tags[key] = value

    def save_tags_to_file(self):
        self.filething.save(self.filepath)

class MP4MetadataSetter(BaseMetadataSetter):
    """
    Metadata setter for MP4 files.
    Info on mutagen's MP4 API:
    https://mutagen.readthedocs.io/en/latest/api/mp4.html
    """

    input_metadata_key_to_target_tag_map = {
        "artist": "\xa9ART",
        "album": "\xa9alb",
        "title": "\xa9nam",
        "track_number": "trkn",
        "recording_year": "\xa9day",
    }

    def set_tag(self, value):
        key = self.input_metadata_key_to_target_tag_map[self.input_metadata_key]
        # edge case: track number takes in a tuple of ints, not an int
        # the second int is the number of total tracks
        # setting to 0 for simplicity
        if key == "trkn":
            value = [[int(value), 0]]
        self.filething.tags[key] = value

class VorbisMetadataSetter(BaseMetadataSetter):
    """
    Metadata setter for files with Vorbis tags (.ogg family, .flac files).
    using metadata fieldname standard outlined by Ogg Vorbis:
    https://xiph.org/vorbis/doc/v-comment.html#fieldnames
    Info on mutagen's Ogg Vorbis API:
    https://mutagen.readthedocs.io/en/latest/api/ogg.html
    """

    input_metadata_key_to_target_tag_map = {
        "artist": "artist",
        "album": "album",
        "title": "title",
        "track_number": "tracknumber",
        "recording_year": "date",
    }

class ID3MetadataSetter(BaseMetadataSetter):
    """
    Metadata setter for files with ID3 tags (mostly .mp3 files).
    Info on mutagen's ID3 API:
    https://mutagen.readthedocs.io/en/latest/api/id3.html
    """

    input_metadata_key_to_id3_tag_map = {
        "artist": [TPE1, TPE2, TOPE],
        "album": TALB,
        "title": TIT2,
        "track_number": TRCK,
        "recording_year": TDRC,
    }

    def set_tag(self, value):
        mapped_ID3_tags = self.input_metadata_key_to_id3_tag_map[
            self.input_metadata_key
        ]
        tags = []
        if not isinstance(mapped_ID3_tags, list):
            mapped_ID3_tags = [mapped_ID3_tags]
        for tag in mapped_ID3_tags:
            filled_tag = tag(encoding=3, text=value)
            self.filething[filled_tag.__class__.__name__] = filled_tag


import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font
from typing import Dict, List
import logging
from controllers.battle_summary_controller import BattleSummaryController, MoveRenderInfo

from gui import custom_components
from gui.popups.battle_config_popup import BattleConfigWindow
from pkmn import damage_calc, universal_data_objects
from routing import full_route_state
from routing import route_events
from utils.config_manager import config
from utils.constants import const
from pkmn.gen_factory import current_gen_info

logger = logging.getLogger(__name__)

class BattleSummary(ttk.Frame):
    def __init__(self, controller:BattleSummaryController, *args, **kwargs):
        self._controller = controller
        super().__init__(*args, **kwargs)

        self.columnconfigure(0, weight=1)

        # these are matched lists, with the solo mon being updated for each enemy pkmn, in case of level-ups
        self._enemy_pkmn:List[universal_data_objects.EnemyPkmn] = None
        self._solo_pkmn:List[universal_data_objects.EnemyPkmn] = None
        self._source_state:full_route_state.RouteState = None
        self._source_event_group:route_events.EventGroup = None
        self._player_stage_modifiers:universal_data_objects.StageModifiers = universal_data_objects.StageModifiers()
        self._enemy_stage_modifiers:universal_data_objects.StageModifiers = universal_data_objects.StageModifiers()
        self._mimic_selection = ""
        self._custom_move_data = None

        self._top_bar = ttk.Frame(self)
        self._top_bar.grid(row=0, column=0, sticky=tk.EW)

        self._setup_half = ttk.Frame(self._top_bar)
        self._setup_half.grid(row=0, column=0, sticky=tk.EW)
        self._weather_half = ttk.Frame(self._top_bar)
        self._weather_half.grid(row=0, column=1, sticky=tk.EW)

        self._top_bar.columnconfigure(0, weight=1)

        self.setup_moves = SetupMovesSummary(self._setup_half, callback=self._player_setup_move_callback)
        self.setup_moves.grid(row=0, column=0, sticky=tk.EW, pady=(0, 2))

        self.enemy_setup_moves = SetupMovesSummary(self._setup_half, callback=self._enemy_setup_move_callback, is_player=False)
        self.enemy_setup_moves.grid(row=1, column=0, sticky=tk.EW)

        self.config_button = custom_components.SimpleButton(self._weather_half, text="Configure/Help", command=self._launch_config_popup)
        self.config_button.grid(row=0, column=0, sticky=tk.EW, padx=10, pady=(0, 2))

        self.weather_status = WeatherSummary(self._weather_half, callback=self._weather_callback)
        self.weather_status.grid(row=0, column=1, sticky=tk.EW, padx=2, pady=(0, 2))

        self.candy_summary = PrefightCandySummary(self._weather_half, callback=self._candy_callback)
        self.candy_summary.grid(row=1, column=1, sticky=tk.EW, padx=2, pady=(0, 2))

        self._mon_pairs:List[MonPairSummary] = []

        for idx in range(6):
            self._mon_pairs.append(MonPairSummary(self._controller, idx, self))

        self.error_message = tk.Label(self, text="Select a battle to see damage calculations")
        self.should_render = False
        self.bind(self._controller.register_refresh(self), self._on_full_refresh)
        self.set_team(None)

    def configure_weather(self, possible_weather_vals):
        self.weather_status.configure_weather(possible_weather_vals)

    def configure_setup_moves(self, possible_setup_moves):
        self.setup_moves.configure_moves(possible_setup_moves)
        self.enemy_setup_moves.configure_moves(possible_setup_moves)

    def hide_contents(self):
        self.should_render = False
        for cur_mon_pair in self._mon_pairs:
            cur_mon_pair.grid_forget()

    def show_contents(self):
        self.should_render = True
        self._on_full_refresh()

    def _launch_config_popup(self, *args, **kwargs):
        BattleConfigWindow(self.winfo_toplevel(), battle_controller=self._controller)

    def _weather_callback(self, *args, **kwargs):
        self._controller.update_weather(self.weather_status.get_weather())

    def _candy_callback(self, *args, **kwargs):
        self._controller.update_prefight_candies(self.candy_summary.get_prefight_candy_count())

    def _player_setup_move_callback(self, *args, **kwargs):
        self._controller.update_player_setup_moves(self.setup_moves._move_list.copy())

    def _enemy_setup_move_callback(self, *args, **kwargs):
        self._controller.update_enemy_setup_moves(self.enemy_setup_moves._move_list.copy())

    def set_team(
        self,
        enemy_pkmn:List[universal_data_objects.EnemyPkmn],
        cur_state:full_route_state.RouteState=None,
        event_group:route_events.EventGroup=None,
    ):
        if event_group is not None:
            self._controller.load_from_event(event_group)
        elif cur_state is not None and enemy_pkmn is not None:
            self._controller.load_from_state(cur_state, enemy_pkmn)
        else:
            self._controller.load_empty()

    def _on_full_refresh(self, *args, **kwargs):
        if not self.should_render:
            return

        self.candy_summary.set_candy_count(self._controller.get_prefight_candy_count())
        if not self._controller.can_support_prefight_candies():
            self.candy_summary.disable()
        else:
            self.candy_summary.enable()
        self.weather_status.set_weather(self._controller.get_weather())
        self.setup_moves.set_move_list(self._controller.get_player_setup_moves())
        self.enemy_setup_moves.set_move_list(self._controller.get_enemy_setup_moves())
        for idx in range(6):
            player_info = self._controller.get_pkmn_info(idx, True)
            enemy_info = self._controller.get_pkmn_info(idx, False)

            if player_info is None and enemy_info is None:
                self._mon_pairs[idx].grid_forget()
                if idx == 0:
                    pass

            else:
                self._mon_pairs[idx].grid(row=idx + 2, column=0, sticky=tk.EW)
                self._mon_pairs[idx].update_rendering()

class SetupMovesSummary(ttk.Frame):
    def __init__(self, *args, callback=None, is_player=True, **kwargs):
        super().__init__(*args, **kwargs)

        self._callback = callback
        self._move_list = []

        self.reset_button = custom_components.SimpleButton(self, text="Reset Setup", command=self._reset)
        self.reset_button.grid(row=0, column=0, padx=2)

        self.setup_label = ttk.Label(self, text="Move:")
        self.setup_label.grid(row=0, column=1, padx=2)

        self.setup_moves = custom_components.SimpleOptionMenu(self, ["N/A"])
        self.setup_moves.grid(row=0, column=2, padx=2)

        self.add_button = custom_components.SimpleButton(self, text="Apply Move", command=self._add_setup_move)
        self.add_button.grid(row=0, column=3, padx=2)

        if is_player:
            label_text = "Player Setup:"
        else:
            label_text = "Enemy Setup:"
        self.extra_label = ttk.Label(self, text=label_text)
        self.extra_label.grid(row=0, column=4, padx=2)

        self.move_list_label = ttk.Label(self)
        self.move_list_label.grid(row=0, column=5, padx=2)

    def _reset(self, *args, **kwargs):
        self._move_list = []
        self._move_list_updated()

    def _add_setup_move(self, *args, **kwargs):
        self._move_list.append(self.setup_moves.get())
        self._move_list_updated()

    def configure_moves(self, new_moves):
        self.setup_moves.new_values(new_moves)

    def set_move_list(self, new_moves, trigger_update=False):
        self._move_list = new_moves
        self._move_list_updated(trigger_update=trigger_update)

    def get_stage_modifiers(self):
        result = universal_data_objects.StageModifiers()

        for cur_move in self._move_list:
            result = result.apply_stat_mod(current_gen_info().move_db().get_stat_mod(cur_move))

        return result

    def _move_list_updated(self, trigger_update=True):
        to_display = ", ".join(self._move_list)
        if not to_display:
            to_display = "None"

        self.move_list_label.configure(text=to_display)
        if self._callback is not None and trigger_update:
            self._callback()

class WeatherSummary(ttk.Frame):
    def __init__(self, *args, callback=None, **kwargs):
        super().__init__(*args, **kwargs)
        self._outer_callback = callback
        self._loading = False

        self.label = ttk.Label(self, text="Weather:")
        self.label.grid(row=0, column=0, padx=2)

        self.weather_dropdown = custom_components.SimpleOptionMenu(self, [const.WEATHER_NONE], callback=self._callback)
        self.weather_dropdown.grid(row=0, column=1, padx=2)

    def _callback(self, *args, **kwargs):
        if self._loading:
            return

        if self._outer_callback is not None:
            self._outer_callback()

    def set_weather(self, new_weather):
        self._loading = True
        self.weather_dropdown.set(new_weather)
        self._loading = False

    def configure_weather(self, weather_vals):
        self.weather_dropdown.new_values(weather_vals)

    def get_weather(self):
        return self.weather_dropdown.get()

class PrefightCandySummary(ttk.Frame):
    def __init__(self, *args, callback=None, **kwargs):
        super().__init__(*args, **kwargs)
        self._outer_callback = callback
        self._loading = False

        self.label = ttk.Label(self, text="Prefight Candies:")
        self.label.grid(row=0, column=0, padx=2)

        self.candy_count = custom_components.AmountEntry(self, min_val=0, init_val=0, callback=self._callback, width=5)
        self.candy_count.grid(row=0, column=1, padx=2)

    def _callback(self, *args, **kwargs):
        if self._loading:
            return

        if self._outer_callback is not None:
            self._outer_callback()

    def set_candy_count(self, new_amount):
        self._loading = True
        self.candy_count.set(new_amount)
        self._loading = False

    def get_prefight_candy_count(self):
        try:
            return int(self.candy_count.get())
        except Exception:
            return 0

    def disable(self):
        self.candy_count.disable()

    def enable(self):
        self.candy_count.enable()

class MonPairSummary(ttk.Frame):
    def __init__(self, controller:BattleSummaryController, mon_idx, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._controller = controller
        self._mon_idx = mon_idx

        bold_font = tkinter.font.nametofont("TkDefaultFont").copy()
        bold_font.configure(weight="bold")

        self.left_mon_label_frame = ttk.Frame(self, style="Header.TFrame")
        self.left_mon_label_frame.grid(row=0, column=0, columnspan=4, sticky=tk.EW, padx=2, pady=2)

        self.left_label = ttk.Label(self.left_mon_label_frame, text="", style="Header.TLabel")
        self.left_label.grid(row=0, column=1)

        self.left_mon_label_frame.columnconfigure(0, weight=1, uniform="left_col_group")
        self.left_mon_label_frame.columnconfigure(2, weight=1, uniform="left_col_group")

        self.divider = ttk.Frame(self, width=4, style="Divider.TFrame")
        self.divider.grid(row=0, column=4, rowspan=2, sticky=tk.NS)
        self.divider.grid_propagate(0)

        self.right_mon_label_frame = ttk.Frame(self, style="Header.TFrame")
        self.right_mon_label_frame.grid(row=0, column=5, columnspan=4, sticky=tk.EW, padx=2, pady=2)

        self.right_label = ttk.Label(self.right_mon_label_frame, text="", style="Header.TLabel")
        self.right_label.grid(row=0, column=1)

        self.right_mon_label_frame.columnconfigure(0, weight=1, uniform="right_col_group")
        self.right_mon_label_frame.columnconfigure(2, weight=1, uniform="right_col_group")

        self.columnconfigure(0, weight=1, uniform="label_group")
        self.columnconfigure(1, weight=1, uniform="label_group")

        self.columnconfigure(0, weight=1, uniform="move_group")
        self.columnconfigure(1, weight=1, uniform="move_group")
        self.columnconfigure(2, weight=1, uniform="move_group")
        self.columnconfigure(3, weight=1, uniform="move_group")

        self.columnconfigure(5, weight=1, uniform="move_group")
        self.columnconfigure(6, weight=1, uniform="move_group")
        self.columnconfigure(7, weight=1, uniform="move_group")
        self.columnconfigure(8, weight=1, uniform="move_group")

        self.move_list:List[DamageSummary] = []
        for cur_idx in range(8):
            self.move_list.append(DamageSummary(self._controller, self._mon_idx, cur_idx % 4, cur_idx < 4, self))

    def update_rendering(self):
        player_rendering_info = self._controller.get_pkmn_info(self._mon_idx, True)
        enemy_rendering_info = self._controller.get_pkmn_info(self._mon_idx, False)

        self.left_label.configure(text=f"{player_rendering_info}")
        self.right_label.configure(text=f"{enemy_rendering_info}")

        for cur_idx, cur_move in enumerate(self.move_list):
            column_idx = cur_idx
            if column_idx >= 4:
                column_idx += 1

            if self._controller.get_move_info(cur_move._mon_idx, cur_move._move_idx, cur_move._is_player_mon) is not None:
                cur_move.grid(row=1, column=column_idx, sticky=tk.NSEW)
            else:
                cur_move.grid_forget()

            cur_move.update_rendering()

class DamageSummary(ttk.Frame):
    def __init__(self, controller:BattleSummaryController, mon_idx, move_idx, is_player_mon, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._controller = controller
        self._mon_idx = mon_idx
        self._move_idx = move_idx
        self._is_player_mon = is_player_mon
        self._move_name = None
        self._is_loading = False

        self.columnconfigure(0, weight=1)

        self.padx = 2
        self.pady = 0
        self.row_idx = 0

        self.header = ttk.Frame(self, style="Primary.TFrame")
        self.header.grid(row=self.row_idx, column=0, sticky=tk.NSEW, padx=self.padx, pady=self.pady)
        self.header.columnconfigure(0, weight=1)
        self.row_idx += 1

        self.move_name_label = ttk.Label(self.header, style="BattleMovePrimary.TLabel")
        self.custom_data_dropdown = custom_components.SimpleOptionMenu(self.header, [""], callback=self._custom_data_callback, width=14)

        self.range_frame = ttk.Frame(self, style="Contrast.TFrame")
        self.range_frame.grid(row=self.row_idx, column=0, sticky=tk.NSEW, padx=self.padx, pady=self.pady)
        self.range_frame.columnconfigure(0, weight=1)
        self.row_idx += 1

        self.damage_range = ttk.Label(self.range_frame, style="Contrast.TLabel")
        self.damage_range.grid(row=0, column=0, sticky=tk.W)
        self.pct_damage_range = ttk.Label(self.range_frame, style="Contrast.TLabel")
        self.pct_damage_range.grid(row=0, column=1, sticky=tk.E)
        self.crit_damage_range = ttk.Label(self.range_frame, style="Contrast.TLabel")
        self.crit_damage_range.grid(row=1, column=0, sticky=tk.W)
        self.crit_pct_damage_range = ttk.Label(self.range_frame, style="Contrast.TLabel")
        self.crit_pct_damage_range.grid(row=1, column=1, sticky=tk.E)

        self.kill_frame = ttk.Frame(self, style="Secondary.TFrame")
        self.kill_frame.grid(row=self.row_idx, column=0, sticky=tk.NSEW, padx=self.padx, pady=self.pady)
        self.rowconfigure(self.row_idx, weight=1)
        self.row_idx += 1

        self.num_to_kill = ttk.Label(self.kill_frame, justify=tk.LEFT, style="Secondary.TLabel")
        self.num_to_kill.grid(row=0, column=0, sticky=tk.NSEW)

    def flag_as_best_move(self):
        if self._is_player_mon:
            style = "Success"
        else:
            style = "Failure"

        self.kill_frame.configure(style=f"{style}.TFrame")
        self.num_to_kill.configure(style=f"{style}.TLabel")

    def unflag_as_best_move(self):
        self.kill_frame.configure(style="Secondary.TFrame")
        self.num_to_kill.configure(style="Secondary.TLabel")

    def _custom_data_callback(self, *args, **kwargs):
        if self._is_loading:
            return
        if self._move_name == const.MIMIC_MOVE_NAME:
            self._controller.update_mimic_selection(self.custom_data_dropdown.get())
        else:
            self._controller.update_custom_move_data(self._mon_idx, self._move_idx, self._is_player_mon, self.custom_data_dropdown.get())

    @staticmethod
    def format_message(kill_info):
        kill_pct = kill_info[1]
        if kill_pct == -1:
            if config.do_ignore_accuracy():
                return f"{kill_info[0]}-hit kill: 100 %"
            else:
                return f"{kill_info[0]}-hit kill, IGNORING ACC"
        if config.do_ignore_accuracy():
            return f"{kill_info[0]}-hit kill: {kill_pct:.2f} %"
        return f"{kill_info[0]}-turn kill: {kill_pct:.2f} %"

    def update_rendering(self):
        move = self._controller.get_move_info(self._mon_idx, self._move_idx, self._is_player_mon)
        self._move_name = None if move is None else move.name

        self._is_loading = True
        if move is None or not move.is_best_move:
            self.unflag_as_best_move()
        else:
            self.flag_as_best_move()

        custom_data_options = None
        custom_data_selection = None
        if move is not None:
            custom_data_options = move.custom_data_options
            custom_data_selection = move.custom_data_selection
        if self._move_name == const.MIMIC_MOVE_NAME:
            custom_data_options = move.mimic_options
            custom_data_selection = move.mimic_data

        if custom_data_options:
            self.move_name_label.grid_forget()
            self.move_name_label.grid(row=0, column=0)
            self.custom_data_dropdown.grid(row=0, column=1)
            self.custom_data_dropdown.new_values(custom_data_options, default_val=custom_data_selection)
        else:
            self.move_name_label.grid_forget()
            self.move_name_label.grid(row=0, column=0, columnspan=2)
            self.custom_data_dropdown.grid_forget()

        if move is None:
            self.move_name_label.configure(text="")
            self.damage_range.configure(text="")
            self.pct_damage_range.configure(text="")
            self.crit_damage_range.configure(text="")
            self.crit_pct_damage_range.configure(text="")
        else:
            self.move_name_label.configure(text=f"{move.name}")
            if move.damage_ranges is None:
                self.damage_range.configure(text="")
                self.pct_damage_range.configure(text="")
                self.crit_damage_range.configure(text="")
                self.crit_pct_damage_range.configure(text="")

            else:
                self.damage_range.configure(text=f"{move.damage_ranges.min_damage} - {move.damage_ranges.max_damage}")
                pct_min_damage = f"{move.damage_ranges.min_damage / move.defending_mon_hp * 100:.2f}%"
                pct_max_damage = f"{move.damage_ranges.max_damage / move.defending_mon_hp * 100:.2f}%"
                self.pct_damage_range.configure(text=f"{pct_min_damage} - {pct_max_damage}")

                self.crit_damage_range.configure(text=f"{move.crit_damage_ranges.min_damage} - {move.crit_damage_ranges.max_damage}")
                crit_pct_min_damage = f"{move.crit_damage_ranges.min_damage / move.defending_mon_hp * 100:.2f}%"
                crit_pct_max_damage = f"{move.crit_damage_ranges.max_damage / move.defending_mon_hp * 100:.2f}%"
                self.crit_pct_damage_range.configure(text=f"{crit_pct_min_damage} - {crit_pct_max_damage}")

            max_num_messages = 3
            kill_ranges = move.kill_ranges
            if len(kill_ranges) > max_num_messages:
                kill_ranges = kill_ranges[:max_num_messages - 1] + [kill_ranges[-1]]

            kill_ranges = [self.format_message(x) for x in kill_ranges]
            self.num_to_kill.configure(text="\n".join(kill_ranges))

        self._is_loading = False


def tokenize(s):
    s = s.replace(" ", "")
    return list(s)

class LLParser_V1:
    def __init__(self):
        self.lookahead = None
        self.tokens = None

    def error(self, code=0):
        MESSAGES = {
            0: "General Error",
            1: "Wrong LA for S rule"

        }
        message = MESSAGES[code] if code in MESSAGES.keys() else MESSAGES[0]
        message = f"{message} | LA:{self.lookahead} | TOKENS: {self.tokens}"
        raise Exception(message)

    def parse(self, s):
        self.tokens = tokenize(s)
        self.lookahead = self.tokens.pop(0)
        self.S()
        return True

    def consume(self, token):
        if token == self.lookahead:
            if len(self.tokens) > 0:
                self.lookahead = self.tokens.pop(0)
            else:
                self.lookahead = None
                self.tokens = None
        else:
            self.error(0)

    def S(self):
        if self.lookahead in ['a', '(']:
            self.E()
            self.consume('#')
        else:
            self.error(1)

    def E(self):
        if self.lookahead in ['a', '(']:
            self.T()
            self.X()
        else:
            self.error(2)

    def T(self):
        if self.lookahead in ['a']:
            self.consume('a')
        elif self.lookahead in ['(']:
            self.consume('(')
            self.E()
            self.consume(')')
        else:
            self.error(3)

    def X(self):
        if self.lookahead in ['+']:
            self.Z()
        elif self.lookahead in [')', '#']:
            pass
        else:
            self.error(4)

    def Z(self):
        if self.lookahead in ['+']:
            self.consume('+')
            self.T()
            self.X()
        else:
            self.error(5)

class Node:
    def __init__(self, ntype="node", value=None, children=None):
        self.ntype = ntype
        self.value = value
        self.children = children

    def repr(self, n=0):
        self_repr = f"{self.ntype}"
        if self.value is not None:
            self_repr = f"{self_repr} : {self.value}"
        if self.children is not None:
            children_repr = ''.join(f"\n{' ' * (n + 1)}{x.repr(n + 1)}" for x in self.children)
            self_repr = f"{self_repr}{children_repr}"
        return self_repr

    def __repr__(self):
        return self.repr()

    #
    #   BUG!
    #
    def eval(self):

        result = ''
        if self.ntype == 'term' and self.value == 'a':
            return '1'
        elif self.ntype == 'term' and self.value == '+':
            return '+'
        elif self.ntype == 'term' and self.value == '#':
            return ''
        elif self.ntype in 'SEXZ':
            esquerda = self.children[0].eval()
            try:
                direita = self.children[1].eval()
            except:
                direita = ''
            result = esquerda + direita

        # result é a string recontruida com a a tomar os valor de 1
        self.value = eval(result)
        return result

class LLParser:
    def __init__(self):
        self.lookahead = None
        self.tokens = None

    def error(self, code=0):
        MESSAGES = {
            0: "General Error",
            1: "Wrong LA for S rule"

        }
        message = MESSAGES[code] if code in MESSAGES.keys() else MESSAGES[0]
        message = f"{message} | LA:{self.lookahead} | TOKENS: {self.tokens}"
        raise Exception(message)

    def parse(self, s):
        self.tokens = tokenize(s)
        self.lookahead = self.tokens.pop(0)
        return self.S()

    def consume(self, token):
        if token == self.lookahead:
            if len(self.tokens) > 0:
                self.lookahead = self.tokens.pop(0)
            else:
                self.lookahead = None
                self.tokens = None
        else:
            self.error(0)

    def S(self):
        if self.lookahead in ['a', '(']:
            e = self.E()
            self.consume('#')
            return Node(ntype="S", children=[e, Node(ntype="term", value='#')])
        else:
            self.error(1)

    def E(self):
        if self.lookahead in ['a', '(']:
            t = self.T()
            x = self.X(t)
            return Node(ntype="E", children=[x])
        else:
            self.error(2)

    def T(self):
        if self.lookahead in ['a']:
            self.consume('a')
            return Node(ntype="term", value='a')
        elif self.lookahead in ['(']:
            self.consume('(')
            e = self.E()
            self.consume(')')
            return Node(
                ntype="T",
                children=[
                    Node(ntype='term', value='('),
                    e,
                    Node(ntype='term', value=')')])
        else:
            self.error(3)

    def X(self, t):
        if self.lookahead in ['+']:
            z = self.Z()
            return Node(ntype="X", children=[t, z])
        elif self.lookahead in [')', '#']:
            return Node(ntype="X", children=[t])
        else:
            self.error(4)

    def Z(self):
        if self.lookahead in ['+']:
            self.consume('+')
            t = self.T()
            x = self.X(t)
            return Node(ntype="Z", children=[Node(ntype="term", value="+"), x])
        else:
            self.error(5)

s = "a+a#"
parser = LLParser()
ir = parser.parse(s)
print(ir)
ir.eval()
print(ir.value)


# Define your model
import matplotlib.pyplot as plt
import pandas as pd
import torch

from cam_tools import *
from d2l import *
from dp.model import *

#加载模型
model_path = r"D:\all_code\cam_code\model\3.pt"
model = ResNet(in_channels=6, classes=3)
model.load_state_dict(torch.load(model_path))
model.eval()

#加载数据
IMU_data=get_test_data(r"D:\all_code\cam_code\data\test1","1x_0")
print(IMU_data.shape)
start=3
IMU_data=IMU_data[:,int(start*500):int(start*500+1024)]
input_tensor=torch.Tensor(IMU_data)

#获取最后一个全连接层的参数

    # 获取模型的所有参数
params = model.parameters()
    # 将参数列表转换为一个可迭代的列表
param_list = list(params)
    # 获取倒数第二层的参数
last_layer_params = param_list[-2]
print(last_layer_params.shape)

#获取网路最后一个卷积层的输出
    # 定义一个列表来保存最后一层卷积层的输出结果
last_conv_output = []
    # 定义一个钩子函数来获取最后一层卷积层的输出结果
def get_last_conv_output(module, input, output):
    last_conv_output.append(output)
    # 获取最后一层卷积层
last_conv_layer=model.features[-2].layer[6]
    # 将钩子函数附加到最后一层卷积层上
hook = last_conv_layer.register_forward_hook(get_last_conv_output)

#获取cam
out = model(input_tensor.unsqueeze(0))
print(out)
print(last_conv_output[-1].shape)
result=get_cam_1D(last_layer_params,last_conv_output[-1],out)
print(result.shape)
print(result)
print(type(result))
plt.plot(IMU_data[0])
plt.show()

import seaborn as sns
result0=pd.DataFrame(result[0].reshape(1,-1))
print(result0.shape)
sns.heatmap(result0, cmap='coolwarm',cbar=False)
plt.show()
# 绘制第二个子图
result1=pd.DataFrame(result[1].reshape(1,-1))
sns.heatmap(result1, cmap='coolwarm',cbar=False)
plt.show()
# 绘制第二个子图
result2=pd.DataFrame(result[2].reshape(1,-1))
sns.heatmap(result2, cmap='coolwarm',cbar=False)
plt.show()
result=pd.DataFrame(result)
sns.heatmap(result, cmap='coolwarm',cbar=False)
plt.show()

print(result0,result1,result0+result1)


from functional import *
from interface import start
import os
os.system('cls')

def clear_console():
    os.system('cls')

path = "phone_book.txt"

start()
actions = {"1": "вывод контактов", "2": "добавление контакта", "3": "поиск", "4": "редактирование", "5": "удаление", "q": "назад"}
action = None

while action != "q":
    print( *[f"{i} - {actions[i]}" for i in actions])
    print()
    action = input("выберите действие? ")
    clear_console()
    if action != "q":
        if action == "1":
            print('\n'*2)
            print("               Cписок контактов : ")
            print('            ======================')
            print_records(path)
        elif action == "2":
            input_records(path)
        elif action == "3":
            find_records(path, *find_char())
        elif action == "4":
            change_records(path)
        elif action == "5":
            delete_records(path)
        else:
            print('Данный параметр неиспользуется')
        print()


#
# @lc app=leetcode.cn id=2 lang=python3
#
# [2] 两数相加
#
# https://leetcode-cn.com/problems/add-two-numbers/description/
#
# algorithms
# Medium (35.49%)
# Likes:    2959
# Dislikes: 0
# Total Accepted:    195.7K
# Total Submissions: 551.4K
# Testcase Example:  '[2,4,3]\n[5,6,4]'
#
# 给出两个 非空 的链表用来表示两个非负的整数。其中，它们各自的位数是按照 逆序 的方式存储的，并且它们的每个节点只能存储 一位 数字。
#
# 如果，我们将这两个数相加起来，则会返回一个新的链表来表示它们的和。
#
# 您可以假设除了数字 0 之外，这两个数都不会以 0 开头。
#
# 示例：
#
# 输入：(2 -> 4 -> 3) + (5 -> 6 -> 4)
# 输出：7 -> 0 -> 8
# 原因：342 + 465 = 807
#
#
#
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        i, j, value = 0, 0, 0
        while l1.next is not None:
            value += pow(10, i) * l1.val
            l1 = l1.next
            i += 1
        value += pow(10, i) * l1.val

        while l2.next is not None:
            value += pow(10, j) * l2.val
            l2 = l2.next
            j += 1
        value += pow(10, j) * l2.val

        value_bit = []
        if value == 0:
            value_bit = [0]
        elif value > 0:
            m = value
            while m != 0:
                value_bit.append(m % 10)
                m //= 10
            value_bit.reverse()
        node = None
        l = None
        for b in value_bit:
            l = ListNode(b)
            l.next = node
            node = l
        return l


import sys
def teszt(sikeres_teszt):
    sorszam = sys._getframe(1).f_lineno
    if sikeres_teszt:
        msg = "A(z){0}. sorban álló teszt sikeres.".format(sorszam)
    else:
        msg = ("A(z){0}. sorban álló teszt SIKERTELEN.".format(sorszam))
    print(msg)
def abszolut_ertek(n):
    if n < 0:
        return 1
    elif n > 0:
        return n
#1 Feladat
n=input("Írj be egy égtáj rövidítését:")
def fordulj_orjarasi_iranyaba(sky):
    if sky=="É":
        print("K")
        return sky
    elif sky == "Ny":
        print("É")
        return sky
    elif sky == "D":
        print("Ny")
        return sky
    elif sky == "K":
        print("D")
        return sky
    elif sky == int:
        sky == None
        return sky
teszt(fordulj_orjarasi_iranyaba(n)== n or fordulj_orjarasi_iranyaba(n)!=n)

#2 Feladat
a = int(input("Írj be egy számot 0-6-ig:"))
def nap_nev(a):
    if a == 0:
        a = "Hétfő"
        print("Hétfői Nap")
        return a
    elif a == 1:
        a = "Kedd"
        print("Keddi Nap")
        return a
    elif a == 2:
        a = "Szerda"
        print("Szerdai Nap")
        return a
    elif a == 3:
        a = "Csütörtök"
        print("Csütörtöki Nap")
        return a
    elif a == 4:
        a = "Péntek"
        print("Pénteki Nap")
        return a
    elif a == 5:
        a = "Szombat"
        print("Szombati Nap")
    elif a == 6:
        a = "Vasárnap"
        print("Vasárnapi nap")
        return a


import json
import urllib.request as ur
import urllib.parse as up

serviceurl = 'http://py4e-data.dr-chuck.net/json?'
api_key = 42

while True:
    address = input('Enter location: ')
    if len(address) < 1: break

    param = dict()
    param['sensor'] = 'false'
    param['address'] = address
    param['key'] = api_key
    url = serviceurl + up.urlencode(param)

    print ('Retrieving ',url)
    url_handle = ur.urlopen(url)
    data = url_handle.read()

    print ('Retrieved',len(data),'characters')

    try:
        js = json.loads(data)
    except:
        js = None

    if not js or 'status' not in js or js['status'] != 'OK':
        print('==== Failure To Retrieve ====')
        print(data)
        continue

    #print(json.dumps(js, indent=4))

    #lat = js['results'][0]['geometry']['location']['lat']
    #lng = js['results'][0]['geometry']['location']['lng']
    #print('lat', lat, 'lng', lng)

    #location = js['results'][0]['formatted_address']
    #print(location)

    print ('Place id',js['results'][0]['place_id'])

#Sample output
#Enter location: UIUC
#Retrieving  http://py4e-data.dr-chuck.net/json?sensor=false&address=UIUC&key=42
#Retrieved 1654 characters
#Place id ChIJ6VUmqSTXDIgR-iZoBCUFPKU
#Enter location:


"""
From: https://pytorch.org/tutorials/beginner/text_sentiment_ngrams_tutorial.html
"""

import time
import os

import torch
from torch import optim
from torch.utils.data import DataLoader
import torch.nn as nn
from torchtext.datasets import text_classification
from torch.utils.data.dataset import random_split

from src.ml_helper.training import (
    register_model_in_db, register_epoch_in_db,
    hash_parameters, delete_model
)

BATCH_SIZE = 16
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

class TextSentiment(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_class):
        super().__init__()
        self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=True)
        self.fc = nn.Linear(embed_dim, num_class)
        self.init_weights()

    def init_weights(self):
        initrange = 0.5
        self.embedding.weight.data.uniform_(-initrange, initrange)
        self.fc.weight.data.uniform_(-initrange, initrange)
        self.fc.bias.data.zero_()

    def forward(self, text, offsets):
        embedded = self.embedding(text, offsets)
        return self.fc(embedded)

def generate_batch(batch):
    label = torch.tensor([entry[0] for entry in batch])
    text = [entry[1] for entry in batch]
    offsets = [0] + [len(entry) for entry in text]
    # torch.Tensor.cumsum returns the cumulative sum
    # of elements in the dimension dim.
    # torch.Tensor([1.0, 2.0, 3.0]).cumsum(dim=0)

    offsets = torch.tensor(offsets[:-1]).cumsum(dim=0)
    text = torch.cat(text)

    return text, offsets, label

def train_func(model, optimizer, criterion, scheduler, sub_train_):

    # Train the model
    train_loss = 0
    train_acc = 0
    data = DataLoader(
        sub_train_,
        batch_size=BATCH_SIZE,
        shuffle=True,
        collate_fn=generate_batch
    )

    for i, (text, offsets, cls) in enumerate(data):
        optimizer.zero_grad()
        text, offsets, cls = text.to(device), offsets.to(device), cls.to(device)
        output = model(text, offsets)
        loss = criterion(output, cls)
        train_loss += loss.item()
        loss.backward()
        optimizer.step()
        train_acc += (output.argmax(1) == cls).sum().item()

    # Adjust the learning rate
    scheduler.step()

    return train_loss / len(sub_train_), train_acc / len(sub_train_)

def test(model, criterion, data_):
    loss = 0
    acc = 0
    data = DataLoader(data_, batch_size=BATCH_SIZE, collate_fn=generate_batch)
    for text, offsets, cls in data:
        text, offsets, cls = text.to(device), offsets.to(device), cls.to(device)
        with torch.no_grad():
            output = model(text, offsets)
            loss = criterion(output, cls)
            loss += loss.item()
            acc += (output.argmax(1) == cls).sum().item()

    return loss / len(data_), acc / len(data_)

def main():
    if not os.path.isdir('./.data'):
        os.mkdir('./.data')

    train_dataset, test_dataset = text_classification.DATASETS['AG_NEWS'](
        root='./.data',
        ngrams=2,
        vocab=None
    )

    VOCAB_SIZE = len(train_dataset.get_vocab())
    NUN_CLASS = len(train_dataset.get_labels())

    params = dict(
        embed_dim=32,
        n_epochs=5,
        lr=0.04,
        model_name="TextSentiment",
        optimizer_name="SGD"
    )

    model_id = hash_parameters(params)
    delete_model(model_id)
    register_model_in_db(model_id, params)
    print("stored model id:", model_id)

    model = TextSentiment(
        VOCAB_SIZE,
        params["embed_dim"],
        NUN_CLASS
    ).to(device)

    criterion = torch.nn.CrossEntropyLoss().to(device)
    optimizer = getattr(optim, params["optimizer_name"])(model.parameters(), lr=params["lr"])
    scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1, gamma=0.9)

    train_len = int(len(train_dataset) * 0.95)
    sub_train_, sub_valid_ = random_split(
        train_dataset,
        [train_len, len(train_dataset) - train_len]
    )

    for epoch in range(params["n_epochs"]):

        start_time = time.time()
        train_loss, train_acc = train_func(
            model, optimizer,
            criterion, scheduler, sub_train_
        )
        valid_loss, valid_acc = test(model, criterion, sub_valid_)

        secs = int(time.time() - start_time)
        mins = secs / 60
        secs = secs % 60

        register_epoch_in_db(
            model_id,
            epoch+1,
            training_loss=train_loss,
            eval_loss=valid_loss.item(),
            training_acc=train_acc,
            eval_acc=valid_acc
        )

        print('Epoch: %d' % (epoch + 1), " | time in %d minutes, %d seconds" % (mins, secs))
        print(f'\tLoss: {train_loss:.4f}(train)\t|\tAcc: {train_acc * 100:.1f} % (train)')
        print(f'\tLoss: {valid_loss:.4f}(valid)\t|\tAcc: {valid_acc * 100:.1f} % (valid)')

if __name__ == '__main__':
    main()


import re

class Program:

    def readFile(self, fileName):

        lineList = []

        # Read file and append each line to lineList if it has content and is not an empty line
        with open(fileName, 'r') as f:
            for line in f:
                if line not in ['\n', '\r\n']:
                    lineList.append(line.strip())

        # Pass the lineList to the program function
        self.program(lineList)

    # <program> -> program begin <statement_list> end
    def program(self, list):

        # Check if program begins with 'program', and 'begin' and ends with 'end'
        if (list[0] == 'program' and list[1]=='begin' and list[len(list) - 1]=='end'):
            # The statement before the 'END' keyword must NOT have a semicolon, so if it does, then raise an error
            if (";" in list[len(list) - 2]):
                raise SyntaxError('The program contains syntax errors.')
            del list[-1]
            del list[0:2]

            # Pass the <statement_list> portion of the code to statement_list func
            self.statement_list(list)
            return True
        else:
            # Raise exception of syntax error if <program> statement is invalid
            raise SyntaxError('The program contains syntax errors.')

    # <statement_list> -> <statement> {;<statement>}
    def statement_list(self, list):

        # Get each individual <statement> which is separated by a ';'
        listString = ' '.join(list)
        list = listString.split(';')
        # Remove any blank spaces in the list
        try:
            while True:
                list.remove('')
        except ValueError:
            pass
        # Pass each individual statement separated by a semicolon to the statement func
        for i in list:
            i = i.strip()
            self.statement(i)

    # <statement> -> <assignment_statement> | <if_statement> | <loop_statement>
    def statement(self, listString):
        list = listString.split(' ')
        # Remove any blank spaces in the list
        try:
            while True:
                list.remove('')
        except ValueError:
            pass

        list[:] = (value for value in list if value != '')
        list[:] = (value for value in list if value != ' ')

        # If the <statement> is an <if_statement>
        if (list[0] == 'if'):

            ifList = listString.split('if', 1)
            ifList[:] = (value for value in ifList if value != ' ')
            ifList[:] = (value for value in ifList if value != '')

            for i in ifList:
                if (i != ''):
                    i = i.strip()
                    self.if_statement(i)

        # If the <statement> is a <loop_statement>
        elif (list[0] == 'loop'):
            # del the 'loop' keyword
            del list[0]
            self.loop_statement(list)
        # If the <statement> is an <assignment_statement>
        else:
            self.assignment_statement(list)

    # <if_statement> -> if (<logic_expression>) then <statement>
    def if_statement(self, listString):

        if ('then' in listString):
            # Remove and split with the 'then' keyword, then remove any /n elements
            list = listString.split('then', 1)
            list[:] = (value for value in list if value != ' ')
            list[:] = (value for value in list if value != '')

            # list[0] is the (<logic_expression>) and list[1] is the <statement>
            # Check if parentheses are balanced
            if(self.parenthesesCheck(list[0])):
                # Get the content inside the parentheses and pass it to logic_expression func
                insideParentheses = list[0][list[0].find('(')+1:list[0].find(')')]
                self.logic_expression(insideParentheses)
            # Raise exception if parentheses not balanced
            else:
                raise SyntaxError('The program contains syntax errors.')

            # Get the statement content and pass it to the statement func
            self.statement(list[1])

        # Raise an exception if the 'then' keyword is absent in the <if_statement>
        else:
            raise SyntaxError('The program contains syntax errors.')

    # <loop_statement> -> loop (<logic_expression>) <statement>
    def loop_statement(self, list):
        listString = ' '.join(list)

        # Ensure parentheses are present
        if not ('(' and ')' in listString):
            raise SyntaxError('The program contains syntax errors.')

        d = ")"
        list =  [i + d for i in listString.split(d) if i]
        list[1] = list[1].replace(')','')

        # list[0] is the (<logic_expression>) and list[1] is the <statement>
        # Check if parentheses are balanced
        if(self.parenthesesCheck(list[0])):
            # Get the content inside the parentheses and pass it to logic_expression func
            insideParentheses = list[0][list[0].find('(')+1:list[0].find(')')]
            self.logic_expression(insideParentheses)
        # Raise exception if parentheses not balanced
        else:
            raise SyntaxError('The program contains syntax errors.')

        # Get the statement content and pass it to the statement func
        self.statement(list[1])

    # <assignment_statement> -> <variable> = <expression>
    def assignment_statement(self,list):
        listString = ' '.join(list)
        print(listString)
        # The statement must NOT contain ANY keywords like 'if' and 'then', because if it does then that means there was a missing semicolon for one of the statements
        if('if' in listString or 'then' in listString):
            raise SyntaxError('The program contains syntax errors.')

        if ('=' in listString):
            list = listString.split('=')
            # list[0] is the <variable> and list[1] is the <expression>
            # Send to variable func
            self.variable(list[0].strip())
            # Send to expression func
            self.expression(list[1].strip())

    # <logic_expression> -> <variable> (< | >) <variable>
    def logic_expression(self, insideParentheses):
        if('>' or '<' in insideParentheses):
            insideParentheses = insideParentheses.replace('<','>')
            list = insideParentheses.split('>')

            # Ensure there is only one occurrence of (< | >)
            if (insideParentheses.count('>') > 1):
                raise SyntaxError('The program contains syntax errors.')

            # Send the two variables to the variable func
            for i in list:
                i = i.strip()
                self.variable(i)

        else:
            raise SyntaxError('The program contains syntax errors.')

    # <expression> -> <term> { (+|-) <term>}
    def expression(self, listString):
        # We cannot include anything in brackets, example, (var2 + var1) * var3, this is only one <term> with no optional second part
        # If the expression contains brackets, AND the parentheses are valid, do NOT evaluate anything inside the brackets
        # If there are brackets, then it MUST be a single term and we can simply send the ENTIRE TERM to the term function
        if ("(" in listString or ")" in listString):
            if(self.parenthesesCheck(listString)):
                self.term(listString)
            else:
                raise SyntaxError('The program contains syntax errors.')
        # if there are no parentheses, and there is a positive or negative sign present
        elif ("-" in listString):
            list = listString.split("-")
            for i in list:
                i=i.strip()
                self.term(i)
        elif ("+" in listString):
            list = listString.split("+")

            for i in list:
                i=i.strip()
                self.term(i)
        # If there are no brackets, we can send the entire term to the term function
        else:
            self.term(listString)

    # <variable> -> identifier (An identifier is a string that begins with a letter followed by 0 or more letters and/or digits)
    def variable(self, identifier):
        # Check if the identifier is valid:
        # An identifier is a string that begins with a letter followed by 0 or more letters and/or digits
        identifierList = list(identifier)

        # Check if the first character in the text is a letter
        if (identifierList[0].isalpha()):
            for i in identifierList:
                if not (i.isalpha() or i.isdigit()):
                    raise SyntaxError('The program contains syntax errors.')
                else:
                    return True
        else:
            raise SyntaxError('The program contains syntax errors.')

    # <term> -> <factor> {(* | /) <factor> }
    def term(self, listString):

        # If the term contains a * or /
        if ("*" in listString):
            list = listString.split('*')
            for i in list:
                i=i.strip()
                self.factor(i)
        elif ("/" in listString):
            list = listString.split('/')
            for i in list:
                i=i.strip()
                self.factor(i)
        #else it is simply a <factor> so we send to factor func
        else:
            self.factor(listString)

    # <factor> -> identifier | int_constant | (<expr>)
    def factor(self, listString):
        # We have to determine if it is either an identifier, int constant or expression.
        # If the factor contains parentheses which are valid, send the content inside the parentheses to the expression func
        if ("(" in listString or ")" in listString):
            if(self.parenthesesCheck(listString)):
                insideParentheses = listString[listString.find('(')+1:listString.find(')')]
                insideParentheses=insideParentheses.strip()
                self.expression(insideParentheses)
            else:
                raise SyntaxError('The program contains syntax errors.')
        # if the factor is an int constant
        elif (listString.isdigit()):
            return
        # If the factor is not a int or expression inside parentheses, then we send to the variable function to check if it is a valid identifier.
        else:
            self.variable(listString)

    # Function returns true if parentheses are balanced, and false otherwise
    def parenthesesCheck(self, string):
        stack = []
        for i in string:
            if (i == '('):
                stack.append(i)
            elif (i ==')'):
                if ((len(stack) > 0) and ('(' == stack[len(stack)-1])):
                    stack.pop()
                else:
                    return False
        if len(stack) == 0:
            return True
        else:
            return False

def isIdentifier(identifier):
    # Check if the identifier is valid:
    # An identifier is a string that begins with a letter followed by 0 or more letters and/or digits
    identifierList = list(identifier)

    # Check if the first character in the text is a letter
    if (identifierList[0].isalpha()):
        for i in identifierList:
            if not (i.isalpha() or i.isdigit()):
                return False
        # Return true if the identifier is able to exit the for loop
        return True
    else: #If the identifier does not begin with a letter or char
        return False

#Function checks if string is a keyword of the language, such as 'if' or 'loop'
def isKeyword(operator):
    if(operator=='if' or operator=='loop' or operator=='program' or operator=='begin' or operator=='end' or operator=='then'):
        return True
    else:
        return False

# Function for tokens which returns the token value
def tokenLookup(string):

    if string.isdigit(): #Int constant
        return 10
    elif isKeyword(string): #Reserved keyword
        return 15
    elif string=='=':
        return 20
    elif string=='+':
        return 21
    elif string=='-':
        return 22
    elif string=='*':
        return 23
    elif string=='/':
        return 24
    elif string=='(':
        return 25
    elif string==')':
        return 26
    elif isIdentifier(string): #Valid variable/identifier
        return 11
    else: #-1 is returned if the string matches none of the tokens
        return -1

def lexicalAnalyzer(fileName):

    list = []

    # Read file and append each line to lineList if it has content and is not an empty line
    with open(fileName, 'r') as f:
        for line in f:
            if line not in ['\n', '\r\n']:
                list.append(line.strip())

    newList=[]
    newList = [word for line in list for word in line.split()]

    for i in newList:
        if not i.isalnum(): # If string contains non-alphanumeric chars
            li = re.split("(\W)", i)
            # Strip spaces and blanks from the list
            try:
                while True:
                    li.remove('')
            except ValueError:
                pass

            for j in li:
                str = f"Next token is: {tokenLookup(j)} Next lexeme is {j}"
                print(str)
        else:
            str = f"Next token is: {tokenLookup(i)} Next lexeme is {i}"
            print(str)

# MAIN SECTION ---------------

### FOR THE TA OR INSTRUCTOR ## If you would like to change the file name, please just alter this variable with the new file name
currentFile = 'test-program-6.txt'
### ------------------------------------------

Program().readFile(currentFile)
lexicalAnalyzer(currentFile)


__all__ = ["base_show_results"]

from icevision.imports import *
from icevision.utils import *
from icevision.core import *
from icevision.visualize import *
from icevision.data import *

def base_show_results(
    predict_fn: callable,
    build_infer_batch_fn: callable,
    model: nn.Module,
    dataset: Dataset,
    class_map: Optional[ClassMap] = None,
    num_samples: int = 6,
    ncols: int = 3,
    denormalize_fn: Optional[callable] = denormalize_imagenet,
    show: bool = True,
    **predict_kwargs,
) -> None:
    samples = random.choices(dataset, k=num_samples)
    batch, samples = build_infer_batch_fn(samples)
    preds = predict_fn(model, batch, **predict_kwargs)

    show_preds(
        samples,
        preds,
        class_map=class_map,
        denormalize_fn=denormalize_fn,
        ncols=ncols,
        show=show,
    )


import pandas as pd
import csv
lula = pd.read_csv('lula.csv')

with open('lula.csv', 'rU') as myfile:
    filtered = (line.replace('\r', '') for line in myfile)
    for row in csv.reader(filtered):
        print(row)

print(lula.head())


from code import interact
from distutils.log import error
from ssl import VerifyFlags
import discord
import random
import asyncio
import os
import json
#-----------------

os.chdir("G:\\pyApps\\SimpleEcoBot") #Setar diretório

from dotenv import load_dotenv
from discord.ui import Button, View
from discord.ext import commands

#--------------

load_dotenv()
TOKEN = os.getenv('TOKEN') #Pegar token do .env

client = discord.Client(intents=discord.Intents.all())
bot = commands.Bot(command_prefix='$',intents=discord.Intents.all())  ##Selecione prefix aqui

@bot.event #            Evento de contar servidores online
async def on_ready():
    guild_count = 0

    for guild in bot.guilds:
        guild_count =+ 1

    print(f"Conectado em {guild_count} guilds!")

#economia--------------------------------------------------------------

@bot.command(pass_context=True)
async def bal(ctx, user : discord.User = None): # Ver saldo
  if user != None:
    await open_account(user)
    users = await get_bank_data()
    id = user.id
    carteira_amt = users[str(id)]["carteira"]
    banco_amt = users[str(id)]["banco"]

    em = discord.Embed(title = f"Banco de {user.name}")
    em.add_field(name = "Saldo na Carteira: $", value = carteira_amt)
    em.add_field(name = "Saldo no Banco: $", value = banco_amt)

    await ctx.send(embed = em)
  else:
    await open_account(ctx.author)
    users = await get_bank_data()
    carteira_amt = users[str(ctx.author.id)]["carteira"]
    banco_amt = users[str(ctx.author.id)]["banco"]

    em = discord.Embed(title = f"Banco de {ctx.author.name}")
    em.add_field(name = "Saldo na Carteira: ", value = carteira_amt)
    em.add_field(name = "Saldo no Banco: ", value = banco_amt)

    await ctx.send(embed = em)

#@===============================

@bot.command()
@commands.cooldown(1, 3, commands.BucketType.user)

async def mendigar(ctx):         # Ganhar dinheiro
  await open_account(ctx.author)
  users = await get_bank_data()
  rng1 = random.randint(1,10)
  rng2 = random.randint(0,15)

  if rng1 == 10:
   loseamt = random.randrange(1,15)
   carteirab4 = users[str(ctx.author.id)]["carteira"]

   await ctx.send(f"**Você estava mendingando na área de outro mendigo, e ele te espancou e roubou ${int(carteirab4 / loseamt)} de você!**")

   carteira_amt = users[str(ctx.author.id)]["carteira"] = users[str(ctx.author.id)]["carteira"] - int(users[str(ctx.author.id)]["carteira"] / loseamt)

  else:
    await ctx.send(f"**Você mendigou o dia inteiro e acabou com mais ${rng2} no bolso.**")

    carteira_amt = users[str(ctx.author.id)]["carteira"] = users[str(ctx.author.id)]["carteira"] + rng2

  with open("utils\\bank.json","w") as f:
    json.dump(users,f)
  return True

#@===============================

@mendigar.error                          ## Detectar erro de cooldown e avisar o usuário
async def mendigar_error(ctx, error):
    if isinstance(error, discord.ext.commands.errors.CommandOnCooldown):
        msg1 =  await ctx.reply("*Comando em cooldown!*")
        await asyncio.sleep(1)
        await msg1.delete()
        await ctx.message.delete()

#@===============================

@bot.command()
async def dep(ctx, *, valor : int):     ## Comando de depositar (para realizar um withdraw é só inverter o comando)
  await open_account(ctx.author)
  users = await get_bank_data()
  carteira_amt = users[str(ctx.author.id)]["carteira"]
  banco_amt = users[str(ctx.author.id)]["banco"]
  if valor <= carteira_amt:
    banco_amt = users[str(ctx.author.id)]["banco"] = users[str(ctx.author.id)]["banco"] + valor
    carteira_amt = users[str(ctx.author.id)]["carteira"] = users[str(ctx.author.id)]["carteira"] - valor
    await ctx.send(f"**Você depositou ${valor}**")
  else:
    await ctx.send("**Você não tem dinheiro suficiente para depositar.**")

  with open("utils\\bank.json","w") as f:
    json.dump(users,f)
  return True

#@===============================

async def open_account(user):         ## Async de criar uma conta no bank.json se o usuário não tiver uma ainda
  users = await get_bank_data()

  if str(user.id) in users:
    return False
  else:
    users[str(user.id)] = {}
    users[str(user.id)]["carteira"] = 0
    users[str(user.id)]["banco"] = 0

  with open("utils\\bank.json","w") as f:
    json.dump(users,f)
  return True

async def get_bank_data():          ## Async de pegar dados de todos os usuários e retornar
  with open("utils\\bank.json","r") as f:
    users = json.load(f)
  return users

#------------------------------------------------------------------------------

bot.run(TOKEN) #      Run


import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import csv
from sigqc import sigqc_asciitestcase
from sigqc import sigqc_unitdata
from sigqc import sigqc_pca
from sigqc import sigqc_report

#########################################################################################################################
# ImplementPCA.py
# Austin Coleman
#
# Script to implement Principal Component Analysis in the context of SigQC data.
# Takes a file exported from SigQC, performs Principal Component Analysis, and
# writes output to a SigQC report.
#
# Example Use:
#  reference_file = "[full path here]\\Selected Good Units-Env Order-Metrics.csv"
#  storeReferenceData(reference_file, input_type='ascii', o_path="[full path here]", o_name="ReferenceData.csv")
#  refresults = "[o_path]\\[o_name]"
#  myTestFilePath = "[path to test file data]\\[test file name]"
#  implementPCA(refresults, myTestFilePath, input_type="ascii", o_file="PCA_Results_My_Test_Data", generate_report=True)
#
##########################################################################################################################

def implementPCA(i_referencefile, i_testfile, input_type="ascii", o_file="PCA_Results", generate_report=True, n_pcs=10):
    '''
    Use a reference set of eigenvectors to generate Principal Component
    Scores for each test unit within a user-specified file.

    Inputs
    ------
        i_referencefile - String containing path to output .csv file from storeReferenceData() method.
            Must contain the eigenvalues, eigenvectors, and average vector of the reference
            dataset.
        i_testfile - String containing path to test file containing units with test case
            values to be tested. It is crucial that the units are consistent through
            each test case, as test case features will all be stacked into
            one array with rows denoting units and columns denoting test case
            values for each features of that particular unit.
        i_type - (Optional) String specifying the file input type. Currently,
            the SigQC ASCII Test Case Files and SigQC Unit Data files are
            supported as "ascii" and "unit" respectively. The type defaults to
            "ascii".
        o_file - (Optional) String specifying the full path and name of the output file(s).
            Defaults to "PCA_Results". Note: This naming convention is used for both the
            generation of the SigQC Report and the PC Scores .csv file (i.e. the default
            output will be produced in the current folder with the names "PCA_Results.docx"
            and "PCA_Results.csv" respectively).
        generate_report - (Optional) Boolean describing whether or not to generate the
            SigQC report file
        n_pcs - (Optional) Number of Principal Components to be plotted.
            Default is the first 10 PCs.

    Outputs
    -------
        If generate_report is set to True, will create SigQC Report file named [o_file].docx
            containing plots of the PC Scores and save it to the path specified in o_file.
        Spreadsheet containing PC Scores for each unit as a file named [o_file].csv
        and save it to the path specified in o_file.
        This method does not explicitly return anything.
    '''
    ##################
    # Assign dataset
    ##################
    if (input_type.lower() == "ascii"):
        # Get test units...
        dataobj = sigqc_asciitestcase.SigQCAsciiTestCaseFile(i_testfile)
        headers = dataobj.getHeaders()
        serialnumbers = dataobj.getMatrixAt(0).getSerialNumbers()
        dataset = np.array(dataobj.getMatrixDataAt(0))
        for i in range(1,dataobj.getTestCaseCount()):
            dataset = np.hstack((dataset,dataobj.getMatrixDataAt(i)))
    elif (input_type.lower() == "unit"):
        dataobj = sigqc_unitdata.SigQCUnitDataFile(i_testfile)
        headers = dataobj.GetCaseNames()
        serialnumbers = dataobj.GetSerialNumbers()
        dataset = np.array(dataobj.GetCaseDataTable())
    else:
        raise Exception("Error: Please provide a valid input_type. Valid options include 'ascii' and 'unit'")

    #########################
    # Parse reference data
    #########################
    avgvec = None
    evals = None
    evecs = []
    with open(i_referencefile, 'r') as f:
        for row in f:
            if ("BEGINAVGVECTOR" in row):
                row = next(f)
                avgvec = np.array(row.split(','), dtype=float)
                while ("ENDAVGVECTOR" not in row):
                    row = next(f)
            if ("BEGINSTANDDEV" in row):
                row = next(f)
                stddev = np.array(row.split(','), dtype=float)
                while ("ENDSTANDDEV" not in row):
                    row = next(f)
            if ("ISCORRMATRIX" in row):
                row = next(f)
                corr_matrix = str(row)
                while ("ENDCORRMATRIX" not in row):
                    row = next(f)
            if ("BEGINEVALS" in row):
                row = next(f)
                evals = np.array(row.split(','), dtype=float)
                while ("ENDEVALS" not in row):
                    row = next(f)
            if ("BEGINEVECS" in row):
                row = next(f)
                while ("ENDEVECS" not in row):
                    evecs.append(np.array(row.split(','),dtype=float))
                    row = next(f)

    ###################################
    # Run PCA and finish SigQC Report
    ###################################
    pcscores = np.zeros((dataset.shape))

    # Initialize list of PC scores for boxplots
    boxplotlist = []

    # Calculate PC Scores with reference dataset as eigenvectors
    if ('True' in corr_matrix):
        pcscores = np.dot((dataset-avgvec)/stddev, evecs)
    else:
        pcscores = np.dot((dataset-avgvec), evecs)

    if (generate_report):
        report = sigqc_report.SigQCReport() # Initialize report

        # Create figures
        oname = "PCScores"
        header = headers[0].getProdName()+" PC Scores"
        sigqc_pca.plotPCScores(pcscores, header, o_name=oname, n_pcs=n_pcs)

        # Add figures to a new section of SigQC Report
        figs = []
        for j in range(n_pcs):
            figs.append(oname+str(j)+"-"+str(j+1)+".png")
            boxplotlist.append(pcscores[:,j])
        figs.append("Boxplot.png")

        sigqc_pca.plotPCBoxPlots(boxplotlist)

        # Add serial numbers
        str_serials = " , "
        str_serials = str_serials.join(serialnumbers)

        report.addSection(header+": Principal Component Boxplot", "Unit(s) Tested: "+str_serials, i_figures=figs)

        report.writeReport(o_docname=o_file)

    #######################################
    # Create .csv file with PC Scores
    #######################################

    colnames = np.arange(1,len(pcscores[0,:])+1)
    colnames = np.hstack(('Serial Number', colnames))
    tmppcscores = np.hstack((np.array(serialnumbers).reshape(len(serialnumbers),1), pcscores))
    finalpc = np.vstack((np.array(colnames).reshape(1,len(colnames)), tmppcscores))
    with open(o_file+".csv", 'w', newline='') as f:
        writer = csv.writer(f, delimiter=',')
        writer.writerows(finalpc)
    return

def storeReferenceData(i_referencefile, input_type="ascii", opath="", oname="ReferenceData.csv", corr_matrix=False):
    '''
    This method takes a file filled with reference (good) units, parses it according to the user
    specified input type, computes the eigenvalues and eigenvectors of the system, computes the
    mean vector of the set, and stores this information in an optionally user specified path and
    file name.

    Inputs
    ------
        i_referencefile - String denoting the absolute path and name of the file filled with reference
            units.
        input_type - (Optional) String that describes the file's input type which changes how the
            reference file is parsed. Currently supported options are "ascii" for a SigQC ASCII
            Test Case file or "unit" for a SigQC Unit Data file. Defaults to "ascii".
        opath - (Optional) String describing the output file path. Defaults to the current directory.
        oname - (Optional) String describing the output file name. Defaults to "ReferenceData.csv".
        corr_matrix - (Optional) Boolean specifying whether to use correlation matrix in
            eigenvector calculation instead of the covariance matrix. Defaults to false.

    Outputs
    -------
        Saves a .csv file containing the eigenvalues, eigenvectors, and mean vector of the system within
        the reference file. Output will be saved using the conventions specified with the opath and oname
        parameters.
        This method does not explicitly return anything.
    '''
    # Parse according to file type
    if (input_type.lower() == "ascii"):
        dataobj = sigqc_asciitestcase.SigQCAsciiTestCaseFile(i_referencefile)
        dataset = np.array(dataobj.getMatrixDataAt(0))
        for i in range(1,dataobj.getTestCaseCount()):
            dataset = np.hstack((dataset, dataobj.getMatrixDataAt(i)))
        avgvector = np.mean(dataset, axis=0)
        stddev = np.std(dataset, axis=0)
    elif (input_type.lower() == "unit"):
        dataobj = sigqc_unitdata.SigQCUnitDataFile(i_referencefile)
        dataset = np.array(dataobj.GetCaseDataTable())
        avgvector = np.mean(dataset, axis=0)
        stddev = np.std(dataset, axis=0)
    else:
        raise Exception("Error: Please provide a valid input_type. Valid options include 'ascii' and 'unit'")

    # Calculate eigenvalues and eigenvectors on covariance (or correlation) matrix
    cov_matrix = sigqc_pca.getCovariance(dataset, center_around_mean=True, scale_by_nrows=True, corr_matrix=corr_matrix)
    evals, evecs = sigqc_pca.getEigen(cov_matrix)

    # Store eigenvalues, eigenvectors, and average vector
    with open(opath+oname, 'w', newline='') as f:
        writer = csv.writer(f, delimiter=",")
        writer.writerow(["BEGINAVGVECTOR"])
        writer.writerow(avgvector)
        writer.writerow(["ENDAVGVECTOR"])
        writer.writerow(["BEGINSTANDDEV"])
        writer.writerow(stddev)
        writer.writerow(["ENDSTANDDEV"])
        writer.writerow(["ISCORRMATRIX"])
        writer.writerow([str(corr_matrix)])
        writer.writerow(["ENDCORRMATRIX"])
        writer.writerow(["BEGINEVALS"])
        writer.writerow(evals)
        writer.writerow(["ENDEVALS"])
        writer.writerow(["BEGINEVECS"])
        writer.writerows(evecs)
        writer.writerow(["ENDEVECS"])
    return


import os
import urllib.parse

from prefect.environments.storage import Docker
from prefect.environments import DaskKubernetesEnvironment
from prefect import Flow, task
import pandas as pd

def score_check(grade, subject, student):
    """
    This is a normal "business logic" function which is not a Prefect task.
    If a student achieved a score > 90, multiply it by 2 for their effort! But only if the subject is not NULL.
    :param grade: number of points on an exam
    :param subject: school subject
    :param student: name of the student
    :return: final nr of points
    """
    if pd.notnull(subject) and grade > 90:
        new_grade = grade * 2
        print(
            f"Doubled score: {new_grade}, Subject: {subject}, Student name: {student}"
        )
        return new_grade
    else:
        return grade

@task
def extract():
    """ Return a dataframe with students and their grades"""
    data = {
        "Name": [
            "Hermione",
            "Hermione",
            "Hermione",
            "Hermione",
            "Hermione",
            "Ron",
            "Ron",
            "Ron",
            "Ron",
            "Ron",
            "Harry",
            "Harry",
            "Harry",
            "Harry",
            "Harry",
        ],
        "Age": [12] * 15,
        "Subject": [
            "History of Magic",
            "Dark Arts",
            "Potions",
            "Flying",
            None,
            "History of Magic",
            "Dark Arts",
            "Potions",
            "Flying",
            None,
            "History of Magic",
            "Dark Arts",
            "Potions",
            "Flying",
            None,
        ],
        "Score": [100, 100, 100, 68, 99, 45, 53, 39, 87, 99, 67, 86, 37, 100, 99],
    }

    df = pd.DataFrame(data)
    return df

@task(log_stdout=True)
def transform(x):
    x["New_Score"] = x.apply(
        lambda row: score_check(
            grade=row["Score"], subject=row["Subject"], student=row["Name"]
        ),
        axis=1,
    )
    return x

@task(log_stdout=True)
def load(y):
    old = y["Score"].tolist()
    new = y["New_Score"].tolist()
    print(f"ETL finished. Old scores: {old}. New scores: {new}")

flow = Flow(
    "etl-flow",
    storage=Docker(
        "tomaugspurger",
        python_dependencies=[
            "pandas==1.1.0",
            "dask-kubernetes",
            "dask==2.25.0",
            "distributed==2.25.0",
        ],
        image_tag="latest",
    ),
    environment=DaskKubernetesEnvironment(min_workers=1, max_workers=3),
)
with flow:
    extracted_df = extract()
    transformed_df = transform(extracted_df)
    load(transformed_df)

if __name__ == "__main__":
    flow.register(project_name="pangeo-forge")


import os
import sys
import yaml

sys.path.append("..")
sys.path.append("../..")
import base64
import traceback
import argparse
from typing import List

from flask import Flask, render_template, jsonify
from flask_cors import CORS

from errudite.server.converter import \
    ListConverter, IntConverter, StrConverter, IntListConverter, \
    BoolConverter, InstanceKeyConverter, InstanceKeyListConverter
from errudite.server.api import API, APIQA, APIVQA
from errudite.rewrites import Rewrite
from errudite.builts import Attribute, Group
from errudite.targets.interfaces import InstanceKey
from errudite.targets.instance import Instance

import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)  # pylint: disable=invalid-name
global api
api = None

app = Flask(__name__)
cors = CORS(app, resources={r"*": {"origins": "*"}})
app.config['SECRET_KEY'] = 'secret!'
app.url_map.converters['list'] = ListConverter
app.url_map.converters['int_list'] = IntListConverter
app.url_map.converters['str_list'] = ListConverter
app.url_map.converters['int'] = IntConverter
app.url_map.converters['str'] = StrConverter
app.url_map.converters['bool'] = BoolConverter
app.url_map.converters['instance_key'] = InstanceKeyConverter
app.url_map.converters['instance_key_list'] = InstanceKeyListConverter

SUCCESS_MSG = "successful query!"

def get_args():
    """Get the user arguments
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('--config_file',
        required=True,
        help='the configuration file required.')
    args = parser.parse_args()
    return args

args = get_args()
try:
    with open(args.config_file) as f:
        configs = yaml.safe_load(f)
    logger.info(configs)
    # construct the API
    API_CONSTRUCTOR =  API.by_name(configs["task"])
    api = API_CONSTRUCTOR(
        cache_path=configs["cache_path"],
        model_metas=configs["model_metas"],
        attr_file_name=configs["attr_file_name"],
        group_file_name=configs["group_file_name"],
        rewrite_file_name=configs["rewrite_file_name"]
    )
except Exception as e:
    api = None
    traceback.print_exc()
    logger.error(e)

def wrap_output(o, msg=None):
    if msg:
        msg = f'ERR! {msg}'
    else:
        msg = SUCCESS_MSG
    return jsonify({ "output" : o, "msg": msg })

@app.route('/')
def index():
    print(type(api))
    return render_template('index.html')

@app.route('/api/get_task')
def get_task(api: API=api):
    output, msg = None, None
    try:
        output = api.task
        msg = None
    except Exception as e:
        msg = f'{e}'
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/get_img/<img_id>')
def get_img(img_id: str, api: API=api):
    """Get the image"""
    # TODO: understand how to set the folder.
    VQA_FOLDER = ""
    output, msg = None, None
    try:
        imgFilename = 'COCO_val2014_' + str(img_id).zfill(12) + '.jpg'
        img_dir = os.path.join(VQA_FOLDER, 'Images', imgFilename)
        with open(img_dir, 'rb') as f:
            output = base64.b64encode(f.read())
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/get_meta_data')
def get_meta_data(api: API=api):
    output, msg = None, None
    try:
        err_overlaps =api.get_err_overlap(show_filtered_err_overlap=False)
        e_serialized = [ e.serialize() for e in Rewrite.values() ]
        groups = [ g.serialize() for g in Group.values() ]
        attrs = [ a.serialize() for a in Attribute.values() ]
        predictors = [ p.serialize() for p in api.predictors.values() ]
        output = {
            'total_size': len(Instance.qid_hash),
            'anchor_predictor': api.get_anchor_predictor(),
            'compare_predictor': api.get_compare_predictor(),
            'selected_rewrite': api.get_selected_rewrite(),
            'predictors': predictors,
            'attributes': attrs,
            'groups': groups,
            'err_overlaps': err_overlaps,
            'rewrites': e_serialized
        }
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/set_anchor_predictor/<model>')
def set_anchor_predictor(model: str, api: API=api):
    output, msg = None, None
    try:
        api.set_anchor_predictor(model)
        return get_meta_data(api)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
        return wrap_output(output, msg)

@app.route('/api/set_compare_predictor/<model>')
def set_compare_predictor(model: str, api: API=api):
    output, msg = None, None
    try:
        api.set_compare_predictor(model)
        output = {
            'compare_predictor': api.get_compare_predictor(),
            'err_overlaps': api.get_err_overlap(),
        }
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

inputs_sample_instances = [
    "str:selected_predictor",
    "str:cmd",
    "str:sample_method",
    "str:sample_rewrite",
    "int:sample_size",
    "int:test_size",
    "bool:show_filtered_arr",
    "bool:show_filtered_err_overlap",
    "bool:show_filtered_group",
    "bool:show_filtered_rewrite",
    "str_list:qids",
]
@app.route('/api/sample_instances')
@app.route('/api/sample_instances/<bool:selected_predictor>')
@app.route('/api/sample_instances/' + '/'.join([f'<{i}>' for i in inputs_sample_instances]))
def sample_instances(
        selected_predictor: str=None,
        cmd: str='',
        sample_method: str="rand",
        sample_rewrite: str=None,
        sample_size: int=10,
        test_size: int=None,
        show_filtered_arr: bool=False,
        show_filtered_err_overlap: bool=False,
        show_filtered_group: bool=False,
        show_filtered_rewrite: bool=False,
        qids: List[str]=None,
        api: API=api):
    output, msg = None, None
    try:
        data = api.sample_instances(
            selected_predictor, cmd, sample_method,
            sample_rewrite, sample_size, test_size,
            show_filtered_arr,
            show_filtered_err_overlap,
            show_filtered_group,
            show_filtered_rewrite,
            qids)
        output = {
            'attrs': data['attrs'],
            'rewrites': data['rewrites'],
            'groups': data['groups'],
            'err_overlaps': data['err_overlaps'],
            'sample_cache_idx': data['sample_cache_idx'],
            'sampled_keys': data['sampled_keys'],
            'info': data['info'],
            'questions': [q.serialize() for q in data['questions']],
            'contexts': [p.serialize() for p in data['contexts']],
            'answers': [a.serialize() for a in data['answers']],
        }
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/get_more_samples/<int:direction>')
@app.route('/api/get_more_samples/<int:direction>/<int:sample_size>')
def get_more_samples(direction: int, sample_size: int=10, api: API=api):
    output, msg = None, None
    try:
        data = api.get_more_samples(direction, sample_size)
        output = {
            'sample_cache_idx': data['sample_cache_idx'],
            'sampled_keys': data['sampled_keys'],
            'questions': [q.serialize() for q in data['questions']],
            'contexts': [p.serialize() for p in data['contexts']],
            'answers': [a.serialize() for a in data['answers']],
        }
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/create_built/<str:name>/<str:description>/<str:cmd>/<str:built_type>')
def creat_built(name: str, description: str, cmd: str, built_type: str, api: API=api):
    output, msg = None, None
    try:
        if built_type == 'group':
            built = Group.create(
                name, description, cmd,
                attr_hash=Attribute.store_hash(), group_hash=Group.store_hash())
        else:
            built = Attribute.create(
                name, description, cmd,
                attr_hash=Attribute.store_hash(), group_hash=Group.store_hash())
        output = built.serialize()
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/create_rewrite/<str:from_cmd>/<str:to_cmd>/<str:target_cmd>')
def create_rewrite(from_cmd: str, to_cmd: str, target_cmd: str, api: API=api):
    output, msg = None, None
    try:
        rewrite = api.create_rewrite(from_cmd, to_cmd, target_cmd)
        output = rewrite.serialize()
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/delete_built/<str:name>/<str:built_type>')
def delete_built(name: str, built_type: str, api: API=api):
    output, msg = None, None
    try:
        output = api.delete_built(name, built_type)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/export_built/<str:file_name>/<str:built_type>')
def export_built(file_name: str, built_type: str, api: API=api):
    output, msg = None, None
    try:
        output = api.export_built(file_name, built_type)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/get_one_attr_of_instances/<str:attr_name>/<instance_key_list:instance_keys>')
def get_one_attr_of_instances(attr_name: str, instance_keys: List[InstanceKey], api: API=api):
    output, msg = None, None
    try:
        output = api.get_one_attr_of_instances(attr_name, instance_keys)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/get_groups_of_instances/<instance_key_list:instance_keys>')
def get_groups_of_instances(instance_keys: List[InstanceKey], api: API=api):
    output, msg = None, None
    try:
        output = api.get_groups_of_instances(instance_keys)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)
@app.route('/api/get_rewrites_of_instances/<instance_key_list:instance_keys>')
def get_rewrites_of_instances(instance_keys: List[InstanceKey], api: API=api):
    output, msg = None, None
    try:
        output = api.get_rewrites_of_instances(instance_keys)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

inputs_attr_distribution = [
    "str_list:attr_names",
    "str:filter_cmd",
    "bool:use_sampled_data",
    "str:include_rewrite",
    "str:include_model",
    "int:test_size"
]
@app.route('/api/get_attr_distribution/' + '/'.join([f'<{i}>' for i in inputs_attr_distribution[:1] ]))
@app.route('/api/get_attr_distribution/' + '/'.join([f'<{i}>' for i in inputs_attr_distribution]))
def get_attr_distribution(
    attr_names: List[str],
    filter_cmd: str='',
    use_sampled_data: bool=False,
    include_rewrite: str=None,
    include_model: str=None,
    test_size: int=None,
    api: API=api):
    output, msg = None, None
    try:
        output = api.get_attr_distribution(
            attr_names=attr_names,
            filter_cmd=filter_cmd,
            test_size=test_size,
            use_sampled_data=use_sampled_data,
            include_model=include_model,
            include_rewrite=include_rewrite)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

inputs_built_distribution = [
    "str:built_type",
    "str_list:built_names",
    "str:filter_cmd",
    "bool:use_sampled_data",
    "str:include_model",
    "int:test_size"
]
@app.route('/api/get_built_distribution/' + '/'.join([f'<{i}>' for i in inputs_built_distribution[:2] ]))
@app.route('/api/get_built_distribution/' + '/'.join([f'<{i}>' for i in inputs_built_distribution]))
def get_built_distribution(
    built_type: str,
    built_names: List[str],
    filter_cmd: str='',
    use_sampled_data: bool=False,
    include_model: str=None,
    test_size: int=None,
    api: API=api):
    output, msg = None, None
    print
    try:
        output = api.get_built_distribution(
            built_type=built_type,
            built_names=built_names,
            filter_cmd=filter_cmd,
            test_size=test_size,
            use_sampled_data=use_sampled_data,
            include_model=include_model)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/get_err_overlap/<bool:show_filtered_err_overlap>')
def get_err_overlap(show_filtered_err_overlap: bool, api: API=api):
    output, msg = None, None
    try:
        output = api.get_err_overlap(show_filtered_err_overlap)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

### Run detections
@app.route('/api/detect_build_blocks/<str:target>/<str:qid>/<int:vid>/<int:start_idx>/<int:end_idx>')
def detect_build_blocks(target: str, qid: str, vid: int, start_idx: int, end_idx: int, api: API=api):
    output, msg = None, None
    try:
        output = api.detect_build_blocks(target, qid, vid, start_idx, end_idx)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/detect_rule_from_rewrite/<str:atext>/<str:btext>/<str:target_cmd>')
def detect_rule_from_rewrite(atext: str, btext: str, target_cmd: str, api: API=api) -> List['Identifier']:
    output, msg = None, None
    try:
        data = api.detect_rule_from_rewrite(atext, btext, target_cmd)
        output = [ r.serialize() for r in data.values() ]
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/evaluate_rewrites_on_groups/<str_list:rids>/<str_list:gnames>/<bool:on_tried>')
def evaluate_rewrites_on_groups(rids: List[str], gnames: List[str], on_tried: bool, API=api):
    output, msg = None, None
    try:
        output = api.evaluate_rewrites_on_groups(rids, gnames, on_tried)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/rewrite_group_instances/<str:rid>/<str:gname>/<int:sample_size>')
def rewrite_group_instances(rid: str, gname: str, sample_size: int, API=api):
    output, msg = None, None
    try:
        output = api.rewrite_group_instances(rid, gname, sample_size)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/rewrite_instances_by_rid')
@app.route('/api/rewrite_instances_by_rid/<str:rid>/<str_list:qids>')
@app.route('/api/rewrite_instances_by_rid/<str:rid>/<str_list:qids>/<int:sample_size>')
@app.route('/api/rewrite_instances_by_rid/<str:rid>/<str_list:qids>/<int:sample_size>/<bool:save>')
def rewrite_instances_by_rid(
    rid: str, qids: List[str]=None, sample_size: int=10, save: bool=False, api: API=api):
    output, msg = None, None
    try:
        output = api.rewrite_instances_by_rid(rid, qids, sample_size, save)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/formalize_rewritten_examples/<str:rid>')
def formalize_rewritten_examples(rid: str, api: API=api):
    output, msg = None, None
    try:
        if Rewrite.exists(rid):
            api.formalize_prev_tried_rewrites(rid)
            e = Rewrite.get(rid)
            output = e.serialize()
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/predict_on_manual_rewrite/<str:qtext>/<str_list:groundtruths>/<str:ctext>')
def predict_on_manual_rewrite(qtext: str, groundtruths: List[str], ctext: str, api: API=api):
    output, msg = None, None
    try:
        output = api.predict_on_manual_rewrite(qtext, groundtruths, ctext)
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

inputs_predict_formalize = [
    "str:qid",
    "str:rid",
    "str:q_rewrite",
    "str_list:groundtruths",
    "str:c_rewrite",
]
@app.route('/api/predict_formalize/' + '/'.join([f'<{i}>' for i in inputs_predict_formalize[:-1] ]))
@app.route('/api/predict_formalize/' + '/'.join([f'<{i}>' for i in inputs_predict_formalize]))
def predict_formalize(
    qid: str, rid: str, q_rewrite: str,
    groundtruths: List[str],
    c_rewrite: str=None, api: API=api) -> List['Identifier']:
    output, msg = None, None
    try:
        data = api.predict_formalize(qid, rid, q_rewrite, groundtruths, c_rewrite)
        output = {
            'key': data['key'],
            'question': data['question'].serialize() if data['question'] else None,
            'context': data['context'].serialize() if data['context'] else None,
            'groundtruths': [g.serialize() for g in data['groundtruths']] if data['groundtruths'] else None,
            'predictions': [g.serialize() for g in data['predictions']] if data['predictions'] else None
        }
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

@app.route('/api/delete_selected_rules/<str_list:rids>')
def delete_selected_rules(rids: List[str], api: API=api):
    output, msg = None, None
    try:
        data = api.delete_selected_rules(rids)
        output = {
            'key': data['key'],
            'question': data['question'].serialize() if data['question'] else None,
            'context': data['context'].serialize() if data['context'] else None,
            'groundtruths': [g.serialize() for g in data['groundtruths']] if data['groundtruths'] else None,
            'predictions': [g.serialize() for g in data['predictions']] if data['predictions'] else None
        }
    except Exception as e:
        msg = e
        logger.error(e)
        traceback.print_exc()
    finally:
        return wrap_output(output, msg)

app.run(debug=False)