import logging
from datetime import datetime
from enum import Enum

from cmdb.framework.cmdb_dao import CmdbDAO
from cmdb.framework.utils import Collection, Model

LOGGER = logging.getLogger(__name__)

class LogAction(Enum):
    CREATE = 0
    EDIT = 1
    ACTIVE_CHANGE = 2
    DELETE = 3

class CmdbMetaLog(CmdbDAO):
    """
    CmdbLog
    """
    COLLECTION: Collection = 'framework.logs'
    MODEL: Model = 'CmdbLog'

    def __init__(self, public_id, log_type, log_time: datetime, action: LogAction, action_name: str):
        self.log_type = log_type
        self.log_time: datetime = log_time
        self.action: LogAction = action
        self.action_name = action_name
        super(CmdbMetaLog, self).__init__(public_id=public_id)

class CmdbObjectLog(CmdbMetaLog):
    DEFAULT_VERSION: str = '1.0.0'
    SCHEMA: dict = {
        'object_id': {
            'type': 'integer'
        },
        'public_id': {
            'type': 'integer'
        },
        'version': {
            'type': 'integer',
            'default': DEFAULT_VERSION
        },
        'user_id': {
            'type': 'integer'
        },
        'user_name': {
            'type': 'string',
            'required': True,
            'regex': r'(\w+)-*(\w)([\w-]*)'  # kebab case validation,
        },
        'render_state': {
            'type': 'string'
        },
        'log_type': {
            'type': 'string',
            'required': True,
        },
        'log_time': {
            'type': 'datetime',
            'required': True,
        },
        'changes': {
            'type': 'list',
            'empty': True,
            'default': []
        },
        'comment': {
            'type': 'string'
        },
        'action': {
            'type': 'integer',
            'required': True,
        },
        'action_name': {
            'type': 'string',
            'required': True
        },

    }

    UNKNOWN_USER_STRING = 'Unknown'

    def __init__(self, public_id: int, log_type, log_time: datetime, action: LogAction, action_name: str,
                 object_id: int, version, user_id: int, user_name: str = None, changes: list = None,
                 comment: str = None, render_state=None):
        self.object_id = object_id
        self.version = version
        self.user_id = user_id
        self.user_name = user_name or self.UNKNOWN_USER_STRING
        self.comment = comment
        self.changes = changes or []
        self.render_state = render_state
        super(CmdbObjectLog, self).__init__(public_id=public_id, log_type=log_type, log_time=log_time, action=action,
                                            action_name=action_name)

    @classmethod
    def from_data(cls, data: dict, *args, **kwargs) -> "CmdbObjectLog":
        """Create a instance of TypeModel from database values"""
        return cls(
            public_id=data.get('public_id'),
            object_id=data.get('object_id'),
            version=data.get('version', None),
            user_name=data.get('user_name'),
            user_id=data.get('user_id'),
            render_state=data.get('render_state'),
            log_time=data.get('log_time', None),
            log_type=data.get('log_type', None),
            changes=data.get('changes', None),
            comment=data.get('comment', None),
            action=data.get('action', None),
            action_name=data.get('action_name', None),
        )

    @classmethod
    def to_json(cls, instance: "CmdbObjectLog") -> dict:
        """Convert a type instance to json conform data"""
        return {
            'public_id': instance.public_id,
            'log_time': instance.log_time,
            'log_type': instance.log_type,
            'action': instance.action,
            'object_id': instance.object_id,
            'version': instance.version,
            'user_name': instance.user_name,
            'user_id': instance.user_id,
            'render_state': instance.render_state,
            'changes': instance.changes,
            'comment': instance.comment,
            'action_name': instance.action_name
        }

class CmdbLog:
    REGISTERED_LOG_TYPE = {}
    DEFAULT_LOG_TYPE = CmdbObjectLog

    @classmethod
    def __get_log_class(cls, *args, **kwargs):
        try:
            log_class = cls.REGISTERED_LOG_TYPE[kwargs['log_type']]
        except (KeyError, ValueError):
            log_class = cls.DEFAULT_LOG_TYPE
        return log_class

    @classmethod
    def register_log_type(cls, log_name, log_class):
        cls.REGISTERED_LOG_TYPE[log_name] = log_class

    @classmethod
    def from_data(cls, data: dict, *args, **kwargs):
        return cls.__get_log_class(**data).from_data(data, *args, **kwargs)

    def __new__(cls, *args, **kwargs):
        return cls.__get_log_class(*args, **kwargs)(*args, **kwargs)


from multiprocessing import Pipe, Process
from multiprocessing.connection import Connection
from typing import Any, Dict, List, Union, Tuple
import psutil
import dill

def testFunc():
	pass

class MpCoordinator():

	def __init__(self, workerCount: int):
		self.count = workerCount
		self.workerCount = workerCount
		self.processes: List[Process] = []
		self.cons: List[Tuple[Connection, Connection]] = []
		self.prepareProcesses()

	def __getstate__(self):
		state = self.__dict__.copy()
		del state["count"]
		del state["workerCount"]
		del state["processes"]
		del state["cons"]
		return state

	def prepareProcesses(self):
		for i in range(self.workerCount):
			recvCon, sendCon = Pipe(False)
			sRecvCon, sSendCon = Pipe(False)
			process = Process(target=self.handleProcess, args=(i, sendCon, sRecvCon))
			self.processes.append(process)
			self.cons.append((recvCon, sSendCon))
			process.start()

		for i in range(self.workerCount):
			con, _ = self.cons[i]
			process = self.processes[i]
			con.recv()
			ps = psutil.Process(process.pid)
			ps.suspend()

	def deactivate(self, id: int = -1):
		# for i in range(self.workerCount):
		# 	_, sendCon = self.cons[i]
		# 	process = self.processes[i]
		# 	ps = psutil.Process(process.pid)
		# 	ps.resume()
			# sendCon.send(None)

		for i in range(self.workerCount):
			# con, _ = self.cons[i]
			process = self.processes[i]
			# con.recv()
			process.kill()

		self.processes = None
		self.cons = None

	def startWork(self, actionCount: int, msgData: Any, iterableData: List[Any] = []) -> List[Any]:
		messages = []

		for i in range(0, actionCount, self.workerCount):
			count = min(self.workerCount, actionCount - i)
			newMessages = self.manageWorkCommunication(count, msgData, iterableData[i:i + count])
			messages.extend(newMessages)

		return messages

	def manageWorkCommunication(self, count: int, msgData: Any, iterableData: List[Any]) -> List[Any]:
		messages = []

		# send request to process
		for i in range(count):
			_, sendCon = self.cons[i]
			process = self.processes[i]
			ps = psutil.Process(process.pid)
			ps.resume()
			sendCon.send((iterableData[i] if i < len(iterableData) else None, msgData))

		# gather answers
		for i in range(count):
			con, _ = self.cons[i]
			process = self.processes[i]
			messages.append(con.recv())
			ps = psutil.Process(process.pid)
			ps.suspend()

		return messages

	def handleProcess(self, index: int, sendCon: Connection, statusCon: Connection):
		sendCon.send(None)

		while True:
			receiveData = statusCon.recv()
			if receiveData is None:
				sendCon.send(None)
			else:
				iterableData, constantData = receiveData
				try:
					answer = self.work(index, *([constantData, iterableData] if (iterableData is not None) else [constantData]))
					sendCon.send(answer)
				except Exception as e:
					print("Error in work function:  " + str(e) + "\n")
					sendCon.send(None)

	def work(self, index: int, data: Any):
		return 10 + index


'''
    This file is part of PM4Py (More Info: https://pm4py.fit.fraunhofer.de).

    PM4Py is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PM4Py is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PM4Py.  If not, see <https://www.gnu.org/licenses/>.
'''
from typing import Optional, Dict, Any
from enum import Enum
from pm4py.util import exec_utils
from pm4py.objects.ocel import constants as ocel_constants
from pm4py.objects.ocel.obj import OCEL
from pm4py.statistics.ocel import act_ot_dependent, act_utils, edge_metrics
from copy import copy

class Parameters(Enum):
    EVENT_ACTIVITY = ocel_constants.PARAM_EVENT_ACTIVITY
    OBJECT_TYPE = ocel_constants.PARAM_OBJECT_TYPE
    COMPUTE_EDGES_PERFORMANCE = "compute_edges_performance"

def apply(ocel: OCEL, parameters: Optional[Dict[Any, Any]] = None) -> Dict[str, Any]:
    """
    Discovers an OC-DFG model from an object-centric event log.
    Reference paper:
    Berti, Alessandro, and Wil van der Aalst. "Extracting multiple viewpoint models from relational databases." Data-Driven Process Discovery and Analysis. Springer, Cham, 2018. 24-51.

    Parameters
    -----------------
    ocel
        Object-centric event log
    parameters
        Parameters of the algorithm, including:
        - Parameters.EVENT_ACTIVITY => the attribute to be used as activity
        - Parameters.OBJECT_TYPE => the attribute to be used as object type
        - Parameters.COMPUTE_EDGES_PERFORMANCE => (boolean) enables/disables the computation of the performance on the edges

    Returns
    -----------------
    ocdfg
        Object-centric directly-follows graph, expressed as a dictionary containing the following properties:
        - activities: complete set of activities derived from the object-centric event log
        - object_types: complete set of object types derived from the object-centric event log
        - edges: dictionary connecting each object type to a set of directly-followed arcs between activities (expressed as tuples,
                  e.g., (act1, act2)). Every pair of activities is linked to some sets:
                - event_pairs: the tuples of event identifiers where the directly-follows arc occurs
                - total_objects: set of tuples containing two event and one object identifier, uniquely identifying an
                                  occurrence of the arc.
        - activities_indep: dictionary linking each activity, regardless of the object type, to some sets:
            - events: the event identifiers where the activity occurs
            - unique_objects: the object identifiers where the activity occurs
            - total_objects: the tuples of event and object identifiers where the activity occurs.
        - activities_ot: dictionary linking each object type to another dictionary, where the activities are linked to some sets:
            - events: the event identifiers where the activity occurs (with at least one object of the given object type)
            - unique_objects: the object identifiers of the given object type where the activity occurs
            - total_objects: the tuples of event and object identifiers where the activity occurs.
        - start_activities: dictionary linking each object type to another dictionary, where the start activities
                            of the given object type are linked to some sets:
            - events: the event identifiers where the start activity occurs (with at least one object of the given object type)
            - unique_objects: the object identifiers of the given object type where the start activity occurs
            - total_objects: the tuples of event and object identifiers where the start activity occurs.
        - end_activities: dictionary linking each object type to another dictionary, where the end activities
                          of the given object type are linked to some sets:
            - events: the event identifiers where the end activity occurs (with at least one object of the given object type)
            - unique_objects: the object identifiers of the given object type where the end activity occurs
            - total_objects: the tuples of event and object identifiers where the end activity occurs.
    """
    if parameters is None:
        parameters = {}

    compute_edges_performance = exec_utils.get_param_value(Parameters.COMPUTE_EDGES_PERFORMANCE, parameters, True)

    ot_independent = act_utils.find_associations_from_ocel(ocel, parameters=parameters)
    ot_dependent = act_ot_dependent.find_associations_from_ocel(ocel, parameters=parameters)
    start_parameters = copy(parameters)
    start_parameters["prefiltering"] = "start"
    ot_dependent_start = act_ot_dependent.find_associations_from_ocel(ocel, parameters=start_parameters)
    end_parameters = copy(parameters)
    end_parameters["prefiltering"] = "end"
    ot_dependent_end = act_ot_dependent.find_associations_from_ocel(ocel, parameters=end_parameters)
    edges = edge_metrics.find_associations_per_edge(ocel, parameters=end_parameters)

    object_type = exec_utils.get_param_value(Parameters.OBJECT_TYPE, parameters, ocel.object_type_column)
    event_activity = exec_utils.get_param_value(Parameters.EVENT_ACTIVITY, parameters, ocel.event_activity)

    ret = {}
    ret["activities"] = set(ocel.events[event_activity].unique())
    ret["object_types"] = set(ocel.objects[object_type].unique())

    ret["edges"] = {}
    ret["edges"]["event_couples"] = edge_metrics.aggregate_ev_couples(edges)
    ret["edges"]["unique_objects"] = edge_metrics.aggregate_unique_objects(edges)
    ret["edges"]["total_objects"] = edge_metrics.aggregate_total_objects(edges)

    ret["activities_indep"] = {}
    ret["activities_indep"]["events"] = act_utils.aggregate_events(ot_independent)
    ret["activities_indep"]["unique_objects"] = act_utils.aggregate_unique_objects(ot_independent)
    ret["activities_indep"]["total_objects"] = act_utils.aggregate_total_objects(ot_independent)

    ret["activities_ot"] = {}
    ret["activities_ot"]["events"] = act_ot_dependent.aggregate_events(ot_dependent)
    ret["activities_ot"]["unique_objects"] = act_ot_dependent.aggregate_unique_objects(ot_dependent)
    ret["activities_ot"]["total_objects"] = act_ot_dependent.aggregate_total_objects(ot_dependent)

    ret["start_activities"] = {}
    ret["start_activities"]["events"] = act_ot_dependent.aggregate_events(ot_dependent_start)
    ret["start_activities"]["unique_objects"] = act_ot_dependent.aggregate_unique_objects(ot_dependent_start)
    ret["start_activities"]["total_objects"] = act_ot_dependent.aggregate_total_objects(ot_dependent_start)

    ret["end_activities"] = {}
    ret["end_activities"]["events"] = act_ot_dependent.aggregate_events(ot_dependent_end)
    ret["end_activities"]["unique_objects"] = act_ot_dependent.aggregate_unique_objects(ot_dependent_end)
    ret["end_activities"]["total_objects"] = act_ot_dependent.aggregate_total_objects(ot_dependent_end)

    ret["edges_performance"] = {}
    ret["edges_performance"]["event_couples"] = {}
    ret["edges_performance"]["total_objects"] = {}

    if compute_edges_performance:
        ret["edges_performance"]["event_couples"] = edge_metrics.performance_calculation_ocel_aggregation(ocel,
                                                                                ret["edges"][
                                                                                "event_couples"],
                                                                                parameters=parameters)
        ret["edges_performance"]["total_objects"] = edge_metrics.performance_calculation_ocel_aggregation(ocel,
                                                                                ret["edges"][
                                                                                "total_objects"],
                                                                                parameters=parameters)

    return ret


from PyPDF2 import PdfFileReader, PdfFileWriter, PdfFileMerger
import os

def get_designated_file_name(path, ext, out_file_name):
    for folder, subdirs, files in os.walk(path):
        for file in files:
            if os.path.splitext(file)[1] == ext:
                if file == out_file_name:
                    print("跳过 %s" % out_file_name)
                    continue
                else:
                    yield os.path.join(folder, file)

current_path = os.path.split(os.path.abspath(__file__))[0]
out_file_name = 'out.pdf'
out_file_path = os.path.join(current_path, out_file_name)
file_name = list(get_designated_file_name(current_path, '.pdf', out_file_name))

# ===================================== #

# pdf_out = PdfFileWriter()
# if len(file_name) != 0:
#     for f in file_name:
#         print("正在处理 %s" %f)
#         pdf_input = PdfFileReader(open(f, 'rb'))
#         pdf_out.addPage(pdf_input.getPage(1))
#     pdf_out.write(open(out_file_path, 'wb'))
# else:
#     print("当前文件夹没有pdf文件！")

# ===================================== #

pdf_out = PdfFileMerger()
if len(file_name) != 0:
    for f in file_name:
        print("正在处理 %s" % f)
        pdf_out.append(f, pages=(1, 2))
    pdf_out.write(out_file_path)
else:
    print("当前文件夹没有pdf文件！")


"""
General purpose visitor pattern implementation, with extensions.
"""
from collections import defaultdict
import enum
import abc
from typing import Dict, Generic, Iterable, List, Optional, Type, TypeVar, Union

T = TypeVar("T")

class Visitor(Generic[T], abc.ABC):
  """
  "Visitor" pattern abstract superclass implementation for tree traversals.

  Each class has corresponding methods, doing nothing by
  default; override individual methods for specific and useful
  behaviour.  The `visit()` method is called by
  `walk()` upon entering a object.  `walkabout()` also calls
  the `depart()` method before exiting a object.

  The generic methods call "``visit_`` + objet class name" or
  "``depart_`` + objet class name", resp.

  This is a base class for visitors whose ``visit_...`` & ``depart_...``
  methods should be implemented for *all* concrete objets types encountered.
  """

  class _TreePruningException(Exception):
    """
    Base class for `Visitor`-related tree pruning exceptions.

    Raise subclasses from within ``visit_...`` or ``depart_...`` methods
    called from `Visitor.walk()` and `Visitor.walkabout()` tree traversals to prune
    the tree traversed.
    """
  class SkipChildren(_TreePruningException):
    """
    Do not visit any children of the current node.  The current node's
    siblings and ``depart_...`` method are not affected.
    """
  class SkipSiblings(_TreePruningException):
    """
    Do not visit any more siblings (to the right) of the current node.  The
    current node's children and its ``depart_...`` method are not affected.
    """
  class SkipNode(_TreePruningException):
    """
    Do not visit the current node's children, and do not call the current
    node's ``depart_...`` method.
    """
  class SkipDeparture(_TreePruningException):
    """
    Do not call the current node's ``depart_...`` method.  The current node's
    children and siblings are not affected.
    """

  def visit(self, ob: T) -> None:
    """Visit an object."""
    method = 'visit_' + ob.__class__.__name__
    visitor = getattr(self, method, getattr(self, method.lower(), self.unknown_visit))
    visitor(ob)

  def depart(self, ob: T) -> None:
    """Depart an object."""
    method = 'depart_' + ob.__class__.__name__
    visitor = getattr(self, method, getattr(self, method.lower(), self.unknown_departure))
    visitor(ob)

  def unknown_visit(self, ob: T) -> None:
    """
    Called when entering unknown object types.

    Raise an exception unless overridden.
    """
    raise NotImplementedError(
        '%s visiting unknown object type: %s'
        % (self.__class__, ob.__class__.__name__))

  def unknown_departure(self, ob: T) -> None:
    """
    Called before exiting unknown object types.

    Raise exception unless overridden.
    """
    raise NotImplementedError(
        '%s departing unknown object type: %s'
        % (self.__class__, ob.__class__.__name__))

  def walk(self, ob: T) -> None:
    """
    Traverse a tree of objects, calling the
    `visit()` method of `visitor` when entering each
    node.  (The `walkabout()` method is similar, except it also
    calls the `depart()` method before exiting each objects.)

    This tree traversal supports limited in-place tree
    modifications.  Replacing one node with one or more nodes is
    OK, as is removing an element.  However, if the node removed
    or replaced occurs after the current node, the old node will
    still be traversed, and any new nodes will not.

    :param ob: An object to walk.
    :param visitor: A `Visitor` object, containing a
        ``visit`` implementation for each object type encountered.
    :param get_children: A callable that returns the children of an object.
    """
    try:
      self.visit(ob)
    except (self.SkipChildren, self.SkipNode):
      return
    except self.SkipDeparture:
      pass # not applicable; ignore
    try:
      for child in self.get_children(ob):
          self.walk(child)
    except self.SkipSiblings:
      pass

  def walkabout(self, ob: T) -> None:
    """
    Perform a tree traversal similarly to `walk()` (which
    see), except also call the `depart()` method before exiting each node.

    :param ob: An object to walk.
    :param visitor: A `Visitor` object, containing a
        ``visit`` and ``depart`` implementation for each concrete object type encountered.
    :param get_children: A callable that returns the children of an object.
    """
    call_depart = True
    try:
      try:
        self.visit(ob)
      except self.SkipNode:
        return
      except self.SkipDeparture:
        call_depart = False
      try:
        for child in self.get_children(ob):
            self.walkabout(child)
      except self.SkipSiblings:
        pass
    except self.SkipChildren:
      pass
    if call_depart:
      self.depart(ob)

  @abc.abstractclassmethod
  def get_children(cls, ob: T) -> Iterable[T]:
    raise NotImplementedError()

# Adapted from https://github.com/pawamoy/griffe
# Copyright (c) 2021, Timothée Mazzucotelli

class PartialVisitor(Visitor[T]):
  """
  Visitor class that do not have to define all possible visit_.* methods since it overrides
  the default behaviour of unknown_visit() and unknown_departure() not to raise NotImplementedError.
  """
  def unknown_visit(self, ob: T) -> None:
    pass
  def unknown_departure(self, ob: T) -> None:
    pass

class When(enum.Enum):
    """This enumeration contains the different times an extension is used.

    Attributes:
        BEFORE: For each node, before calling the visit() method on the customizable visitor.
          ..note:: The depart() method will be called AFTER calling depart() on
            the customizable visitor. Outer scope.
        AFTER: For each node, before calling the visit(), and before the children gets visited.
          ..note:: The depart() method will be called  after the children have been visited,
            and BEFORE calling depart() on the customizable visitor. Inner scope.

    Example:
      Considering that the customizable visitor `MainVisitor` is set up with two extension visitors:
      one that runs `BEFORE` and one that runs `AFTER`, all 3 visitors simply print the name of
      the visitor class and the call beeing made.

      Running the `MainVisitor` on the following tree::

        :0 - Module: a
        | :1 - Indirection: Union

      Will generate the following output::

        Before              .visit(a)
        MainVistor          .visit(a)
        After               .visit(a)
        Before              .visit(a.Union)
        MainVistor          .visit(a.Union)
        After               .visit(a.Union)
        After               .depart(a.Union)
        MainVistor          .depart(a.Union)
        Before              .depart(a.Union)
        After               .depart(a)
        MainVistor          .depart(a)
        Before              .depart(a)
    """

    BEFORE = enum.auto()
    AFTER = enum.auto()

class VisitorExtensionList(Generic[T]):
    """
    This class helps iterating on visitor extensions that should run at different times.
    """

    def __init__(self, *extensions: 'VisitorExtension[T]') -> None:
        """Initialize the extensions container.

        Parameters:
            *extensions: The extensions to add.
        """
        self._visitors: Dict[When, List['VisitorExtension[T]']] = defaultdict(list)
        self.add(*extensions)

    def add(self, *extensions: Union['VisitorExtension[T]', Type['VisitorExtension[T]']]) -> None:
        """Add extensions to this container.

        Parameters:
            *extensions: The extensions to add.
        """
        for extension in extensions:
            if isinstance(extension, type) and issubclass(extension, VisitorExtension):
              extension = extension()
            if isinstance(extension, VisitorExtension):
              if extension.when == NotImplemented:
                raise AttributeError(f'Class variable "when" must be set on visitor extension {type(extension)}')
              self._visitors[extension.when].append(extension)
            else:
              raise TypeError(f"Visitor extensions must be an instance or a subclass of 'VisitorExtension', got '{extension!r}'")

    def attach_visitor(self, parent_visitor: 'CustomizableVisitor[T]') -> None:
        """Attach a parent visitor to the visitor extensions.

        Parameters:
            parent_visitor: The parent visitor, leading the visit.
        """
        for when in self._visitors.keys():
            for visitor in self._visitors[when]:
                visitor.attach(parent_visitor)

    @property
    def before_visit(self) -> List['VisitorExtension[T]']:
        """Return the visitors that run before the visit.

        Returns:
            Visitors.

        See: `When`
        """
        return self._visitors[When.BEFORE]

    @property
    def after_visit(self) -> List['VisitorExtension[T]']:
        """Return the visitors that run after the visit.

        Returns:
            Visitors.

        See: `When`
        """
        return self._visitors[When.AFTER]

class VisitorExtension(PartialVisitor[T]):
    """
    The node visitor extension base class, to inherit from.

    Subclasses must defined the `when` class variable, and your custom visit_* methods.

    .. python::

      class TypeGuardTracker(AstVisitorExtension):
        when = When.AFTER

        def visit_If(self, node: astroid.nodes.If) -> None:
          # self.visitor  # the main visitor
          # self.visitor.current  # the current API object
          # self.visitor.state  # the TreeWalkingState object

          if not self.visitor.state.is_type_guarged and astroidutils.is_type_guard(node):
              self.visitor.state.is_type_guarged = True
              logging.getLogger('pydocspec').info('Entering TYPE_CHECKING if block')

        def depart_If(self, node: astroid.nodes.If) -> None:
          if self.visitor.state.is_type_guarged and astroidutils.is_type_guard(node):
              logging.getLogger('pydocspec').info('Leaving TYPE_CHECKING if block')
              self.visitor.state.is_type_guarged = False

    See: `When`
    """

    when: When = NotImplemented
    When = When

    def __init__(self) -> None:
        """Initialize the visitor extension."""
        super().__init__()
        self.visitor: Visitor[T] = None  # type: ignore[assignment]
        """The parent visitor"""

    def walk(self, ob: T) -> None:
        raise NotImplementedError("Not supposed to walk the tree from a visitor extension")

    def walkabout(self, ob: T) -> None:
        raise NotImplementedError("Not supposed to walk the tree from a visitor extension")

    def attach(self, visitor: Visitor[T]) -> None:
        """Attach the parent visitor to this extension.

        Parameters:
            visitor: The parent visitor.
        """
        self.visitor = visitor

class CustomizableVisitor(Visitor[T]):
  """
  A visitor that can be composed by other vistitors.

  Subclasses must implement:
  - get_children()
  - all the required visit_*() methods
  - at least unknown_departure() such that it does not raise NotImplementedError
  """
  def __init__(self, extensions: Optional[VisitorExtensionList[T]]=None) -> None:
    self.extensions: 'VisitorExtensionList[T]' = extensions or VisitorExtensionList()
    self.extensions.attach_visitor(self)

  def visit(self, ob: T) -> None:
    """Extend the base visit with extensions.

    Parameters:
        node: The node to visit.
    """
    for v in self.extensions.before_visit:
      v.visit(ob)

    super().visit(ob)

    for v in self.extensions.after_visit:
      v.visit(ob)

  def depart(self, ob: T) -> None:
    """Extend the base depart with extensions."""

    # TODO: Does it makes sens?
    for v in self.extensions.after_visit:
      v.depart(ob)

    super().depart(ob)

    for v in self.extensions.before_visit:
      v.depart(ob)


import pandas
import pandas.api.types as pd_types
import pytest

from utils import api

@pytest.mark.vcr
def test_return_value_and_format():
    # Check return value and format
    result = api.get_city_forecast("london")

    assert isinstance(result, pandas.DataFrame)
    assert len(result) == 7

@pytest.mark.vcr
def test_column_types():
    result = api.get_city_forecast("london")

    # The date column contains date information
    assert pd_types.is_datetime64_any_dtype(result["date"])

    # Check that all pollutants and statistics are in column
    # and are of float type
    for param in ["pm2.5", "pm10", "o3", "uvi"]:
        for stat in ["min", "max", "avg"]:
            assert pd_types.is_float_dtype(result[(param, stat)])

@pytest.mark.vcr
def test_bad_city_input():
    # Check for bad inputs
    with pytest.raises(Exception, match="no known AQI station"):
        api.get_city_forecast("a definitely nonexistent city")

    with pytest.raises(Exception):
        api.get_city_forecast("")


# -*- coding: utf-8 -*-
"""
Created on Thu Mar 18 18:06:56 2021

@author: diego
"""
#import neccesary libraries
import numpy as np
import tensorflow as tf # tensorflow 2.0 Google Deep learning release
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from progressbar import progressbar
import numpy as np
import random
import os
import tensorflow as tf # tensorflow 2.0 Google Deep learning release
import cv2 as cv
from skimage.morphology import disk
from skimage.filters import threshold_otsu, rank

try:
    from . import hairReplacement
    from . import customedProcessing
except:
    import hairReplacement
    import customedProcessing
def testModels(models,testImgs,testLabels):
    multiple_y_Scores=[]
    for model in progressbar(models):
        #reshaoe images
        _,testImgs=model.reshapeImgs(testImgs,testImgs)
        predictions = model.model.predict(testImgs)
        multiple_y_Scores.append(predictions)

    return multiple_y_Scores
#show the test acc. and test loss
def evaluateModel(model,testImgs, testingLabels):# evaluate the model
    score = model.evaluate(testImgs, testingLabels, verbose=1)
    # print performance
    print()
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])
    return score
#display a confusion matrix
def confusionMat(predictions,testImgs,testingLabels,classes,dp=2):
    #generate confusion mat
    conMat = tf.math.confusion_matrix(labels=testingLabels[:,1], predictions=predictions).numpy()#use 2 row in TLs

    conMatNorm = np.around(conMat.astype('float') / conMat.sum(axis=1)[:, np.newaxis], decimals=dp)

    conMatDf = pd.DataFrame(conMatNorm,
                          index =  [0,1],
                          columns = [0,1])

    figure = plt.figure(figsize=(8, 8))
    sns.heatmap(conMatDf, annot=True,cmap=plt.cm.Blues)
    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()

#display the segmentation process applied to 10 unique images
def showImgProUnique10():
    # Set random seed for purposes of reproducibility
    seed=0
    np.random.seed(seed) # fix random seed
    tf.random.set_seed(seed)
    dataDir= r'C:\Users\yeyit\OneDrive\Desktop\project\projectModel\projectModel\unique10'
    print("hello")
    #declare array
    #imgArray=[]
    #colour arry
    imgArray=[]
    hairlessImgs=[]
    borderlessImgs=[]
    segmentedImgs=[]

    ###counter=1
        #get images
    for file in progressbar(os.listdir(dataDir)):
        #get colour img
        colourImg=cv.imread(os.path.join(dataDir,file))
        imgArray.append(colourImg)

       #display original
    fig = plt.figure(figsize=(30,10))
    for i in range(len(imgArray)):
        fig.add_subplot(2,5,i+1),plt.imshow(cv.cvtColor(imgArray[i], cv.COLOR_BGR2RGB))
        plt.xticks([]),plt.yticks([])
    plt.show()

    #display hairless
    for img in progressbar(imgArray):
        #get colour img
        img=hairReplacement.deleteHair(img)
        hairlessImgs.append(img)
    fig = plt.figure(figsize=(30,10))
    for i in range(len(hairlessImgs)):
        fig.add_subplot(2,5,i+1),plt.imshow(cv.cvtColor(hairlessImgs[i], cv.COLOR_BGR2RGB))
        plt.xticks([]),plt.yticks([])
    plt.show()

    #display borderless
    for cleanImg in progressbar(hairlessImgs):
        borderlessImg=customedProcessing.BorderRemoval(cleanImg)
        borderlessImgs.append(borderlessImg)
    fig = plt.figure(figsize=(30,10))
    for i in range(len(borderlessImgs)):
        fig.add_subplot(2,5,i+1),plt.imshow(cv.cvtColor(borderlessImgs[i], cv.COLOR_BGR2RGB))
        plt.xticks([]),plt.yticks([])
    plt.show()

    #display final segmented
    for processedImg in progressbar(borderlessImgs):
        processedImg= cv.resize(processedImg, (100,100))
        finalImg=customedProcessing.Segmentation(processedImg)
        segmentedImgs.append(finalImg)
    fig = plt.figure(figsize=(30,10))
    for i in range(len(segmentedImgs)):
        fig.add_subplot(2,5,i+1),plt.imshow(cv.cvtColor(segmentedImgs[i], cv.COLOR_BGR2RGB))
        plt.xticks([]),plt.yticks([])
    plt.show()

    return imgArray#,imgArray


from setuptools import setup, Extension
import glob
import platform
import os
import sys
import re

#Does gcc compile with this header and library?
def compile_test(header, library):
    dummy_path = os.path.join(os.path.dirname(__file__), "dummy")
    command = "bash -c \"g++ -include " + header + " -l" + library + " -x c++ - <<<'int main() {}' -o " + dummy_path + " >/dev/null 2>/dev/null && rm " + dummy_path + " 2>/dev/null\""
    return os.system(command) == 0

max_order = "6"
is_max_order = [s for s in sys.argv if "--max_order" in s]
for element in is_max_order:
    max_order = re.split('[= ]',element)[1]
    sys.argv.remove(element)

FILES = glob.glob('util/*.cc') + glob.glob('lm/*.cc') + glob.glob('util/double-conversion/*.cc') + glob.glob('python/*.cc')
FILES = [fn for fn in FILES if not (fn.endswith('main.cc') or fn.endswith('test.cc'))]

if platform.system() == 'Linux':
    LIBS = ['stdc++', 'rt']
elif platform.system() == 'Darwin':
    LIBS = ['c++']
else:
    LIBS = []

#We don't need -std=c++11 but python seems to be compiled with it now.  https://github.com/kpu/kenlm/issues/86
ARGS = ['-O3', '-DNDEBUG', '-DKENLM_MAX_ORDER='+max_order, '-std=c++11']

#Attempted fix to https://github.com/kpu/kenlm/issues/186 and https://github.com/kpu/kenlm/issues/197
if platform.system() == 'Darwin':
    ARGS += ["-stdlib=libc++", "-mmacosx-version-min=10.7"]

if compile_test('zlib.h', 'z'):
    ARGS.append('-DHAVE_ZLIB')
    LIBS.append('z')

if compile_test('bzlib.h', 'bz2'):
    ARGS.append('-DHAVE_BZLIB')
    LIBS.append('bz2')

if compile_test('lzma.h', 'lzma'):
    ARGS.append('-DHAVE_XZLIB')
    LIBS.append('lzma')

ext_modules = [
    Extension(name='kenlm',
        sources=FILES + ['python/kenlm.cpp'],
        language='C++',
        include_dirs=['.'],
        libraries=LIBS,
        extra_compile_args=ARGS)
]

setup(
    name='kenlm',
    ext_modules=ext_modules,
    include_package_data=True,
)


from random import randint
import os

from poseModel.Node import Node
from poseModel.Pose import Pose
from utils.personLoading import loadPersonOne, loadPersonTwo
from visualize import draw
# Change the parameters here
# the number of frame
# iter time
from utils.pose import createNewPose
from utils.Comparator import Comparator

frameNum = 50
iterationTime = 30
cameraHeight = 100
cameraDistance = 100
viewHeight = 1080
viewWidth = 1980
minSpeed = 3
maxSpeed = 14
walkingDirectionRange = [-10, 10]
personNum = 1

comparator = Comparator()
cwd = os.getcwd()

def createRandomNoise(currPose):
    newPose = Pose()
    for node in currPose.getPoseNodes():
        newNode = Node(node.getID(), node.getX() / (1 + (50/node.getX())), node.getY() / (1 + (50/node.getY())), node.getConfidence())
        newPose.addNode(newNode)
    return newPose

def inputDataWithRandomOrder(currPoseList):
    for i in range(0, personNum):
        index = randint(0, len(currPoseList) - 1)
        for node in currPoseList[index].getPoseNodes():
            out2.write(str(node.getX()) + " " + str(node.getY()) + " ")
        currPoseList.remove(currPoseList[index])

def inputDataWithIDOrder(currPoseList):
    for i in range(0, personNum):
        for node in currPoseList[i].getPoseNodes():
            out2.write(str(node.getX()) + " " + str(node.getY()) + " ")

def inputDataWithSumOrder(currPoseList):
    while len(currPoseList) != 0:
        curSmallestDistPose = currPoseList[0]
        for pose in currPoseList:
            curSmallestDistPose = comparator.getSmallerDistancePose(pose, curSmallestDistPose)
        for node in curSmallestDistPose.getPoseNodes():
            out2.write(str(node.getX()) + " " + str(node.getY()) + " ")
        currPoseList.remove(curSmallestDistPose)

def inputDataWithRankingOrder(currPoseList):
    while len(currPoseList) != 0:
        curSmallestDistPose = currPoseList[0]
        for pose in currPoseList:
            curSmallestDistPose = comparator.getSmallerRankingPose(pose, curSmallestDistPose)
        for node in curSmallestDistPose.getPoseNodes():
            out2.write(str(node.getX()) + " " + str(node.getY()) + " ")
        currPoseList.remove(curSmallestDistPose)

def getOverlap(x1, y1, x2, y2, x3, y3, x4, y4):
    dx = min(x2, x4) - max(x1, x3)
    dy = min(y2, y4) - max(y1, y3)
    if (dx >= 0) and (dy >= 0):
        return dx * dy / (x2 - x1) * (y2 - y1)
    else:
        return -1
def checkOcclusion(currPose):
    minX1, minY1, maxX1, maxY1 = currPose[0].getBound()
    minX2, minY2, maxX2, maxY2 = currPose[1].getBound()
    minX3, minY3, maxX3, maxY3 = currPose[2].getBound()
    oAB = 0
    oAC = 0
    oBC = 0
    if minX1 != -1:
        oAB = getOverlap(minX1, minY1, maxX1, maxY1, minX2, minY2, maxX2, maxY2)
    if minX2 != -1:
        oAC = getOverlap(minX1, minY1, maxX1, maxY1, minX3, minY3, maxX3, maxY3)
    if minX3 != -1:
        oAC = getOverlap(minX2, minY2, maxX2, maxY2, minX3, minY3, maxX3, maxY3)
    return oAB, oAC, oBC

def occlusion(currPose):
    oAB, oAC, oBC = checkOcclusion(currPose)
    if oAB != -1:
        if oAC != -1 and oBC != -1:
            currPose.remove(currPose[2])
            currPose.remove(currPose[1])
        else:
            newPose = createNewPose(currPose[0], currPose[1])
            currPose.remove(currPose[0])
            currPose.remove(currPose[0])
            currPose.append(newPose)
    elif oAC != -1:
        if oAB != -1 and oBC != -1:
            currPose.remove(currPose[2])
            currPose.remove(currPose[1])
        else:
            newPose = createNewPose(currPose[0], currPose[2])
            currPose.remove(currPose[2])
            currPose.remove(currPose[0])
            currPose.append(newPose)
    elif oBC != -1:
        if oAC != -1 and oAB != -1:
            currPose.remove(currPose[2])
            currPose.remove(currPose[1])
        else:
            newPose = createNewPose(currPose[1], currPose[2])
            currPose.remove(currPose[2])
            currPose.remove(currPose[1])
            currPose.append(newPose)
    return currPose

def getRandomRange():
    x = randint(walkingDirectionRange[0], walkingDirectionRange[1])
    y = randint(walkingDirectionRange[0], walkingDirectionRange[1])
    z = 0
    if x > y:
        z = x
        x = y
        y = z
    return x, y

out2 = open(cwd + "/data/out2.txt", "w")
out3 = open(cwd + "/data/out3.txt", "w")
start_position = (0, 0)
box_width_height = (10, 10)
moving_speed = 10
gap = 1

randomX = 0
randomY = 360

# perform random walk
for j in range(0, iterationTime):
    personList = []
    for k in range(0, personNum):
        newPerson = loadPersonOne(cwd, viewWidth, viewHeight)
        newPerson.startFromEdge()
        personList.append(newPerson)
        randomNoiseIndex = randint(10, 40)

    for i in range(1, frameNum + int(frameNum/10) + 1):
        currPoseList = []
        # person 1
        for person in personList:
            speedOne = randint(minSpeed, maxSpeed)
            direction = 0
            if i % 20 == 0:
                randX , randY = getRandomRange()
                direction += randint(randX, randY)
            person.walk(speedOne, direction)
            currPose = person.getCurrentWalkingPose()
            if i == randomNoiseIndex:
                currPose = createRandomNoise(currPose)
            currPoseList.append(currPose)

            minX, minY, maxX, maxY = currPose.getBound()
            if minX < 0 or minY < 0 or maxX >= 1980 or maxY >= 1080:
                out3.write("-1 -1 -1 -1 ")
                # for n in currPoseList[0].getPoseNodes():
                #     n.invalid()
            else:
                out3.write(str(minX) + " " + str(minY) + " " + str(maxX) + " " + str(maxY) + " ")

        # specify the output file order
        inputDataWithRankingOrder(currPoseList)

        out2.write("\n")
        out3.write("\n")

out2.close()
out3.close()

#inputData = open(cwd + "/data/inputData.txt", 'w')
#outputData = open(cwd + "/data/outputData.txt", 'w')

inputData = open("/Users/mars/Desktop/PData/inputData.txt", 'w')
outputData = open("/Users/mars/Desktop/PData/outputData.txt", 'w')

out2 = open(cwd + "/data/out2.txt", 'r')
out3 = open(cwd + "/data/out3.txt", 'r')

# this is for a bug in file operations, remove unrelated lines and spaces
for line in out2:
    if line != "\n":
        inputData.write(line)

for line in out3:
    b = "100000 100000 -1 -1 " in line
    if b == False:
        outputData.write(line)
# ***********************************************************************

inputData.close()
outputData.close()

draw()


import difflib
import io
import re
from typing import List

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

from reworkd_platform.schemas.workflow.base import Block, BlockIOBase

class DiffPDFInput(BlockIOBase):
    original: str
    updated: str

class DiffPDFOutput(BlockIOBase):
    file_url: str

class DiffPDF(Block):
    type = "DiffPDF"
    description = "Create a PDF that shows the difference between two bodies of text"
    input: DiffPDFInput

    async def run(self, workflow_id: str) -> DiffPDFOutput:
        with io.BytesIO() as diff_pdf_file:
            diffs = get_diff(self.input.original, self.input.updated)
            diff_pdf_file = get_diff_pdf(diffs, diff_pdf_file)
            print(diff_pdf_file)

            return DiffPDFOutput(file_url="# TODO: Save file to S3 and return the URL")

def get_diff(original: str, updated: str) -> List[str]:
    differ = difflib.Differ()
    words1: List[str] = re.findall(r"\b\w[\w-]*\b|\S", original, re.UNICODE)
    words2: List[str] = re.findall(r"\b\w[\w-]*\b|\S", updated, re.UNICODE)

    return list(differ.compare(words1, words2))

def get_diff_pdf(diff_list: List[str], in_memory_file: io.BytesIO) -> io.BytesIO:
    """
    Create a PDF that shows the difference between two bodies of text
    Each element of diff_list is a string of type "  word", "- word", or "+ word"
    """
    in_memory_file = io.BytesIO()

    c = canvas.Canvas(in_memory_file, pagesize=letter)
    width, height = letter

    text_obj = c.beginText()
    text_obj.setTextOrigin(10, height - 50)  # Place text at the top of the canvas/page

    for word in diff_list:
        if word.startswith("  "):
            # Black for normal text
            text_obj.setFillColorRGB(0, 0, 0)
            text_obj.textOut(word[2:] + " ")
        elif word.startswith("- "):
            # Darker red for deleted words
            text_obj.setFillColorRGB(0.5, 0, 0)
            text_obj.textOut(word[2:] + " ")
        elif word.startswith("+ "):
            # Darker green for added words
            text_obj.setFillColorRGB(0, 0.5, 0)
            text_obj.textOut(word[2:] + " ")
        else:
            continue

    c.drawText(text_obj)
    c.save()

    in_memory_file.seek(0)
    return in_memory_file


#from django.shortcuts import render
from .forms import *
from .models import table
from .models import faculty
from .models import course
from .models import examtype
from django.forms import modelformset_factory
from django.contrib import messages

import os
import csv
from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth.forms import UserCreationForm,AuthenticationForm
from django.contrib.auth import login as new, logout as out,authenticate
from django.conf import settings
from django.core.files.storage import FileSystemStorage

def simple_upload(request,course_id):
    #form = file_upload(request.POST, request.FILES)
    if request.method == 'POST':
        form = file_upload(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            print(request.FILES['fileupload'])
            create_table(str(request.FILES['fileupload']),request.user.id,course_id)
            messages.success(request,'uploaded successfuly');
            return redirect('post_list')

    else:
        form = file_upload()
        return render(request, 'fileindb/basic.html', {
        'form': form
    })

def create_table(file,id,course_id):
    path = 'media\static'

    c = open(path+'\\'+file,'r')
    data=[]
    q=c.readlines()
    a=q[0].split(",")
    for i in q:
        print(i)

        data.append(i.split(","))
    print(data)
    proff=faculty.objects.get(user_id=id)
    proff_id=proff.id

    size=int((len(data)))
    print(size)
    for j in range(size):
        print(data[j][0])
        exam=examtype.objects.get(course_id_id=course_id,exam_type=data[j][0]).id
        table.objects.create(exam_id=exam,student_id=data[j][1],student_name=data[j][2],marks=data[j][3],proff_id_id=proff_id,course_id_id=course_id)

def course_add(request):
    form1 = modelformset_factory(examtype, fields=('max_marks','exam_type'), extra=5)
    if request.method=='POST':
        form=add_course(request.POST or None)
        formset = form1(request.POST or None)
        if form.is_valid() and formset.is_valid():
            courses=form.save(commit=False)
            id=request.user.id
            proff = faculty.objects.get(user_id=id)
            proff_id = proff.id
            courses.proff_id_id=proff_id
            courses.save()
            for file in formset:
                if file.cleaned_data:
                    fiveform = examtype(course_id_id=request.POST['course_id'],max_marks=file.cleaned_data.get('max_marks'),exam_type=file.cleaned_data.get('exam_type'))
                    fiveform.save()
            context={
                'id':proff.id
            }
            return render(request,'fileindb/exam.html',context)

    else:
        form = add_course()
        formset = form1(queryset=examtype.objects.none())
    return render(request, 'fileindb/temp.html', {
        'form': form,
        'formset': formset,
    })

def add_exams(request,id):
    ur_courses=course.objects.filter(proff_id_id=id)
    if request.method=='POST':
        add_id=request.POST['cname']
        context={
            'add_id':add_id
        }
        return render(request,'fileindb/uploadcsv.html',context)

    context={
        'ur_courses':ur_courses
    }
    if ur_courses:
        return render(request,'fileindb/add_exam.html',context)
    else:
        messages.success(request, "User Does't Exist . Create it first")
        return redirect('user_register')


import argparse
import os
import numpy as np
import math

import torchvision.transforms as transforms
from torchvision.utils import save_image

from torch.utils.data import DataLoader
from torchvision import datasets
from torch.autograd import Variable

import torch.nn as nn
import torch.nn.functional as F
import torch
import pdb

#import torchvision.datasets as dset
from mydataset import customDataset
from wgan_gp import *

os.makedirs("fid_pic", exist_ok=True)

parser = argparse.ArgumentParser()
parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space")
parser.add_argument("--n_classes", type=int, default=144, help="number of classes for dataset")
parser.add_argument("--img_size", type=int, default=128, help="size of each image dimension")
parser.add_argument("--channels", type=int, default=3, help="number of image channels")
parser.add_argument("--testlabel", type=str, default='sample_test/sample_fid_testing_labels.txt', help="test label")
opt = parser.parse_args()

img_shape = (opt.channels, opt.img_size, opt.img_size)

cuda_available = torch.cuda.is_available()
cuda = True if torch.cuda.is_available() else False
device = torch.device("cuda" if cuda_available else "cpu")

FloatTensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor

def gen_rand_noise_with_label(label=None,batch_size=1):
    if label is None:
        label = np.random.randint(0, opt.n_classes, batch_size)
    #attach label into noise
    noise = np.random.normal(0, 1, (batch_size, 256))
    prefix = np.zeros((batch_size, opt.n_classes))
    prefix[np.arange(batch_size), label] = 1
    noise[np.arange(batch_size), :opt.n_classes] = prefix[np.arange(batch_size)]

    noise = torch.from_numpy(noise).float()
    noise = noise.to(device)

    return noise

generator = GoodGenerator()
generator.load_state_dict(torch.load('./generator.pkl'))
if cuda:
    generator.cuda()
generator.eval()

test_lab = []
ftest = open(opt.testlabel, "r")
testlines = ftest.readlines()
test_len = int(testlines[0])
for tcount in range(test_len):
    onehots = list(map(lambda x:int(x),testlines[tcount+2].split()[0:]))
    test_lab.append(24*np.argmax(onehots[0:6])+6*np.argmax(onehots[6:10])+2*np.argmax(onehots[10:13])+np.argmax(onehots[13:15]))
#test_lab = torch.cuda.LongTensor(test_lab)

for i in range(len(test_lab)):
# Sample noise
    #z = Variable(FloatTensor(np.random.normal(0, 1, (1, opt.latent_dim))))
# Get labels ranging from 0 to n_classes for n rows
#labels = np.array([num for _ in range(n_row) for num in range(n_row)])#
    labels = test_lab[i]
    z=gen_rand_noise_with_label(labels,1)
    #labels = Variable(FloatTensor(labels).view(1,-1))#
    gen_imgs = generator(z)
    gen_imgs = gen_imgs.view(-1, 3, opt.img_size, opt.img_size)
    save_image(gen_imgs.data, "fid_pic/%d.png" % i, normalize=True)#nrow=n_row


from bs4 import BeautifulSoup

html = """ <title>test site</title>
ttt123123test2<c>test3</c>
 """

soup = BeautifulSoup(html, 'lxml')

tag_p_nexts = soup.p.next_elements

print(soup.prettify())
print('**elements**')

for i in tag_p_nexts:
    print(i)


import logging
import sys
from pytsa.tsa import *
from pytsa.tsa import SeqView_double_t as SV
import os
import numpy as np
import time
from wdfml.config.parameters import Parameters
from wdfml.processes.whitening import *
from wdfml.processes.filtering import *
from wdfml.processes.wdf import *
from wdfml.observers.observable import Observable
from wdfml.observers.ClusteringObserver import Clustering
from wdfml.observers.PrintFileObserver import PrintTriggers
from wdfml.observers.ClassifierObserver import Classifier
from sklearn.externals import joblib

def main ( ):
    logging.basicConfig(level=logging.INFO)
    logging.info("read Parameters")
    par = Parameters()
    par.load("fileParameters.json")
    # logging.info(par.__dict__)
    # Parameter for sequence of data
    gpsE = float(par.gpsStart) + 10.0
    Learn = SV()
    Learn_DS = SV()
    # logging.info(par.sampling, par.resampling)

    # parameter for whitening and its estimation parameters
    whiten = Whitening(par.ARorder)
    ###Name of the files where the whitening parameters are saved
    LVfile = "./ARparameters/LVstate_%s_%s_%s.txt" % (par.ARorder, par.channel, int(par.gps))
    ARfile = "./ARparameters/ARstate_%s_%s_%s.txt" % (par.ARorder, par.channel, int(par.gps))
    if par.estimation == "True":
        logging.info('Start AR parameter estimation')
        ######## read data for AR estimation###############
        learnlen = 2.0 * float(par.learn)
        strLearn = FrameIChannel(par.file, par.channel, learnlen, gpsE)
        par.Noutdata = int(par.learn * par.resampling)
        ds = downsamplig(par)
        strLearn.GetData(Learn)
        ds.Process(Learn, Learn_DS)
        whiten.ParametersEstimate(Learn_DS)
        whiten.ParametersSave(ARfile, LVfile)
    else:
        logging.info('Load AR parameter')
        whiten.ParametersLoad(ARfile, LVfile)

    ######################
    # Parameter for sequence of data
    # read data
    par.Noutdata = int(par.len * par.resampling)
    ds = downsamplig(par)
    gpsstart = par.gpsStart - par.len
    streaming = FrameIChannel(par.file, par.channel, par.lenStart, gpsstart)
    data = SV()
    data_ds = SV()
    dataw = SV()
    ###---preheating---###
    streaming.GetData(data)
    ds.Process(data, data_ds)
    whiten.Process(data_ds, dataw)
    ### WDF process
    # sigma for the noise
    par.sigma = whiten.GetSigma()
    logging.info('Estimated sigma= %s' % par.sigma)
    par.Ncoeff = par.window

    ###Start detection loop
    logging.info("Starting detection loop")

    streaming.SetDataLength(par.len)
    startT = data.GetStart()
    ## gpsEnd=par.gpsEnd +par.lenStart
    clf = joblib.load('./pipelines/pca-gmm.pkl')
    WDF = wdf(par)

    observable = Observable()
    observableO = Observable()
    clustering = Clustering(par)
    savetrigger = PrintTriggers(par)
    classifier=Classifier(par,clf)
    observable.register(clustering)
    observableO.register(savetrigger)
    observableO.register(classifier)
    while data.GetStart() < par.gpsEnd:
        streaming.GetData(data)
        ds.Process(data, data_ds)
        whiten.Process(data_ds, dataw)
        WDF.SetData(dataw)
        while WDF.wdf2classify.GetDataNeeded() > 0:
            ev = WDF.FindEvents()
            observable.update_observers(ev)
            cev=clustering.CEV
            observableO.update_observers(cev)
    logging.info(classifier.classified)
    logging.info('Program terminated')
    par.dump("fileParametersUsed.json")

if __name__ == '__main__':  # pragma: no cover
    start_time = time.time()
    main()
    elapsed_time = time.time() - start_time
    logging.info('elapsed_time= %s' % elapsed_time)


import os
import time
import uuid
import warnings
from shutil import make_archive

import requests as requests
from selenium import webdriver
from tqdm import tqdm
from selenium.webdriver.common.by import By
from termcolor import colored

# Added to ignore Deprecation Warnings because I can't be bothered to switch to new system
warnings.filterwarnings("ignore", category=DeprecationWarning)

# Checks if the Downloads folder exists
if not os.path.exists("./Downloads"):
    os.mkdir("./Downloads")

# Sets the user agent
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"
# Defines options for the headless Chrome browser
options = webdriver.ChromeOptions()
options.add_argument(f'user-agent={user_agent}')
#options.add_argument("--headless")
options.add_argument("--window-size=1920,1080")
options.add_argument('--ignore-certificate-errors')
options.add_argument('--allow-running-insecure-content')
options.add_experimental_option('excludeSwitches', ['enable-logging'])
browser = webdriver.Chrome(options=options)

try:
    # CLI Title
    print(colored("""
█████████""", "red") + colored("""  THE BINDING OF
""", "yellow") + colored("""   ███   █████   ██████    ██████    ██████
   ███  ███          ███       ███  ███  ███
   ███   █████   ███████   ███████  ███
   ███      ███ ███  ███  ███  ███  ███  ███
   ███  ██████   ████████  ████████  ██████
""", "red") + colored("""█████████""", "red") + """                CARD DOWNLOADER""" + colored("""

https://github.com/CoronaCarrot/Isaac-Foursuls-Sorted-Downloader""", "white"))
    print(
        "\n\nPlease enter a search filter link from https://foursouls.com/card-search"
        "\nwith the cards you wish to download.\n")
    loop = True
    while loop:
        # Await valid link input
        web = input("> ")
        if web.startswith("https://foursouls.com/card-search/?"):
            loop = False
            browser.get(web)
            browser.switch_to.window(browser.window_handles[0])
        else:
            print("Invalid link, please try again.")

    # generates a download file for the current download
    filename = str(uuid.uuid1())
    os.mkdir(f"./Downloads/{filename}")
except:
    exit()

# Finds the card count
cardcount = browser.find_element(By.XPATH, "//*[contains(text(), 'cards found')]")

# gets page amount
pages = browser.find_elements(By.XPATH, "//*[contains(@class, 'page-numbers')]")
prev = 0

# gets a list of all card links within those pages
for page in pages:
    if int(page.text) > prev:
        prev = int(page.text)
cardcount = str(cardcount.text).strip(" CARDS FOUND")

print(f"\nFound {cardcount} cards. beginning download...\n")

cardhref = []

runc = 0
while prev > 0:
    print("Scanning Results... {} Pages scanned...".format(runc))

    if prev != 1:
        page = web.replace("card-search/", f"card-search/page/{prev}/")
    else:
        page = web
    browser.get(page)
    prev -= 1
    cards = browser.find_elements(By.XPATH, "//*[contains(@href, 'https://foursouls.com/cards/')]")
    for card in cards:
        href = card.get_attribute("href")
        if href != "https://foursouls.com/cards/":
            cardhref.append(href)

    runc += 1
    time.sleep(1)

# runs through the full list of cards to download
for card in tqdm(cardhref, bar_format="{l_bar}{bar}|{n_fmt}/{total_fmt} [Est. {remaining}]"):
    browser.get(card)
    try:
        cards = browser.find_element(By.XPATH, "//*[contains(@alt, 'Treasure Card Back')]")
        type = "treasure"
    except:
        try:
            cards = browser.find_element(By.XPATH, "//*[contains(@alt, 'Soul Card Back')]")
            type = "soul"
        except:
            try:
                cards = browser.find_element(By.XPATH, "//*[contains(@alt, 'Character Card Back')]")
                type = "character"
            except:
                try:
                    cards = browser.find_element(By.XPATH, "//*[contains(@alt, 'Eternal Card Back')]")
                    type = "eternal"
                except:
                    try:
                        cards = browser.find_element(By.XPATH, "//*[contains(@alt, 'Loot Card Back')]")
                        type = "loot"
                    except:
                        try:
                            cards = browser.find_element(By.XPATH, "//*[contains(@alt, 'Monster Card Back')]")
                            type = "monster"
                        except:
                            try:
                                cards = browser.find_element(By.XPATH, "//*[contains(@alt, 'Room Card Back')]")
                                type = "room"
                            except:
                                type = "unsorted"
    cardimg = browser.find_element(By.XPATH, "//*[contains(@class, 'cardFront')]")
    url = cardimg.get_attribute("src")
    imgname = card.split("/")
    imgname = imgname[len(imgname) - 2]

    # checks if the category exists, if not it creates it
    if not os.path.exists(f"Downloads/{filename}/{type}"):
        os.mkdir(f"Downloads/{filename}/{type}")
    # saves card to folder
    with open(f'Downloads/{filename}/{type}/{imgname}.png', 'wb') as f:
        f.write(requests.get(url.replace("-308x420", "")).content)
        f.close()

# zips all cards into an archive
print("\nDownload complete. Zipping files...")
make_archive(f'./Downloads/{filename}/Output', 'zip', root_dir=f'./Downloads/{filename}')


import os
import tempfile
from pathlib import Path
from shutil import rmtree

import pytest

from tests.utils import SAMPLE1_PATH
from .basefs import BaseFsTest
from zipreport.fileutils import DiskFs, FsError

class TestDiskFs(BaseFsTest):
    dname = 'this_test_dir'
    fname = 'this_test_file.txt'
    fcontents = b"The quick brown fox jumped over the lazy dog"

    temp_dir = '/tmp'
    temp_methods = ['test_diskfs_tree', 'test_diskfs_files']

    def setup_method(self, method):
        if method.__name__ in self.temp_methods:
            self.temp_dir = tempfile.mkdtemp()

    def teardown_method(self, method):
        if method.__name__ in self.temp_methods:
            if os.path.exists(self.temp_dir) and self.temp_dir != '/tmp':
                rmtree(self.temp_dir)
                self.temp_dir = '/tmp'

    def test_diskfs_list(self):
        """
        Simple diskfs operations on examples/sample1
        :return:
        """
        path = Path(SAMPLE1_PATH)
        dfs = DiskFs(path)
        assert dfs.get_backend() is None

        rootdirs, rootfiles, items = self.path_walk(path)

        assert len(items) > 0
        assert len(rootdirs) > 0
        assert len(rootfiles) > 0
        assert len(dfs.list('')) == len(items)
        assert len(dfs.list_dirs('/')) == len(rootdirs)
        assert len(dfs.list_files('/')) == len(rootfiles)

        for dir in dfs.list_dirs('/'):
            assert dir in rootdirs
            assert dfs.is_dir(dir) is True
        for file in dfs.list_files('/'):
            assert file in rootfiles
            assert dfs.is_dir(file) is False

    def test_diskfs_files(self):
        """
        Simple add/get tests
        :return:
        """
        path = Path(self.temp_dir)
        dfs = DiskFs(path)

        assert dfs.exists(self.fname) is False
        # == add file to root
        dfs.add(self.fname, self.fcontents)

        # can we read the file?
        assert dfs.exists(self.fname) is True
        assert dfs.get(self.fname).getbuffer() == self.fcontents

        # check if file was created
        fpath = path / self.fname
        with open(fpath, 'rb') as f:
            assert f.read() == self.fcontents
        os.unlink(fpath)

        # == add file to new dir
        assert dfs.exists(self.dname) is False
        dfs.mkdir(self.dname)
        assert dfs.exists(self.dname) is True
        dfs.add(os.path.join(self.dname, self.fname), self.fcontents)

        # can we read the file?
        assert dfs.get(os.path.join(self.dname, self.fname)).getbuffer() == self.fcontents

        # check if file was created inside dname
        fpath = path / self.dname / self.fname
        with open(fpath, 'rb') as f:
            assert f.read() == self.fcontents
        os.unlink(fpath)
        os.rmdir(path / self.dname)

    def test_diskfs_tree(self):
        """
        Test a full directory tree
        :return:
        """
        dfs = DiskFs(self.temp_dir)
        self.build_tree(dfs)

        # test that we can't overwrite files
        with pytest.raises(FsError):
            self.build_tree(dfs)

        # test that we can't create dirs on top of existing stuff
        for i in range(1, 10):
            with pytest.raises(FsError):
                dfs.mkdir(self.tree_filename.format(0, i))
            with pytest.raises(FsError):
                dfs.mkdir(self.tree_dirname.format(0, i))

        # verify tree
        self.verify_tree(dfs)


# -*- coding: utf-8 -*-
# @Time    : 2018/7/12 16:22
# @Author  : Parker
# @File    : 理解优化函数.py
# @Software: PyCharm

import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from skimage.feature import hog

def convert_color(img, conv='RGB2YCrCb'):
    if conv == 'RGB2YCrCb':
        return cv2.cvtColor(img, cv2.COLOR_RGB2YCrCb)
    if conv == 'BGR2YCrCb':
        return cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
    if conv == 'RGB2LUV':
        return cv2.cvtColor(img, cv2.COLOR_RGB2LUV)

def get_hog_features(img, orient, pix_per_cell, cell_per_block, vis=False, feature_vec=True):
    if vis == True:
        features, hog_image = hog(img, orientations=orient, pixels_per_cell=(pix_per_cell,pix_per_cell),
                                 cells_per_block=(cell_per_block,cell_per_block),
                                 block_norm='L2-Hys', transform_sqrt=False,
                                 visualise=vis, feature_vector=feature_vec)
        return features, hog_image
    else:
        features = hog(img,orientations=orient, pixels_per_cell=(pix_per_cell,pix_per_cell),
                       cells_per_block=(cell_per_block,cell_per_block),
                       block_norm='L2-Hys',transform_sqrt=False,
                       visualize=vis, feature_vector= feature_vec)
        return features

def bin_saptial(img, size=(32,32)):
    color1 = cv2.resize(img[:,:,0],size).ravel()
    color2 = cv2.resize(img[:,:,1],size).ravel()
    color3 = cv2.resize(img[:,:,2],size).ravel()
    return np.hstack((color1,color2,color3))

def color_hist(img, nbins=32):
    hist1 = np.histogram(img[:,:,0], bins=nbins)
    hist2 = np.histogram(img[:,:,1], bins=nbins)
    hist3 = np.histogram(img[:,:,2], bins=nbins)
    hist_features=np.concatenate((hist1[0],hist2[0],hist3[0]))

y_start = 380
y_stop = 660

def find_cars(img, y_start, y_stop, scale, svc, X_scaler, orient, pix_per_cell, cell_per_block, spatial_size, hist_bins ):
    draw_img = np.copy(img)
    img = draw_img.astype(np.float32)/255

    img_tosearch = img[y_start:y_stop,:,:]
    # 转换颜色空间
    ctrans_tosearch = convert_color(img_tosearch)

    # 缩放图像
    if scale != 1:
        imgshape = ctrans_tosearch.shape
        ctrans_tosearch = cv2.resize(ctrans_tosearch,(np.int(imgshape[1]/scale),np.int(imgshape[0])/scale))

    ch1 = ctrans_tosearch[:,:,0]
    ch2 = ctrans_tosearch[:,:,1]
    ch3 = ctrans_tosearch[:,:,2]

    nxblocks = (ch1.shape[1] // pix_per_cell) - cell_per_block + 1

    return ctrans_tosearch

img_name = 'test_image.jpg'
image = mpimg.imread(img_name)

result = find_cars(image)

f, axes = plt.subplots(1,3,figsize=(18,4))
for i in range(3):
    axes[i].imshow(result[:,:,i],cmap='gray')
plt.show()


#!/usr/bin/env python
from config.config import *
import logging
import tornado.escape
import tornado.ioloop
import tornado.web
import os.path
from KMeans import *
from database.MysqlDriver import MysqlDriver
from tornado.concurrent import Future
from tornado import web, websocket
from tornado.options import define, options, parse_command_line
from threading import Thread
import json

define("port", default=8888, help="run on the given port", type=int)

class HomePage(tornado.web.RequestHandler):
    @web.asynchronous
    def get(self):
        # self.render("index.html")
        self.write("Hello World")
        print("This will be the main page")
        self.finish()

class DoAnalysis(tornado.web.RequestHandler):
    @web.asynchronous
    def set_default_headers(self): # this as safety issues, cors
        origin = self.request.headers.get('Origin')
        if origin:
            self.set_header('Access-Control-Allow-Origin', origin)
        self.set_header('Access-Control-Allow-Credentials', 'true')
    def post(self):
        year = self.get_argument("year")
        taskId = self.get_argument("taskId")
        self.db = MysqlDriver(DATABASE.host,DATABASE.username, DATABASE.password, DATABASE.dbname) # connect to MySql database server
        dataset = self.db.getFeatures()
        km=KMeans(dataset,50,3, year, taskId)#initiatating ML algo
        MLthread = Thread(target = km.main, args=())
        MLthread.daemon = True
        MLthread.start()
        self.write("Request created")#send the response of requested created
        self.finish()

def main():
    # try:
    parse_command_line()
    app = tornado.web.Application(
        [
            (r"/", HomePage),
            (r"/doAnalysis", DoAnalysis),
        ]
    )
    app.listen(options.port)
    print("MLServer core is hot now "+str(options.port))
    tornado.ioloop.IOLoop.current().start()
    # except:
    #     print("Server cannot be initialised")

if __name__ == "__main__":
    thread = Thread(target = main)
    thread.start()
    # thread.join()
    # main()


from django.core.management import BaseCommand
import JokrBackend.Constants as Const
from JokrBackend.models import Session, OnlineContent

class Command(BaseCommand):
#-------------------------------------------------------------------------------
# handle
# the 'main method'
#-------------------------------------------------------------------------------
    def handle(self, *args, **options):

        dummySession = Session.objects.get(id=Const.Database.Defaults.ID)
        content = OnlineContent.objects.all()

        for c in content:
            try:
                c.fromSession.id
            except Exception:
                c.fromSession = dummySession
                c.save()
                print('ERROR, REWRITING SESSION DATA')


import os
import shutil
import pathlib
import itertools
import csv
import zipfile
import pcbnew  # https://docs.kicad.org/doxygen-python-7.0/namespacepcbnew.html
import wx  # https://docs.wxpython.org/wx.functions.html

class InputLabsExport(pcbnew.ActionPlugin):
    def Run(self):
        self.board = pcbnew.GetBoard()
        project_file = pathlib.Path(self.board.GetFileName())
        self.project_folder = project_file.parent
        self.output_folder = self.project_folder / 'order'
        self.temp_folder = self.project_folder / 'order/temp'
        self.log_init()

    def log_init(self):
        self.log_file = self.project_folder / 'plugins/kicad_log'
        if self.log_file.exists():
            os.remove(self.log_file)

    def log(self, *msg):
        with open(self.log_file, 'a') as file:
            if len(msg) == 1: msg = msg[0]
            file.write(f'{msg}\n')

    def delete_temp(self):
        shutil.rmtree(self.temp_folder, ignore_errors=True)

    def export_plot(self):
        plot_controller = pcbnew.PLOT_CONTROLLER(self.board)
        plot_options = plot_controller.GetPlotOptions()
        plot_options.SetOutputDirectory(self.temp_folder)
        # General options.
        plot_options.SetPlotFrameRef(False)
        plot_options.SetPlotValue(False)
        plot_options.SetPlotReference(True)
        plot_options.SetPlotInvisibleText(False)
        # plot_options.SetExcludeEdgeLayer(True)  # Deprecated ?
        plot_options.SetSketchPadsOnFabLayers(False)
        plot_options.SetUseAuxOrigin(False)
        plot_options.SetAutoScale(True)
        plot_options.SetMirror(False)
        plot_options.SetNegative(False)
        # Gerber options.
        plot_options.SetUseGerberProtelExtensions(True)
        plot_options.SetCreateGerberJobFile(False)
        plot_options.SetSubtractMaskFromSilk(True)
        plot_options.SetIncludeGerberNetlistInfo(False)
        # Plot.
        layers = {
            'F.Cu': pcbnew.F_Cu,
            'B.Cu': pcbnew.B_Cu,
            'F.Paste': pcbnew.F_Paste,
            'B.Paste': pcbnew.B_Paste,
            'F.Silkscreen': pcbnew.F_SilkS,
            'B.Silkscreen': pcbnew.B_SilkS,
            'F.Mask': pcbnew.F_Mask,
            'B.Mask': pcbnew.B_Mask,
            'Edge.Cuts': pcbnew.Edge_Cuts,
        }
        for name, layer in layers.items():
            plot_controller.SetLayer(layer)
            plot_controller.OpenPlotfile(name, pcbnew.PLOT_FORMAT_GERBER, name)
            plot_controller.PlotLayer()
        plot_controller.ClosePlot()

    def export_drill(self):
        writer = pcbnew.EXCELLON_WRITER(self.board)
        writer.SetRouteModeForOvalHoles(False)
        writer.SetFormat(
            True,  # aMetric
            pcbnew.GENDRILL_WRITER_BASE.DECIMAL_FORMAT,  # aZerosFmt
            3,  # aLeftDigits
            3,  # aRightDigits
        )
        writer.SetOptions(
            False,  # aMirror.
            False,  # aMinimalHeader
            writer.GetOffset(),  # aOffset.
            False,  # aMerge_PTH_NPTH
        )
        writer.CreateDrillandMapFilesSet(
            str(self.temp_folder),  # aPlotDirectory
            True,   # aGenDrill
            False,  # aGenMap
            None,   # aReporter
        )

class InputLabsExportJLCPCB(InputLabsExport):
    def defaults(self):
        self.name = "Input Labs: JLCPCB export"
        self.category = "Export"
        self.description = "Export plot and drill files"
        self.show_toolbar_button = False

    def Run(self):
        super(InputLabsExportJLCPCB, self).Run()
        self.prepare_folders()
        self.export_plot()
        self.export_drill()
        self.zip_gerber()
        self.delete_temp()
        self.export_cpl()
        self.export_bom()
        msg = (
            'Production files successfully created at:\n' +
            str(self.output_folder)
        )
        wx.MessageBox(msg, self.name, wx.OK)

    def prepare_folders(self):
        self.delete_temp()
        if not self.output_folder.exists():
            os.makedirs(self.output_folder)
        for path in self.output_folder.glob('jlcpcb_*'):
            os.remove(path)

    def get_footprints(self):
        footprints = self.board.GetFootprints()
        def is_exportable(footprint):
            if not footprint.HasProperty('LCSC'): return False
            if footprint.GetProperty('LCSC') == '': return False
            # Evaluate 'Export' attribute as boolean, even though the type
            # is a string in Kicad.
            truthly = ['True', 'true', 'TRUE', 'Yes', 'yes', 'YES', '1']
            if footprint.GetProperty('Export') not in truthly: return False
            return True
        return filter(is_exportable, footprints)

    def export_cpl(self):
        fields = ['Designator', 'Mid X', 'Mid Y', 'Layer', 'Rotation']
        cpl_file = self.output_folder / 'jlcpcb_cpl.csv'
        writer = csv.DictWriter(open(cpl_file, 'w'), fieldnames=fields)
        writer.writeheader()
        footprints = self.get_footprints()
        for footprint in sorted(footprints, key=lambda x: x.GetReference()):
            position_x, position_y = footprint.GetPosition()
            writer.writerow({
                'Designator': footprint.GetReference(),
                'Mid X': position_x /  1000000,
                'Mid Y': position_y / -1000000,
                'Layer': 'bottom' if footprint.IsFlipped() else 'top',
                'Rotation': int(footprint.GetOrientation().AsDegrees()),
            })

    def export_bom(self):
        fields = ['Comment', 'Designator', 'Footprint', 'LCSC Part Number']
        bom_file = self.output_folder / 'jlcpcb_bom.csv'
        writer = csv.DictWriter(open(bom_file, 'w'), fieldnames=fields)
        writer.writeheader()
        footprints = sorted(
            self.get_footprints(),
            key=lambda x: x.GetProperty('LCSC')
        )
        groups = itertools.groupby(footprints, lambda x: x.GetProperty('LCSC'))
        for lcsc, group in groups:
            if not lcsc: continue
            group = list(group)  # Making a reusable copy.
            references = [x.GetReference() for x in group]
            comment = group[0].GetPropertyNative('Group')
            mount = group[0].GetProperty('Mount')
            writer.writerow({
                'Comment': comment,
                'Designator': ','.join(sorted(references)),
                'Footprint': mount,
                'LCSC Part Number': lcsc,
            })

    def zip_gerber(self):
        zip_path = self.output_folder / 'jlcpcb_gerber.zip'
        zipper = zipfile.ZipFile(
            zip_path,
            mode='w',
            compression=zipfile.ZIP_DEFLATED,
        )
        for path in self.temp_folder.glob('*'):
            zipped_path = path.relative_to(self.temp_folder)
            zipped_path = zipped_path.with_name(
                zipped_path.name.replace('alpaca', 'board')
            )
            zipper.write(path, zipped_path)

InputLabsExportJLCPCB().register()


import allure
from selenium.webdriver.common.keys import Keys

from pages.custom_elements.app_dropdown import DropDownSuggest
from pages.incident_card.base_container import BaseContainer

class QuestionListContainer(BaseContainer):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._keyboard_combinations = [Keys.ALT, 't']
        self._input = self.element.s('//input[@placeholder="добавить тип происшествия"]')
        self._autocomplete_dropdown = DropDownSuggest(xpath='//*[@aria-label="добавить тип происшествия"]')
        self._elements_for_assert = [
            self._input,
        ]

    @allure.step('Добавление типа инцидента')
    def add_incident_type(self, incident: str):
        self._autocomplete_dropdown.set_partial_value_and_choose_suggest(value=incident)


#
# python3 massCheck.py testmode
# scroll down to line 64 to add your profile info - this subscribes to accounts using network effect
from minds import Minds, Profile
import sys
import json
import time
import random
import _thread

# ignore long wait times
IGNORE_TIME = 0

# if 1, we don't actually commit API calls
testmode = 0

# add custom do not subscribes
nosub_list = []
nosub_list.append('981635836376260618')  #artopium - for being a bitch fag
nosub_list.append('981603004186632193')  #mizantroop too much attention

# load skip list
skiplist = {
	"list":[],
}
with open('skiplist.json','r') as f:
	skiplist = json.load(f)
print("skiplist loaded")

# update skip list
def updateSkipList():
	while 1 == 1:
		with open("skiplist.json","r") as f:
			skiplist = json.load(f)
			#json.dump(skiplist,f)
		time.sleep(60*30)
_thread.start_new_thread(updateSkipList,tuple())

# for some reason our stack counter is buggy,
# so this will force reset it when enough threads complain
fullStack = 0
def resetStack():
	global fullStack, __STACK
	while 1 == 1:
		if fullStack > 10:
			__STACK = 0
			fullStack = 0
		time.sleep(25)
_thread.start_new_thread(resetStack,tuple())

counter = 0

if len(sys.argv) > 1:
	testmode = int(sys.argv[1])

print("testmode: " + str(testmode))

__GUIDS = []
__STACK = 0

# log in
while 1 == 1:
	try:
		minds_api = Minds(Profile("YOUR_USER","YOUR_PASS"))
	except:
		continue
	break

self_guid = "1048152926922481673"
subscriptions = minds_api.channel_subscriptions(0,1000)['users']
alreadySubscribed = []
for user in subscriptions:
	alreadySubscribed.append(user['guid'])

#
#	get new people from the subscriptions
#	of GUID
#
def get_leads(guid,level):
	if level == 5:
		return

	global __STACK, fullStack

	attempt = 0
	while 1 == 1:
		try:
			if __STACK < 8:
				print(" :: " + str(level) + " > loading subs " + str(guid))
				__STACK = __STACK + 1
				subs = minds_api.channel_subscriptions_of(guid,0,200)
				__STACK = __STACK - 1
				break
			else:
				fullStack = fullStack + 1
			time.sleep(15)
		except:
			__STACK = __STACK - 1
			if level > 2 or attempt == 2:
				print(" :: ? load subs fail guid " + guid)
				return
			attempt = attempt + 1
			continue

	random.shuffle(subs['users'])
	for u in subs['users']:
		aguid = u['guid']
		if aguid in skiplist['list']:
			continue
		if aguid in alreadySubscribed:
			# MAYBE go to their followers, but we have to get through others
			if random.choice([0,0,0,1]) == 1:
				_thread.start_new_thread(get_leads,(aguid,level + 1,))
				time.sleep(1)
			continue
		try:
			#lastPostTime = minds_api.newsfeed_channel(aguid,0,1)['activity'][0]['time_created']
			while 1 == 1:
				try:
					if __STACK < 8:
						__STACK = __STACK + 1
						lastPostTime = minds_api.newsfeed_channel(aguid,0,1)['activity'][0]['time_created']
						__STACK = __STACK - 1
						break
					else:
						fullStack = fullStack + 1
					time.sleep(2)
				except:
					__STACK = __STACK - 1
					continue
			if (int(lastPostTime) < time.time() - 86400 * 2):
				skiplist['list'].append(aguid)
				continue
			__GUIDS.append(aguid)
			print(" > " + aguid + " added too.")
			_thread.start_new_thread(get_leads,(aguid,level + 1,))
		except Exception as e:
			pass

#
#	mass subscribe function, automating the subscription
#	process after leads are found
#
def mass_subscribe():
	while 1 == 1:
		time.sleep(1)
		guids = __GUIDS
		if len(guids) == 0:
			continue
		print()
		print("subscribing...")

		for target in guids:
			_thread.start_new_thread(act_on,(target,))
			time.sleep(30)

	print("add another username:")
	mass_subscribe()

_thread.start_new_thread(mass_subscribe,tuple())

#
#	give three likes and a follow
#	so that they notice us
#
def act_on(target):
	__GUIDS.remove(target)

	# check if we're already subbed to them
	if target in alreadySubscribed:
		print("user " + str(target) + " already subscribed.")
		return

	try:

		# load up the newsfeed of that particular target
		pp = minds_api.newsfeed_channel(target,1,3)
		time.sleep(1)

		# scan their posts for things to remind, like, etc
		if pp['status'] != 'success' or pp.get('activity') == None:
			return

		if len(pp['activity']) == 0:
			return

		print(" :: " + pp['activity'][0]['ownerObj']['name'])
		so = pp['activity'][0]['ownerObj']['guid']

		for _xx in pp['activity']:
			if random.choice([0,0,0,0,0,1]) == 1:
				continue
			xx = _xx
			r = 0

			if xx['guid'] == False:
				continue

			#
			# like
			#
			try:
				if testmode == 0:
					minds_api.upvote(xx['guid'])
					time.sleep(15)
				print(" L " + xx['guid'])
			except Exception as e:
				print(" ? failed " + str(e))
			s = 1
			sn = xx['ownerObj']['name']

		# after three posts attempt to subscribe
		if s == 1:
			try:
				if testmode == 0:
					minds_api.subscribe(so)
					alreadySubscribed.append(so)
					time.sleep(20)
				print(" | S " + str(sn))
			except Exception as e:
				print(" ? failed " + e)
	except Exception as e:
		print(" ? failed " + str(e))

#
# accept input from USER on new accounts to track
#
ok = 1
while 1 == 1:
	time.sleep(1)
	if ok == 0:
		username = ""
		ok = 1
	else:
		username = input("add username to lead queue: ")

	try:
		guid = minds_api.get_channel(username)['channel']['guid']
		__GUIDS.append(guid)
		print(" > user " + str(guid) + " added.")
		_thread.start_new_thread(get_leads,(guid,0,))
	except:
		print(" ? failed")


'''
Module MESRequest to authenticate the Connector plug-in and collect threat events
from the Lookout RISK API.
'''
import json
import sys
import logging
import requests
import os
from .azuresecret_handler import AzureSecretHandler

class MESRequest:
    '''
    Class MESRequest to authenticate the plug-in and collect threat events
    from the Lookout RISK API.
    '''
    def __init__(self, api_domain, ent_name, api_key, vault_uri, key_index=0):
        # static fields
        self.api_domain = api_domain
        self.ent_name = ent_name
        self.api_key = api_key

        # populate dynamic variables from the Azure Key Vault
        self.az_kv = AzureSecretHandler(vault_uri)

        self.access_token = self.az_kv.get_secret("AccessToken")
        self.refresh_token = self.az_kv.get_secret("RefreshToken")
        self.stream_position = self.az_kv.get_secret("StreamPosition")
        self.is_valid = self.az_kv.get_secret("IsValid")
        self.retry_counter = self.az_kv.get_secret("AuthRetryCounter")

        if not self.retry_counter:
            self.retry_counter = 1
        else:
            self.retry_counter = int(self.retry_counter)

        if not self.is_valid:
            self.is_valid = "YES"

        #For very first time, vault doesn't have any stream position saved, so start from 0
        if not self.stream_position:
            self.stream_position = 0

        self.stale_token_errors = ["REVOKED_REFRESH_TOKEN", "EXPIRED_TOKEN"]

    def refresh_header(self):
        '''Format request headers'''
        return {
            "accept": "application/json",
            "content-type": "application/x-www-form-urlencoded",
            "cache-control": "no-cache"
        }

    def header(self, token):
        '''Format request headers'''
        return {
            "accept": "application/json",
            "authorization": "Bearer {}".format(token),
            "content-type": "application/x-www-form-urlencoded",
            "cache-control": "no-cache"
        }

    def refresh_oauth(self):
        '''
        Refresh access token using the refresh token
        - Stores the new access token in the Azure Vault and in this object
        - If the refresh token has expired, requests a new refresh and access token
          and stores them in the Azure Vault and in this object
        '''
        try:
            response = requests.post(self.api_domain + "/oauth/token",
                                    data="refresh_token={}&grant_type=refresh_token"
                                    .format(self.refresh_token),
                                    headers=self.refresh_header())
            response_content = json.loads(response.text)
            if 'access_token' in response_content:
                self.access_token = response_content['access_token']
                self.az_kv.set_secret("AccessToken", self.access_token)
                self.az_kv.set_secret("IsValid", "YES")
                self.az_kv.set_secret("AuthRetryCounter", 1)
            else:
                # if the refresh failed, request brand new API credentials
                response = requests.post(self.api_domain + "/oauth/token",
                                        data="grant_type=client_credentials",
                                        headers=self.header(self.api_key))
                response_content = json.loads(response.text)
                if 'access_token' in response_content:
                    self.access_token = response_content['access_token']
                    self.refresh_token = response_content['refresh_token']
                    self.az_kv.set_secret("AccessToken", self.access_token)
                    self.az_kv.set_secret("RefreshToken", self.refresh_token)
                    self.az_kv.set_secret("IsValid", "YES")
                    self.az_kv.set_secret("AuthRetryCounter", 1)
                else:
                    if response_content['error'] and response_content['error'] == 'invalid_client':
                        # Set flag to avoid unwanted retries in case of invalid key/client
                        self.retry_counter = int(self.retry_counter) + 1
                        self.az_kv.set_secret("AuthRetryCounter", self.retry_counter)
                        if int(self.retry_counter) >= 10:
                            self.az_kv.set_secret("IsValid", "NO")

                    logging.error("Your Lookout application key has expired. " +
                                "Please get a new key and set up this connector app again.\n" +
                                "Go to https://mtp.lookout.com and generate a new key by " +
                                "navigating to System => Application Keys.")
                    logging.error("Exiting...")
                    sys.exit(1)
        except requests.exceptions.ProxyError as e:
            logging.error("Cannot connect to proxy. Remote end closed connection without response")
        except requests.exceptions.RequestException as e:
            logging.error(e)

    def get_oauth(self):
        '''
        Retrieve OAuth tokens from Lookout API
        - Returns the access_token and the refresh_token
        - If the access token is already stored, returns the
          variables stored locally
        '''
        token_json = {}
        if self.access_token:
            logging.info("The access token has been found locally")
            return self.access_token, self.refresh_token

        logging.info("Could not find an access token, getting one now")

        try:
            response = requests.post(self.api_domain + "/oauth/token",
                                    data="grant_type=client_credentials",
                                    headers=self.header(self.api_key))
            try:
                token_json = json.loads(response.text)
            except (AttributeError, ValueError) as e:
                logging.info("Exception when requesting new access token: " + str(e))
                logging.info("Refreshing access token...")
                self.refresh_oauth()

            if 'access_token' in token_json and 'error' not in token_json:
                logging.info("Storing creds in Azure Vault")
                self.access_token = token_json['access_token']
                self.refresh_token = token_json['refresh_token']
                self.az_kv.set_secret("AccessToken", self.access_token)
                self.az_kv.set_secret("RefreshToken", self.refresh_token)
                self.az_kv.set_secret("IsValid", "YES")
                self.az_kv.set_secret("AuthRetryCounter", 1)
                logging.info("Got authenticated")
                return self.access_token, self.refresh_token
            else:
                if token_json['error'] and token_json['error'] == 'invalid_client':
                    # Set flag to avoid unwanted retries in case of invalid key/client
                    self.retry_counter = int(self.retry_counter) + 1
                    self.az_kv.set_secret("AuthRetryCounter", self.retry_counter)
                    if int(self.retry_counter) >= 10:
                        self.az_kv.set_secret("IsValid", "NO")
                logging.info("Auth API retry count :  " + str(self.retry_counter))
                logging.info("Error in oauth")
                logging.info(str(token_json))
                return False

        except requests.exceptions.ProxyError as e:
            logging.error("Cannot connect to proxy. Remote end closed connection without response")
        except requests.exceptions.RequestException as e:
            logging.error(e)

    def get_events(self):
        '''
        Method to collect events from Metis API
        - Gets access token and stream position from Azure Vault
        - Requests events (retries if error HTTP code)
        - Collect events lists from Metis API, returns full list of events
        '''

        events = []
        retry_count = 0
        more_events = True

        if self.is_valid == "NO" or int(self.retry_counter) >= 10:
            logging.info("Please check API key, Auth API responds with Invalid Client error after 10 retries")
            return events

        if not self.access_token:
            self.get_oauth()

        if self.access_token:
            # Added cycle count to avoid long data polling
            cycle_count = 0
            while more_events and retry_count < 10 and cycle_count < 10 :
                logging.info("Fetching Events from Position {}".format(self.stream_position))
                try:
                    response = requests.get(self.api_domain + "/events?eventType=DEVICE,THREAT,AUDIT",
                                            headers=self.header(self.access_token),
                                            params={"streamPosition": self.stream_position})
                    if response.status_code == 400 and response.json()['errorCode'] in self.stale_token_errors:
                        self.refresh_oauth()
                        continue
                    elif response.status_code != requests.codes.ok:
                        logging.info("Received error code {}, trying again to get events".format(response.status_code))
                        retry_count = retry_count + 1
                        continue
                except requests.exceptions.ProxyError as e:
                    logging.error("Cannot connect to proxy. Remote end closed connection without response")
                except requests.exceptions.RequestException as e:
                    logging.error(e)

                cycle_count = cycle_count + 1
                events = events + response.json()['events']
                self.stream_position = response.json()['streamPosition']

                #update stream position in Azure Vault
                self.az_kv.set_secret("StreamPosition", self.stream_position)

                more_events = response.json()['moreEvents']
                logging.info("Fetched Event Count {}".format(len(events)))
                logging.info("More Events to Fetch : {}".format(more_events))

            if retry_count >= 10:
                logging.error("Too many failed attempts to retrieve events, shutting down.")
                sys.exit(2)

        return events


from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import re
import xlsxwriter

def scrape_prepositions():
    driver = webdriver.Chrome()
    driver.get("https://www.englishclub.com/grammar/prepositions-list.htm")
    all_ul = driver.find_elements_by_xpath("//main/ul")
    prepositions = ''
    for item in all_ul:
        prepositions += item.text.rstrip().lower() + ' '

    prepositions_arr = prepositions.split()
    # print(prepositions_arr)

    prepositions_arr.insert(0, 'Prepositions')
    driver.close()
    return prepositions_arr

def scrape_sports():
    driver = webdriver.Chrome()
    driver.get("https://www.topendsports.com/sport/list/index.htm")
    all_ul = driver.find_elements_by_xpath("//div/div/ul/li/a[1]")
    sports = []
    for item in all_ul:
        sports.append(item.text.rstrip().lower())

    # eliminate the random hyperlinks at the end
    reduce_array = sports[:-15]
    # print(reduce_array)

    reduce_array.insert(0, 'Sports')
    driver.close()
    return reduce_array

def scrape_politics():
    driver = webdriver.Chrome()
    driver.get("https://myvocabulary.com/word-list/politics-vocabulary/")
    all_ul = driver.find_elements_by_xpath("//tbody/tr/td[2]")
    politics = []
    for item in all_ul:
        temp_arr = item.text.rstrip().split(' ')
        for word in temp_arr:
            regex = re.compile('[^a-zA-Z]')
            word = regex.sub('', word)
            politics.append(word.strip().lower())

    politics.insert(0, 'Politics')
    driver.close()
    return politics

def scrape_social_issues():
    driver = webdriver.Chrome()
    driver.get("https://www.isidewith.com/polls/popular")
    all_ul = driver.find_elements_by_xpath("//div/div/a/div/p/span")
    social = []
    for item in all_ul:
        social.append(item.text.lower())

    social.insert(0, "Social Justice")
    social.append('blm')
    driver.close()
    return social

def scrape_science():
    driver = webdriver.Chrome()
    driver.get("https://myvocabulary.com/word-list/science-vocabulary/")
    all_ul = driver.find_elements_by_xpath("//tbody/tr/td[2]")
    science = []
    for item in all_ul:
        temp_arr = item.text.rstrip().split(' ')
        for word in temp_arr:
            regex = re.compile('[^a-zA-Z]')
            word = regex.sub('', word)
            science.append(word.strip().lower())

    science.insert(0, 'Science')
    driver.close()

    driver = webdriver.Chrome()
    driver.get("https://myvocabulary.com/word-list/global-warming-vocabulary/")
    all_ul = driver.find_elements_by_xpath("tbody/tr/td[2]")
    for item in all_ul:
        science.append(item.text.lower())

    driver.close()
    return science

def scrape_contractions():
    driver = webdriver.Chrome()
    driver.get("https://en.wikipedia.org/wiki/Wikipedia:List_of_English_contractions")
    #mw-content-text > div.mw-parser-output > table.wikitable.sortable.jquery-tablesorter > tbody > tr:nth-child(1) > td:nth-child(1)
    all_ul = driver.find_elements_by_xpath("//div/div/table/tbody/tr/td[1]")
    contractions = []
    regex = re.compile('[^a-zA-Z]')
    for item in all_ul:
        if len(item.text) == 0:
            continue
        words = regex.sub('', item.text)
        contractions.append(words.lower())

    contractions.insert(0, 'Contractions')
    contractions_reduce = contractions[:-2]
    driver.close()
    return contractions_reduce

names = []

def scrape_names(names):
    driver = webdriver.Chrome()
    driver.get("https://family.disney.com/articles/1000-most-popular-boy-names/")
    all_ul = driver.find_elements_by_xpath("//body/div/div/article/div/main/ol/li")
    for item in all_ul:
        if len(names) > 450:
            break
        names.append(item.text.lower())

    names.insert(0, "Names")
    driver.close()

def scrape_names_two(names):
    driver = webdriver.Chrome()
    driver.get("https://www.whattoexpect.com/baby-names/list/top-baby-names-for-girls/")
    girls_ul = driver.find_elements_by_xpath("//body/div/div/div[2]/div[2]/article/div[2]/section[2]/div[2]/div/div[2]/ol/li")
    for item in girls_ul:
        if len(names) > 900:
            break
        names.append(item.text.lower())
    driver.close()

def create_spreadsheet():
    workbook = xlsxwriter.Workbook('Words.xlsx')
    worksheet = workbook.add_worksheet()

    scrape_names(names)
    scrape_names_two(names)

    array = [scrape_prepositions(),
            scrape_sports(),
            scrape_social_issues(),
            scrape_politics(),
            scrape_science(),
            scrape_contractions(),
            names]

    row = 0

    for col, data in enumerate(array):
        worksheet.write_column(row, col, data)

    workbook.close()

create_spreadsheet()