from collections import defaultdict

# Word square
# HARD: https://leetcode.com/problems/word-squares
# Use trie to store each word, for each word, check if every letter of it
# has other word with begin letter, use dfs to find list of words
class TrieNode:
    def __init__(self):
        self.children = [None for _ in range(26)]
        self.word = None
        self.possibles = []

class WordSquareSolution:
    def buildTrie(self, words):
        root = TrieNode()
        for word in words:
            p = root
            for char in word:
                idx = ord(char) - ord('a')
                if not p.children[idx]:
                    p.children[idx] = TrieNode()
                p = p.children[idx]
                p.possibles.append(word)
            p.word = word
        return root

    def dfs(self, wordlist, root, n):
        if len(wordlist) == n:
            return wordlist
        # next word index
        curr = len(wordlist)
        node = root
        for i in range(curr):
            char = wordlist[i][curr]
            idx = ord(char) - ord('a')
            if node.children[idx]:
                node = node.children[idx]
            else:
                return None

        if not node or not node.possibles:
            return None

        possibles = node.possibles
        for p in possibles:
            res = self.dfs(wordlist + [p], root, n)
            if res:
                return res
        return None

    def wordSquare(self, words):
        if not words:
            return []
        trie = self.buildTrie(words)
        candidates = []

        for word in words:
            for i in range(1, len(word)):
                idx = ord(word[i]) - ord('a')
                if not trie.children[idx]:
                    break
            else:
                candidates.append(word)

        res = []
        size = len(words[0])
        for word in candidates:
            l = self.dfs([word], trie, size)
            if l:
                res.append(l)
        return res

# Another way to implement trie using hashmap
# Runtime: O(N*26^L) where L is length of word, O(N*L)
class WordSquareMinimal:
    def square(self, wordlist, invert, res):
        if wordlist and len(wordlist) == len(wordlist[0]):
            res.append(wordlist)
            return
        # Next word prefix is combination of all current word at index n
        n = len(wordlist)
        prefix = ''.join(word[n] for word in wordlist)

        if prefix not in invert:
            return

        candidates = invert[prefix]
        for word in candidates:
            self.square(wordlist + [word], invert, res)

    def wordSquares(self, words):
        invert = defaultdict(set)
        res = []
        for word in words:
            for i in range(len(word)):
                invert[word[:i+1]].add(word)
        candidates = []

        # Find candidate for first word
        # if all char in word appears as starting char in other words
        for word in words:
            for char in word:
                if char not in invert:
                    break
            else:
                candidates.append(word)

        for word in candidates:
            self.square([word], invert, res)
        return res

wq = WordSquareMinimal()
print("square word...\n", wq.wordSquare(['area', 'ball', 'dear', 'lady', 'lead', 'yard']))


from flask_api import FlaskAPI, status
from dummyapi import token
import models
from models import Token
from flask import jsonify, request, _app_ctx_stack
from database import SessionLocal, engine
from sqlalchemy.orm import scoped_session
import pandas as pd

app = FlaskAPI(__name__)
app.tokens = []

#sqlalchemy stuff
models.Base.metadata.create_all(bind=engine)

db_session= scoped_session(SessionLocal,scopefunc=_app_ctx_stack.__ident_func__)

@app.route("/token", methods=["GET"])
def get_token():
    """
    Generate and store a new token.
    """
    new_token: str = token.generate_token()
    app.tokens.append(new_token)
    #store token here into db
    db_session.add(Token(token=f'{new_token}'))
    db_session.commit()
    db_session.close()
    #fix this part
    #
    retJson = {
                    "status":200,
                    "msg":"Token generated successfully!" ,
                    "token":new_token
                }

    #df = pd.read_sql_table('tokens',sqlalchemy_db_url)
    #print(df)
    return jsonify(retJson)

@app.route("/verify", methods=["POST"])
def verify_token():
    """
    Verify that the provided token has been previously generated.
    """
    if request:
        postedData = request.get_json()

        reqToken = postedData["token"]

        if len(reqToken) >= 8 and len(reqToken) <= 32:
            query = db_session.query(Token).filter(Token.token == f'{reqToken}').first()

            if query:
                retJson = {
                        "status":200,
                        "msg":"Token already saved once"
                    }
                return jsonify(retJson)

            else:
                retJson = {
                    "status": 200,
                    "msg": "Token not found!"}
                return jsonify(retJson)

        else:
            retJson = {
                    "status": 200,
                    "msg": "Invalid Token Length!"}

            return jsonify(retJson)

    else:
        retJson = {
            "status":400,
            "msg": "Invalid JSON Request"
        }
        return jsonify(retJson)

@app.route(
    "/<path:path>", methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]
)
def catch_all(path):
    """
    Return errors for all invalid paths or request methods.
    """
    return (
        {"status": "error"},
        status.HTTP_404_NOT_FOUND,
    )

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080, debug=True)


from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('posts/create/', views.create, name='create'),
    path('posts/<int:id>/', views.detail, name='detail'),
    path('posts/update/<int:id>/', views.update, name='update'),
    path('posts/delete/<int:id>/', views.delete, name='delete'),
    #path('posts/comment/<int:id>/', views.comments, name='comment'),
    path('posts/comment/<int:id>/update/', views.update_comment, name='update_comment'),
    path('posts/comment/delete/<int:id>/', views.delete_comment, name='delete_comment'),
]


"""
This file contains all the utilities used in other scripts.
"""
import os
import sys
import subprocess
import numpy as np
import cv2
from natsort import natsorted
import scipy.io as scio
from tqdm import tqdm
import datetime
import inspect
import matplotlib.pyplot as plt
from scipy.ndimage import gaussian_filter1d
from src import defines as ds

def return_data_dict(data_dict, data_size, num_frames=None, frame_index=None, bounding_box=None, label=None):
    """
    Returns a dict containing all given data.
    :param data_dict:
    :param data_size:
    :param num_frames:
    :param frame_index:
    :param bounding_box:
    :param label:
    :return:
    """
    dict_subset = dict()
    dict_subset['data'] = data_dict
    dict_subset['data_size'] = data_size
    if num_frames is not None:
        dict_subset['num_frames'] = num_frames
    if frame_index is not None:
        dict_subset['frame_index'] = frame_index
    if bounding_box is not None:
        dict_subset['bounding_box'] = bounding_box
    if label is not None:
        dict_subset['label'] = label
    return dict_subset

def return_score_dict(data, scores, bounding_box=None, label=None):
    """
    Returns a dict containing the essential video information and the corresponding scores.
    :param data:
    :param scores:
    :param bounding_box:
    :param label
    :return:
    """
    assert data['data_size'] == len(scores), 'Size of scores mismatch.'

    dict_scores = dict()
    dict_scores['data_size'] = data['data_size']
    dict_scores['num_frames'] = data['num_frames']
    dict_scores['frame_index'] = data['frame_index']
    dict_scores['scores'] = scores
    if bounding_box is not None:
        dict_scores['bounding_box'] = data['bounding_box']
    if label is not None:
        dict_scores['label'] = data['label']
    return dict_scores

def load_detections(src_dir, video_names, det_mdl_name):
    """
    Loads all the detections for all the given videos.
    :param src_dir:
    :param video_names:
    :param det_mdl_name:
    :return:
    """
    # Get all the detections
    return np.array([np.load(os.path.join(os.path.join(src_dir, v), ds.DET_FILENAMES[det_mdl_name]), allow_pickle=True)
                     for v in tqdm(video_names, file=sys.stdout, desc='Loading detections')])

def visualize_data(dict_subset, n_samples_per_viz=ds.DEFAULT_N_SAMPLES_PER_VIZ):
    """
    Produces visualization image with some randomly selected RoI samples.
    :param dict_subset
    :param n_samples_per_viz:
    :return: Viz image.
    """
    assert dict_subset['data_size'] >= n_samples_per_viz, f'The data size must be >= {n_samples_per_viz}.'

    # Show some randomly selected samples
    idx = np.array(list(range(dict_subset['data_size'])))
    np.random.shuffle(idx)
    idx = idx[:n_samples_per_viz]

    # Merge images for nice visualisation
    img_size = len(next(iter(dict_subset['data'].values()))[0])
    mg_h = np.ones((img_size, ds.HORIZONTAL_MARGIN_SIZE), np.float32)

    # stacked images horizontally
    stack_images = []
    for _, data in dict_subset['data'].items():
        stack_images.append(cv2.hconcat([cv2.hconcat([mg_h, d[:, :, 0], mg_h]) for d in data[idx]]))

    # Stack stacked images vertically
    mg_b = np.ones((ds.HORIZONTAL_MARGIN_SIZE, stack_images[0].shape[1]), np.float32)
    mg_v = np.ones((ds.VERTICAL_MARGIN_SIZE, stack_images[0].shape[1]), np.float32)

    stacked_images = cv2.vconcat([mg_b] + intersperse(stack_images, mg_v) + [mg_b])

    # Convert to uint8
    stacked_images *= ds.WHITE_COLOR
    return stacked_images.astype('uint8')

class MAData:
    """
    Structure of the spatio-temporal RoI sample.
    """
    def __init__(self,
                 dataset=ds.DEFAULT_DATASET,
                 frame_diff_gap=ds.FRAME_DIFF_GAP,
                 min_train_det_score=ds.DEFAULT_MIN_TRAIN_DET_SCORE,
                 min_test_det_score=ds.DEFAULT_MIN_TEST_DET_SCORE,
                 n_frames_per_video=ds.DEFAULT_N_FRAMES_PER_VIDEO,
                 normalize_images=ds.NORMALIZE_IMAGES,
                 frames_step=ds.FRAMES_STEP,
                 det_model_name=ds.DEFAULT_DET_MODEL_NAME,
                 estimations_path=ds.ESTIMATIONS_PATH):
        """
        Initializes the data extraction parameters.
        :param dataset:
        :param frame_diff_gap:
        :param min_train_det_score:
        :param min_test_det_score:
        :param n_frames_per_video:
        :param normalize_images:
        :param frames_step:
        :param det_model_name:
        :param estimations_path:
        """
        self.dataset = dataset
        self.frame_diff_gap = frame_diff_gap
        self.n_frames_per_video = n_frames_per_video
        self.normalize_images = normalize_images
        self.frames_step = frames_step
        self.det_model_name = det_model_name
        self.estimations_path = estimations_path

        self.subset_dir_names = [ds.TRAIN_DIRNAME, ds.TEST_DIRNAME]
        self.subset_dirs = {s: os.path.join(self.estimations_path, self.dataset, s) for s in self.subset_dir_names}
        self.subset_videos = {s: natsorted([v for v in os.listdir(self.subset_dirs[s])
                                            if os.path.isdir(os.path.join(self.subset_dirs[s], v))])
                              for s in self.subset_dir_names}
        self.subset_det = {s: None for s in self.subset_dir_names}
        self.min_det_score = {ds.TRAIN_DIRNAME: min_train_det_score,
                              ds.TEST_DIRNAME: min_test_det_score}

        self.frame_size = ds.FRAME_SIZE
        self.roi_size = ds.ROI_SIZE

    def get_roi_subset(self,
                       subset_name,
                       video_name=None,
                       rand_select=False):
        """
        Extracts the RoI data from frames.
        :return:
        """
        assert subset_name in self.subset_dir_names, 'Invalid subset.'
        assert video_name is None or video_name in self.subset_videos[subset_name], 'Invalid video.'

        # Get detections if necessary
        if self.subset_det[subset_name] is None:
            self.subset_det[subset_name] = load_detections(self.subset_dirs[subset_name],
                                                           self.subset_videos[subset_name],
                                                           self.det_model_name)

        # Get samples randomly distributed
        data_curr = []
        data_past = []
        data_next = []
        n_frames = None
        frames_idx = []
        bounding_boxes = []

        if video_name is None:
            videos = tqdm(zip(self.subset_videos[subset_name], self.subset_det[subset_name]),
                          file=sys.stdout,
                          total=len(self.subset_videos[subset_name]),
                          desc='Extracting RoI subset')
        else:
            videos = zip(self.subset_videos[subset_name], self.subset_det[subset_name])

        for video, det_data in videos:
            if video_name is not None and video != video_name:
                continue

            video_dir = os.path.join(self.subset_dirs[subset_name], video)

            frames = np.load(os.path.join(video_dir, ds.FRAMES_FILENAME), mmap_mode='r')

            n_frames = len(frames)

            if video_name is not None or rand_select:
                idx = np.array(list(range(self.frame_diff_gap, n_frames - self.frame_diff_gap)))
            else:
                idx = np.array(list(range(self.frame_diff_gap, n_frames - self.frame_diff_gap, self.frames_step)))

            if rand_select:
                np.random.shuffle(idx)
                idx = idx[:self.n_frames_per_video]

            for i in idx:
                curr_img = frames[i]
                past_img = frames[i - self.frame_diff_gap]
                next_img = frames[i + self.frame_diff_gap]

                # Detections will be a python dict: {category_id : [[x1, y1, x2, y2, score], ...], }
                curr_a_det = det_data[i]
                # Remove empty detections
                curr_a_det = {k: curr_a_det[k] for k in curr_a_det if curr_a_det[k].size}
                # transform ret into [[x1, y1, x2, y2, score], ...]
                curr_a_det = np.vstack(list(curr_a_det.values()))

                # Exclude detections that have lower score
                curr_a_det = curr_a_det[curr_a_det[:, 4] >= self.min_det_score[subset_name], :]

                if not len(curr_a_det):
                    continue

                max_det_y_pixels = int(ds.MAX_DET_SIZE_RATIO * curr_img.shape[0])
                max_det_x_pixels = int(ds.MAX_DET_SIZE_RATIO * curr_img.shape[1])

                for box in curr_a_det:
                    (x1, y1, x2, y2) = box[:-1].astype(int)

                    # Bug fixed
                    if x1 < 0:
                        x1 = 0
                    if y1 < 0:
                        y1 = 0
                    if x2 > curr_img.shape[1]:
                        x2 = curr_img.shape[1]
                    if y2 > curr_img.shape[0]:
                        y2 = curr_img.shape[0]

                    if (x2 - x1) < ds.MIN_DET_PIXELS or (y2 - y1) < ds.MIN_DET_PIXELS:
                        continue

                    if self.dataset == 'ped1' or self.dataset == 'ped2':
                        # Fix whole frame detections on ped2
                        if (x2 - x1) > max_det_x_pixels and (y2 - y1) > max_det_y_pixels:
                            continue

                    # Resize RoIs
                    curr_resized = cv2.resize(curr_img[y1:y2, x1:x2], (self.roi_size, self.roi_size))
                    past_resized = cv2.resize(past_img[y1:y2, x1:x2], (self.roi_size, self.roi_size))
                    next_resized = cv2.resize(next_img[y1:y2, x1:x2], (self.roi_size, self.roi_size))

                    if self.normalize_images:
                        # Normalize images
                        curr_resized = cv2.normalize(curr_resized, None,
                                                     alpha=ds.MIN_NORM, beta=ds.MAX_NORM,
                                                     norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
                        past_resized = cv2.normalize(past_resized, None,
                                                     alpha=ds.MIN_NORM, beta=ds.MAX_NORM,
                                                     norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
                        next_resized = cv2.normalize(next_resized, None,
                                                     alpha=ds.MIN_NORM, beta=ds.MAX_NORM,
                                                     norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)

                    # Store results
                    data_curr.append(curr_resized)
                    data_past.append(past_resized)
                    data_next.append(next_resized)

                    frames_idx.append(i)
                    bounding_boxes.append({'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2})

        # Convert to arrays
        data_curr = np.array(data_curr)
        data_past = np.array(data_past)
        data_next = np.array(data_next)

        # Reshape and transform to float
        data_curr = data_curr.reshape((*data_curr.shape, 1))
        data_past = data_past.reshape((*data_past.shape, 1))
        data_next = data_next.reshape((*data_next.shape, 1))
        if not self.normalize_images:
            data_curr = (ds.MAX_NORM - ds.MIN_NORM) * data_curr.astype('float32') / ds.WHITE_COLOR + ds.MIN_NORM
            data_past = (ds.MAX_NORM - ds.MIN_NORM) * data_past.astype('float32') / ds.WHITE_COLOR + ds.MIN_NORM
            data_next = (ds.MAX_NORM - ds.MIN_NORM) * data_next.astype('float32') / ds.WHITE_COLOR + ds.MIN_NORM

        # Get data size
        data_size = len(data_curr)
        assert data_size == len(data_past) and data_size == len(data_next), 'Size of subset mismatch.'

        # Normalize data and return a dict containing data
        dict_data = dict()
        dict_data['curr'] = data_curr
        dict_data['past'] = data_past
        dict_data['next'] = data_next

        if video_name is None:
            return return_data_dict(dict_data, data_size)
        else:
            return return_data_dict(dict_data, data_size,
                                    frame_index=np.array(frames_idx),
                                    bounding_box=np.array(bounding_boxes), num_frames=n_frames)

class EST5EDT(datetime.tzinfo):

    def utcoffset(self, dt):
        return datetime.timedelta(hours=-5) + self.dst(dt)

    def dst(self, dt):
        d = datetime.datetime(dt.year, 3, 8)        # 2nd Sunday in March
        self.dston = d + datetime.timedelta(days=6-d.weekday())
        d = datetime.datetime(dt.year, 11, 1)       # 1st Sunday in Nov
        self.dstoff = d + datetime.timedelta(days=6-d.weekday())
        if self.dston <= dt.replace(tzinfo=None) < self.dstoff:
            return datetime.timedelta(hours=1)
        else:
            return datetime.timedelta(0)

    def tzname(self, dt):
        return 'EST5EDT'

def subprocess_cmd(command):
    process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    proc_stdout = process.communicate()[0].strip()
    print(proc_stdout.decode())

def get_results(scores_data,
                smoothing_factor=ds.DEFAULT_SMOOTHING_FACTOR,
                normalize=ds.DEFAULT_NORMALIZE_SCORES,
                binarize=ds.DEFAULT_BINARIZE_SCORES):
    """
    Gets the frame-level reconstruction error scores for all test sequences.
    :param scores_data:
    :param smoothing_factor:
    :param normalize:
    :param binarize:
    :return:
    """
    min_score = scores_data['scores'].min()
    max_score = scores_data['scores'].max()

    if normalize:
        scores_data['scores'] = np.interp(scores_data['scores'], (min_score, max_score), (0, 1))

    full_frames = list(range(1, scores_data['num_frames'] + 1))

    # get all fame number used in the test data
    test_frames = list(set(scores_data['frame_index']))
    test_frames.sort()

    max_scores = []
    for f in test_frames:
        frame_scores = scores_data['scores'][scores_data['frame_index'] == f]
        max_scores.append(np.max(frame_scores))

    if binarize:
        threshold = np.mean(max_scores)
        test_scores = [1 if x > threshold else 0 for x in max_scores]
    else:
        test_scores = max_scores

    # Put missing scores in frames to 0 (normal)
    test_frames = np.array(test_frames)
    match_index = [np.where(test_frames == f)[0] for f in range(scores_data['num_frames'])]
    full_scores = np.array([test_scores[i[0]] if i.size > 0 else min_score for i in match_index])

    # Smooth scores using Gaussian 1d filter
    if smoothing_factor:
        final_scores = gaussian_filter1d(full_scores, smoothing_factor)
    else:
        final_scores = full_scores

    return np.array(full_frames), final_scores

def get_gt_results(dataset=ds.DEFAULT_DATASET,
                   dataset_path=ds.DATASETS_PATH):
    """
    Get the frame-level ground-truth results.
    Inspired from:
    https://github.com/StevenLiuWen/ano_pred_cvpr2018/blob/master/Codes/evaluate.py
    :param dataset:
    :param dataset_path:
    :return:
    """
    tests_dir = os.path.join(dataset_path, dataset, ds.TEST_DIRNAME)

    if dataset == 'shanghaitech':
        gt_dir = os.path.join(tests_dir, 'test_frame_mask')

        video_path_list = [f for f in os.listdir(gt_dir)]
        video_path_list.sort()

        gt = []
        for video in video_path_list:
            gt.append(np.load(os.path.join(gt_dir, video)).tolist()[1:])
    else:
        gt_dir = os.path.join(dataset_path, dataset)
        gt_filename = '{}.mat'.format(dataset)

        abnormal_events = scio.loadmat(os.path.join(gt_dir, gt_filename), squeeze_me=True)['gt']

        if abnormal_events.ndim == 2:
            abnormal_events = abnormal_events.reshape(-1, abnormal_events.shape[0], abnormal_events.shape[1])

        num_video = abnormal_events.shape[0]

        frames_dir = os.path.join(tests_dir, ds.FRAMES_DIRNAME)
        video_list = [v for v in os.listdir(frames_dir) if os.path.isdir(os.path.join(frames_dir, v))]
        video_list.sort()

        assert num_video == len(video_list), 'ground truth does not match the number of testing videos. {} != {}' \
            .format(num_video, len(video_list))

        # get the total frames of sub video
        def get_video_length(sub_video_number):
            # video_name = video_name_template.format(sub_video_number)
            video_name = os.path.join(frames_dir, video_list[sub_video_number])
            assert os.path.isdir(video_name), '{} is not directory!'.format(video_name)
            return len(os.listdir(video_name))

        gt = []
        for i in range(num_video):
            length = get_video_length(i)

            sub_video_gt = np.zeros((length,), dtype=np.int8)
            sub_abnormal_events = abnormal_events[i]
            if sub_abnormal_events.ndim == 1:
                sub_abnormal_events = sub_abnormal_events.reshape((sub_abnormal_events.shape[0], -1))

            _, num_abnormal = sub_abnormal_events.shape

            for j in range(num_abnormal):
                # (start - 1, end - 1)
                start = int(sub_abnormal_events[0, j]) - 1
                end = int(sub_abnormal_events[1, j])

                sub_video_gt[start: end] = 1

            gt.append(sub_video_gt.tolist()[1:])  # Skip the first frame

    return gt

def convert_videos_to_frames(videos_dir, frames_dir):
    """
    Converts all videos in the videos dir to frames and saves them to frames dir.
    :param videos_dir:
    :param frames_dir:
    :return:
    """
    videos = [v for v in os.listdir(videos_dir) if os.path.isfile(os.path.join(videos_dir, v)) and
              any(v[v.rfind('.'):] == ext for ext in ds.VIDEO_EXTENSIONS)]
    videos = natsorted(videos)
    for video in tqdm(videos, file=sys.stdout, desc='Extracting frames'):
        video_frames_dir = os.path.join(frames_dir, video[:video.rfind('.')])
        if not os.path.exists(video_frames_dir):
            os.makedirs(video_frames_dir)

        video_cap = cv2.VideoCapture(os.path.join(videos_dir, video))
        success, frame = video_cap.read()
        count = 0
        while success:
            # save frame as JPEG file
            cv2.imwrite(os.path.join(video_frames_dir, '{:04d}.jpg'.format(count)), frame)
            success, frame = video_cap.read()
            count += 1

def get_class_from_name(module, class_name):
    """
    Gets the class from the string name within the given module.
    :param module:
    :param class_name:
    :return: class
    """
    cls_names = [m[0] for m in inspect.getmembers(module, inspect.isclass)]
    assert class_name.lower() in [x.lower() for x in cls_names], 'Class name not found.'
    cls_name = cls_names[[x.lower() for x in cls_names].index(class_name.lower())]
    return getattr(module, cls_name)

def intersperse(lst, item):
    """
    Adds the item between each item in the list.
    :param lst:
    :param item:
    :return:
    """
    result = [item] * (len(lst) * 2 - 1)
    result[0::2] = lst
    return result

def plot_video_anomaly_curve(frame_index, frame_score, true_score, filename):
    """
    Plots the video frame-level anomaly score.
    :param frame_index:
    :param frame_score:
    :param true_score:
    :param filename:
    :return:
    """
    assert len(true_score) == len(frame_score), 'Mismatch between the size of true and predicted scores.'
    # Plot a curve of scores and threshold_value
    fig = plt.figure(figsize=(10, 4))
    plt.plot(frame_index, frame_score, 'r', label='score', lw=3)
    plt.fill_between(frame_index, np.zeros(frame_index.shape), true_score, facecolor='c', label='ground-truth', lw=1)
    plt.xlabel('Frame')
    plt.ylabel('Score')
    plt.yticks(np.arange(0, 1.2, step=0.2))
    plt.legend(loc='best')
    fig.savefig(filename, bbox_inches='tight')
    plt.close(fig)

def add_bool_parser(parser, arg_name, default_arg):
    """
    Adds a boolean parser.
    Ref.: https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse
    :param parser:
    :param arg_name:
    :param default_arg:
    :return:
    """
    group = parser.add_mutually_exclusive_group(required=False)
    group.add_argument('--' + arg_name, dest=arg_name, action='store_true')
    group.add_argument('--no-' + arg_name, dest=arg_name, action='store_false')
    parser.set_defaults(**{arg_name: default_arg})


from __future__ import absolute_import, division, print_function, unicode_literals
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator

class DataGenerator:
    def data_augmentation(x_train, y_train, augment_size=25000):
        image_generator = ImageDataGenerator(
            rotation_range=10,
            zoom_range=1.1,
            width_shift_range=0.07,
            height_shift_range=0.07,
            brightness_range=[0.2,1.0],
            shear_range=0.25,
            horizontal_flip=False,
            vertical_flip=False,
            data_format="channels_last")
        # fit data for zca whitening
        image_generator.fit(x_train, augment=True)
        # get transformed images
        randidx = np.random.randint(x_train.shape[0], size=augment_size)
        x_augmented = x_train[randidx].copy()
        y_augmented = y_train[randidx].copy()
        x_augmented = image_generator.flow(x_augmented, np.zeros(augment_size),
                                           batch_size=augment_size, shuffle=False).next()[0]
        # append augmented data to trainset
        x_train2 = np.concatenate((x_train, x_augmented))
        y_train2 = np.concatenate((y_train, y_augmented))
        return x_train2, y_train2


import matplotlib.pyplot as plt
import sklearn.datasets
import numpy as np
import sklearn.linear_model
import matplotlib

def initialize(input_num, layer1_num, layer2_num):
    model = dict()
    np.random.seed(12)
    w1 = np.random.randn(input_num, layer1_num)
    b1 = np.random.randn(1, layer1_num)
    w2 = np.random.randn(layer1_num, layer2_num)
    b2 = np.random.randn(1, layer2_num)
    model['w1'] = w1
    model['b1'] = b1
    model['w2'] = w2
    model['b2'] = b2
    return model

def predict(model, x):
    w1, b1, w2, b2 = model['w1'], model['b1'], model['w2'], model['b2']
    z1 = x.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    exp_scores = np.exp(z2)
    probs = exp_scores/np.sum(exp_scores, axis=1, keepdims=True)
    return np.argmax(probs, axis=1)

def forward(model, x, y):
    epsilon = 0.043
    reg_lamda =0.0001
    x = x.reshape(1,2) #为什么要reshape?
    w1, b1, w2, b2 = model['w1'], model['b1'], model['w2'], model['b2']
    z1 = x.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    exp_scores = np.exp(z2)
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)#维度问题
    loss = -np.log(probs[0,y])

    #导数信息
    delta3 = probs
    delta3[0, y] -= 1#原来的代码时使用迭代器一起取数
    dw2 = (a1.T).dot(delta3)
    db2 = np.sum(delta3, axis=0, keepdims=True)
    delta2 = delta3.dot(w2.T)*(1-np.power(a1,2))
    dw1 = np.dot(x.T, delta2)

    db1 = np.sum(delta2, axis=0)

    dw2 += reg_lamda*w2
    dw1 += reg_lamda*w1

    w1 += -epsilon*dw1
    b1 += -epsilon * db1
    w2 += -epsilon * dw2
    b2 += -epsilon * db2

    model['w1'] = w1
    model['b1'] = b1
    model['w2'] = w2
    model['b2'] = b2
    return loss, model

def plot_decision_boundary(pred_func, X, y):
    # Set min and max values and give it some padding
    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    h = 0.01
    # Generate a grid of points with distance h between them
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole gid
    Z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # Plot the contour and training examples
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Spectral)

def main():
    epochs = 200
    matplotlib.rcParams['figure.figsize'] = (10.0, 8.0)
    np.random.seed(3)
    X, Y = sklearn.datasets.make_moons(200, noise=0.20)
    print(len(X))
    model = initialize(2, 5, 2)
    for epoch in range(epochs):
        loss_ep = 0
        for i in range(len(X)):
            loss, model = forward(model, X[i], Y[i])
            loss_ep += loss
        loss_ep = loss_ep/len(X)
        if epoch%100==0:
            print('epoch:', epoch, 'loss:', loss_ep, '\n')
    plot_decision_boundary(lambda x: predict(model, x), X, Y)
    plt.scatter(X[:, 0], X[:, 1], s=40, c=Y, cmap=plt.cm.Spectral)
    plt.show()

if __name__ == '__main__':
    main()


# -*- coding:utf-8 -*-
from django.shortcuts import HttpResponse
from web.jsonEncoder import *
import os, time
from pathlib import Path
from django.conf import settings

def size_format(size):
    if size < 1000:
        return '%i' % size + ' Byte'
    elif 1000 <= size < 1000000:
        return '%.1f' % float(size/1000) + ' KB'
    elif 1000000 <= size < 1000000000:
        return '%.1f' % float(size/1000000) + ' MB'
    elif 1000000000 <= size < 1000000000000:
        return '%.1f' % float(size/1000000000) + ' GB'
    elif 1000000000000 <= size:
        return '%.1f' % float(size/1000000000000) + ' TB'

node_count = 0
def retrieve_all(dir):
    global node_count
    p=Path(dir)
    DirTree =[]
    for p in list(p.glob('*')):
        filepath = os.path.join(dir, p.name)
        modifiedTime = time.localtime(os.stat(filepath).st_mtime)
        mTime = time.strftime('%Y-%m-%d %H:%M:%S', modifiedTime)
        if p.is_file():
            file_size = size_format(os.path.getsize(filepath))
            node_count = node_count + 1
            DirTree.append({"id":node_count, "label":p.name, "value":"file", "file_size":file_size, "file_time":mTime})
        else:
            #注释掉递归，只查当前目录下的所有
            #subdir=[]
            #subdir=retrieve_dir(filepath)
            node_count = node_count + 1
            DirTree.append({"id":node_count, "label":p.name, "value":"dir", "file_time":mTime})
    return DirTree

count = 0
def retrieve_dir(dir):
    global count
    p=Path(dir)
    DirTree =[]
    for p in list(p.glob('*')):
        if p.is_file():
            pass
            #忽略文件，只进行目录处理
        else:
            subdir=[]
            subdir=retrieve_dir(os.path.join(dir,p.name))
            count = count + 1
            DirTree.append({"id": count, "label":p.name,"value":"dir","children":subdir})
    return DirTree

def get_floder(request):
    Dir = 'E:\Production\ManageSystem\static\Public'
    DirTree = retrieve_dir(Dir)
    json_data = {"msg": 'ok', "state_code": 200, "items": DirTree}
    return HttpResponse(json.dumps(json_data, cls=DateJSONEncoder), content_type="application/json")

def get_floder_all(request):
    Dir = 'E:\Production\ManageSystem\static\Public'
    dirList = json.loads(request.POST.get('dir'))
    for i in dirList:
        Dir = os.path.join(Dir, i)

    DirTree = retrieve_all(Dir)
    DirTree.sort(key = lambda x:x["value"])     #排序，文件夹优先
    json_data = {"msg": 'ok', "state_code": 200, "items": DirTree}
    return HttpResponse(json.dumps(json_data, cls=DateJSONEncoder), content_type="application/json")

def get_now_path(self):
    return '返回当前路径'

def md(request):
    try:
        path = json.loads(request.POST.get('path'))
        name = request.POST.get('name')

        Dir = 'E:\Production\ManageSystem\static\Public'
        for i in path:
            Dir = os.path.join(Dir, i)

        Dir = os.path.join(Dir, name)

        if not os.path.exists(Dir):
            os.makedirs(Dir)

        json_data = {"msg": 'ok', "state_code": 200}
    except:
        json_data = {"msg": 'error', "state_code": 444}
    return HttpResponse(json.dumps(json_data, cls=DateJSONEncoder), content_type="application/json")

def rd(self):
    return '删除目录及下面所有文件'

def delete_file(request):
    try:
        path = json.loads(request.POST.get('path'))
        type = request.POST.get('type')

        Dir = 'E:\Production\ManageSystem\static\Public'
        for i in path:
            Dir = os.path.join(Dir, i)

        print(Dir)

        if type == 'file':
            os.remove(Dir)
        else:
            os.rmdir(Dir)

        json_data = {"msg": 'ok', "state_code": 200}
    except:
        json_data = {"msg": 'error', "state_code": 444}

    return HttpResponse(json.dumps(json_data, cls=DateJSONEncoder), content_type="application/json")

def delete_many(self):
    return '删除多个文件'

def download(request):
    try:
        filepath = request.POST.get('filepath')
        print(filepath)
        json_data = {"msg": 'ok', "state_code": 200}
    except:
        json_data = {"msg": 'error', "state_code": 444}

    return HttpResponse(json.dumps(json_data, cls=DateJSONEncoder), content_type="application/json")

def ren(request):
    try:
        oldDir = json.loads(request.POST.get('oldDir'))
        newDir = json.loads(request.POST.get('newDir'))
        newName = request.POST.get('newName')

        Dir = 'E:\Production\ManageSystem\static\Public'
        for i in oldDir:
            Dir = os.path.join(Dir, i)

        srcFile = Dir

        nDir = 'E:\Production\ManageSystem\static\Public'
        for n in newDir:
            nDir = os.path.join(nDir, n)

        dstFile = os.path.join(nDir, newName)

        os.rename(srcFile, dstFile)

        json_data = {"msg": 'ok', "state_code": 200}
    except:
        json_data = {"msg": 'error', "state_code": 444}

    return HttpResponse(json.dumps(json_data, cls=DateJSONEncoder), content_type="application/json")

def uploadFile(path, fileobj):
    try:
        #file_path = os.path.join(path, fileobj) #打开这个物理文件
        #file_path = os.path.join(path, unicode(str(fileobj), 'utf-8'))
        file_path = os.path.join(path, fileobj)
        f = open(file_path, mode="wb")  #执行写数据
        for i in fileobj.chunks():
            f.write(i)
        f.close()
        return True
    except:
        return False

def upload(request):
    try:
        path = json.loads(request.POST.get('path'))
        Dir = 'E:\Production\ManageSystem\static\Public'

        upfileForm = request.GET.get('upfileForm', 'fileName')  # 如果一个表单中存在多个上传则需要变改每一个UPLOAD的 NAME名称
        fileName = request.FILES.get(upfileForm)
        for i in path:
            Dir = os.path.join(Dir, i)

        imgurl = uploadFile(Dir, fileName)

        if imgurl == False:
            msg = 'error'
        else:
            msg = 'ok'

        json_data = {"msg": msg, "state_code": 200}
    except:
        json_data = {"msg": 'error', "state_code": 444}

    return HttpResponse(json.dumps(json_data, cls=DateJSONEncoder), content_type="application/json")


import numpy as np
from ROOT import *
import matplotlib.pyplot as plt

network=np.load('../../../slac_ML/slac_ML/training/train35PU_test35PU.npy')
data=np.load('../../../Jetinfo35PU_noimage.npz')
output='train35PU_test35PU'

mass=data['jet_mass']
tau21=data['tau21']
net=network

c1=TCanvas("c1","c1",800,600)
h=TH2D("2dplot","DNN vs Mass",100,65,95,100,0,1)
h.GetXaxis().SetTitle("Jet Mass (GeV)")
h.GetYaxis().SetTitle("DNN Output")
for k in range(len(net)):
#    print k

    h.Fill(mass[k],net[k])

gPad.SetLogz(1)
gStyle.SetOptStat(0)
#c1.SetXTitle("Jet Mass (GeV)")
h.Draw("colz")
c1.SaveAs(output+"_DNNvsmass.pdf")

c2=TCanvas("c2","c2",800,600)
w=TH2D("2dplot1","DNN vs Tau21",100,0,1,100,0,1)
w.GetXaxis().SetTitle("Tau21")
w.GetYaxis().SetTitle("DNN Output")
for k in range(len(net)):
#    print k

    w.Fill(tau21[k],net[k])

gPad.SetLogz(1)
gStyle.SetOptStat(0)
#gStyle.SetXaxisTitle("Tau21")
w.Draw("colz")
c2.SaveAs(output+"_DNNvstau21.pdf")

"""
#print '{} jets before preselection'.format(data.shape[0])
data = np.load('../../jetimages.npy')
signal, pt, mass, tau_21 = data['signal'], data['jet_pt'], data['jet_mass'], data['tau_21']
signal = (signal == 1)
background = (signal == 0)
plt.figure()
plt.hist(tau_21[background],bins=100)
plt.savefig('QCDTau21_SLAC.pdf')

data = np.load('../../preprocessing/Jetimages_0PU.npz')
signal, pt, mass, tau_21 = data['signal'], data['jet_pt'], data['jet_mass'], data['tau21']
signal = (signal == 1)
background = (signal == 0)
plt.figure()
plt.hist(tau_21[background],bins=100)
plt.savefig('QCDTau21_0PU.pdf')
"""


import collections
class TrieNode:
    # Initialize your data structure here.
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.is_word = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        current = self.root
        for letter in word:
            current = current.children[letter]
        current.is_word = True

    def search(self, word, ignoreCase=False):
        wordList = []
        current = self.root
        chars = []
        for letter in word:
            if ignoreCase:
                letter = letter.lower()
            chars.append(letter)
            current = current.children.get(letter)

            if current is None:
                return wordList
            if current.is_word:
                wordList.append(chars.copy())

    def startsWith(self, prefix):
        current = self.root
        for letter in prefix:
            current = current.children.get(letter)
            if current is None:
                return False
        return True


import numpy as np

def hand():
    return False

def is_arr_in_list(myarr, list_arrays):
    return next((True for elem in list_arrays if np.array_equal(elem, myarr)), False)

class GameEvaluator:

    def __init__(self, board_updater):
        self.board_updater = board_updater
        self.game_history = []
        self.black_stones = 0
        self.black_captured = 0
        self.white_stones = 0
        self.white_captured = 0
        self.is_blacks_turn = True
        self.frame_counter = 0

    def get_change_at_position(self, position):
        difference_board = self.board_updater.get_board_differences()
        return difference_board[position[0]][position[1]]

    def get_added_and_removed(self, positions):
        added = 0
        removed = 0
        for position in positions:
            value = self.get_change_at_position(position)
            if value < 0:
                color = "black" if value == -1 else "white"
                print(f'added {color} to {position}')
                added += 1
            else:
                color = "black" if value == 1 else "white"
                print(f'removed {color} from {position}')
                removed += 1
        return added, removed

    def is_valid_board(self, changes):
        if hand():
            return False
        if not np.array_equal(self.board_updater.recording_board, self.board_updater.next_board):
            self.frame_counter = 0
            self.board_updater.update_next_board()
            return False

        if self.frame_counter < 10:
            self.frame_counter += 1
            return False
        black_valid = self.board_updater.count_black_on_board() + self.black_captured == self.black_stones + 1
        white_valid = self.board_updater.count_white_on_board() + self.white_captured == self.white_stones + 1

        if len(changes) == 1:
            is_valid_black_turn = self.is_blacks_turn and black_valid and \
                                  self.board_updater.count_white_on_board() + self.white_captured == self.white_stones
            is_valid_white_turn = not self.is_blacks_turn and white_valid and \
                                  self.board_updater.count_black_on_board() + self.black_captured == self.black_stones
            return is_valid_black_turn or is_valid_white_turn

        if len(changes) > 1:
            added, removed = self.get_added_and_removed(changes)
            if added == 1 and self.remove_is_valid(changes):
                is_valid_black_turn = self.is_blacks_turn and black_valid and \
                                      self.board_updater.count_white_on_board() + \
                                      self.white_captured + removed == self.white_stones
                is_valid_white_turn = not self.is_blacks_turn and white_valid and \
                                      self.board_updater.count_black_on_board() + \
                                      self.black_captured + removed == self.black_stones
                return is_valid_black_turn or is_valid_white_turn
        return False

    def update_board(self, positions):
        _, removed = self.get_added_and_removed(positions)
        if self.is_blacks_turn:
            self.black_stones += 1
            self.white_captured += removed
            self.is_blacks_turn = False
        else:
            self.white_stones += 1
            self.black_captured += removed
            self.is_blacks_turn = True
        self.save_last_move(positions)
        self.board_updater.update_last_board()

    def get_last_move_position(self, positions):
        for position in positions:
            value = self.get_change_at_position(position)
            if value < 0:
                return tuple(position)
        return RuntimeError('No new added stone found')

    def get_removed_positions(self, positions):
        removed_position = []
        for position in positions:
            value = self.get_change_at_position(position)
            if value > 0:
                removed_position.append(position)
        return removed_position

    def save_last_move(self, positions):
        position = self.get_last_move_position(positions)
        color = 'W'
        # since moved got already changed in update board we have to invert the boolean statement
        if not self.is_blacks_turn:
            color = 'B'
        self.game_history.append([color, position])

    def remove_is_valid(self, positions):
        x, y = self.get_last_move_position(positions)
        print(x,y)
        board = self.board_updater.last_board.copy()
        color = '1' if self.is_blacks_turn else '2'
        opponent = '2' if self.is_blacks_turn else '1'
        board[x][y] = color
        removed_positions = self.get_removed_positions(positions)
        print(board)
        print(removed_positions)
        for move in removed_positions:
            if not self.captured(opponent, color, move, board, removed_positions):
                return False
        return True

    def print_last_move(self):
        print(self.game_history[-1])

    def captured(self, opponent, color, move, board, position):
        x = move[0]
        y = move[1]

        left_color_and_removed = board[x - 1][y] == color and not is_arr_in_list(np.array([x - 1, y]), position)
        right_color_and_removed = board[x + 1][y] == color and not is_arr_in_list(np.array([x + 1, y]), position)
        top_color_and_removed = board[x][y - 1] == color and not is_arr_in_list(np.array([x, y - 1]), position)
        bottom_color_and_removed = board[x][y + 1] == color and not is_arr_in_list(np.array([x, y + 1]), position)

        print(board[x - 1][y] == color)

        # Check left neighbor if not at left edge
        if x > 1 and (board[x - 1][y] == 0 or left_color_and_removed):
            return False
            # Check right neighbor if not at right edge
        if x < 19 and (board[x + 1][y] == 0 or right_color_and_removed):
            return False
            # Check top neighbor if not at top edge
        if y > 1 and (board[x][y - 1] == 0 or top_color_and_removed):
            return False
            # Check bottom neighbor if not at bottom edge
        if y < 19 and (board[x][y + 1] == 0 or bottom_color_and_removed):
            return False
            # If none of the above conditions are met, return False
        return True


import io
import subprocess
import base64
from IPython.display import HTML

def make_movie(fname_glob, fname_out, fps_in=15, fps_out=15):
    # To force the frame rate of the input file (valid for raw formats only) to 1 fps and the frame rate of the output file to 24 fps:

    cmd = ['ffmpeg',
           '-y', # override existing file
#           '-r', str(fps_in),
           '-f', 'image2',
           '-framerate', str(fps_in),
           '-pattern_type', 'glob',
           '-i', fname_glob,
#           '-r', str(fps_out),
           '-pix_fmt', 'yuv420p',
           '-vcodec', 'libx264',
#           '-vf', 'scale=trunc(iw/2)*2:trunc(ih/2)*2',
           '-s','1200x800',
           '-f', 'mp4', fname_out]

    print('[make_mp4]: ffmpeg command:')
    print('{0:s}'.format(' '.join(cmd)))

    ret = subprocess.call(cmd)
    if ret == 0:
        print('[make_movie]: Successful execution. Output:')
        print('{0:s}'.format(fname_out))
    else:
        print('[make_movie]: subprocess.call returned {0:d}. Something went wrong.'.format(ret))

def display_movie(filename):

    video = io.open(filename, 'r+b').read()
    encoded = base64.b64encode(video)
    return HTML(data='''<video alt="test" controls>
                <source src="data:video/mp4;base64,{0}" type="video/mp4" />
                </video>'''.format(encoded.decode('ascii')))


import unittest
from contextlib import contextmanager
import os
import logging
import errno
from shutil import rmtree
from tempfile import mkdtemp, NamedTemporaryFile

from swift.common import db_replicator
from swift.common import utils
from swift.common.utils import normalize_timestamp
from swift.container import server as container_server

from test.unit import FakeLogger

def teardown_module():
    "clean up my monkey patching"
    reload(db_replicator)

@contextmanager
def lock_parent_directory(filename):
    yield True

class FakeRing:
    class Ring:
        devs = []

        def __init__(self, path, reload_time=15, ring_name=None):
            pass

        def get_part_nodes(self, part):
            return []

        def get_more_nodes(self, *args):
            return []

class FakeRingWithNodes:
    class Ring:
        devs = [dict(
            id=1, weight=10.0, zone=1, ip='1.1.1.1', port=6000, device='sdb',
            meta=''
        ), dict(
            id=2, weight=10.0, zone=2, ip='1.1.1.2', port=6000, device='sdb',
            meta=''
        ), dict(
            id=3, weight=10.0, zone=3, ip='1.1.1.3', port=6000, device='sdb',
            meta=''
        ), dict(
            id=4, weight=10.0, zone=4, ip='1.1.1.4', port=6000, device='sdb',
            meta='')]

        def __init__(self, path, reload_time=15, ring_name=None):
            pass

        def get_part_nodes(self, part):
            return self.devs[:3]

        def get_more_nodes(self, *args):
            return (d for d in self.devs[3:])

class FakeProcess:
    def __init__(self, *codes):
        self.codes = iter(codes)

    def __call__(self, *args, **kwargs):
        class Failure:
            def communicate(innerself):
                next = self.codes.next()
                if isinstance(next, int):
                    innerself.returncode = next
                    return next
                raise next
        return Failure()

@contextmanager
def _mock_process(*args):
    orig_process = db_replicator.subprocess.Popen
    db_replicator.subprocess.Popen = FakeProcess(*args)
    yield
    db_replicator.subprocess.Popen = orig_process

class ReplHttp:
    def __init__(self, response=None):
        self.response = response
    replicated = False
    host = 'localhost'

    def replicate(self, *args):
        self.replicated = True

        class Response:
            status = 200
            data = self.response

            def read(innerself):
                return self.response
        return Response()

class ChangingMtimesOs:
    def __init__(self):
        self.mtime = 0
        self.path = self
        self.basename = os.path.basename

    def getmtime(self, file):
        self.mtime += 1
        return self.mtime

class FakeBroker:
    db_file = __file__
    get_repl_missing_table = False
    stub_replication_info = None
    db_type = 'container'

    def __init__(self, *args, **kwargs):
        return None

    @contextmanager
    def lock(self):
        yield True

    def get_sync(self, *args, **kwargs):
        return 5

    def get_syncs(self):
        return []

    def get_items_since(self, point, *args):
        if point == 0:
            return [{'ROWID': 1}]
        return []

    def merge_syncs(self, *args, **kwargs):
        self.args = args

    def merge_items(self, *args):
        self.args = args

    def get_replication_info(self):
        if self.get_repl_missing_table:
            raise Exception('no such table')
        if self.stub_replication_info:
            return self.stub_replication_info
        return {'delete_timestamp': 0, 'put_timestamp': 1, 'count': 0}

    def reclaim(self, item_timestamp, sync_timestamp):
        pass

    def get_info(self):
        pass

class TestReplicator(db_replicator.Replicator):
    server_type = 'container'
    ring_file = 'container.ring.gz'
    brokerclass = FakeBroker
    datadir = container_server.DATADIR
    default_port = 1000

class TestDBReplicator(unittest.TestCase):
    def setUp(self):
        db_replicator.ring = FakeRing()
        self.delete_db_calls = []

    def stub_delete_db(self, object_file):
        self.delete_db_calls.append(object_file)

    def test_repl_connection(self):
        node = {'ip': '127.0.0.1', 'port': 80, 'device': 'sdb1'}
        conn = db_replicator.ReplConnection(node, '1234567890', 'abcdefg',
                    logging.getLogger())

        def req(method, path, body, headers):
            self.assertEquals(method, 'REPLICATE')
            self.assertEquals(headers['Content-Type'], 'application/json')

        class Resp:
            def read(self):
                return 'data'
        resp = Resp()
        conn.request = req
        conn.getresponse = lambda *args: resp
        self.assertEquals(conn.replicate(1, 2, 3), resp)

        def other_req(method, path, body, headers):
            raise Exception('blah')
        conn.request = other_req
        self.assertEquals(conn.replicate(1, 2, 3), None)

    def test_rsync_file(self):
        replicator = TestReplicator({})
        with _mock_process(-1):
            fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
            self.assertEquals(False,
                    replicator._rsync_file('/some/file', 'remote:/some/file'))
        with _mock_process(0):
            fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
            self.assertEquals(True,
                    replicator._rsync_file('/some/file', 'remote:/some/file'))

    def test_rsync_db(self):
        replicator = TestReplicator({})
        replicator._rsync_file = lambda *args: True
        fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
        replicator._rsync_db(FakeBroker(), fake_device, ReplHttp(), 'abcd')

    def test_in_sync(self):
        replicator = TestReplicator({})
        self.assertEquals(replicator._in_sync(
            {'id': 'a', 'point': -1, 'max_row': 0, 'hash': 'b'},
            {'id': 'a', 'point': -1, 'max_row': 0, 'hash': 'b'},
            FakeBroker(), -1), True)
        self.assertEquals(replicator._in_sync(
            {'id': 'a', 'point': -1, 'max_row': 0, 'hash': 'b'},
            {'id': 'a', 'point': -1, 'max_row': 10, 'hash': 'b'},
            FakeBroker(), -1), True)
        self.assertEquals(bool(replicator._in_sync(
            {'id': 'a', 'point': -1, 'max_row': 0, 'hash': 'c'},
            {'id': 'a', 'point': -1, 'max_row': 10, 'hash': 'd'},
            FakeBroker(), -1)), False)

    def test_run_once(self):
        replicator = TestReplicator({})
        replicator.run_once()

    def test_usync(self):
        fake_http = ReplHttp()
        replicator = TestReplicator({})
        replicator._usync_db(0, FakeBroker(), fake_http, '12345', '67890')

    def test_repl_to_node(self):
        replicator = TestReplicator({})
        fake_node = {'ip': '127.0.0.1', 'device': 'sda1', 'port': 1000}
        fake_info = {'id': 'a', 'point': -1, 'max_row': 0, 'hash': 'b',
                    'created_at': 100, 'put_timestamp': 0,
                    'delete_timestamp': 0,
                    'metadata': {'Test': ('Value', normalize_timestamp(1))}}
        replicator._http_connect = lambda *args: ReplHttp(
                                                   '{"id": 3, "point": -1}')
        self.assertEquals(replicator._repl_to_node(
            fake_node, FakeBroker(), '0', fake_info), True)

    def test_stats(self):
        # I'm not sure how to test that this logs the right thing,
        # but we can at least make sure it gets covered.
        replicator = TestReplicator({})
        replicator._zero_stats()
        replicator._report_stats()

    def test_replicate_object(self):
        db_replicator.ring = FakeRingWithNodes()
        replicator = TestReplicator({})
        replicator.delete_db = self.stub_delete_db
        replicator._replicate_object('0', '/path/to/file', 'node_id')
        self.assertEquals([], self.delete_db_calls)

    def test_replicate_object_quarantine(self):
        replicator = TestReplicator({})
        was_db_file = replicator.brokerclass.db_file
        try:

            def mock_renamer(was, new, cause_colision=False):
                if cause_colision and '-' not in new:
                    raise OSError(errno.EEXIST, "File already exists")
                self.assertEquals('/a/b/c/d/e', was)
                if '-' in new:
                    self.assert_(
                        new.startswith('/a/quarantined/containers/e-'))
                else:
                    self.assertEquals('/a/quarantined/containers/e', new)

            def mock_renamer_error(was, new):
                return mock_renamer(was, new, cause_colision=True)
            was_renamer = db_replicator.renamer
            db_replicator.renamer = mock_renamer
            replicator.brokerclass.get_repl_missing_table = True
            replicator.brokerclass.db_file = '/a/b/c/d/e/hey'
            replicator._replicate_object('0', 'file', 'node_id')
            # try the double quarantine
            db_replicator.renamer = mock_renamer_error
            replicator._replicate_object('0', 'file', 'node_id')
        finally:
            replicator.brokerclass.db_file = was_db_file
            db_replicator.renamer = was_renamer

    def test_replicate_object_delete_because_deleted(self):
        replicator = TestReplicator({})
        try:
            replicator.delete_db = self.stub_delete_db
            replicator.brokerclass.stub_replication_info = {
                'delete_timestamp': 2, 'put_timestamp': 1, 'count': 0}
            replicator._replicate_object('0', '/path/to/file', 'node_id')
        finally:
            replicator.brokerclass.stub_replication_info = None
        self.assertEquals(['/path/to/file'], self.delete_db_calls)

    def test_replicate_object_delete_because_not_shouldbehere(self):
        replicator = TestReplicator({})
        replicator.delete_db = self.stub_delete_db
        replicator._replicate_object('0', '/path/to/file', 'node_id')
        self.assertEquals(['/path/to/file'], self.delete_db_calls)

    def test_delete_db(self):
        db_replicator.lock_parent_directory = lock_parent_directory
        replicator = TestReplicator({})
        replicator._zero_stats()
        replicator.extract_device = lambda _: 'some_device'
        replicator.logger = FakeLogger()

        temp_dir = mkdtemp()
        try:
            temp_suf_dir = os.path.join(temp_dir, '16e')
            os.mkdir(temp_suf_dir)
            temp_hash_dir = os.path.join(temp_suf_dir,
                                         '166e33924a08ede4204871468c11e16e')
            os.mkdir(temp_hash_dir)
            temp_file = NamedTemporaryFile(dir=temp_hash_dir, delete=False)
            temp_hash_dir2 = os.path.join(temp_suf_dir,
                                         '266e33924a08ede4204871468c11e16e')
            os.mkdir(temp_hash_dir2)
            temp_file2 = NamedTemporaryFile(dir=temp_hash_dir2, delete=False)

            # sanity-checks
            self.assertTrue(os.path.exists(temp_dir))
            self.assertTrue(os.path.exists(temp_suf_dir))
            self.assertTrue(os.path.exists(temp_hash_dir))
            self.assertTrue(os.path.exists(temp_file.name))
            self.assertTrue(os.path.exists(temp_hash_dir2))
            self.assertTrue(os.path.exists(temp_file2.name))
            self.assertEqual(0, replicator.stats['remove'])

            replicator.delete_db(temp_file.name)

            self.assertTrue(os.path.exists(temp_dir))
            self.assertTrue(os.path.exists(temp_suf_dir))
            self.assertFalse(os.path.exists(temp_hash_dir))
            self.assertFalse(os.path.exists(temp_file.name))
            self.assertTrue(os.path.exists(temp_hash_dir2))
            self.assertTrue(os.path.exists(temp_file2.name))
            self.assertEqual([(('removes.some_device',), {})],
                             replicator.logger.log_dict['increment'])
            self.assertEqual(1, replicator.stats['remove'])

            replicator.delete_db(temp_file2.name)

            self.assertTrue(os.path.exists(temp_dir))
            self.assertFalse(os.path.exists(temp_suf_dir))
            self.assertFalse(os.path.exists(temp_hash_dir))
            self.assertFalse(os.path.exists(temp_file.name))
            self.assertFalse(os.path.exists(temp_hash_dir2))
            self.assertFalse(os.path.exists(temp_file2.name))
            self.assertEqual([(('removes.some_device',), {})] * 2,
                             replicator.logger.log_dict['increment'])
            self.assertEqual(2, replicator.stats['remove'])
        finally:
            rmtree(temp_dir)

    def test_extract_device(self):
        replicator = TestReplicator({'devices': '/some/root'})
        self.assertEqual('some_device', replicator.extract_device(
            '/some/root/some_device/deeper/and/deeper'))

#    def test_dispatch(self):
#        rpc = db_replicator.ReplicatorRpc('/', '/', FakeBroker, False)
#        no_op = lambda *args, **kwargs: True
#        self.assertEquals(rpc.dispatch(('drv', 'part', 'hash'), ('op',)
#                ).status_int, 400)
#        rpc.mount_check = True
#        self.assertEquals(rpc.dispatch(('drv', 'part', 'hash'), ['op',]
#                ).status_int, 507)
#        rpc.mount_check = False
#        rpc.rsync_then_merge = lambda drive, db_file,
#                                      args: self.assertEquals(args, ['test1'])
#        rpc.complete_rsync = lambda drive, db_file,
#                                      args: self.assertEquals(args, ['test2'])
#        rpc.dispatch(('drv', 'part', 'hash'), ['rsync_then_merge','test1'])
#        rpc.dispatch(('drv', 'part', 'hash'), ['complete_rsync','test2'])
#        rpc.dispatch(('drv', 'part', 'hash'), ['other_op',])

    def test_rsync_then_merge(self):
        rpc = db_replicator.ReplicatorRpc('/', '/', FakeBroker, False)
        rpc.rsync_then_merge('sda1', '/srv/swift/blah', ('a', 'b'))

    def test_merge_items(self):
        rpc = db_replicator.ReplicatorRpc('/', '/', FakeBroker, False)
        fake_broker = FakeBroker()
        args = ('a', 'b')
        rpc.merge_items(fake_broker, args)
        self.assertEquals(fake_broker.args, args)

    def test_merge_syncs(self):
        rpc = db_replicator.ReplicatorRpc('/', '/', FakeBroker, False)
        fake_broker = FakeBroker()
        args = ('a', 'b')
        rpc.merge_syncs(fake_broker, args)
        self.assertEquals(fake_broker.args, (args[0],))

    def test_roundrobin_datadirs(self):
        listdir_calls = []
        isdir_calls = []
        exists_calls = []
        shuffle_calls = []

        def _listdir(path):
            listdir_calls.append(path)
            if not path.startswith('/srv/node/sda/containers') and \
                    not path.startswith('/srv/node/sdb/containers'):
                return []
            path = path[len('/srv/node/sdx/containers'):]
            if path == '':
                return ['123', '456', '789']  # 456 will pretend to be a file
            elif path == '/123':
                return ['abc', 'def.db']  # def.db will pretend to be a file
            elif path == '/123/abc':
                # 11111111111111111111111111111abc will pretend to be a file
                return ['00000000000000000000000000000abc',
                        '11111111111111111111111111111abc']
            elif path == '/123/abc/00000000000000000000000000000abc':
                return ['00000000000000000000000000000abc.db',
                        # This other.db isn't in the right place, so should be
                        # ignored later.
                        '000000000000000000000000000other.db',
                        'weird1']  # weird1 will pretend to be a dir, if asked
            elif path == '/789':
                return ['ghi', 'jkl']  # jkl will pretend to be a file
            elif path == '/789/ghi':
                # 33333333333333333333333333333ghi will pretend to be a file
                return ['22222222222222222222222222222ghi',
                        '33333333333333333333333333333ghi']
            elif path == '/789/ghi/22222222222222222222222222222ghi':
                return ['22222222222222222222222222222ghi.db',
                        'weird2']  # weird2 will pretend to be a dir, if asked
            return []

        def _isdir(path):
            isdir_calls.append(path)
            if not path.startswith('/srv/node/sda/containers') and \
                    not path.startswith('/srv/node/sdb/containers'):
                return False
            path = path[len('/srv/node/sdx/containers'):]
            if path in ('/123', '/123/abc',
                        '/123/abc/00000000000000000000000000000abc',
                        '/123/abc/00000000000000000000000000000abc/weird1',
                        '/789', '/789/ghi',
                        '/789/ghi/22222222222222222222222222222ghi',
                        '/789/ghi/22222222222222222222222222222ghi/weird2'):
                return True
            return False

        def _exists(arg):
            exists_calls.append(arg)
            return True

        def _shuffle(arg):
            shuffle_calls.append(arg)

        orig_listdir = db_replicator.os.listdir
        orig_isdir = db_replicator.os.path.isdir
        orig_exists = db_replicator.os.path.exists
        orig_shuffle = db_replicator.random.shuffle
        try:
            db_replicator.os.listdir = _listdir
            db_replicator.os.path.isdir = _isdir
            db_replicator.os.path.exists = _exists
            db_replicator.random.shuffle = _shuffle
            datadirs = [('/srv/node/sda/containers', 1),
                        ('/srv/node/sdb/containers', 2)]
            results = list(db_replicator.roundrobin_datadirs(datadirs))
            # The results show that the .db files are returned, the devices
            # interleaved.
            self.assertEquals(results, [
                ('123', '/srv/node/sda/containers/123/abc/'
                        '00000000000000000000000000000abc/'
                        '00000000000000000000000000000abc.db', 1),
                ('123', '/srv/node/sdb/containers/123/abc/'
                        '00000000000000000000000000000abc/'
                        '00000000000000000000000000000abc.db', 2),
                ('789', '/srv/node/sda/containers/789/ghi/'
                        '22222222222222222222222222222ghi/'
                        '22222222222222222222222222222ghi.db', 1),
                ('789', '/srv/node/sdb/containers/789/ghi/'
                        '22222222222222222222222222222ghi/'
                        '22222222222222222222222222222ghi.db', 2)])
            # The listdir calls show that we only listdir the dirs
            self.assertEquals(listdir_calls, [
                '/srv/node/sda/containers',
                '/srv/node/sda/containers/123',
                '/srv/node/sda/containers/123/abc',
                '/srv/node/sdb/containers',
                '/srv/node/sdb/containers/123',
                '/srv/node/sdb/containers/123/abc',
                '/srv/node/sda/containers/789',
                '/srv/node/sda/containers/789/ghi',
                '/srv/node/sdb/containers/789',
                '/srv/node/sdb/containers/789/ghi'])
            # The isdir calls show that we did ask about the things pretending
            # to be files at various levels.
            self.assertEquals(isdir_calls, [
                '/srv/node/sda/containers/123',
                '/srv/node/sda/containers/123/abc',
                ('/srv/node/sda/containers/123/abc/'
                 '00000000000000000000000000000abc'),
                '/srv/node/sdb/containers/123',
                '/srv/node/sdb/containers/123/abc',
                ('/srv/node/sdb/containers/123/abc/'
                 '00000000000000000000000000000abc'),
                ('/srv/node/sda/containers/123/abc/'
                 '11111111111111111111111111111abc'),
                '/srv/node/sda/containers/123/def.db',
                '/srv/node/sda/containers/456',
                '/srv/node/sda/containers/789',
                '/srv/node/sda/containers/789/ghi',
                ('/srv/node/sda/containers/789/ghi/'
                 '22222222222222222222222222222ghi'),
                ('/srv/node/sdb/containers/123/abc/'
                 '11111111111111111111111111111abc'),
                '/srv/node/sdb/containers/123/def.db',
                '/srv/node/sdb/containers/456',
                '/srv/node/sdb/containers/789',
                '/srv/node/sdb/containers/789/ghi',
                ('/srv/node/sdb/containers/789/ghi/'
                 '22222222222222222222222222222ghi'),
                ('/srv/node/sda/containers/789/ghi/'
                 '33333333333333333333333333333ghi'),
                '/srv/node/sda/containers/789/jkl',
                ('/srv/node/sdb/containers/789/ghi/'
                 '33333333333333333333333333333ghi'),
                '/srv/node/sdb/containers/789/jkl'])
            # The exists calls are the .db files we looked for as we walked the
            # structure.
            self.assertEquals(exists_calls, [
                ('/srv/node/sda/containers/123/abc/'
                 '00000000000000000000000000000abc/'
                 '00000000000000000000000000000abc.db'),
                ('/srv/node/sdb/containers/123/abc/'
                 '00000000000000000000000000000abc/'
                 '00000000000000000000000000000abc.db'),
                ('/srv/node/sda/containers/789/ghi/'
                 '22222222222222222222222222222ghi/'
                 '22222222222222222222222222222ghi.db'),
                ('/srv/node/sdb/containers/789/ghi/'
                 '22222222222222222222222222222ghi/'
                 '22222222222222222222222222222ghi.db')])
            # Shows that we called shuffle twice, once for each device.
            self.assertEquals(
                shuffle_calls, [['123', '456', '789'], ['123', '456', '789']])
        finally:
            db_replicator.os.listdir = orig_listdir
            db_replicator.os.path.isdir = orig_isdir
            db_replicator.os.path.exists = orig_exists
            db_replicator.random.shuffle = orig_shuffle

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


from AccessControl import ClassSecurityInfo
from AccessControl.class_init import InitializeClass
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from zope.interface import Interface
from ZPublisher import xmlrpc

from ..interfaces.plugins import IRequestTypeSniffer
from ..interfaces.request import IBrowserRequest
from ..interfaces.request import IWebDAVRequest
from ..interfaces.request import IXMLRPCRequest
from ..plugins.BasePlugin import BasePlugin
from ..utils import classImplements

class IRequestTypeSnifferPlugin(Interface):
    """ Marker interface.
    """

_sniffers = ()

def registerSniffer(iface, func):
    global _sniffers
    registry = list(_sniffers)
    registry.append((iface, func))
    _sniffers = tuple(registry)

manage_addRequestTypeSnifferForm = PageTemplateFile(
    'www/rtsAdd', globals(), __name__='manage_addRequestTypeSnifferForm')

def addRequestTypeSnifferPlugin(dispatcher, id, title=None, REQUEST=None):
    """ Add a RequestTypeSnifferPlugin to a Pluggable Auth Service. """

    rts = RequestTypeSniffer(id, title)
    dispatcher._setObject(rts.getId(), rts)

    if REQUEST is not None:
        REQUEST['RESPONSE'].redirect('%s/manage_workspace'
                                     '?manage_tabs_message='
                                     'RequestTypeSniffer+added.' %
                                     dispatcher.absolute_url())

class RequestTypeSniffer(BasePlugin):

    """ PAS plugin for detecting a Request's type
    """
    meta_type = 'Request Type Sniffer Plugin'
    zmi_icon = 'fas fa-broadcast-tower'

    security = ClassSecurityInfo()

    def __init__(self, id, title=None):

        self._id = self.id = id
        self.title = title

    @security.private
    def sniffRequestType(self, request):
        found = None
        for iface, func in _sniffers:
            if func(request):
                found = iface

        if found is not None:
            return found

classImplements(RequestTypeSniffer, IRequestTypeSnifferPlugin,
                IRequestTypeSniffer)

InitializeClass(RequestTypeSniffer)

# Most of the sniffing code below has been inspired by
# similar tests found in BaseRequest, HTTPRequest and ZServer
def webdavSniffer(request):
    dav_src = request.get('WEBDAV_SOURCE_PORT', None)
    method = request.get('REQUEST_METHOD', 'GET').upper()
    path_info = request.get('PATH_INFO', '')

    if dav_src:
        return True

    if request.maybe_webdav_client and method not in ('GET', 'POST'):
        return True

    if method in ('GET',) and path_info.endswith('manage_DAVget'):
        return True

registerSniffer(IWebDAVRequest, webdavSniffer)

def xmlrpcSniffer(request):
    response = request['RESPONSE']
    method = request.get('REQUEST_METHOD', 'GET').upper()

    if method in ('GET', 'POST') and isinstance(response, xmlrpc.Response):
        return True

registerSniffer(IXMLRPCRequest, xmlrpcSniffer)

def browserSniffer(request):
    # If it's none of the above, it's very likely a browser request.
    for sniffer in (xmlrpcSniffer, webdavSniffer):
        if sniffer is not None and sniffer(request):
            return False

    return True

registerSniffer(IBrowserRequest, browserSniffer)


from nltk import pos_tag
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

def get_user_name(user_input):
    common_word = ["name", "people", "please", "call", "me", "my", "change"]

    tokens = word_tokenize(user_input)

    # Remove text that is present in the COMMON_WORD , stopword list and not alphabetic letters
    user_name = [token for token in tokens
                 if not token.lower() in common_word and not token.lower() in stopwords.words(
            'english') and token.isalpha()]

    user_name = " ".join(user_name)

    return user_name.title()


# Isomorphic Strings
#
# [Easy] [AC:39.6% 291.8K of 736.9K] [filetype:python3]
#
# Given two strings s and t, determine if they are isomorphic.
#
# Two strings are isomorphic if the characters in s can be replaced
# to get t.
#
# All occurrences of a character must be replaced with another
# character while preserving the order of characters. No two
# characters may map to the same character but a character may map to
# itself.
#
# Example 1:
#
# Input: s = "egg", t = "add"
#
# Output: true
#
# Example 2:
#
# Input: s = "foo", t = "bar"
#
# Output: false
#
# Example 3:
#
# Input: s = "paper", t = "title"
#
# Output: true
#
# Note:
#
# You may assume both s and t have the same length.
#
# [End of Description]:
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False
        alph = {}
        for i in range(len(s)):
            # first we need to check if s[i] already in alph
            if s[i] in alph.keys():
                # s[i] in alph, then we need to check if t[i] matches its value
                # we cannot make it an 'and' condition
                if alph[s[i]] != t[i]:
                    return False
            # s[i] not in alph, then before we add it to alph,
            # we need to confirm t[i] is not in alph
            elif t[i] in list(alph.values()):
                return False
            else:
                alph[s[i]] = t[i]
        return True


import json
from typing import List

def isSingleChannel(lac: str)->bool:
    s = lac.split("_")
    if len(s) > 2:
        return True
    return False

def isModuleAddress(lac: str)->bool:
    s = lac.split("_")
    if len(s) > 2:
        return False
    if len(s) > 1:
        return True
    return False

def getTransitions(transitions: str)->List[str]:
    jobjtransitions = json.loads(transitions)
    return jobjtransitions['TRANSITION']

def getTransitionNames(transitions: str)->List[str]:
    rv = []
    tr = getTransitions(transitions)
    for t in tr:
        for name in t:
            rv.append(name)
    return rv

def getStatusValue(channel: str, item: str, statusjsonstr: str):
    allj = json.loads(statusjsonstr)
    for it in allj:
        if it == channel:
            objects = allj[channel]
            for cmd in objects:
                if cmd == item:
                    vu = objects[cmd]
                    return vu['v']
    return None

def getGroupNames(groups: str)->List[str]:
    rv = []
    jobjgroups = json.loads(groups)
    groups = jobjgroups['GROUP']
    for group in groups:
        # pylint: disable=unused-variable
        for key, val in group.items():
            rv.append(key)
    return rv

def getChannels(groups: str, groupname: str)->List[str]:
    rv = []
    jobjgroups = json.loads(groups)
    ggroups = jobjgroups['GROUP']

    for group in ggroups:
        for key, val in group.items():
            if key == groupname:
                channels = val["CHANNEL"]
                for ch in channels:
                    rv.append(ch)
    return rv


from games.pole import pole_launcher
from games.pixelcopter import pixel_launcher

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Parameter parser')
    parser.add_argument('--game', type=str, help='Game to play')
    args = parser.parse_args()
    game = args.game
    if game == 'pole':
        print(f'Playing pole!')
        pole_launcher()
    elif game == 'pixel':
        print(f'Playing pixelcopter!')
        pixel_launcher()


#!/usr/bin/env python
"""
Created on 02 15, 2023

model: main.py

@Author: Stormzudi
"""
from Code.GAMCLDA.utils import bulid_graph, buildDataLoder
from Code.GAMCLDA.model import GAMCLDA
import torch
from torch_geometric.utils import negative_sampling
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import train_test_split
import pandas as pd
import os
import datetime

# ========================== Args ========================
args = {
    "num_edges": 18789
    , "num_features": 233
    , "num_nodes": 828
    , "hidden_channels": [256]
    , "out_channels": 128
    , "n_class_size": 64
    , "lncRNA-miRNA": "../../dataset/lncRNA_miRNA_association.csv"
    , "disease-miRNA": "../../dataset/miRNA_disease_association.csv"
    , "weight": [0.7, 0.3] # [miRNA, node2vec]
    , "dropout": 0.0
    , "epoch": 10
}

path = "../../dataset/valdata/"
index, edges_index, node_attr, label = bulid_graph(path)

# 1 load dataset
train_data, val_data, test_data = buildDataLoder(node_attr, edges_index, y=label)

# 2 define model
gamclda = GAMCLDA(
    num_features=args['num_features'],hidden_channels=args['out_channels'],num_classes=args['n_class_size'])
model = gamclda.model()

# 3 define optimization
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
criterion = torch.nn.BCEWithLogitsLoss()

# 4 train
def train():
    model.train()

    optimizer.zero_grad()
    z = model(train_data.x, train_data.edge_index)

    # We perform a new round of negative sampling for every training epoch:
    neg_edge_index = negative_sampling(
        edge_index=train_data.edge_index, num_nodes=train_data.num_nodes,
        num_neg_samples=train_data.edge_label_index.size(1))

    # add edges (train_edge, neg_edge)
    edge_label_index = torch.cat(
        [train_data.edge_label_index, neg_edge_index],
        dim=-1,
    )

    # label
    edge_label = torch.cat([
        train_data.edge_label,
        train_data.edge_label.new_zeros(neg_edge_index.size(1))
    ], dim=0)

    out = model.decode(z, edge_label_index).view(-1)
    loss = criterion(out, edge_label)
    loss.backward()
    train_auc = roc_auc_score(edge_label.numpy(), out.detach().numpy())
    optimizer.step()

    # save auc score
    data_ = pd.DataFrame({
        'pred': out.detach().numpy(),
        'labels': edge_label.numpy()
    })
    date = datetime.date.today()
    data_.to_csv("{}_GAMCLDA_0.87.csv".format(date))
    return loss, train_auc

@torch.no_grad()
def test(data):
    model.eval()
    z = model(data.x, data.edge_index)
    out = model.decode(z, data.edge_label_index).view(-1).sigmoid()
    return roc_auc_score(data.edge_label.cpu().numpy(), out.cpu().numpy())

# ======================
# ==== Train  =======================
best_val_auc = final_test_auc = 0
for epoch in range(1, args["epoch"]):
    loss, train_auc= train()
    val_auc = test(val_data)
    test_auc = test(test_data)
    if val_auc > best_val_auc:
        best_val_auc = val_auc
        final_test_auc = test_auc

    print(f'Epoch: {epoch:03d}, '
          f'Loss: {loss:.4f}, '
          f'train: {train_auc:.4f}, '
          f'Val: {val_auc:.4f}, '
          f'Test: {test_auc:.4f}')


"""
2. * (вместо задачи 1) Доработать предыдущую функцию в num_translate_adv(): реализовать корректную работу
с числительными, начинающимися с заглавной буквы — результат тоже должен быть с заглавной. Например:
num_translate_adv("One")
"Один"
num_translate_adv("two")
"два
"""

def num_translate_adv(any_num):
    internal_dict = {
        'zero': 'ноль',
        'one': 'один',
        'two': 'два',
        'three': 'три',
        'four': 'четыре',
        'five': 'пять',
        'six': 'шесть',
        'seven': 'семь',
        'eight': 'восемь',
        'nine': 'девять',
        'ten': 'десять'
    }

    if any_num.istitle():
        return internal_dict[any_num.lower()].capitalize()

    return internal_dict[any_num]

# список со значениями, которые нужно получить от пользователя
eng_num_lst = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']
capit_eng_num_lts = [i.capitalize() for i in eng_num_lst]
what_number = None

# Запрос числа от пользователя и вызов функции
while what_number not in eng_num_lst and what_number not in capit_eng_num_lts:
    what_number = input('Введите число на англйском от 0 до 10, которое нужно перевести: ')
else:
    print(f'"{what_number}" перевод на русский - {num_translate_adv(what_number)}')


import pandas as pd
import matplotlib.pyplot as plt
#
# plt.style.use('ggplot')
# res = pd.read_csv("resnet44_benchmark_a0d5e4lr01_11111_0.0.csv")
# fixup = pd.read_csv("fixup_resnet44_benchmark_a0d5e4lr01_11111_0.0Meng_complete.csv")
# fig_1 = plt.figure(figsize=(8,4))
# ax_1 = fig_1.add_subplot(111)
#
#
# ax_1.set_ylabel("Loss")
# ax_1.set_xlabel("Epoch number")
# ax_1.plot(res["epoch"],res['train loss'])
# ax_1.plot(res["epoch"],res['test loss'])
#
# ax_1.plot(fixup["epoch"],fixup['train loss'])
# ax_1.plot(fixup["epoch"],fixup['test loss'])
#
# ax_1.legend(("resnet_44_train_loss","resnet_44_test_loss","fixup_44_train_loss","fixup_44_test_loss"))
# fig_2 = plt.figure(figsize=(8,4))
# ax_2 = fig_2.add_subplot(111)
#
#
# ax_2.set_ylabel("Acc")
# ax_2.set_xlabel("Epoch number")
#
# ax_2.plot(res["epoch"],res['train acc'])
# ax_2.plot(res["epoch"],res['test acc'])
#
# ax_2.plot(fixup["epoch"],fixup['train acc'])
# ax_2.plot(fixup["epoch"],fixup['test acc'])
#
# ax_2.legend(("resnet_44_train_acc","resnet_44_test_acc","fixup_44_train_acc","fixup_44_test_acc"))
#
# fig_1.savefig('44_loss.pdf',dpi = None,facecolor = 'w',edgecolor = 'w',orientation = 'portrait',papertype = None, format = 'pdf',transparent=False,bbox_inches=None,pad_inches=0.1,frameon = None, metadata = None)
# fig_2.savefig('44_acc.pdf',dpi = None,facecolor = 'w',edgecolor = 'w',orientation = 'portrait',papertype = None, format = 'pdf',transparent=False,bbox_inches=None,pad_inches=0.1,frameon = None, metadata = None)
# plt.show()

plt.style.use('ggplot')
tt1 = pd.read_csv("0.0SGDR_1T.csv")
tt10 = pd.read_csv("0.0SGDR_10T.csv")
tt50 = pd.read_csv("0.0SGDR_50T.csv")
tt100 = pd.read_csv("0.0SGDR_100T.csv")
tt200 = pd.read_csv("0.0SGDR_200T.csv")

fig_1 = plt.figure(figsize=(8,4))
ax_1 = fig_1.add_subplot(111)

ax_1.set_ylabel("Test Acc")
ax_1.set_xlabel("Epoch number")

ax_1.plot(tt1["epoch"],tt1['test acc'])
ax_1.plot(tt10["epoch"],tt10['test acc'])
ax_1.plot(tt50["epoch"],tt50['test acc'])
ax_1.plot(tt100["epoch"],tt100['test acc'])
ax_1.plot(tt200["epoch"],tt200['test acc'])
ax_1.legend(('1','10','50','100','200'))
plt.show()


from random import randint
import os
import time

os.system('cls')

print("Program do trenowania mnożenia. Wpisz 'q', aby zakończyć.")

first = [value_first for value_first in range(0,10)]
second = [value_second for value_second in range(0,10)]

active = True
while active:
    a = first[randint(0,9)]

    b = second[randint(0,9)]

    answer = input(f"{a} x {b} = ")
    if answer == 'q':
        active = False
    else:
        answer = int(answer)
        try:
            if answer == a * b:
                print("Correct!")
                time.sleep(0.5)
                os.system('cls')
            else:
                print("Incorrect!")
                time.sleep(0.5)
                os.system('cls')
        except ValueError:
            print("Unexpected input value!")
            time.sleep(0.5)
            os.system('cls')