import datetime
from time import sleep

from django.core.urlresolvers import reverse

from ft.base import FunctionalTestBase

class ItemPurchaseFormVisit(FunctionalTestBase):
    """
    Test for item purchase form actions when user opens the pop-up via
    "Purchase" button on item maintenance page.

    """

    test_uri = reverse('item_maintenance')

    test_data_items = [
        {'name': 'test item #1', 'extended_threshold': 5, },
        {'name': 'test item #2', },
    ]

    def test_submitting_form_blank_fields_show_the_error_messages(self):
        """
        Verify that hitting the submit button with quantity field blank on the
        form is showing the appropriate error message.

        """

        error_messages = [
            'Quantity cannot be blank',
            'Quantity must be a number',
        ]

        # Shopper opens the add item form
        modal = self.open_purchase_item_form(1)

        # Form shows no error messages
        for msg in error_messages:
            self.assertNotIn(msg, modal.text)

        # then she and click the submit button.
        modal.find_element_by_css_selector(
            '.modal-footer button.btn-primary').click()

        # Error message is displayed saying that name is required
        self.assertIn(error_messages[0], modal.text)

        # Then shopper start to enter a non-numeric text to quantity, and the
        # message now says that it should be a number.
        modal.find_element_by_id('id_quantity').send_keys('a')
        self.assertIn(error_messages[1], modal.text)

        # Entering a numeric value in the quantity box clears the error
        # message.
        modal.find_element_by_id('id_quantity').clear()
        modal.find_element_by_id('id_quantity').send_keys('1')
        self.assertNotIn(error_messages[0], modal.text)
        self.assertNotIn(error_messages[1], modal.text)

    def test_focus_on_date_brings_up_the_datepicker(self):
        """
        Verify the focusing on the (readonly) date field rinds up the
        datepicker dialog.

        """

        # Shopper opens the add item form
        modal = self.open_purchase_item_form(1)

        # and click on the date text box
        modal.find_element_by_id('id_date').click()

        # Datepicker pop-up is not visible
        self.assertTrue(modal.find_element_by_class_name(
            'purchase-date').is_displayed())

    def test_saved_purchas_date_show_up_in_the_items_table(self):
        """
        Verify that after adding a new purchase,the date in the item list gets
        updated.

        """

        # Shopper opens the add item form,
        modal = self.open_purchase_item_form(1)

        # enter a quantity value
        modal.find_element_by_id('id_quantity').send_keys('1')

        # then she and click the submit button.
        modal.find_element_by_css_selector(
            '.modal-footer button.btn-primary').click()

        # wait for the animation
        sleep(.1)

        # Purchase date now shows up in the item maintenance page
        self.assertIn(datetime.date.today().strftime('%B, %-d'),
                      self.browser.find_element_by_css_selector(
                          '.items-table tbody tr:nth-child(1) .last_purchase')
                      .text)
        self.assertEqual('21 days',
                         self.browser.find_element_by_css_selector(
                             '.items-table tbody tr:nth-child(1) ' +
                             '.purchase_threshold').text)


from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium import webdriver

class BasePage():

    def __init__(self, driver):
        self.driver = driver
        self.driver.maximize_window()
        self.wait = WebDriverWait(self.driver, 5)
        self.actions = ActionChains(self.driver)
        if self.url:
            self.driver.get(self.url)

    def click(self, locator):
        try:
            self.wait.until(
                EC.element_to_be_clickable((*locator,))
            )
            self.driver.find_element(*locator).click()
        except Exception as err:
            print("Element not found or clickable. Error: ", err)
            raise

    def click_js(self, locator):
        try:
            self.wait.until(
                EC.element_to_be_clickable((*locator,))
            )
            field = self.driver.find_element(*locator)
            self.driver.execute_script("arguments[0].click();", field)
        except Exception as err:
            print("Element not found or clickable. Error: ", err)
            raise

    def enter_text(self, locator, text):
        try:
            self.wait.until(
                EC.visibility_of_element_located((*locator,))
            )
        except Exception as err:
            print("Unable to find input field. Error: ", err)
            raise
        self.driver.find_element(*locator).send_keys(text)

    def get_element(self, locator):
        try:
            self.wait.until(
                EC.visibility_of_element_located((*locator,))
            )
        except Exception as err:
            print("Unable to find element. Error: ", err)
            raise
        return self.driver.find_element(*locator)

    def wait_until_not_visible(self, locator):
        try:
            self.wait.until(
                EC.invisibility_of_element_located((*locator,))
            )
        except Exception as err:
            print("Element still visbile. Error: ", err)
            raise

    def wait_until_visible(self, locator):
        try:
            self.wait.until(
                EC.visibility_of_element_located((*locator,))
            )
        except Exception as err:
            print("Element not found. Error: ", err)
            raise

    def is_element_visibile(self, locator):
        try:
            self.wait.until(
                EC.visibility_of_element_located((*locator,))
            )
            return True
        except Exception as err:
            print("Cound not find element. Error: ", err)
            return False

    def get_all_elements(self, locator):
        try:
            self.wait_until_visible(locator)
            elements = self.driver.find_elements(*locator)
            return elements
        except Exception as err:
            print("Could not find elements. Error: ", err)
            raise

    def get_current_url(self):
        return self.driver.current_url


import sys
import time
from collections import namedtuple
from tuplestate import *
from timebudget import timebudget
from policies import *

sys.setrecursionlimit(10 ** 6)

def solve(state, max_states=50_000, **solver_params):
    visited = set()
    moveseq = []
    i = 0
    while True:
        v = len(visited)
        if i >= max_states:
            return EndState(solved=False, visited=v, msg="exceeded max states")
        if state in visited:
            return EndState(solved=False, msg="revisited state", visited=v)
        visited.add(state)
        # Yan et al. Section 4 "Machine Play"
        # 1. identify set of legal moves
        result = yan_et_al_rollout(state, **solver_params)
        # 2. select and execute a legal move
        if result is None:
            return EndState(solved=False, msg="no avail moves", visited=v)
        if hasattr(result, "solved"):
            return result  # solved in rollout
        # otherwise the rollout gives the old heuristic strategy
        action = result
        moveseq.append(action)
        state = play_move(state, action)
        # 3. If all cards are on suit stacks, declare victory and terminate.
        if state_is_win(state):
            return EndState(solved=True, moveseq=moveseq, visited=v)
        # 4. If new card configuration repeats a previous one, declare loss and terminate.
        # 5. Repeat procedure.
        i += 1

if __name__ == "__main__":
    from benchmarking import convert_shootme_to_solvitaire_json

    timebudget.report_atexit()

    import os

    for fname in os.listdir("./fixtures/shootme/solvedmin"):
        with open(f"./fixtures/shootme/solvedmin/{fname}") as f:
            ret = f.read()
        print(fname)
        deck_json = convert_shootme_to_solvitaire_json(ret)
        state = init_from_solvitaire(deck_json)
        solution = solve(state, max_states=100_000, k=1)
        # print()
        if solution.solved:
            moveseq = list(solution.moveseq)
            visited = solution.visited
            print(f"solved, visited {visited} states, solved in {len(moveseq)} moves")
            # print(moveseq)
        else:
            print("no solution")
        # print()


from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import unittest
from SampleProjects.POMDemo.Pages.loginPage import LoginPage
from SampleProjects.POMDemo.Pages.homePage import HomePage
import HtmlTestRunner
class LoginTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Chrome(executable_path="drivers/chromedriver.exe")
        cls.driver.implicitly_wait(10)
        cls.driver.maximize_window()

    def test01_login_valid(self):
        driver = self.driver
        driver.get("https://opensource-demo.orangehrmlive.com/")
        login = LoginPage(driver)
        login.enter_username("Admin")
        login.enter_password("admin123")
        login.click_login()

        homepage = HomePage(driver)
        homepage.click_welcome()
        homepage.click_logout()
        time.sleep(2)

    def test02_login_invalid_username(self):
        driver = self.driver
        driver.get("https://opensource-demo.orangehrmlive.com/")
        login = LoginPage(driver)
        login.enter_username("Admin1")
        login.enter_password("admin123")
        login.click_login()
        message = driver.find_element(By.XPATH,"//p[@class='oxd-text oxd-text--p oxd-alert-content-text']").text
        self.assertEqual(message,"Invalid credentials")
        time.sleep(2)

    @classmethod
    def tearDownClass(cls):
        cls.driver.close()
        cls.driver.quit()
        print("Test Completed")

if __name__ == '__main__':
    unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output="reports"))


from sklearn.cluster import KMeans
from pathlib import Path
from threading import Thread
from configparser import ConfigParser
import json
import argparse
import numpy as np
import logging as log
import os
import pickle
import sys

class MakeYoloConfig:
    def __init__(
            self,
            config_file_name: str,
            classes_file_path: str,
            sys_config_path: str = './sys.ini',
            pretrain_file_path: str = '',
            model_type: str = 'yolov4',
            frame_work: str = 'tf',
            size: int = 416,
            batch_size: int = 4,
            epoch: int = 30,
            train_size: int = 1000,
            val_size: int = 200,
            tiny: bool = False,
            score_threshold: float = 0.25
    ):
        self.sys_config = ConfigParser()
        self.sys_config_file = Path(sys_config_path)
        self.name = config_file_name
        self.classes_file = Path(classes_file_path)
        self.pretrain_file = Path(pretrain_file_path) if pretrain_file_path else None
        self.model_type = model_type
        self.frame_work = frame_work
        self.size = size
        self.score_threshold = score_threshold
        self.batch_size = batch_size
        self.epoch = epoch
        self.warmup_epochs = 2
        self.first_stage_epochs = int(epoch * 1 / 5) if pretrain_file_path else 0
        self.second_stage_epochs = epoch - self.first_stage_epochs
        self.train_size = train_size
        self.test_size = val_size
        self.tiny = tiny
        self.yolo_config = {}
        self.classes = []
        self.anchors = []
        self.anchors_v3 = []
        self.anchors_tiny = []
        self.yolo_config_file: Path = Path()
        self.model_save_dir: Path = Path()
        self.train_set_dir: Path = Path()
        self.train_annotation_file: Path = Path()
        self.test_set_dir: Path = Path()
        self.test_annotation_file: Path = Path()
        self.checkpoints_save_dir: Path = Path()
        self.weights_save_dir: Path = Path()
        self.configs_save_dir: Path = Path()
        self.train_bbox_save_dir: Path = Path()
        self.test_bbox_save_dir: Path = Path()
        self.train_bbox_file: Path = Path()
        self.test_bbox_file: Path = Path()
        self.logdir: Path = Path()

    def make(self):
        self.check_all_paths()
        classes = self.load_classes()
        train = Thread(
            target=self.write,
            args=(self.train_annotation_file, self.train_bbox_file, classes, True)
        )
        test = Thread(
            target=self.write,
            args=(self.test_annotation_file, self.test_bbox_file, classes, False)
        )
        train.start()
        test.start()
        train.join()
        test.join()

        if not (self.train_bbox_file.is_file() and self.test_bbox_file.is_file()):
            self.train_bbox_file.unlink(missing_ok=True)
            self.test_bbox_file.unlink(missing_ok=True)
            raise RuntimeError('Writing Train bbox file or Test box file fail')

        self.write_yolo_config()

    def check_all_paths(self):
        if self.sys_config_file.is_file():
            log.info(f'System config file path: {self.sys_config_file.absolute()}')
            self.sys_config.read(self.sys_config_file.name)
        else:
            raise FileNotFoundError(self.sys_config_file.name)

        self.train_set_dir = Path(self.sys_config['Annotations']['train_set_dir'])
        self.train_annotation_file = Path(self.sys_config['Annotations']['train_annotation_path'])
        self.test_set_dir = Path(self.sys_config['Annotations']['test_set_dir'])
        self.test_annotation_file = Path(self.sys_config['Annotations']['test_annotation_path'])
        self.checkpoints_save_dir = Path(self.sys_config['Save_dir']['checkpoints'])
        self.weights_save_dir = Path(self.sys_config['Save_dir']['weights'])
        self.configs_save_dir = Path(self.sys_config['Save_dir']['configs'])
        self.yolo_config_file = self.configs_save_dir / Path(self.name).with_suffix('.json')
        self.model_save_dir = self.checkpoints_save_dir / self.name
        self.train_bbox_save_dir = Path(self.sys_config['Save_dir']['train_processed_data'])
        self.test_bbox_save_dir = Path(self.sys_config['Save_dir']['test_processed_data'])
        self.train_bbox_file = self.train_bbox_save_dir / Path(self.name).with_suffix('.bbox')
        self.test_bbox_file = self.test_bbox_save_dir / Path(self.name).with_suffix('.bbox')
        self.logdir = Path(self.sys_config['Save_dir']['logs']) / Path(self.name)

        checking_exist_dir_group = (
            self.train_set_dir,
            self.test_set_dir,
        )

        checking_exist_file_group = (
            self.classes_file,
            self.train_annotation_file,
            self.test_annotation_file,
        )

        make_dirs = (
            self.configs_save_dir,
            self.checkpoints_save_dir,
            self.weights_save_dir,
            self.train_bbox_save_dir,
            self.test_bbox_save_dir,
            self.logdir
        )

        rm_files = (
            self.train_bbox_file,
            self.test_bbox_file
        )

        for ex_dir in checking_exist_dir_group:
            if not ex_dir.is_dir():
                raise NotADirectoryError(ex_dir.absolute())

        for ex_file in checking_exist_file_group:
            if not ex_file.is_file():
                raise FileNotFoundError(str(ex_file.absolute()))

        for mk_dir in make_dirs:
            if not mk_dir.is_dir():
                os.makedirs(mk_dir.absolute(), exist_ok=True)
                log.info('Make dir %s' % str(mk_dir.absolute()))

        for rm_file in rm_files:
            if rm_file.is_file():
                rm_file.unlink(missing_ok=True)
                log.info('Remove exist file: %s' % str(rm_file.absolute()))

        if self.pretrain_file:
            if not self.pretrain_file.is_file():
                raise FileNotFoundError(str(self.pretrain_file.absolute()))

    def load_classes(self):
        with self.classes_file.open('r') as f:
            classes = [line.strip() for line in f.readlines()]
        return classes

    def write(self, annotation_file: Path, bbox_file: Path, classes: list, training: bool):
        try:
            self.write_coco2yolo(annotation_file, bbox_file, classes, training)
        except Exception as e:
            log.error(f'{e.__class__.__name__}({e.args})', exc_info=True)
            self.train_bbox_file.unlink(missing_ok=True)
            self.test_bbox_file.unlink(missing_ok=True)

    def write_coco2yolo(self, annotation_file: Path, bbox_file: Path, classes: list, training: bool):
        images, classes = self.load_annotation_file(annotation_file, classes)
        classes = {
            class_name: index
            for index, class_name in enumerate(classes)
        }
        done = 0
        anchor_boxes = []

        if training:
            data_save_dir = self.train_set_dir
            set_size = self.train_size
        else:
            data_save_dir = self.test_set_dir
            set_size = self.test_size

        with bbox_file.open('w') as bf:
            for image in images:
                image_file = data_save_dir / image['file_name']

                if done >= set_size:
                    break
                if not image_file.is_file() or len(image['items']) < 1:
                    continue

                bf.write(str(image_file.absolute()) + ' ')

                for item in image['items']:
                    bbox = item['bbox']
                    x_min = int(bbox[0])
                    y_min = int(bbox[1])
                    x_max = x_min + int(bbox[2])
                    y_max = y_min + int(bbox[3])
                    anchor_boxes.append(
                        (bbox[2],
                         bbox[3],
                         image['width'],
                         image['height'])
                    )

                    x_min, y_min, x_max, y_max = str(x_min), str(y_min), str(x_max), str(y_max)
                    label = str(classes[item['category_name']])
                    bf.write(','.join([x_min, y_min, x_max, y_max, label]) + ' ')

                bf.write('\n')
                done += 1

        if done < 1:
            raise RuntimeError('bbox file did not have any images')
        log.info(f'{bbox_file.name} have {done} images')

        if training:
            self.calculate_anchor_box(anchor_boxes)
            self.classes = list(classes.keys())

    def load_annotation_file(self, file: Path, classes: list):
        log.info(f'Start loading annotation file: {file.absolute()}')
        if file.suffix == '.pickle':
            with file.open('rb') as f:
                data = pickle.load(f)
                np.random.shuffle(data['images'])
                np.random.shuffle(data['annotations'])
        elif file.suffix == '.json':
            with file.open('r') as f:
                data = json.load(f)
                np.random.shuffle(data['images'])
                np.random.shuffle(data['annotations'])
        else:
            raise RuntimeError('Unknown file suffix')

        log.info(f'loading annotation file: {file.absolute()} finish')
        return self._filter(data, classes)

    def _filter(self, data, classes: list):
        cats = {
            cat['id']: cat['name']
            for cat in data['categories'] if cat['name'] in classes
        }

        if len(cats) < 1:
            raise RuntimeError('Can not find any classes in annotation file')

        images = {
            image['id']: {
                'file_name': image['file_name'],
                'width': image['width'],
                'height': image['height'],
                'items': []
            }
            for image in data['images']
        }

        for anno in data['annotations']:
            if anno['category_id'] in cats.keys():
                image_id = anno['image_id']
                images[image_id]['items'].append(
                    {
                        'bbox': anno['bbox'],
                        'category_name': cats[anno['category_id']]
                    }
                )

        images = (
            img for img in images.values() if len(img['items']) > 0
        )

        cats = (class_name for class_name in cats.values())

        return images, cats

    def calculate_anchor_box(self, bbox_wh_img_size):
        w_h = tuple(
            (
                box[0] / box[2] * self.size,
                box[1] / box[3] * self.size,
            )
            for box in bbox_wh_img_size
        )

        self.anchors_tiny = self.calculate_kmeans(w_h, 6)
        self.anchors = self.calculate_kmeans(w_h, 9)
        self.anchors_v3 = self.anchors

    @staticmethod
    def calculate_kmeans(w_h, k):
        x = np.array(w_h)
        kmeans = KMeans(n_clusters=k).fit(x)
        cluster = kmeans.cluster_centers_
        boxes_size = [box[0] * box[1] for box in cluster]
        sort_args = np.argsort(boxes_size)
        arranged_cluster = np.zeros_like(cluster, int)

        for i, arg in enumerate(sort_args):
            arranged_cluster[i] = cluster[arg]

        return arranged_cluster.reshape(-1).tolist()

    def write_yolo_config(self):
        self.yolo_config = {
            'name': self.name,
            'model_path': self.model_save_dir.as_posix(),
            'weight_path': (self.weights_save_dir / self.name).with_suffix('.h5').as_posix(),
            'logdir': self.logdir.as_posix(),
            'frame_work': self.frame_work,
            'model_type': self.model_type,
            'size': self.size,
            'tiny': self.tiny,
            'max_output_size_per_class': 40,
            'max_total_size': 50,
            'iou_threshold': 0.5,
            'score_threshold': self.score_threshold,
            'YOLO': {
                'CLASSES': self.classes,
                'ANCHORS': self.anchors,
                'ANCHORS_V3': self.anchors_v3,
                'ANCHORS_TINY': self.anchors_tiny,
                'STRIDES': [8, 16, 32],
                'STRIDES_TINY': [16, 32],
                'XYSCALE': [1.2, 1.1, 1.05],
                'XYSCALE_TINY': [1.05, 1.05],
                'ANCHOR_PER_SCALE': 3,
                'IOU_LOSS_THRESH': 0.5,
            },
            'TRAIN': {
                'ANNOT_PATH': self.train_bbox_file.as_posix(),
                'BATCH_SIZE': self.batch_size,
                'INPUT_SIZE': self.size,
                'DATA_AUG': True,
                'LR_INIT': 1e-03,
                'LR_END': 1e-06,
                'WARMUP_EPOCHS': self.warmup_epochs,
                'INIT_EPOCH': 0,
                'FIRST_STAGE_EPOCHS': self.first_stage_epochs,
                'SECOND_STAGE_EPOCHS': self.second_stage_epochs,
                'PRETRAIN': self.pretrain_file.as_posix() if self.pretrain_file else None,
            },
            'TEST': {
                'ANNOT_PATH': self.test_bbox_file.as_posix(),
                'BATCH_SIZE': self.batch_size,
                'INPUT_SIZE': self.size,
                'DATA_AUG': False,
                'SCORE_THRESHOLD': self.score_threshold,
                'IOU_THRESHOLD': 0.5,
            }
        }

        with self.yolo_config_file.open('w') as f:
            json.dump(self.yolo_config, f)

        if sys.platform.startswith('linux'):
            cmd = 'python3 -m json.tool %s' % (str(self.yolo_config_file.absolute()))
        else:
            cmd = 'python -m json.tool %s' % (str(self.yolo_config_file.absolute()))
        os.system(cmd)
        log.info(f'Write YOLO Config to {self.yolo_config_file.absolute()}')

if __name__ == '__main__':
    log.basicConfig(
        format='%(asctime)s %(levelname)s: %(message)s',
        datefmt='%Y/%m/%d %H:%M:%S',
        level=log.INFO
    )

    parser = argparse.ArgumentParser(description='Make YOLO config file')
    parser.add_argument('name', type=str, help='Config file and model name')
    parser.add_argument('classes', type=str, help='Classes file path')
    parser.add_argument('-s', '--size', type=int, default=416,
                        choices=[320, 352, 384, 416, 448, 480, 512, 544, 576, 608],
                        help='Image detect size')
    parser.add_argument('-m', '--model', type=str, default='yolov4', choices=['yolov4', 'yolov3'], help='Model type')
    parser.add_argument('-f', '--frame_work', type=str, default='tf', choices=['tf', 'trt', 'tflite'],
                        help='Frame work type')
    parser.add_argument('-sc', '--score_threshold', type=float, default=0.25, help='Object score threshold')
    parser.add_argument('-t', '--tiny', action='store_true', help='Tiny model?')
    parser.add_argument('-p', '--pretrain', type=str, default='', help='Pretrain weight path')
    parser.add_argument('-bs', '--batch_size', type=int, default=4, help='Batch size')
    parser.add_argument('-ep', '--epoch', type=int, default=30, help='Total of epoch')
    parser.add_argument('-ts', '--train_size', type=int, default=1000, help='Train epoch size')
    parser.add_argument('-vs', '--val_size', type=int, default=200, help='Val epoch size')
    args = parser.parse_args()
    try:
        myc = MakeYoloConfig(
            args.name,
            args.classes,
            sys_config_path='./sys.ini',
            size=args.size,
            model_type=args.model,
            frame_work=args.frame_work,
            tiny=args.tiny,
            pretrain_file_path=args.pretrain,
            batch_size=args.batch_size,
            epoch=args.epoch,
            train_size=args.train_size,
            val_size=args.val_size,
            score_threshold=args.score_threshold
        )
        myc.make()
    except Exception as E:
        log.error(f'{E.__class__.__name__}({E.args})', exc_info=True)


from utility.util import MenuResponses
import pygame
import ctypes
from ConvertToPython import PythonConvertMenu
from mainmenu import MainMenu
from executeMenu import ExecuteMenu

# pygame yahoo
def main():
    myappid = u'alterra.software.simplehotkey.testing'  # arbitrary string
    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

    pygame.init()

    RES = (1080, 720)  # idek what resolution this is
    pygame.display.set_caption("Simple Hotkey (SHK)")
    window = pygame.display.set_mode(RES)
    fpsClock = pygame.time.Clock()
    fps = 60
    pcm = PythonConvertMenu(window, fpsClock, fps, RES)
    mm = MainMenu(window, fpsClock, fps, RES)
    em = ExecuteMenu(window, fpsClock, fps, RES)
    response = mm.run()
    while True:
        if response == MenuResponses.QUIT:
            return
        elif response == MenuResponses.EnterPCMMenu:
            pcm.reset()
            response = pcm.run()
        elif response == MenuResponses.EnterMainMenu:
            mm.reset()
            response = mm.run()
        elif response == MenuResponses.EnterExecuteMenu:
            em.reset()
            response = em.run()

if __name__ == "__main__":
    main()

    # since the pygame interface is currently not working, please just uncomment the code below when actually using SHK.
    # directoryToFile = input("What's the exact directory to the file you are converting? ")
    #
    # with open(directoryToFile) as f:
    #     pyhk = parse(f.read())
    #
    # print(pyhk)


"""
The test module for :mod:`algos.text` . Consists of a data class :class:`DataText` that stores expected inputs and
outputs for the different text based algorithms. The class also provides data for exception handling tests.

Each function in :mod:`algos.text` is assigned to a test class and the expected inputs and unexpected inputs tests are
performed within. The inputs and outputs are then tested in a parametrized fashion.
"""
import pytest
from algos.text import anagrams

class DataText:
    """
    Holds the data for :mod:`algos.text` .
    """
    anagrams__expected = [
        (
            {'the', 'car', 'can', 'caused', 'a', 'and', 'during', 'cried', 'by', 'its', 'rat', 'bowel', 'drinking',
             'elbow', 'bending', 'that', 'while', 'an', 'thing', 'cider', 'like', 'pain', 'cat', 'which', 'in', 'this',
             'act', 'below', 'is', 'night', 'arc'},
            [['act', 'cat'], ['arc', 'car'], ['below', 'bowel', 'elbow'], ['cider', 'cried'], ['night', 'thing']]
        ),
        (
            {"elbow", "below", "bowel"},
            [['below', 'bowel', 'elbow']]
        ),
        (
            {""},
            []
        )
    ]
    """
    Test cases for :func:`algos.text.anagrams`, testing that it functions correctly for expected inputs. The test
    cases are as follows

    +--------------------------------------+----------------------------------------------------------------------+
    | description                          | reason                                                               |
    +======================================+======================================================================+
    | many anagram lists                   | Test to see if multiple lists of anagrams are produced when input    |
    |                                      | set has multiple instances of different words which are anagrams of  |
    |                                      | each other.                                                          |
    +--------------------------------------+----------------------------------------------------------------------+
    | single anagram list                  | Test to see if a single set of anagrams is identified.               |
    +--------------------------------------+----------------------------------------------------------------------+
    | no anagrams                          | Test to see if a non-empty set with no anagrams produces no results  |
    +--------------------------------------+----------------------------------------------------------------------+

    """

    anagrams__unexpected = [
        (set(), [ValueError, "Empty Set"]),
        (["hello"], [TypeError, "Input Data Type Not Set"]),
        ({1, 2, 3}, [TypeError, "Not All Elements of Type str"])
    ]
    """
    Test cases for :func:`algos.text.anagrams`, testing that it raises an error for unexpected inputs. The test cases
    are as follows

    +--------------------------------------+----------------------------------------------------------------------+
    | description                          | reason                                                               |
    +======================================+======================================================================+
    | empty set input                      | Check that :class:`ValueError` is raised for empty input             |
    +--------------------------------------+----------------------------------------------------------------------+
    | incorrect input type                 | Check that :class:`TypeError` is raised if input is not a set        |
    +--------------------------------------+----------------------------------------------------------------------+
    | incorrect elements type              | Check that :class:`TypeError` is raised if any element of the set is |
    |                                      | not :class:`str` .                                                   |
    +--------------------------------------+----------------------------------------------------------------------+

    """

class TestAnagrams:
    """
    Class to test :func:`algos.text.anagrams` . Holds the expected input tests and exception handlings tests.
    """
    @pytest.mark.parametrize(
        "test_input,expected",
        DataText.anagrams__expected,
        ids=[str(v) for v in range(len(DataText.anagrams__expected))]
    )
    def test_anagrams__expected(self, test_input, expected):
        """
        Test that the :func:`algos.text.anagrams` function works properly for expected inputs. Test input can be found
        in :attr:`DataText.anagrams__expected` along with a description of their purpose.
        """
        # Assign a meaningful name to the test set.
        word_set = test_input

        # Find the anagrams.
        anagrams_found = anagrams(word_set)

        # Sort in order to compare generated anagrams against expected value.
        anagrams_found = [sorted(x) for x in anagrams_found]
        anagrams_found.sort()

        # Check that the output is as expected.
        assert anagrams_found == expected

    @pytest.mark.parametrize(
        "test_input,error",
        DataText.anagrams__unexpected,
        ids=[repr(v) for v in DataText.anagrams__unexpected]
    )
    def test_anagrams__unexpected(self, test_input, error):
        """
        Test that the :func:`algos.text.anagrams` raises exceptions for unexpected inputs. Test input can be found
        in :attr:`DataText.anagrams__unexpected` along with a description of their purpose.
        """
        # Check if error is raised.
        with pytest.raises(error[0]) as excinfo:
            anagrams(test_input)

        assert excinfo.match(error[1])


# -*- coding: utf-8 -*-
from __future__ import absolute_import
import sys
from django.conf import settings
from django.core.files.storage import get_storage_class, default_storage
from django.db.models import FileField, ImageField
from django.utils import six

__version_info__ = '0.1.0'
__version__ = '0.1.0'
version = '0.1.0'
def get_version(): return version  # pragma: no cover

class recursive_itemgetter(object):
    """
    This was a couple of hours ago when I was going to have nested dicts ...
    """
    __slots__ = ('item', 'func')
    def __init__(self, item):
        self.item = item
        names = item.split('.')
        def func(obj):
            for name in names:
                try:
                    obj = obj[name]
                except LookupError:
                    # return the nearest up the chain
                    return obj
                except TypeError:
                    if not isinstance(obj, six.string_types):
                        six.reraise(*sys.exc_info())
                    return obj
            return obj
        self.func = func

    def __call__(self, obj):
        return self.func(obj)

    def __repr__(self):
        return '%s.%s(%s)' % (self.__class__.__module__,
                              self.__class__.__name__,
                              self.item)

def gen_keys(key):
    names = key.split('.')
    count = len(names)
    for x in xrange(count, 0, -1):
        yield '.'.join(names[0:x])

def get_storage(key):
    names = tuple(gen_keys(key))
    best_match = (settings.NAMEDSTORAGES[possible_name]
                  for possible_name in names
                  if possible_name in settings.NAMEDSTORAGES)
    name = next(best_match)
    # name = recursive_itemgetter(key)(settings.NAMEDSTORAGES)
    # if it's the same as the normal storage, avoid writing it to migrations...
    if name in (settings.DEFAULT_FILE_STORAGE, ''):
        return default_storage
    return get_storage_class(name)()

class NamedStorageFileField(FileField):
    def __init__(self, verbose_name=None, name=None, upload_to='',
                 storage='default', **kwargs):
        self._storage_name = storage
        storage = get_storage(self._storage_name)
        super(NamedStorageFileField, self).__init__(
            verbose_name=verbose_name, name=name, upload_to=upload_to,
            storage=storage, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super(NamedStorageFileField, self).deconstruct()
        kwargs['storage'] = self._storage_name
        return name, path, args, kwargs

class NamedStorageImageField(ImageField):
    def __init__(self, verbose_name=None, name=None, width_field=None,
                 height_field=None, storage='default', **kwargs):
        self._storage_name = storage
        storage = get_storage(self._storage_name)
        super(NamedStorageImageField, self).__init__(
            verbose_name=verbose_name, name=name, width_field=width_field,
            height_field=height_field, storage=storage, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super(NamedStorageImageField, self).deconstruct()
        kwargs['storage'] = self._storage_name
        return name, path, args, kwargs


import cv2
import numpy as np

# Uploading the image and convert it to gray scale
img = cv2.imread('owl.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)

# Run harris corners detection
dst = cv2.cornerHarris(gray,2,5,0.002)

# Thresholding for, and mark the corner in blue(because the picture is gray-greenish)
img[dst>0.01*dst.max()]=[255,0,0]

# Show the image
cv2.imshow('Image_with_corners',img)
if cv2.waitKey(0)  >30:
    cv2.destroyAllWindows()


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
""" Drives an android device.
"""
import os
import posixpath
import tempfile
import contextlib
import time
import logging

import attr
from arsenic.services import Geckodriver, free_port, subprocess_based_service
from mozdevice import ADBDeviceFactory, ADBError

from condprof.util import write_yml_file, logger, DEFAULT_PREFS, BaseEnv

# XXX most of this code should migrate into mozdevice - see Bug 1574849
class AndroidDevice:
    def __init__(
        self,
        app_name,
        marionette_port=2828,
        verbose=False,
        remote_test_root="/sdcard/test_root/",
    ):
        self.app_name = app_name

        # XXX make that an option
        if "fenix" in app_name:
            self.activity = "org.mozilla.fenix.IntentReceiverActivity"
        else:
            self.activity = "org.mozilla.geckoview_example.GeckoViewActivity"
        self.verbose = verbose
        self.device = None
        self.marionette_port = marionette_port
        self.profile = None
        self.remote_profile = None
        self.log_file = None
        self.remote_test_root = remote_test_root
        self._adb_fh = None

    def _set_adb_logger(self, log_file):
        self.log_file = log_file
        if self.log_file is None:
            return
        logger.info("Setting ADB log file to %s" % self.log_file)
        adb_logger = logging.getLogger("adb")
        adb_logger.setLevel(logging.DEBUG)
        self._adb_fh = logging.FileHandler(self.log_file)
        self._adb_fh.setLevel(logging.DEBUG)
        adb_logger.addHandler(self._adb_fh)

    def _unset_adb_logger(self):
        if self._adb_fh is None:
            return
        logging.getLogger("adb").removeHandler(self._adb_fh)
        self._adb_fh = None

    def clear_logcat(self, timeout=None, buffers=[]):
        if not self.device:
            return
        self.device.clear_logcat(timeout, buffers)

    def get_logcat(self):
        if not self.device:
            return None
        # we don't want to have ADBCommand dump the command
        # in the debug stream so we reduce its verbosity here
        # temporarely
        old_verbose = self.device._verbose
        self.device._verbose = False
        try:
            return self.device.get_logcat()
        finally:
            self.device._verbose = old_verbose

    def prepare(self, profile, logfile):
        self._set_adb_logger(logfile)
        try:
            # See android_emulator_pgo.py run_tests for more
            # details on why test_root must be /sdcard/test_root
            # for android pgo due to Android 4.3.
            self.device = ADBDeviceFactory(
                verbose=self.verbose, logger_name="adb", test_root=self.remote_test_root
            )
        except Exception:
            logger.error("Cannot initialize device")
            raise
        device = self.device
        self.profile = profile

        # checking that the app is installed
        if not device.is_app_installed(self.app_name):
            raise Exception("%s is not installed" % self.app_name)

        # debug flag
        logger.info("Setting %s as the debug app on the phone" % self.app_name)
        device.shell(
            "am set-debug-app --persistent %s" % self.app_name,
            stdout_callback=logger.info,
        )

        # creating the profile on the device
        logger.info("Creating the profile on the device")

        remote_profile = posixpath.join(self.remote_test_root, "profile")
        logger.info("The profile on the phone will be at %s" % remote_profile)

        device.rm(remote_profile, force=True, recursive=True)
        logger.info("Pushing %s on the phone" % self.profile)
        device.push(profile, remote_profile)
        device.chmod(remote_profile, recursive=True)
        self.profile = profile
        self.remote_profile = remote_profile

        # creating the yml file
        yml_data = {
            "args": ["-marionette", "-profile", self.remote_profile],
            "prefs": DEFAULT_PREFS,
            "env": {"LOG_VERBOSE": 1, "R_LOG_LEVEL": 6, "MOZ_LOG": ""},
        }

        yml_name = "%s-geckoview-config.yaml" % self.app_name
        yml_on_host = posixpath.join(tempfile.mkdtemp(), yml_name)
        write_yml_file(yml_on_host, yml_data)
        tmp_on_device = posixpath.join("/data", "local", "tmp")
        if not device.exists(tmp_on_device):
            raise IOError("%s does not exists on the device" % tmp_on_device)
        yml_on_device = posixpath.join(tmp_on_device, yml_name)
        try:
            device.rm(yml_on_device, force=True, recursive=True)
            device.push(yml_on_host, yml_on_device)
            device.chmod(yml_on_device, recursive=True)
        except Exception:
            logger.info("could not create the yaml file on device. Permission issue?")
            raise

        # command line 'extra' args not used with geckoview apps; instead we use
        # an on-device config.yml file
        intent = "android.intent.action.VIEW"
        device.stop_application(self.app_name)
        device.launch_application(
            self.app_name, self.activity, intent, extras=None, url="about:blank"
        )
        if not device.process_exist(self.app_name):
            raise Exception("Could not start %s" % self.app_name)

        logger.info("Creating socket forwarding on port %d" % self.marionette_port)
        device.forward(
            local="tcp:%d" % self.marionette_port,
            remote="tcp:%d" % self.marionette_port,
        )

        # we don't have a clean way for now to check that GV or Fenix
        # is ready to handle our tests. So here we just wait 30s
        logger.info("Sleeping for 30s")
        time.sleep(30)

    def stop_browser(self):
        logger.info("Stopping %s" % self.app_name)
        try:
            self.device.stop_application(self.app_name)
        except ADBError:
            logger.info("Could not stop the application using force-stop")

        time.sleep(5)
        if self.device.process_exist(self.app_name):
            logger.info("%s still running, trying SIGKILL" % self.app_name)
            num_tries = 0
            while self.device.process_exist(self.app_name) and num_tries < 5:
                try:
                    self.device.pkill(self.app_name)
                except ADBError:
                    pass
                num_tries += 1
                time.sleep(1)
        logger.info("%s stopped" % self.app_name)

    def collect_profile(self):
        logger.info("Collecting profile from %s" % self.remote_profile)
        self.device.pull(self.remote_profile, self.profile)

    def close(self):
        self._unset_adb_logger()
        if self.device is None:
            return
        try:
            self.device.remove_forwards("tcp:%d" % self.marionette_port)
        except ADBError:
            logger.warning("Could not remove forward port")

# XXX redundant, remove
@contextlib.contextmanager
def device(
    app_name, marionette_port=2828, verbose=True, remote_test_root="/sdcard/test_root/"
):
    device_ = AndroidDevice(
        app_name, marionette_port, verbose, remote_test_root=remote_test_root
    )
    try:
        yield device_
    finally:
        device_.close()

@attr.s
class AndroidGeckodriver(Geckodriver):
    async def start(self):
        port = free_port()
        await self._check_version()
        logger.info("Running Webdriver on port %d" % port)
        logger.info("Running Marionette on port 2828")
        pargs = [
            self.binary,
            "--log",
            "trace",
            "--port",
            str(port),
            "--marionette-port",
            "2828",
        ]
        logger.info("Connecting on Android device")
        pargs.append("--connect-existing")
        return await subprocess_based_service(
            pargs, f"http://localhost:{port}", self.log_file
        )

class AndroidEnv(BaseEnv):
    @contextlib.contextmanager
    def get_device(self, *args, **kw):
        with device(self.firefox, *args, **kw) as d:
            self.device = d
            yield self.device

    def get_target_platform(self):
        app = self.firefox.split("org.mozilla.")[-1]
        if self.device_name is None:
            return app
        return "%s-%s" % (self.device_name, app)

    def dump_logs(self):
        logger.info("Dumping Android logs")
        try:
            logcat = self.device.get_logcat()
            if logcat:
                # local path, not using posixpath
                logfile = os.path.join(self.archive, "logcat.log")
                logger.info("Writing logcat at %s" % logfile)
                with open(logfile, "wb") as f:
                    for line in logcat:
                        f.write(line.encode("utf8", errors="replace") + b"\n")
            else:
                logger.info("logcat came back empty")
        except Exception:
            logger.error("Could not extract the logcat", exc_info=True)

    @contextlib.contextmanager
    def get_browser(self):
        yield

    def get_browser_args(self, headless, prefs=None):
        # XXX merge with DesktopEnv.get_browser_args
        options = ["--allow-downgrade"]
        if headless:
            options.append("-headless")
        if prefs is None:
            prefs = {}
        return {"moz:firefoxOptions": {"args": options, "prefs": prefs}}

    def prepare(self, logfile):
        self.device.prepare(self.profile, logfile)

    def get_browser_version(self):
        return self.target_platform + "-XXXneedtograbversion"

    def get_geckodriver(self, log_file):
        return AndroidGeckodriver(binary=self.geckodriver, log_file=log_file)

    def check_session(self, session):
        async def fake_close(*args):
            pass

        session.close = fake_close

    def collect_profile(self):
        self.device.collect_profile()

    def stop_browser(self):
        self.device.stop_browser()


import requests
from bs4 import BeautifulSoup

#不直接爬圖是因為網站的圖不來自遊戲卡面angelic

def get_img(name: str):
    img_r = requests.get(f"https://angelic.wikiru.jp/?plugin=attach&refer={name}&openfile={name}.png")
    with open(f"./angelic_dataset/{name}.png", "wb") as fwb:
        fwb.write(img_r.content)

size_map = {}
r = requests.get("https://angelic.wikiru.jp/?%E3%83%90%E3%82%B9%E3%83%88%E3%82%B5%E3%82%A4%E3%82%BA%E9%A0%86%E4%B8%80%E8%A6%A7")
soup = BeautifulSoup(r.text, "html.parser")
full_table = soup.find_all("table",class_="style_table")[-1]
chuck_data = full_table.find("tbody").find_all("tr")
for chuck in [chuck_data[x] for x in range(0, len(chuck_data)-1, 2)]:
    # size, charac_list
    size_map[chuck.find("th",class_="style_th").text] = []
    chracs = chuck.find("td",class_="style_td").find_all("a")
    for chrac in chracs:
        name = chrac['title']
        size_map[chuck.find("th",class_="style_th").text].append(name)

for size, charac_list in size_map.items():
    for charac in charac_list:
        get_img(charac)
        print(f"{charac} done")


"""
TDT4113 - Computer Science, Programming Project (Spring 2021)
Project 3 Cryptography
made with ❤ by mathiom

Test environment for encrypted conversations
"""

from termcolor import colored
from ciphers import CaesarCipher, MultiplicationCipher, AffineCipher, UnbreakableCipher
from persons import Sender, Receiver, Hacker

TEST_MESSAGE = "The quick brown fox jumps over the lazy dog"

for cipher in [
    CaesarCipher(17),
    MultiplicationCipher(34525),
    AffineCipher(143, 2132),
    UnbreakableCipher("cherrypicked"),
]:
    print(f"Conversation with {cipher.__class__.__name__}")

    keys = cipher.generate_keys()

    sender = Sender()
    sender.set_key(keys[0])
    encoded_message = sender.operate_cipher(cipher, TEST_MESSAGE)
    print(colored(f"\tSender's encoded message: {colored(encoded_message, 'cyan')}","white"))

    receiver = Receiver()
    receiver.set_key(keys[1])
    decoded_message = receiver.operate_cipher(cipher, encoded_message)
    print(colored(f"\tReceiver's decoded message: {colored(decoded_message, 'green')}","white"))

    print(colored("\r\tHacking...", "white"), end="")
    hacker = Hacker()
    hacked_message = hacker.operate_cipher(cipher, encoded_message)
    if hacked_message == decoded_message:
        print(colored("\r\tHacker brute forced ✔\n", "magenta"))
    else:
        print(colored("\r\tHacker failed ❌\n", "red"))


from pathlib import Path
import subprocess
import os
import re
import json

def m4a_to_wav(m4a_file, out_dir):
    # transposes: m4a memos file into wav 16kHz
    # saves them in out_dir
    # returns: wav_file

    wav_filename = "memo.wav"
    wav_file = out_dir / wav_filename
    CMD = [
        "ffmpeg",
        "-y",
        "-i",
        m4a_file,
        "-vn",
        "-ar",
        "16000",
        "-ac",
        "1",
        wav_file,
    ]
    with open(wav_file, "w") as out_file:
        out = subprocess.run(CMD, capture_output=True, text=True)
        out_file.write(out.stdout)

    return wav_file

def whisper_process(m4a_file, output_dir, whisper_main, whisper_model, tmp_dir):
    # transposes wav_filename from tmp_dir
    # saves into a transposed_filename in output_dir
    # returns: transposed_filename [.txt]

    if not tmp_dir.exists():
        os.makedirs(tmp_dir)

    if not output_dir.exists():
        os.makedirs(output_dir)

    # preprocess - whisper requires wav 16kHz
    wav_file = m4a_to_wav(m4a_file, tmp_dir)

    # define paths
    output_filename = wav_file.with_suffix(".md").name
    output_file = output_dir / output_filename

    with open(output_file, "a") as file:
        # make section with metadata
        file.write(f"# MEMO {m4a_file.stem}\n")
        print(f"Executing whisper for {m4a_file.stem}")
        out = subprocess.run(
            [whisper_main, "-m", whisper_model, "-f", wav_file],
            capture_output=True,
            text=True,
        )
        output = re.sub(r"\[.*-->.*\]   ", "", out.stdout)
        file.write(output)

    return m4a_file.name

def get_source_list(source_dir):
    if not source_dir.exists():
        raise Exception(
            f"Source dir {source_dir} cannot be accessed. Check if it exists and if you have right privileges."
        )
    source_list = []
    source_dir_contents = Path(source_dir)
    for entry in sorted(source_dir_contents.iterdir()):
        if entry.match("*.m4a"):
            source_list.append(entry.name)
    return source_list

def load_processed_list(processed_file):
    if not processed_file.exists():
        return []
    with open(processed_file, "r") as file:
        processed_list = json.load(file)
    return processed_list

def save_processed_list(processed_list, processed_list_file):
    with open(processed_list_file, "w") as file:
        json.dump(processed_list, file)

def source_params(params_file):
    variables = {}
    with open(params_file, "r") as params_file:
        for line in params_file:
            # Remove leading and trailing whitespace
            line = line.strip()

            # Check if the line is a variable assignment
            if "=" in line:
                # Split the line into variable name and value
                var_name, var_value = line.split("=", 1)

                # Remove any surrounding quotes from the value
                var_value = var_value.strip("\"'")

                # Set the variable in Python (e.g., in a dictionary)
                variables[var_name] = Path(var_value)
    return variables

if __name__ == "__main__":
    # source dir - dir containing m4a files to transcribe
    # output_dit - transcriptions destination
    PARAMS = source_params("params.sh")

    MEMOS_INPUT_DIR = PARAMS["MEMOS_INPUT_DIR"]
    MEMOS_OUTPUT_DIR = PARAMS["MEMOS_OUTPUT_DIR"]
    WHISPER_MAIN = PARAMS["WHISPER_MAIN"]
    WHISPER_MODEL = PARAMS["WHISPER_MODEL"]
    MEMOS_OUTPUT_DIR = PARAMS["MEMOS_OUTPUT_DIR"]
    TMP_DIR = PARAMS["TMP_DIR"]

    source_list = get_source_list(MEMOS_INPUT_DIR)
    processed_list_file = MEMOS_INPUT_DIR / "processed.txt"
    processed_list = load_processed_list(processed_list_file)

    for m4a_file in source_list:
        if locals()["processed_list"] and m4a_file in processed_list:
            continue
        processed_filename = whisper_process(
            MEMOS_INPUT_DIR / m4a_file,
            MEMOS_OUTPUT_DIR,
            WHISPER_MAIN,
            WHISPER_MODEL,
            TMP_DIR,
        )
        processed_list.append(str(processed_filename))

    save_processed_list(processed_list, processed_list_file)


from app.reddit import get_posts
from app.vk import post_meme
from config import settings

def drive():
    posts = get_posts(settings.SUBREDDIT_NAME)
    posts_count = len(posts)
    fail = ""

    print("\n")
    for index, post in enumerate(posts):
        result = post_meme(post=post, hours_delta=index)
        if "post_id" in result.get("response"):
            print(
                f"VK Posting: "
                f"{post.title, post.url_overridden_by_dest} - SUCCESS ({index}/{posts_count})"
            )
        else:
            fail += f"{post.title, post.url_overridden_by_dest} - FAILED ({index}/{posts_count})\n"

    if fail:
        print(f"FAILS:\n{fail}")

    print("\n")


from typing import Generator, Union
from field import Field, TangentVector
from controller import Controller
import numpy as np
import numpy.typing as npt

FloatVec = npt.NDArray[np.float64]

def SimulateControllerOnField(field: Field[FloatVec, FloatVec], initial_point: FloatVec, controller: Union[Controller, None], stepsize = 0.1, steps = 10000) -> Generator:
    if controller is None:
        controller = Controller(np.zeros(field.domain.dim), 0)

    point = initial_point

    for i in range(steps):
        try:
            tangent = field(point)
        except ValueError:
            print("Returned early due to escaping the domain.")
            break

        u = controller.direction(field, point) * controller.force
        point = tangent.basepoint + (tangent.v + u) * stepsize
        yield tangent, u


import av
import cv2
import numpy as np
import streamlit as st
from streamlit_webrtc import (
    ClientSettings,
    VideoTransformerBase,
    WebRtcMode,
    webrtc_streamer,
)
from src.modelling.model import Model

st.title('Add title here')

WEBRTC_CLIENT_SETTINGS = ClientSettings(
    rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]},
    media_stream_constraints={"video": True, "audio": True},
)

def app_object_detection():
    """Object detection demo with MobileNet SSD.
    This model and code are based on
    https://github.com/robmarkcole/object-detection-app
    """

    DEFAULT_CONFIDENCE_THRESHOLD = 0.5

    # This class is kept here to show the class required for webrtc_streamer
    class NNVideoTransformer(VideoTransformerBase):
        confidence_threshold: float

        def __init__(self) -> None:
            self._net = cv2.dnn.readNetFromCaffe(
                str(PROTOTXT_LOCAL_PATH), str(MODEL_LOCAL_PATH)
            )
            self.confidence_threshold = DEFAULT_CONFIDENCE_THRESHOLD

        def _annotate_image(self, image, detections):
            # loop over the detections
            (h, w) = image.shape[:2]
            labels = []
            for i in np.arange(0, detections.shape[2]):
                confidence = detections[0, 0, i, 2]

                if confidence > self.confidence_threshold:
                    # extract the index of the class label from the `detections`,
                    # then compute the (x, y)-coordinates of the bounding box for
                    # the object
                    idx = int(detections[0, 0, i, 1])
                    box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                    (startX, startY, endX, endY) = box.astype("int")

                    # display the prediction
                    label = f"{CLASSES[idx]}: {round(confidence * 100, 2)}%"
                    labels.append(label)
                    cv2.rectangle(image, (startX, startY), (endX, endY), COLORS[idx], 2)
                    y = startY - 15 if startY - 15 > 15 else startY + 15
                    cv2.putText(
                        image,
                        label,
                        (startX, y),
                        cv2.FONT_HERSHEY_SIMPLEX,
                        0.5,
                        COLORS[idx],
                        2,
                    )
            return image, labels

        def transform(self, frame: av.VideoFrame) -> np.ndarray:
            image = frame.to_ndarray(format="bgr24")
            blob = cv2.dnn.blobFromImage(
                cv2.resize(image, (300, 300)), 0.007843, (300, 300), 127.5
            )
            self._net.setInput(blob)
            detections = self._net.forward()
            annotated_image, labels = self._annotate_image(image, detections)
            # TODO: Show labels

            return annotated_image

    webrtc_ctx = webrtc_streamer(
        key="object-detection",
        mode=WebRtcMode.SENDRECV,
        client_settings=WEBRTC_CLIENT_SETTINGS,
        video_transformer_factory=Model, #NNVideoTransformer originally
        async_transform=True,
    )

    confidence_threshold = st.slider(
        "Confidence threshold", 0.0, 1.0, 0.5, 0.05
    )
    if webrtc_ctx.video_transformer:
        webrtc_ctx.video_transformer.confidence_threshold = confidence_threshold

    st.markdown(
        "This demo uses a model and code from "
        "https://github.com/robmarkcole/object-detection-app. "
        "Many thanks to the project."
    )

if __name__ == "__main__":
    app_object_detection()


from collections import Counter
import sys
input = sys.stdin.readline
n = int(input().rstrip())
l = []
for _ in range(n):
    l.append(int(input()))

counter = Counter(l)
m = counter.most_common(n)
m.sort(key=lambda x: (-x[1], x[0]))
print(m[0][0])


from pathlib import Path

from ruamel.yaml import YAML

def load_yaml(file: Path) -> dict:
    """
    Load dict from yaml file (yaml version 1.2)

    :param file: path to yaml file
    :return: dict of data
    """

    yaml = YAML(typ="safe")
    data = yaml.load(file)

    return data

def write_yaml(file: Path, data: dict):
    """
    Write dict to yaml file (yaml version 1.2)

    :param file: path to yaml file to create
    :param data: dict of data to write in the file
    """

    yaml = YAML()
    yaml.width = 4096
    yaml.dump(data, file)


import json
import numpy as np
import pdb
import torch
import random
import os
import trimesh
import datasets.scene_bounds as scene_bounds
import marching_cubes as mcubes
from torch.cuda.amp import autocast as autocast
from kornia import create_meshgrid

from pytorch3d.transforms import matrix_to_quaternion, quaternion_to_axis_angle

BOX_OFFSETS = torch.tensor([[[i,j,k] for i in [0, 1] for j in [0, 1] for k in [0, 1]]],
                               device='cuda')

def get_ray_directions(H, W, focal):
    """
    Get ray directions for all pixels in camera coordinate.
    Reference: https://www.scratchapixel.com/lessons/3d-basic-rendering/
               ray-tracing-generating-camera-rays/standard-coordinate-systems

    Inputs:
        H, W, focal: image height, width and focal length

    Outputs:
        directions: (H, W, 3), the direction of the rays in camera coordinate
    """
    grid = create_meshgrid(H, W, normalized_coordinates=False)[0]
    i, j = grid.unbind(-1)
    # the direction here is without +0.5 pixel centering as calibration is not so accurate
    # see https://github.com/bmild/nerf/issues/24
    directions = \
        torch.stack([(i-W/2)/focal, -(j-H/2)/focal, -torch.ones_like(i)], -1) # (H, W, 3)

    dir_bounds = directions.view(-1, 3)
    # print("Directions ", directions[0,0,:], directions[H-1,0,:], directions[0,W-1,:], directions[H-1, W-1, :])
    # print("Directions ", dir_bounds[0], dir_bounds[W-1], dir_bounds[H*W-W], dir_bounds[H*W-1])

    return directions

def get_ndc_rays(H, W, focal, near, rays_o, rays_d):
    """
    Transform rays from world coordinate to NDC.
    NDC: Space such that the canvas is a cube with sides [-1, 1] in each axis.
    For detailed derivation, please see:
    http://www.songho.ca/opengl/gl_projectionmatrix.html
    https://github.com/bmild/nerf/files/4451808/ndc_derivation.pdf

    In practice, use NDC "if and only if" the scene is unbounded (has a large depth).
    See https://github.com/bmild/nerf/issues/18

    Inputs:
        H, W, focal: image height, width and focal length
        near: (N_rays) or float, the depths of the near plane
        rays_o: (N_rays, 3), the origin of the rays in world coordinate
        rays_d: (N_rays, 3), the direction of the rays in world coordinate

    Outputs:
        rays_o: (N_rays, 3), the origin of the rays in NDC
        rays_d: (N_rays, 3), the direction of the rays in NDC
    """
    # Shift ray origins to near plane
    t = -(near + rays_o[...,2]) / rays_d[...,2]
    rays_o = rays_o + t[...,None] * rays_d

    # Store some intermediate homogeneous results
    ox_oz = rays_o[...,0] / rays_o[...,2]
    oy_oz = rays_o[...,1] / rays_o[...,2]

    # Projection
    o0 = -1./(W/(2.*focal)) * ox_oz
    o1 = -1./(H/(2.*focal)) * oy_oz
    o2 = 1. + 2. * near / rays_o[...,2]

    d0 = -1./(W/(2.*focal)) * (rays_d[...,0]/rays_d[...,2] - ox_oz)
    d1 = -1./(H/(2.*focal)) * (rays_d[...,1]/rays_d[...,2] - oy_oz)
    d2 = 1 - o2

    rays_o = torch.stack([o0, o1, o2], -1) # (B, 3)
    rays_d = torch.stack([d0, d1, d2], -1) # (B, 3)

    return rays_o, rays_d

def seed_everything(seed):
    random.seed(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)

def hash(coords, log2_hashmap_size):
    '''
    coords: this function can process upto 7 dim coordinates (Bs, 8, 3)
    log2T:  logarithm of T w.r.t 2
    '''
    primes = [1, 2654435761, 805459861, 3674653429, 2097192037, 1434869437, 2165219737]

    xor_result = torch.zeros_like(coords)[..., 0]
    for i in range(coords.shape[-1]):
        xor_result ^= coords[..., i]*primes[i]

    return torch.tensor((1<<log2_hashmap_size)-1).to(xor_result.device) & xor_result

def get_rays_(directions, c2w, test=False):
    """
    Get ray origin and normalized directions in world coordinate for all pixels in one image.
    Reference: https://www.scratchapixel.com/lessons/3d-basic-rendering/
               ray-tracing-generating-camera-rays/standard-coordinate-systems

    Inputs:
        directions: (H, W, 3) precomputed ray directions in camera coordinate
        c2w: (3, 4) transformation matrix from camera coordinate to world coordinate

    Outputs:
        rays_o: (H*W, 3), the origin of the rays in world coordinate
        rays_d: (H*W, 3), the normalized direction of the rays in world coordinate
    """
    # Rotate ray directions from camera coordinate to the world coordinate

    rays_d = directions @ c2w[:3, :3].T # (H, W, 3)
    rays_d = rays_d / torch.norm(rays_d, dim=-1, keepdim=True)
    # The origin of all rays is the camera origin in world coordinate
    rays_o = c2w[:3, -1].expand(rays_d.shape) # (H, W, 3)

    if test:
        print('rays_o', rays_o)

    rays_d = rays_d.view(-1, 3)
    rays_o = rays_o.view(-1, 3)

    return rays_o, rays_d

def get_bbox3d_for_scanNet(poses, hwf, near=0.0, far=2.0):
    '''
    Params:
        poses: all camera poses
        hwf: intrinsic parameters
    Return:
        bounding_box: tuple (bound_min, bound_min)
    '''
    H, W, focal = hwf
    H, W = int(H), int(W)
    directions = get_ray_directions(H, W, focal)

    min_bound = [100, 100, 100]
    max_bound = [-100, -100, -100]
    points = []
    poses = torch.FloatTensor(poses)
    for pose in poses:
        rays_o, rays_d = get_rays_(directions, pose[:3, :4])

        def find_min_max(pt):
            for i in range(3):
                if(min_bound[i] > pt[i]):
                    min_bound[i] = pt[i]
                if(max_bound[i] < pt[i]):
                    max_bound[i] = pt[i]
            return

        for i in [0, W-1, H*W-W, H*W-1]:
            min_point = rays_o[i] + near*rays_d[i]
            max_point = rays_o[i] + far*rays_d[i]
            points += [min_point, max_point]
            find_min_max(min_point)
            find_min_max(max_point)

    bound_min = min(min_bound)
    bound_max = max(max_bound)

    if abs(bound_min) > bound_max:
        bound_arg = abs(bound_min)
    else:
        bound_arg = bound_max

    assert bound_arg > 0, 'Bound should be larger than 0'

    return (torch.tensor(min_bound)-torch.tensor([0.1,0.1,0.1]), torch.tensor(max_bound)+torch.tensor([0.1,0.1,0.1])), bound_arg

def get_voxel_vertices(xyz, bounding_box, resolution, log2_hashmap_size):
    '''
    xyz: 3D coordinates of samples. B x 3
    bounding_box: min and max x,y,z coordinates of object bbox
    resolution: number of voxels per axis
    '''
    box_min, box_max = bounding_box

    if not torch.all(xyz <= box_max) or not torch.all(xyz >= box_min):
        #print("ALERT: some points are outside bounding box. Clipping them!")
        #pdb.set_trace()
        xyz = torch.clamp(xyz, min=box_min, max=box_max)

    grid_size = (box_max-box_min)/resolution  # The size of each grid

    bottom_left_idx = torch.floor((xyz-box_min)/grid_size).int()
    voxel_min_vertex = bottom_left_idx*grid_size + box_min
    voxel_max_vertex = voxel_min_vertex + torch.tensor([1.0,1.0,1.0])*grid_size

    # hashed_voxel_indices = [] # B x 8 ... 000,001,010,011,100,101,110,111
    # for i in [0, 1]:
    #     for j in [0, 1]:
    #         for k in [0, 1]:
    #             vertex_idx = bottom_left_idx + torch.tensor([i,j,k])
    #             # vertex = bottom_left + torch.tensor([i,j,k])*grid_size
    #             hashed_voxel_indices.append(hash(vertex_idx, log2_hashmap_size))

    # BOX_OFFSETS (1, 8, 3)
    # bottom_left_idx.unsqueeze(1) (Bs, 1, 3)
    # voxel_indices (Bs, 8, 3)
    voxel_indices = bottom_left_idx.unsqueeze(1) + BOX_OFFSETS
    hashed_voxel_indices = hash(voxel_indices, log2_hashmap_size)

    return voxel_min_vertex, voxel_max_vertex, hashed_voxel_indices

def get_rays(H, W, K, c2w):
    i, j = torch.meshgrid(torch.linspace(0, W-1, W), torch.linspace(0, H-1, H))  # pytorch's meshgrid has indexing='ij'
    i = i.t()
    j = j.t()
    dirs = torch.stack([(i-K[0][2])/K[0][0], -(j-K[1][2])/K[1][1], -torch.ones_like(i)], -1)
    # Rotate ray directions from camera frame to the world frame
    rays_d = torch.sum(dirs[..., None, :] * c2w[:3,:3], -1)  # dot product, equals to: [c2w.dot(dir) for dir in dirs]
    # Translate camera frame's origin to the world frame. It is the origin of all rays.
    rays_o = c2w[:3,-1].expand(rays_d.shape)
    return rays_o, rays_d

def get_camera_rays_np(H, W, focal):
    """Get ray origins, directions from a pinhole camera."""
    #  ----> i
    # |
    # |
    # X
    # j
    i, j = np.meshgrid(np.arange(W, dtype=np.float32),
                       np.arange(H, dtype=np.float32), indexing='xy')

    # View direction (X, Y, Lambda) / lambda
    # Move to the center of the screen
    #  -------------
    # |      y      |
    # |      |      |
    # |      .-- x  |
    # |             |
    # |             |
    #  -------------
    dirs = np.stack([(i + 0.5 - W*.5)/focal, -(j + 0.5 - H*.5)/focal, -np.ones_like(i)], -1)
    rays_d = dirs
    return rays_d

def get_rays_rgbd(H, W, focal, poses, images, depth_images, normal=None, shuffle=False, mask=None):
    print('get rays')
    # get_camera_rays_np() returns rays_direction=[H, W, 3]
    # origin is at center, coordinate system is shown above
    # rays: [N, H, W, 3]
    # rays is in camera space
    rays = np.stack([get_camera_rays_np(H, W, focal) for _ in range(poses.shape[0])], 0)  # [N, H, W, 3]
    print('done, concats')

    # Concatenate color and depth
    # rays = view direction (3) + RGB (3) + Depth (1)
    rays = np.concatenate([rays, images], -1)  # [N, H, W, 6]
    rays = np.concatenate([rays, depth_images], -1)  # [N, H, W, 7]

    # Concatenate frame ids
    ids = np.arange(rays.shape[0], dtype=np.float32)
    ids = ids[:, np.newaxis, np.newaxis, np.newaxis]
    ids = np.tile(ids, [1, rays.shape[1], rays.shape[2], 1])

    # rays = view direction (3) + RGB (3) + Depth (1) + Frame id (1)
    rays = np.concatenate([rays, ids], -1)  # [N, H, W, 8]

    if normal is not None:
        rays = np.concatenate([rays, normal], -1)  # [N, H, W, 11]

    if mask is not None:
        rays = np.concatenate([rays, mask], -1)  # [N, H, W, 11]

    rays = rays.reshape([-1, rays.shape[-1]])  # [N_rays, 8 or 11]

    if shuffle:
        print('Shuffle rays')
        np.random.shuffle(rays)

    return rays

def coordinates(voxel_dim, device: torch.device, flatten=True):
    if type(voxel_dim) is int:
        nx = ny = nz = voxel_dim
    else:
        nx, ny, nz = voxel_dim[0], voxel_dim[1], voxel_dim[2]
    x = torch.arange(0, nx, dtype=torch.long, device=device)
    y = torch.arange(0, ny, dtype=torch.long, device=device)
    z = torch.arange(0, nz, dtype=torch.long, device=device)
    x, y, z = torch.meshgrid(x, y, z, indexing="ij")

    if not flatten:
        return torch.stack([x, y, z], dim=-1)

    return torch.stack((x.flatten(), y.flatten(), z.flatten()))

def get_batch_query_fn(query_fn):

    fn = lambda f, i0, i1: query_fn(f[i0:i1, None, :])

    return fn

def extract_mesh(query_fn, config, voxel_size=0.01, isolevel=0.0, scene_name='', mesh_savepath=''):
    # TODO: TCNN encoding mesh extraction need to be changed
    # Query network on dense 3d grid of points
    volume = config.bounding_box[1] - config.bounding_box[0]
    center = config.bounding_box[0] + volume / 2

    voxel_size *= config.sc_factor  # in "network space"
    x_min, y_min, z_min = config.bounding_box[0]
    x_max, y_max, z_max = config.bounding_box[1]

    tx, ty, tz = scene_bounds.getVoxels(x_max, x_min, y_max, y_min, z_max, z_min, voxel_size)

    query_pts = torch.stack(torch.meshgrid(tx, ty, tz, indexing='ij'), -1).to(torch.float32)

    sh = query_pts.shape
    flat = query_pts.reshape([-1, 3]).to(config.bounding_box[0])

    if config.tcnn_encoding:
        flat = (flat - config.bounding_box[0]) / (config.bounding_box[1] - config.bounding_box[0])

    fn = get_batch_query_fn(query_fn)

    chunk = 1024 * 64
    with autocast(False):
        raw = [fn(flat, i, i + chunk).cpu().data.numpy() for i in range(0, flat.shape[0], chunk)]

    raw = np.concatenate(raw, 0).astype(np.float32)
    raw = np.reshape(raw, list(sh[:-1]) + [-1])

    print('Running Marching Cubes')
    vertices, triangles = mcubes.marching_cubes(raw.squeeze(), isolevel, truncation=3.0)
    print('done', vertices.shape, triangles.shape)

    # voxel_sizes = volume.cpu().numpy() / (np.array([len(tx), len(ty), len(tz)])-1)
    # vertices *= voxel_sizes

    # vertices += center.cpu().numpy()

    # normalize vertex positions
    vertices[:, :3] /= np.array([[tx.shape[0] - 1, ty.shape[0] - 1, tz.shape[0] - 1]])

    # Rescale and translate
    tx = tx.cpu().data.numpy()
    ty = ty.cpu().data.numpy()
    tz = tz.cpu().data.numpy()

    scale = np.array([tx[-1] - tx[0], ty[-1] - ty[0], tz[-1] - tz[0]])
    offset = np.array([tx[0], ty[0], tz[0]])
    vertices[:, :3] = scale[np.newaxis, :] * vertices[:, :3] + offset

    # Transform to metric units
    vertices[:, :3] = vertices[:, :3] / config.sc_factor - config.translation

    # Create mesh
    mesh = trimesh.Trimesh(vertices, triangles, process=False)

    # Transform the mesh to Scannet's coordinate system
    # gl_to_scannet = np.array([[1, 0, 0, 0],
    #                           [0, 0, -1, 0],
    #                           [0, 1, 0, 0],
    #                           [0, 0, 0, 1]]).astype(np.float32).reshape([4, 4])

    # mesh.apply_transform(gl_to_scannet)

    if mesh_savepath == '':
        mesh_savepath = os.path.join(config.basedir, config.expname, f"mesh_vs{voxel_size / config.sc_factor.ply}")
    mesh.export(mesh_savepath)

    print('Mesh saved')

def rmse(predictions, targets):
    return torch.sqrt(((predictions - targets) ** 2).mean(dim=[-1, -2])).mean()

def matrix_to_axis_angle(rot):
    """
    :param rot: [N, 3, 3]
    :return:
    """
    return quaternion_to_axis_angle(matrix_to_quaternion(rot))


from astropy.io import fits
import numpy as np
from glob import glob
import os
import time

# TODO: Plannig to wrap this as a class

PATH = os.getcwd()
# Helper function to get d
def get_subDIR(DIR):
    return [os.path.join(DIR,d) for d in os.listdir(DIR) if os.path.isdir(os.path.join(DIR, d))]

def get_subFITS(DIR, fileExt):
    file_list = [os.path.normcase(f) for f in os.listdir(DIR)]
    return [os.path.join(DIR, f) for f in file_list if os.path.splitext(f)[-1] == fileExt and not f[0]=='.']

# TODO: Right now it's size fixed. Maybe decide by header is better.
def combine_Sensor(sensor_list):
    # TODO: image dimension to be retrived from header
    # Right now assume it's 4072*4000 only for our purpose
    dim_x, dim_y = 4072, 4000
    new_data = np.zeros(shape=(dim_x*3,dim_y*3), dtype = np.float32)
    for elem in sensor_list:
        hdulist = fits.open(elem)
        # TODO: datatype to retrive from header.
        # Right now assume it's floating point.
        sensor_image_data = hdulist[0].data
        # To check: gzip'ed fits always in the form 'eimage_886947091_R01_S00_E000.fits.gz'
        temp_name = elem.split('_')
        X , Y = int(temp_name[-2][1]) , int(temp_name[-2][2])
        new_data[X*dim_x : (X+1)*dim_x , Y*dim_y:(Y+1)*dim_y] = sensor_image_data
        hdulist.close()
    write_Path = os.path.join(PATH,'RAFTS')
    if not os.path.exists(write_Path):
        os.makedirs(write_Path)
    hdu = fits.PrimaryHDU(new_data)
    hdulist = fits.HDUList([hdu])
    hdulist.writeto(os.path.join(write_Path, '%s_CCD_%s.fits' % ((sensor_list[0].split('_')[-1][:4]).upper(), (sensor_list[0].split('_')[-3]).upper())))
    print('Processed Raft %s' % sensor_list[0].split('_')[-3])

# TODO: See comments in the combine_Sensor function
# TODO: still need to fix memory error !
def combine_RAFT(CCD_list):
    # Using fixed X & Y coordinates
    dim_x, dim_y = 4072*3, 4000*3
    # Memmap in numpy.ndarray
    filename = os.path.join(os.path.join(PATH,"RAFTS"), "memmap_temp.data")
    print(filename)
    new_data = np.memmap(filename, mode = 'w+', shape=(dim_x*5,dim_y*5), dtype = np.float32)
    for elem in CCD_list:
        #print(elem)
        HDUList = fits.open(elem)
        CCD_image_data = HDUList[0].data
        temp_name = elem.split('_')
        X, Y = int(temp_name[-1][1]), int(temp_name[-1][2])
        new_data[X*dim_x : (X+1)*dim_x, Y*dim_y : (Y+1)*dim_y] = CCD_image_data
        HDUList.close()
    hdu = fits.PrimaryHDU(new_data)
    hdulist = fits.HDUList([hdu])
    hdulist.writeto(os.path.join(PATH,"FOCAL_PLANE_combined.fits"))
    del new_data
    print('Focal plane FITS combined!')

R_list = get_subDIR(PATH)

# Directories like 'E000' or 'E001' are valid. E at -4 position
R_list = [get_subDIR(d) for d in R_list if 'E' == d[-4]]

# Total number of images to combine
num_image = len(R_list)

# Get all the fits file with '.gz' into a list.
fits_gz_list = [[get_subFITS(sub_dir, '.gz') for sub_dir in elem] for elem in R_list]

#combine_Sensor(fits_gz_list[0][0])

# TODO: Get keywords from header file

# Testing the runnig time
t = time.process_time()
for image in fits_gz_list:
    for raft in image:
        combine_Sensor(raft)
print(str(time.process_time()- t)+' s')

# Not enough memory by this naive implementation, consider using memmap
t = time.process_time()
CCD_list = get_subFITS(os.path.join(PATH,"RAFTS"), '.fits')
combine_RAFT(CCD_list)
print(str(time.process_time()-t)+'s')

###
# Test purpose. Below should be ignored.
'''
hdulist = fits.open(os.path.join(PATH, 'eimage_886947091_R20_S00_E000.fits.gz'))
data = hdulist[0].data
print(data.max())
hdulist.close()
'''

#n = np.arange(100.0) # Sample sequence of floats
#hdu = fits.PrimaryHDU(n)
#hdulist = fits.HDUList([hdu])
#hdulist.writeto('new.fits')


import mdtraj as md
import numpy as np
import sys

def lipic(traj_file, top_file, stride, toAl):
	# load trajectory
	traj = md.load_xtc(traj_file, top = top_file, stride = stride)
	# align if needed
	if toAl:
		# align to the first frame
		traj.superpose(traj[0])

		# get average structure
		avg_xyz = traj.xyz.astype(np.float64).\
		mean(axis = 0, dtype=np.float64)
		avg_traj = md.Trajectory([avg_xyz], traj.top)

		# second step alignment to the average structure
		traj.superpose(avg_traj[0])

	# calculate average structure
	avg_xyz = traj.xyz.astype(np.float64).\
	mean(axis = 0, dtype=np.float64)
	avg_traj = md.Trajectory([avg_xyz], traj.top)

	# add average structure to the trajectory
	traj = traj.join(avg_traj)

	return traj

def main(traj_file, top_file, stride, conf_out, toAl):
	if not traj_file or not top_file:
		print("Trajectory and topology have to be provided. \n\
			Please run pcalipids.py conspace -h for help")
		return
	# create pdb file with conformations
	traj = lipic(traj_file, top_file, stride, toAl)
	traj.save_pdb(conf_out)
	print('Conformations saved in file "%s"' % conf_out)


import codecs
import json
import os
import shutil
import sys
import tempfile
import unittest

import mock

from telemetry import story
from telemetry.core import exceptions
from telemetry.internal.results import chart_json_output_formatter
from telemetry.internal.results import histogram_set_json_output_formatter
from telemetry.internal.results import html_output_formatter
from telemetry.internal.results import page_test_results
from telemetry.internal.results import results_processor
from telemetry import page as page_module
from telemetry.value import improvement_direction
from telemetry.value import scalar
from tracing.trace_data import trace_data
from tracing.value import histogram as histogram_module
from tracing.value import histogram_set
from tracing.value.diagnostics import diagnostic
from tracing.value.diagnostics import generic_set
from tracing.value.diagnostics import reserved_infos

def _CreateException():
  try:
    raise exceptions.IntentionalException
  except Exception: # pylint: disable=broad-except
    return sys.exc_info()

class _PageTestResultsTestBase(unittest.TestCase):
  def setUp(self):
    story_set = story.StorySet()
    story_set.AddStory(page_module.Page("http://www.foo.com/", story_set,
                                        name='http://www.foo.com/'))
    story_set.AddStory(page_module.Page("http://www.bar.com/", story_set,
                                        name='http://www.bar.com/'))
    story_set.AddStory(page_module.Page("http://www.baz.com/", story_set,
                                        name='http://www.baz.com/'))
    self.story_set = story_set
    self._output_dir = tempfile.mkdtemp()

  def tearDown(self):
    shutil.rmtree(self._output_dir)

  @property
  def pages(self):
    return self.story_set.stories

  def CreateResults(self, **kwargs):
    kwargs.setdefault('output_dir', self._output_dir)
    return page_test_results.PageTestResults(**kwargs)

class PageTestResultsTest(_PageTestResultsTestBase):
  def testFailures(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.Fail(_CreateException())
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      results.DidRunPage(self.pages[1])

    all_story_runs = list(results.IterStoryRuns())
    self.assertEqual(len(all_story_runs), 2)
    self.assertTrue(results.had_failures)
    self.assertTrue(all_story_runs[0].failed)
    self.assertTrue(all_story_runs[1].ok)

  def testSkips(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.Skip('testing reason')
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      results.DidRunPage(self.pages[1])

    all_story_runs = list(results.IterStoryRuns())
    self.assertTrue(all_story_runs[0].skipped)
    self.assertEqual(self.pages[0], all_story_runs[0].story)

    self.assertEqual(2, len(all_story_runs))
    self.assertTrue(results.had_skips)
    self.assertTrue(all_story_runs[0].skipped)
    self.assertTrue(all_story_runs[1].ok)

  def testBenchmarkInterruption(self):
    reason = 'This is a reason'
    with self.CreateResults() as results:
      self.assertIsNone(results.benchmark_interruption)
      self.assertFalse(results.benchmark_interrupted)
      results.InterruptBenchmark(reason)

    self.assertEqual(results.benchmark_interruption, reason)
    self.assertTrue(results.benchmark_interrupted)

  def testPassesNoSkips(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.Fail(_CreateException())
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      results.DidRunPage(self.pages[1])

      results.WillRunPage(self.pages[2])
      results.Skip('testing reason')
      results.DidRunPage(self.pages[2])

    all_story_runs = list(results.IterStoryRuns())
    self.assertEqual(3, len(all_story_runs))
    self.assertTrue(all_story_runs[0].failed)
    self.assertTrue(all_story_runs[1].ok)
    self.assertTrue(all_story_runs[2].skipped)

  def testAddValueWithStoryGroupingKeys(self):
    with self.CreateResults() as results:
      self.pages[0].grouping_keys['foo'] = 'bar'
      self.pages[0].grouping_keys['answer'] = '42'
      results.WillRunPage(self.pages[0])
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])

    values = list(results.IterAllLegacyValues())
    self.assertEqual(1, len(values))
    self.assertEqual(values[0].grouping_label, '42_bar')

  def testUrlIsInvalidValue(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      with self.assertRaises(AssertionError):
        # Invalid because of non-numeric value.
        results.AddValue(scalar.ScalarValue(
            self.pages[0], name='url', units='string', value='foo',
            improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])

  def testAddSummaryValueWithPageSpecified(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      with self.assertRaises(AssertionError):
        # Invalid because should have no page.
        results.AddSummaryValue(scalar.ScalarValue(
            self.pages[0], 'a', 'units', 3,
            improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])

  def testUnitChange(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      with self.assertRaises(AssertionError):
        results.AddValue(scalar.ScalarValue(
            self.pages[1], 'a', 'foobgrobbers', 3,
            improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[1])

  def testNoSuccessesWhenAllPagesFailOrSkip(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.Fail('message')
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      results.Skip('message')
      results.DidRunPage(self.pages[1])

    self.assertFalse(results.had_successes)

  def testIterAllLegacyValuesForSuccessfulPages(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      value1 = scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP)
      results.AddValue(value1)
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      value2 = scalar.ScalarValue(
          self.pages[1], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP)
      results.AddValue(value2)
      results.DidRunPage(self.pages[1])

      results.WillRunPage(self.pages[2])
      value3 = scalar.ScalarValue(
          self.pages[2], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP)
      results.AddValue(value3)
      results.DidRunPage(self.pages[2])

    self.assertEqual(
        [value1, value2, value3], list(results.IterAllLegacyValues()))

  def testAddTraces(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.AddTraces(trace_data.CreateTestTrace(1))
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      results.AddTraces(trace_data.CreateTestTrace(2))
      results.DidRunPage(self.pages[1])

    runs = list(results.IterRunsWithTraces())
    self.assertEqual(2, len(runs))

  def testAddTracesForSamePage(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.AddTraces(trace_data.CreateTestTrace(1))
      results.AddTraces(trace_data.CreateTestTrace(2))
      results.DidRunPage(self.pages[0])

    runs = list(results.IterRunsWithTraces())
    self.assertEqual(1, len(runs))

  def testOutputEmptyResults_ChartJSON(self):
    output_file = os.path.join(self._output_dir, 'chart.json')
    with open(output_file, 'w') as stream:
      formatter = chart_json_output_formatter.ChartJsonOutputFormatter(stream)
      with self.CreateResults(
          output_formatters=[formatter],
          benchmark_name='fake_benchmark_name'):
        pass

    with open(output_file) as f:
      chartjson_output = json.load(f)

    self.assertFalse(chartjson_output['enabled'])
    self.assertEqual(chartjson_output['benchmark_name'], 'fake_benchmark_name')

  def testOutputEmptyResults_HTML(self):
    output_file = os.path.join(self._output_dir, 'results.html')
    with codecs.open(output_file, 'w', encoding='utf-8') as stream:
      formatter = html_output_formatter.HtmlOutputFormatter(stream)
      with self.CreateResults(output_formatters=[formatter]):
        pass

    self.assertGreater(os.stat(output_file).st_size, 0)

  def testOutputEmptyResults_Histograms(self):
    output_file = os.path.join(self._output_dir, 'histograms.json')
    with open(output_file, 'w') as stream:
      formatter = histogram_set_json_output_formatter.\
          HistogramSetJsonOutputFormatter(stream)
      with self.CreateResults(output_formatters=[formatter]):
        pass

    with open(output_file) as f:
      self.assertEqual(f.read(), '[]')

  def testImportHistogramDicts(self):
    hs = histogram_set.HistogramSet()
    hs.AddHistogram(histogram_module.Histogram('foo', 'count'))
    hs.AddSharedDiagnosticToAllHistograms(
        'bar', generic_set.GenericSet(['baz']))
    histogram_dicts = hs.AsDicts()

    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results._ImportHistogramDicts(histogram_dicts)
      results.DidRunPage(self.pages[0])

    self.assertEqual(results.AsHistogramDicts(), histogram_dicts)

  def testAddSharedDiagnosticToAllHistograms(self):
    with self.CreateResults(benchmark_name='benchmark_name') as results:
      results.WillRunPage(self.pages[0])
      results.DidRunPage(self.pages[0])
      results.AddSharedDiagnosticToAllHistograms(
          reserved_infos.BENCHMARKS.name,
          generic_set.GenericSet(['benchmark_name']))
      results.PopulateHistogramSet()

    histogram_dicts = results.AsHistogramDicts()
    self.assertEqual(1, len(histogram_dicts))

    diag = diagnostic.Diagnostic.FromDict(histogram_dicts[0])
    self.assertIsInstance(diag, generic_set.GenericSet)

  def testPopulateHistogramSet_UsesScalarValueData(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])
      results.PopulateHistogramSet()

    hs = histogram_set.HistogramSet()
    hs.ImportDicts(results.AsHistogramDicts())
    self.assertEqual(1, len(hs))
    self.assertEqual('a', hs.GetFirstHistogram().name)

  def testPopulateHistogramSet_UsesHistogramSetData(self):
    with self.CreateResults(benchmark_name='benchmark_name') as results:
      results.WillRunPage(self.pages[0])
      results.AddHistogram(histogram_module.Histogram('foo', 'count'))
      results.DidRunPage(self.pages[0])
      results.PopulateHistogramSet()

    histogram_dicts = results.AsHistogramDicts()
    self.assertEqual(8, len(histogram_dicts))

    hs = histogram_set.HistogramSet()
    hs.ImportDicts(histogram_dicts)

    hist = hs.GetHistogramNamed('foo')
    self.assertItemsEqual(hist.diagnostics[reserved_infos.BENCHMARKS.name],
                          ['benchmark_name'])

class PageTestResultsFilterTest(_PageTestResultsTestBase):
  def testFilterValue(self):
    def AcceptValueNamed_a(name, _):
      return name == 'a'

    with self.CreateResults(should_add_value=AcceptValueNamed_a) as results:
      results.WillRunPage(self.pages[0])
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'b', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      results.AddValue(scalar.ScalarValue(
          self.pages[1], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.AddValue(scalar.ScalarValue(
          self.pages[1], 'd', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[1])

    self.assertEqual(
        [('a', 'http://www.foo.com/'), ('a', 'http://www.bar.com/')],
        [(v.name, v.page.url) for v in results.IterAllLegacyValues()])

  def testFilterValueWithImportHistogramDicts(self):
    def AcceptValueStartsWith_a(name, _):
      return name.startswith('a')

    hs = histogram_set.HistogramSet()
    hs.AddHistogram(histogram_module.Histogram('a', 'count'))
    hs.AddHistogram(histogram_module.Histogram('b', 'count'))

    with self.CreateResults(
        should_add_value=AcceptValueStartsWith_a) as results:
      results.WillRunPage(self.pages[0])
      results._ImportHistogramDicts(hs.AsDicts())
      results.DidRunPage(self.pages[0])

    new_hs = histogram_set.HistogramSet()
    new_hs.ImportDicts(results.AsHistogramDicts())
    self.assertEqual(len(new_hs), 1)

  def testFilterIsFirstResult(self):
    def AcceptSecondValues(_, is_first_result):
      return not is_first_result

    with self.CreateResults(should_add_value=AcceptSecondValues) as results:
      # First results (filtered out)
      results.WillRunPage(self.pages[0])
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 7,
          improvement_direction=improvement_direction.UP))
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'b', 'seconds', 8,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])
      results.WillRunPage(self.pages[1])
      results.AddValue(scalar.ScalarValue(
          self.pages[1], 'a', 'seconds', 5,
          improvement_direction=improvement_direction.UP))
      results.AddValue(scalar.ScalarValue(
          self.pages[1], 'd', 'seconds', 6,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[1])

      # Second results
      results.WillRunPage(self.pages[0])
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'a', 'seconds', 3,
          improvement_direction=improvement_direction.UP))
      results.AddValue(scalar.ScalarValue(
          self.pages[0], 'b', 'seconds', 4,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[0])
      results.WillRunPage(self.pages[1])
      results.AddValue(scalar.ScalarValue(
          self.pages[1], 'a', 'seconds', 1,
          improvement_direction=improvement_direction.UP))
      results.AddValue(scalar.ScalarValue(
          self.pages[1], 'd', 'seconds', 2,
          improvement_direction=improvement_direction.UP))
      results.DidRunPage(self.pages[1])

    expected_values = [
        ('a', 'http://www.foo.com/', 3),
        ('b', 'http://www.foo.com/', 4),
        ('a', 'http://www.bar.com/', 1),
        ('d', 'http://www.bar.com/', 2)]
    actual_values = [(v.name, v.page.url, v.value)
                     for v in results.IterAllLegacyValues()]
    self.assertEqual(expected_values, actual_values)

  def testFilterHistogram(self):
    def AcceptValueNamed_a(name, _):
      return name.startswith('a')

    with self.CreateResults(should_add_value=AcceptValueNamed_a) as results:
      results.WillRunPage(self.pages[0])
      hist0 = histogram_module.Histogram('a', 'count')
      # Necessary to make sure avg is added
      hist0.AddSample(0)
      results.AddHistogram(hist0)
      hist1 = histogram_module.Histogram('b', 'count')
      hist1.AddSample(0)
      results.AddHistogram(hist1)
      results.DidRunPage(self.pages[0])

    # Filter out the diagnostics
    dicts = results.AsHistogramDicts()
    histogram_dicts = []
    for d in dicts:
      if 'name' in d:
        histogram_dicts.append(d)

    self.assertEqual(len(histogram_dicts), 1)
    self.assertEqual(histogram_dicts[0]['name'], 'a')

  def testFilterHistogram_AllStatsNotFiltered(self):
    def AcceptNonAverage(name, _):
      return not name.endswith('avg')

    with self.CreateResults(should_add_value=AcceptNonAverage) as results:
      results.WillRunPage(self.pages[0])
      hist0 = histogram_module.Histogram('a', 'count')
      # Necessary to make sure avg is added
      hist0.AddSample(0)
      results.AddHistogram(hist0)
      hist1 = histogram_module.Histogram('a_avg', 'count')
      # Necessary to make sure avg is added
      hist1.AddSample(0)
      results.AddHistogram(hist1)
      results.DidRunPage(self.pages[0])

    # Filter out the diagnostics
    dicts = results.AsHistogramDicts()
    histogram_dicts = []
    for d in dicts:
      if 'name' in d:
        histogram_dicts.append(d)

    self.assertEqual(len(histogram_dicts), 2)
    histogram_dicts.sort(key=lambda h: h['name'])

    self.assertEqual(len(histogram_dicts), 2)
    self.assertEqual(histogram_dicts[0]['name'], 'a')
    self.assertEqual(histogram_dicts[1]['name'], 'a_avg')

  @mock.patch('py_utils.cloud_storage.Insert')
  def testUploadArtifactsToCloud(self, cs_insert_mock):
    cs_path_name = 'https://cs_foo'
    cs_insert_mock.return_value = cs_path_name
    with self.CreateResults(upload_bucket='abc') as results:
      results.WillRunPage(self.pages[0])
      with results.CreateArtifact('screenshot.png') as screenshot1:
        pass
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      with results.CreateArtifact('log.txt') as log2:
        pass
      results.DidRunPage(self.pages[1])

      results_processor.UploadArtifactsToCloud(results)

    cs_insert_mock.assert_has_calls(
        [mock.call('abc', mock.ANY, screenshot1.name),
         mock.call('abc', mock.ANY, log2.name)],
        any_order=True)

    # Assert that the path is now the cloud storage path
    for run in results.IterStoryRuns():
      for artifact in run.IterArtifacts():
        self.assertEqual(cs_path_name, artifact.url)

  @mock.patch('py_utils.cloud_storage.Insert')
  def testUploadArtifactsToCloud_withNoOpArtifact(self, _):
    with self.CreateResults(upload_bucket='abc', output_dir=None) as results:
      results.WillRunPage(self.pages[0])
      with results.CreateArtifact('screenshot.png'):
        pass
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      with results.CreateArtifact('log.txt'):
        pass
      results.DidRunPage(self.pages[1])

      # Just make sure that this does not crash
      results_processor.UploadArtifactsToCloud(results)

  def testCreateArtifactsForDifferentPages(self):
    with self.CreateResults() as results:
      results.WillRunPage(self.pages[0])
      with results.CreateArtifact('log.txt') as log_file:
        log_file.write('page0\n')
      results.DidRunPage(self.pages[0])

      results.WillRunPage(self.pages[1])
      with results.CreateArtifact('log.txt') as log_file:
        log_file.write('page1\n')
      results.DidRunPage(self.pages[1])

    all_story_runs = list(results.IterStoryRuns())
    log0_path = all_story_runs[0].GetArtifact('log.txt').local_path
    with open(log0_path) as f:
      self.assertEqual(f.read(), 'page0\n')

    log1_path = all_story_runs[1].GetArtifact('log.txt').local_path
    with open(log1_path) as f:
      self.assertEqual(f.read(), 'page1\n')